static int snd_ivtv_pcm_capture_open(struct snd_pcm_substream *substream) { struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct v4l2_device *v4l2_dev = itvsc->v4l2_dev; struct ivtv *itv = to_ivtv(v4l2_dev); struct ivtv_stream *s; struct ivtv_open_id item; int ret; /* Instruct the CX2341[56] to start sending packets */ snd_ivtv_lock(itvsc); if (ivtv_init_on_first_open(itv)) { snd_ivtv_unlock(itvsc); return -ENXIO; } s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM]; v4l2_fh_init(&item.fh, s->vdev); item.itv = itv; item.type = s->type; /* See if the stream is available */ if (ivtv_claim_stream(&item, item.type)) { /* No, it's already in use */ snd_ivtv_unlock(itvsc); return -EBUSY; } if (test_bit(IVTV_F_S_STREAMOFF, &s->s_flags) || test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) { /* We're already streaming. No additional action required */ snd_ivtv_unlock(itvsc); return 0; } runtime->hw = snd_ivtv_hw_capture; snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); itvsc->capture_pcm_substream = substream; runtime->private_data = itv; itv->pcm_announce_callback = ivtv_alsa_announce_pcm_data; /* Not currently streaming, so start it up */ set_bit(IVTV_F_S_STREAMING, &s->s_flags); ret = ivtv_start_v4l2_encode_stream(s); snd_ivtv_unlock(itvsc); return ret; }
int ivtv_start_capture(struct ivtv_open_id *id) { struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; struct ivtv_stream *s_vbi; if (s->type == IVTV_ENC_STREAM_TYPE_RAD || s->type == IVTV_DEC_STREAM_TYPE_MPG || s->type == IVTV_DEC_STREAM_TYPE_YUV || s->type == IVTV_DEC_STREAM_TYPE_VOUT) { /* you cannot read from these stream types. */ return -EINVAL; } /* Try to claim this stream. */ if (ivtv_claim_stream(id, s->type)) return -EBUSY; /* This stream does not need to start capturing */ if (s->type == IVTV_DEC_STREAM_TYPE_VBI) { set_bit(IVTV_F_S_APPL_IO, &s->s_flags); return 0; } /* If capture is already in progress, then we also have to do nothing extra. */ if (test_bit(IVTV_F_S_STREAMOFF, &s->s_flags) || test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) { set_bit(IVTV_F_S_APPL_IO, &s->s_flags); return 0; } /* Start VBI capture if required */ s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; if (s->type == IVTV_ENC_STREAM_TYPE_MPG && test_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags) && !test_and_set_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags)) { /* Note: the IVTV_ENC_STREAM_TYPE_VBI is claimed automatically when the MPG stream is claimed. We only need to start the VBI capturing. */ if (ivtv_start_v4l2_encode_stream(s_vbi)) { IVTV_DEBUG_WARN("VBI capture start failed\n"); /* Failure, clean up and return an error */ clear_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags); clear_bit(IVTV_F_S_STREAMING, &s->s_flags); /* also releases the associated VBI stream */ ivtv_release_stream(s); return -EIO; } IVTV_DEBUG_INFO("VBI insertion started\n"); } /* Tell the card to start capturing */ if (!ivtv_start_v4l2_encode_stream(s)) { /* We're done */ set_bit(IVTV_F_S_APPL_IO, &s->s_flags); /* Resume a possibly paused encoder */ if (test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags)) ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1); return 0; } /* failure, clean up */ IVTV_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name); /* Note: the IVTV_ENC_STREAM_TYPE_VBI is released automatically when the MPG stream is released. We only need to stop the VBI capturing. */ if (s->type == IVTV_ENC_STREAM_TYPE_MPG && test_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags)) { ivtv_stop_v4l2_encode_stream(s_vbi, 0); clear_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags); } clear_bit(IVTV_F_S_STREAMING, &s->s_flags); ivtv_release_stream(s); return -EIO; }