1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * ALSA PCM device for the 4 * ALSA interface to cx18 PCM capture streams 5 * 6 * Copyright (C) 2009 Andy Walls <awalls@md.metrocast.net> 7 * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> 8 * 9 * Portions of this work were sponsored by ONELAN Limited. 10 */ 11 12 #include <linux/init.h> 13 #include <linux/kernel.h> 14 #include <linux/vmalloc.h> 15 16 #include <media/v4l2-device.h> 17 18 #include <sound/core.h> 19 #include <sound/pcm.h> 20 21 #include "cx18-driver.h" 22 #include "cx18-queue.h" 23 #include "cx18-streams.h" 24 #include "cx18-fileops.h" 25 #include "cx18-alsa.h" 26 #include "cx18-alsa-pcm.h" 27 28 static unsigned int pcm_debug; 29 module_param(pcm_debug, int, 0644); 30 MODULE_PARM_DESC(pcm_debug, "enable debug messages for pcm"); 31 32 #define dprintk(fmt, arg...) do { \ 33 if (pcm_debug) \ 34 printk(KERN_INFO "cx18-alsa-pcm %s: " fmt, \ 35 __func__, ##arg); \ 36 } while (0) 37 38 static const struct snd_pcm_hardware snd_cx18_hw_capture = { 39 .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | 40 SNDRV_PCM_INFO_MMAP | 41 SNDRV_PCM_INFO_INTERLEAVED | 42 SNDRV_PCM_INFO_MMAP_VALID, 43 44 .formats = SNDRV_PCM_FMTBIT_S16_LE, 45 46 .rates = SNDRV_PCM_RATE_48000, 47 48 .rate_min = 48000, 49 .rate_max = 48000, 50 .channels_min = 2, 51 .channels_max = 2, 52 .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ 53 .period_bytes_min = 64, /* 12544/2, */ 54 .period_bytes_max = 12544, 55 .periods_min = 2, 56 .periods_max = 98, /* 12544, */ 57 }; 58 59 void cx18_alsa_announce_pcm_data(struct snd_cx18_card *cxsc, u8 *pcm_data, 60 size_t num_bytes) 61 { 62 struct snd_pcm_substream *substream; 63 struct snd_pcm_runtime *runtime; 64 unsigned int oldptr; 65 unsigned int stride; 66 int period_elapsed = 0; 67 int length; 68 69 dprintk("cx18 alsa announce ptr=%p data=%p num_bytes=%zu\n", cxsc, 70 pcm_data, num_bytes); 71 72 substream = cxsc->capture_pcm_substream; 73 if (substream == NULL) { 74 dprintk("substream was NULL\n"); 75 return; 76 } 77 78 runtime = substream->runtime; 79 if (runtime == NULL) { 80 dprintk("runtime was NULL\n"); 81 return; 82 } 83 84 stride = runtime->frame_bits >> 3; 85 if (stride == 0) { 86 dprintk("stride is zero\n"); 87 return; 88 } 89 90 length = num_bytes / stride; 91 if (length == 0) { 92 dprintk("%s: length was zero\n", __func__); 93 return; 94 } 95 96 if (runtime->dma_area == NULL) { 97 dprintk("dma area was NULL - ignoring\n"); 98 return; 99 } 100 101 oldptr = cxsc->hwptr_done_capture; 102 if (oldptr + length >= runtime->buffer_size) { 103 unsigned int cnt = 104 runtime->buffer_size - oldptr; 105 memcpy(runtime->dma_area + oldptr * stride, pcm_data, 106 cnt * stride); 107 memcpy(runtime->dma_area, pcm_data + cnt * stride, 108 length * stride - cnt * stride); 109 } else { 110 memcpy(runtime->dma_area + oldptr * stride, pcm_data, 111 length * stride); 112 } 113 snd_pcm_stream_lock(substream); 114 115 cxsc->hwptr_done_capture += length; 116 if (cxsc->hwptr_done_capture >= 117 runtime->buffer_size) 118 cxsc->hwptr_done_capture -= 119 runtime->buffer_size; 120 121 cxsc->capture_transfer_done += length; 122 if (cxsc->capture_transfer_done >= 123 runtime->period_size) { 124 cxsc->capture_transfer_done -= 125 runtime->period_size; 126 period_elapsed = 1; 127 } 128 129 snd_pcm_stream_unlock(substream); 130 131 if (period_elapsed) 132 snd_pcm_period_elapsed(substream); 133 } 134 135 static int snd_cx18_pcm_capture_open(struct snd_pcm_substream *substream) 136 { 137 struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); 138 struct snd_pcm_runtime *runtime = substream->runtime; 139 struct v4l2_device *v4l2_dev = cxsc->v4l2_dev; 140 struct cx18 *cx = to_cx18(v4l2_dev); 141 struct cx18_stream *s; 142 struct cx18_open_id item; 143 int ret; 144 145 /* Instruct the cx18 to start sending packets */ 146 snd_cx18_lock(cxsc); 147 s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM]; 148 149 item.cx = cx; 150 item.type = s->type; 151 item.open_id = cx->open_id++; 152 153 /* See if the stream is available */ 154 if (cx18_claim_stream(&item, item.type)) { 155 /* No, it's already in use */ 156 snd_cx18_unlock(cxsc); 157 return -EBUSY; 158 } 159 160 if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) || 161 test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) { 162 /* We're already streaming. No additional action required */ 163 snd_cx18_unlock(cxsc); 164 return 0; 165 } 166 167 168 runtime->hw = snd_cx18_hw_capture; 169 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); 170 cxsc->capture_pcm_substream = substream; 171 runtime->private_data = cx; 172 173 cx->pcm_announce_callback = cx18_alsa_announce_pcm_data; 174 175 /* Not currently streaming, so start it up */ 176 set_bit(CX18_F_S_STREAMING, &s->s_flags); 177 ret = cx18_start_v4l2_encode_stream(s); 178 snd_cx18_unlock(cxsc); 179 180 return ret; 181 } 182 183 static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream) 184 { 185 struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); 186 struct v4l2_device *v4l2_dev = cxsc->v4l2_dev; 187 struct cx18 *cx = to_cx18(v4l2_dev); 188 struct cx18_stream *s; 189 190 /* Instruct the cx18 to stop sending packets */ 191 snd_cx18_lock(cxsc); 192 s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM]; 193 cx18_stop_v4l2_encode_stream(s, 0); 194 clear_bit(CX18_F_S_STREAMING, &s->s_flags); 195 196 cx18_release_stream(s); 197 198 cx->pcm_announce_callback = NULL; 199 snd_cx18_unlock(cxsc); 200 201 return 0; 202 } 203 204 static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream, 205 unsigned int cmd, void *arg) 206 { 207 struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); 208 int ret; 209 210 snd_cx18_lock(cxsc); 211 ret = snd_pcm_lib_ioctl(substream, cmd, arg); 212 snd_cx18_unlock(cxsc); 213 return ret; 214 } 215 216 217 static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, 218 size_t size) 219 { 220 struct snd_pcm_runtime *runtime = subs->runtime; 221 222 dprintk("Allocating vbuffer\n"); 223 if (runtime->dma_area) { 224 if (runtime->dma_bytes > size) 225 return 0; 226 227 vfree(runtime->dma_area); 228 } 229 runtime->dma_area = vmalloc(size); 230 if (!runtime->dma_area) 231 return -ENOMEM; 232 233 runtime->dma_bytes = size; 234 235 return 0; 236 } 237 238 static int snd_cx18_pcm_hw_params(struct snd_pcm_substream *substream, 239 struct snd_pcm_hw_params *params) 240 { 241 dprintk("%s called\n", __func__); 242 243 return snd_pcm_alloc_vmalloc_buffer(substream, 244 params_buffer_bytes(params)); 245 } 246 247 static int snd_cx18_pcm_hw_free(struct snd_pcm_substream *substream) 248 { 249 struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); 250 unsigned long flags; 251 unsigned char *dma_area = NULL; 252 253 spin_lock_irqsave(&cxsc->slock, flags); 254 if (substream->runtime->dma_area) { 255 dprintk("freeing pcm capture region\n"); 256 dma_area = substream->runtime->dma_area; 257 substream->runtime->dma_area = NULL; 258 } 259 spin_unlock_irqrestore(&cxsc->slock, flags); 260 vfree(dma_area); 261 262 return 0; 263 } 264 265 static int snd_cx18_pcm_prepare(struct snd_pcm_substream *substream) 266 { 267 struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); 268 269 cxsc->hwptr_done_capture = 0; 270 cxsc->capture_transfer_done = 0; 271 272 return 0; 273 } 274 275 static int snd_cx18_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 276 { 277 return 0; 278 } 279 280 static 281 snd_pcm_uframes_t snd_cx18_pcm_pointer(struct snd_pcm_substream *substream) 282 { 283 unsigned long flags; 284 snd_pcm_uframes_t hwptr_done; 285 struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); 286 287 spin_lock_irqsave(&cxsc->slock, flags); 288 hwptr_done = cxsc->hwptr_done_capture; 289 spin_unlock_irqrestore(&cxsc->slock, flags); 290 291 return hwptr_done; 292 } 293 294 static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, 295 unsigned long offset) 296 { 297 void *pageptr = subs->runtime->dma_area + offset; 298 299 return vmalloc_to_page(pageptr); 300 } 301 302 static const struct snd_pcm_ops snd_cx18_pcm_capture_ops = { 303 .open = snd_cx18_pcm_capture_open, 304 .close = snd_cx18_pcm_capture_close, 305 .ioctl = snd_cx18_pcm_ioctl, 306 .hw_params = snd_cx18_pcm_hw_params, 307 .hw_free = snd_cx18_pcm_hw_free, 308 .prepare = snd_cx18_pcm_prepare, 309 .trigger = snd_cx18_pcm_trigger, 310 .pointer = snd_cx18_pcm_pointer, 311 .page = snd_pcm_get_vmalloc_page, 312 }; 313 314 int snd_cx18_pcm_create(struct snd_cx18_card *cxsc) 315 { 316 struct snd_pcm *sp; 317 struct snd_card *sc = cxsc->sc; 318 struct v4l2_device *v4l2_dev = cxsc->v4l2_dev; 319 struct cx18 *cx = to_cx18(v4l2_dev); 320 int ret; 321 322 ret = snd_pcm_new(sc, "CX23418 PCM", 323 0, /* PCM device 0, the only one for this card */ 324 0, /* 0 playback substreams */ 325 1, /* 1 capture substream */ 326 &sp); 327 if (ret) { 328 CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n", 329 __func__, ret); 330 goto err_exit; 331 } 332 333 spin_lock_init(&cxsc->slock); 334 335 snd_pcm_set_ops(sp, SNDRV_PCM_STREAM_CAPTURE, 336 &snd_cx18_pcm_capture_ops); 337 sp->info_flags = 0; 338 sp->private_data = cxsc; 339 strscpy(sp->name, cx->card_name, sizeof(sp->name)); 340 341 return 0; 342 343 err_exit: 344 return ret; 345 } 346