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