0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include "ivtv-driver.h"
0013 #include "ivtv-queue.h"
0014 #include "ivtv-streams.h"
0015 #include "ivtv-fileops.h"
0016 #include "ivtv-alsa.h"
0017 #include "ivtv-alsa-pcm.h"
0018
0019 #include <sound/core.h>
0020 #include <sound/pcm.h>
0021
0022
0023 static unsigned int pcm_debug;
0024 module_param(pcm_debug, int, 0644);
0025 MODULE_PARM_DESC(pcm_debug, "enable debug messages for pcm");
0026
0027 #define dprintk(fmt, arg...) \
0028 do { \
0029 if (pcm_debug) \
0030 pr_info("ivtv-alsa-pcm %s: " fmt, __func__, ##arg); \
0031 } while (0)
0032
0033 static const struct snd_pcm_hardware snd_ivtv_hw_capture = {
0034 .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
0035 SNDRV_PCM_INFO_MMAP |
0036 SNDRV_PCM_INFO_INTERLEAVED |
0037 SNDRV_PCM_INFO_MMAP_VALID,
0038
0039 .formats = SNDRV_PCM_FMTBIT_S16_LE,
0040
0041 .rates = SNDRV_PCM_RATE_48000,
0042
0043 .rate_min = 48000,
0044 .rate_max = 48000,
0045 .channels_min = 2,
0046 .channels_max = 2,
0047 .buffer_bytes_max = 62720 * 8,
0048 .period_bytes_min = 64,
0049 .period_bytes_max = 12544,
0050 .periods_min = 2,
0051 .periods_max = 98,
0052 };
0053
0054 static void ivtv_alsa_announce_pcm_data(struct snd_ivtv_card *itvsc,
0055 u8 *pcm_data,
0056 size_t num_bytes)
0057 {
0058 struct snd_pcm_substream *substream;
0059 struct snd_pcm_runtime *runtime;
0060 unsigned int oldptr;
0061 unsigned int stride;
0062 int period_elapsed = 0;
0063 int length;
0064
0065 dprintk("ivtv alsa announce ptr=%p data=%p num_bytes=%zu\n", itvsc,
0066 pcm_data, num_bytes);
0067
0068 substream = itvsc->capture_pcm_substream;
0069 if (substream == NULL) {
0070 dprintk("substream was NULL\n");
0071 return;
0072 }
0073
0074 runtime = substream->runtime;
0075 if (runtime == NULL) {
0076 dprintk("runtime was NULL\n");
0077 return;
0078 }
0079
0080 stride = runtime->frame_bits >> 3;
0081 if (stride == 0) {
0082 dprintk("stride is zero\n");
0083 return;
0084 }
0085
0086 length = num_bytes / stride;
0087 if (length == 0) {
0088 dprintk("%s: length was zero\n", __func__);
0089 return;
0090 }
0091
0092 if (runtime->dma_area == NULL) {
0093 dprintk("dma area was NULL - ignoring\n");
0094 return;
0095 }
0096
0097 oldptr = itvsc->hwptr_done_capture;
0098 if (oldptr + length >= runtime->buffer_size) {
0099 unsigned int cnt =
0100 runtime->buffer_size - oldptr;
0101 memcpy(runtime->dma_area + oldptr * stride, pcm_data,
0102 cnt * stride);
0103 memcpy(runtime->dma_area, pcm_data + cnt * stride,
0104 length * stride - cnt * stride);
0105 } else {
0106 memcpy(runtime->dma_area + oldptr * stride, pcm_data,
0107 length * stride);
0108 }
0109 snd_pcm_stream_lock(substream);
0110
0111 itvsc->hwptr_done_capture += length;
0112 if (itvsc->hwptr_done_capture >=
0113 runtime->buffer_size)
0114 itvsc->hwptr_done_capture -=
0115 runtime->buffer_size;
0116
0117 itvsc->capture_transfer_done += length;
0118 if (itvsc->capture_transfer_done >=
0119 runtime->period_size) {
0120 itvsc->capture_transfer_done -=
0121 runtime->period_size;
0122 period_elapsed = 1;
0123 }
0124
0125 snd_pcm_stream_unlock(substream);
0126
0127 if (period_elapsed)
0128 snd_pcm_period_elapsed(substream);
0129 }
0130
0131 static int snd_ivtv_pcm_capture_open(struct snd_pcm_substream *substream)
0132 {
0133 struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
0134 struct snd_pcm_runtime *runtime = substream->runtime;
0135 struct v4l2_device *v4l2_dev = itvsc->v4l2_dev;
0136 struct ivtv *itv = to_ivtv(v4l2_dev);
0137 struct ivtv_stream *s;
0138 struct ivtv_open_id item;
0139 int ret;
0140
0141
0142 snd_ivtv_lock(itvsc);
0143
0144 if (ivtv_init_on_first_open(itv)) {
0145 snd_ivtv_unlock(itvsc);
0146 return -ENXIO;
0147 }
0148
0149 s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
0150
0151 v4l2_fh_init(&item.fh, &s->vdev);
0152 item.itv = itv;
0153 item.type = s->type;
0154
0155
0156 if (ivtv_claim_stream(&item, item.type)) {
0157
0158 v4l2_fh_exit(&item.fh);
0159 snd_ivtv_unlock(itvsc);
0160 return -EBUSY;
0161 }
0162
0163 if (test_bit(IVTV_F_S_STREAMOFF, &s->s_flags) ||
0164 test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
0165
0166 snd_ivtv_unlock(itvsc);
0167 return 0;
0168 }
0169
0170
0171 runtime->hw = snd_ivtv_hw_capture;
0172 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
0173 itvsc->capture_pcm_substream = substream;
0174 runtime->private_data = itv;
0175
0176 itv->pcm_announce_callback = ivtv_alsa_announce_pcm_data;
0177
0178
0179 set_bit(IVTV_F_S_STREAMING, &s->s_flags);
0180 ret = ivtv_start_v4l2_encode_stream(s);
0181 snd_ivtv_unlock(itvsc);
0182
0183 return ret;
0184 }
0185
0186 static int snd_ivtv_pcm_capture_close(struct snd_pcm_substream *substream)
0187 {
0188 struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
0189 struct v4l2_device *v4l2_dev = itvsc->v4l2_dev;
0190 struct ivtv *itv = to_ivtv(v4l2_dev);
0191 struct ivtv_stream *s;
0192
0193
0194 snd_ivtv_lock(itvsc);
0195 s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
0196 ivtv_stop_v4l2_encode_stream(s, 0);
0197 clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
0198
0199 ivtv_release_stream(s);
0200
0201 itv->pcm_announce_callback = NULL;
0202 snd_ivtv_unlock(itvsc);
0203
0204 return 0;
0205 }
0206
0207 static int snd_ivtv_pcm_prepare(struct snd_pcm_substream *substream)
0208 {
0209 struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
0210
0211 itvsc->hwptr_done_capture = 0;
0212 itvsc->capture_transfer_done = 0;
0213
0214 return 0;
0215 }
0216
0217 static int snd_ivtv_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
0218 {
0219 return 0;
0220 }
0221
0222 static
0223 snd_pcm_uframes_t snd_ivtv_pcm_pointer(struct snd_pcm_substream *substream)
0224 {
0225 unsigned long flags;
0226 snd_pcm_uframes_t hwptr_done;
0227 struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
0228
0229 spin_lock_irqsave(&itvsc->slock, flags);
0230 hwptr_done = itvsc->hwptr_done_capture;
0231 spin_unlock_irqrestore(&itvsc->slock, flags);
0232
0233 return hwptr_done;
0234 }
0235
0236 static const struct snd_pcm_ops snd_ivtv_pcm_capture_ops = {
0237 .open = snd_ivtv_pcm_capture_open,
0238 .close = snd_ivtv_pcm_capture_close,
0239 .prepare = snd_ivtv_pcm_prepare,
0240 .trigger = snd_ivtv_pcm_trigger,
0241 .pointer = snd_ivtv_pcm_pointer,
0242 };
0243
0244 int snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc)
0245 {
0246 struct snd_pcm *sp;
0247 struct snd_card *sc = itvsc->sc;
0248 struct v4l2_device *v4l2_dev = itvsc->v4l2_dev;
0249 struct ivtv *itv = to_ivtv(v4l2_dev);
0250 int ret;
0251
0252 ret = snd_pcm_new(sc, "CX2341[56] PCM",
0253 0,
0254 0,
0255 1,
0256 &sp);
0257 if (ret) {
0258 IVTV_ALSA_ERR("%s: snd_ivtv_pcm_create() failed with err %d\n",
0259 __func__, ret);
0260 goto err_exit;
0261 }
0262
0263 spin_lock_init(&itvsc->slock);
0264
0265 snd_pcm_set_ops(sp, SNDRV_PCM_STREAM_CAPTURE,
0266 &snd_ivtv_pcm_capture_ops);
0267 snd_pcm_set_managed_buffer_all(sp, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
0268 sp->info_flags = 0;
0269 sp->private_data = itvsc;
0270 strscpy(sp->name, itv->card_name, sizeof(sp->name));
0271
0272 return 0;
0273
0274 err_exit:
0275 return ret;
0276 }