Ejemplo n.º 1
0
static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
{
    struct cx18 *cx = s->cx;
    struct cx18_open_id *item;

    CX18_DEBUG_FILE("open %s\n", s->name);

    /* Allocate memory */
    item = kmalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
    if (NULL == item) {
        CX18_DEBUG_WARN("nomem on v4l2 open\n");
        return -ENOMEM;
    }
    item->cx = cx;
    item->type = s->type;
    v4l2_prio_open(&cx->prio, &item->prio);

    item->open_id = cx->open_id++;
    filp->private_data = item;

    if (item->type == CX18_ENC_STREAM_TYPE_RAD) {
        /* Try to claim this stream */
        if (cx18_claim_stream(item, item->type)) {
            /* No, it's already in use */
            kfree(item);
            return -EBUSY;
        }

        if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
            if (atomic_read(&cx->ana_capturing) > 0) {
                /* switching to radio while capture is
                   in progress is not polite */
                cx18_release_stream(s);
                kfree(item);
                return -EBUSY;
            }
        }

        /* Mark that the radio is being used. */
        set_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
        /* We have the radio */
        cx18_mute(cx);
        /* Switch tuner to radio */
        cx18_call_i2c_clients(cx, AUDC_SET_RADIO, NULL);
        /* Select the correct audio input (i.e. radio tuner) */
        cx18_audio_set_io(cx);
        /* Done! Unmute and continue. */
        cx18_unmute(cx);
    }
    return 0;
}
Ejemplo n.º 2
0
static int snd_cx18_pcm_capture_open(struct snd_pcm_substream *substream)
{
	struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
	struct cx18 *cx = to_cx18(v4l2_dev);
	struct cx18_stream *s;
	struct cx18_open_id item;
	int ret;

	/* Instruct the cx18 to start sending packets */
	snd_cx18_lock(cxsc);
	s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];

	item.cx = cx;
	item.type = s->type;
	item.open_id = cx->open_id++;

	/* See if the stream is available */
	if (cx18_claim_stream(&item, item.type)) {
		/* No, it's already in use */
		snd_cx18_unlock(cxsc);
		return -EBUSY;
	}

	if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
	    test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
		/* We're already streaming.  No additional action required */
		snd_cx18_unlock(cxsc);
		return 0;
	}


	runtime->hw = snd_cx18_hw_capture;
	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
	cxsc->capture_pcm_substream = substream;
	runtime->private_data = cx;

	cx->pcm_announce_callback = cx18_alsa_announce_pcm_data;

	/* Not currently streaming, so start it up */
	set_bit(CX18_F_S_STREAMING, &s->s_flags);
	ret = cx18_start_v4l2_encode_stream(s);
	snd_cx18_unlock(cxsc);

	return ret;
}
Ejemplo n.º 3
0
int cx18_start_capture(struct cx18_open_id *id)
{
    struct cx18 *cx = id->cx;
    struct cx18_stream *s = &cx->streams[id->type];
    struct cx18_stream *s_vbi;

    if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
        /* you cannot read from these stream types. */
        return -EPERM;
    }

    /* Try to claim this stream. */
    if (cx18_claim_stream(id, s->type))
        return -EBUSY;

    /* If capture is already in progress, then we also have to
       do nothing extra. */
    if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
            test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
        set_bit(CX18_F_S_APPL_IO, &s->s_flags);
        return 0;
    }

    /* Start VBI capture if required */
    s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
    if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
            test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
            !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
        /* Note: the CX18_ENC_STREAM_TYPE_VBI is claimed
           automatically when the MPG stream is claimed.
           We only need to start the VBI capturing. */
        if (cx18_start_v4l2_encode_stream(s_vbi)) {
            CX18_DEBUG_WARN("VBI capture start failed\n");

            /* Failure, clean up and return an error */
            clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
            clear_bit(CX18_F_S_STREAMING, &s->s_flags);
            /* also releases the associated VBI stream */
            cx18_release_stream(s);
            return -EIO;
        }
        CX18_DEBUG_INFO("VBI insertion started\n");
    }

    /* Tell the card to start capturing */
    if (!cx18_start_v4l2_encode_stream(s)) {
        /* We're done */
        set_bit(CX18_F_S_APPL_IO, &s->s_flags);
        /* Resume a possibly paused encoder */
        if (test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
            cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, s->handle);
        return 0;
    }

    /* failure, clean up */
    CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);

    /* Note: the CX18_ENC_STREAM_TYPE_VBI is released
       automatically when the MPG stream is released.
       We only need to stop the VBI capturing. */
    if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
            test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
        cx18_stop_v4l2_encode_stream(s_vbi, 0);
        clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
    }
    clear_bit(CX18_F_S_STREAMING, &s->s_flags);
    cx18_release_stream(s);
    return -EIO;
}