diff options
Diffstat (limited to 'v4l_experimental/pvrusb2/pvrusb2-video-v4l.c')
-rw-r--r-- | v4l_experimental/pvrusb2/pvrusb2-video-v4l.c | 301 |
1 files changed, 131 insertions, 170 deletions
diff --git a/v4l_experimental/pvrusb2/pvrusb2-video-v4l.c b/v4l_experimental/pvrusb2/pvrusb2-video-v4l.c index 037ba5a71..bf91e3d2a 100644 --- a/v4l_experimental/pvrusb2/pvrusb2-video-v4l.c +++ b/v4l_experimental/pvrusb2/pvrusb2-video-v4l.c @@ -1,6 +1,6 @@ /* * - * $Id: pvrusb2-video-v4l.c,v 1.5 2005/12/28 16:28:02 mcisely Exp $ + * $Id: pvrusb2-video-v4l.c,v 1.6 2006/01/01 08:26:03 mcisely Exp $ * * Copyright (C) 2005 Mike Isely <isely@pobox.com> * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> @@ -22,11 +22,6 @@ /* - This module connects the pvrusb2 driver to the I2C chip level - driver which handles device video processing. This interface is - used internally by the driver; higher level code should only - interact through the interface provided by pvrusb2-hdw.h. - This source file is specifically designed to interface with the saa711x support that is available in the v4l available starting with linux 2.6.15. @@ -37,7 +32,6 @@ #ifndef PVR2_SUPPRESS_SAA711X -#include "pvrusb2-i2c.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include <linux/videodev.h> @@ -45,41 +39,21 @@ #include <linux/errno.h> #include <linux/slab.h> - -#define pvr2_decoder_trace(...) pvr2_trace(PVR2_TRACE_DECODER,__VA_ARGS__) - - -static int pvr2_decoder_v4l_enable_output(struct pvr2_decoder *dcp) -{ - int status; - struct pvr2_hdw *hdw = dcp->hdw; - pvr2_decoder_trace("pvr2_decoder_enable_output"); - status = pvr2_i2c_saa7115_cmd(hdw,VIDIOC_STREAMON,0); - if (status) return status; - hdw->subsys_enabled_mask |= PVR2_SUBSYS_DIGITIZER_RUN; - return 0; -} - - -static int pvr2_decoder_v4l_disable_output(struct pvr2_decoder *dcp) -{ - int status; - struct pvr2_hdw *hdw = dcp->hdw; - pvr2_decoder_trace("pvr2_decoder_disable_output"); - status = pvr2_i2c_saa7115_cmd(hdw,VIDIOC_STREAMOFF,0); - if (status) return status; - hdw->subsys_enabled_mask &= ~PVR2_SUBSYS_DIGITIZER_RUN; - return 0; -} +struct pvr2_v4l_decoder { + struct pvr2_i2c_handler handler; + struct pvr2_decoder_ctrl ctrl; + struct pvr2_i2c_client *client; + struct pvr2_hdw *hdw; + unsigned long stale_mask; +}; -static int pvr2_decoder_v4l_set_input(struct pvr2_decoder *dcp) +static void set_input(struct pvr2_v4l_decoder *ctxt) { - int status; - struct pvr2_hdw *hdw = dcp->hdw; + struct pvr2_hdw *hdw = ctxt->hdw; int v = 0; - pvr2_decoder_trace("pvr2_decoder_set_input(%d)", - hdw->controls[PVR2_CID_INPUT].value); + pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)", + hdw->controls[PVR2_CID_INPUT].value); switch(hdw->controls[PVR2_CID_INPUT].value){ case PVR2_CVAL_INPUT_TV: v = 4; @@ -93,179 +67,166 @@ static int pvr2_decoder_v4l_set_input(struct pvr2_decoder *dcp) case PVR2_CVAL_INPUT_RADIO: // ????? No idea yet what to do here default: - return -EINVAL; - } - status = pvr2_i2c_saa7115_cmd(hdw,VIDIOC_S_INPUT,&v); - if (!status) { - hdw->subsys_enabled_mask |= PVR2_SUBSYS_DIGITIZER_CFG_INPUT; + return; } - return status; + pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_INPUT,&v); } -static int pvr2_decoder_v4l_set_bcsh(struct pvr2_decoder *dcp) +static int check_input(struct pvr2_v4l_decoder *ctxt) { - struct v4l2_control ctrl; - struct pvr2_hdw *hdw = dcp->hdw; - int ret; - memset(&ctrl,0,sizeof(ctrl)); - - pvr2_decoder_trace("pvr2_decoder_set_bcsh b=%d c=%d s=%d h=%d", - hdw->controls[PVR2_CID_BRIGHTNESS].value, - hdw->controls[PVR2_CID_CONTRAST].value, - hdw->controls[PVR2_CID_SATURATION].value, - hdw->controls[PVR2_CID_HUE].value); - - ctrl.id = V4L2_CID_BRIGHTNESS; - ctrl.value = hdw->controls[PVR2_CID_BRIGHTNESS].value; - ret = pvr2_i2c_saa7115_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - if (ret) return ret; - ctrl.id = V4L2_CID_CONTRAST; - ctrl.value = hdw->controls[PVR2_CID_CONTRAST].value; - ret = pvr2_i2c_saa7115_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - if (ret) return ret; - ctrl.id = V4L2_CID_SATURATION; - ctrl.value = hdw->controls[PVR2_CID_SATURATION].value; - ret = pvr2_i2c_saa7115_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - if (ret) return ret; - ctrl.id = V4L2_CID_HUE; - ctrl.value = hdw->controls[PVR2_CID_HUE].value; - ret = pvr2_i2c_saa7115_cmd(hdw,VIDIOC_S_CTRL,&ctrl); - if (ret) return ret; - - hdw->subsys_enabled_mask |= PVR2_SUBSYS_DIGITIZER_CFG_BCSH; - return 0; + struct pvr2_hdw *hdw = ctxt->hdw; + return hdw->controls[PVR2_CID_INPUT].dirty != 0; } -static int pvr2_decoder_v4l_is_tuned(struct pvr2_decoder *dcp) +static void set_audio(struct pvr2_v4l_decoder *ctxt) { - struct v4l2_tuner vt; - struct pvr2_hdw *hdw = dcp->hdw; - int ret; + u32 val; + struct pvr2_hdw *hdw = ctxt->hdw; - memset(&vt,0,sizeof(vt)); - ret = pvr2_i2c_saa7115_cmd(hdw,VIDIOC_G_TUNER,&vt); - if (ret < 0) return -EINVAL; - return vt.signal ? 1 : 0; + pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_audio %d", + hdw->controls[PVR2_CID_SRATE].value); + switch (hdw->controls[PVR2_CID_SRATE].value) { + default: + case PVR2_CVAL_SRATE_48: + val = 48000; + break; + case PVR2_CVAL_SRATE_44_1: + val = 44100; + break; + } + pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val); } -static int pvr2_decoder_v4l_set_size(struct pvr2_decoder *dcp) +static int check_audio(struct pvr2_v4l_decoder *ctxt) { - struct v4l2_format fmt; - struct pvr2_hdw *hdw = dcp->hdw; - int ret; + struct pvr2_hdw *hdw = ctxt->hdw; + return hdw->controls[PVR2_CID_SRATE].dirty != 0; +} - memset(&fmt,0,sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt.fmt.pix.width = hdw->controls[PVR2_CID_HRES].value; - fmt.fmt.pix.height = hdw->controls[PVR2_CID_VRES].value; +struct pvr2_v4l_decoder_ops { + void (*update)(struct pvr2_v4l_decoder *); + int (*check)(struct pvr2_v4l_decoder *); +}; - pvr2_decoder_trace("pvr2_decoder_set_size(%dx%d)", - fmt.fmt.pix.width,fmt.fmt.pix.height); - ret = pvr2_i2c_saa7115_cmd(hdw,VIDIOC_S_FMT,&fmt); - if (ret) return ret; +static const struct pvr2_v4l_decoder_ops decoder_ops[] = { + { .update = set_input, .check = check_input}, + { .update = set_audio, .check = check_audio}, +}; - hdw->subsys_enabled_mask |= PVR2_SUBSYS_DIGITIZER_CFG_SIZE; - return 0; + +static void decoder_detach(struct pvr2_v4l_decoder *ctxt) +{ + ctxt->client->handler = 0; + ctxt->hdw->decoder_ctrl = 0; + kfree(ctxt); } -static int pvr2_decoder_v4l_set_audio(struct pvr2_decoder *dcp) +static int decoder_check(struct pvr2_v4l_decoder *ctxt) { - int ret; - struct pvr2_hdw *hdw = dcp->hdw; - u32 val; - - pvr2_decoder_trace("pvr2_decoder_set_audio %d", - hdw->controls[PVR2_CID_SRATE].value); - switch (hdw->controls[PVR2_CID_SRATE].value) { - default: - case PVR2_CVAL_SRATE_48: - val = 48000; - break; - case PVR2_CVAL_SRATE_44_1: - val = 44100; - break; + unsigned long msk; + unsigned int idx; + + for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]); + idx++) { + msk = 1 << idx; + if (ctxt->stale_mask & msk) continue; + if (decoder_ops[idx].check(ctxt)) { + ctxt->stale_mask |= msk; + } } - ret = pvr2_i2c_saa7115_cmd(hdw,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val); - if (ret) return ret; - hdw->subsys_enabled_mask |= PVR2_SUBSYS_DIGITIZER_CFG_AUDIO; - return 0; + return ctxt->stale_mask != 0; } -static int pvr2_decoder_v4l_set_norm(struct pvr2_decoder *dcp) +static void decoder_update(struct pvr2_v4l_decoder *ctxt) { - v4l2_std_id std; - struct pvr2_hdw *hdw = dcp->hdw; - int status; - pvr2_decoder_trace("pvr2_decoder_set_norm %d", - hdw->controls[PVR2_CID_VIDEOSTANDARD].value); - switch (hdw->controls[PVR2_CID_VIDEOSTANDARD].value) { - default: - case PVR2_CVAL_VIDEOSTANDARD_NTSC_M: - std = V4L2_STD_NTSC_M; - break; - case PVR2_CVAL_VIDEOSTANDARD_SECAM_L: - std = V4L2_STD_SECAM; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_I: - std = V4L2_STD_PAL_I; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_DK: - std = V4L2_STD_PAL_DK; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_BG: - std = V4L2_STD_PAL_BG; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_M: - std = V4L2_STD_PAL_M; - break; + unsigned long msk; + unsigned int idx; + + for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]); + idx++) { + msk = 1 << idx; + if (!(ctxt->stale_mask & msk)) continue; + ctxt->stale_mask &= ~msk; + decoder_ops[idx].update(ctxt); } - status = pvr2_i2c_saa7115_cmd(hdw,VIDIOC_S_STD,&std); - if (status) return status; - hdw->subsys_enabled_mask |= PVR2_SUBSYS_DIGITIZER_CFG_NORM; - return 0; } -static const struct pvr2_decoder_func_table pvr2_decoder_v4l_table = { - (pvr2_decoder_func)0, - (pvr2_decoder_func)pvr2_decoder_v4l_set_norm, - (pvr2_decoder_func)pvr2_decoder_v4l_set_input, - (pvr2_decoder_func)pvr2_decoder_v4l_set_size, - (pvr2_decoder_func)pvr2_decoder_v4l_set_audio, - (pvr2_decoder_func)pvr2_decoder_v4l_set_bcsh, - (pvr2_decoder_func)pvr2_decoder_v4l_is_tuned, - (pvr2_decoder_func)pvr2_decoder_v4l_enable_output, - (pvr2_decoder_func)pvr2_decoder_v4l_disable_output, -}; +static int decoder_detect(struct pvr2_i2c_client *cp) +{ + /* Attempt to query the decoder - let's see if it will answer */ + struct v4l2_tuner vt; + int ret; + memset(&vt,0,sizeof(vt)); + ret = pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&vt); + return ret == 0; /* Return true if it answered */ +} -struct pvr2_decoder *pvr2_decoder_v4l_create(struct pvr2_hdw *hdw) + +static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl) +{ + pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 decoder_enable(%d)",fl); + pvr2_i2c_client_cmd(ctxt->client, + (fl ? VIDIOC_STREAMON : VIDIOC_STREAMOFF),0); +} + + +static int decoder_is_tuned(struct pvr2_v4l_decoder *ctxt) { - /* Attempt to query the decoder - let's see if it will answer */ struct v4l2_tuner vt; int ret; - struct pvr2_decoder *dcp; memset(&vt,0,sizeof(vt)); - ret = pvr2_i2c_saa7115_cmd(hdw,VIDIOC_G_TUNER,&vt); - if (ret < 0) return 0; /* Nope, not there */ - - /* Yes, it's there. So initialize... */ - dcp = kmalloc(sizeof(*dcp),GFP_KERNEL); - if (!dcp) return 0; - memset(dcp,0,sizeof(*dcp)); - dcp->hdw = hdw; - dcp->func_table = &pvr2_decoder_v4l_table; - return dcp; + ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt); + if (ret < 0) return -EINVAL; + return vt.signal ? 1 : 0; } + +const static struct pvr2_i2c_handler_functions hfuncs = { + .detach = (void (*)(void *))decoder_detach, + .check = (int (*)(void *))decoder_check, + .update = (void (*)(void *))decoder_update, +}; + + +int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, + struct pvr2_i2c_client *cp) +{ + struct pvr2_v4l_decoder *ctxt; + + if (hdw->decoder_ctrl) return 0; + if (cp->handler) return 0; + if (!decoder_detect(cp)) return 0; + + ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); + if (!ctxt) return 0; + memset(ctxt,0,sizeof(*ctxt)); + + ctxt->handler.func_data = ctxt; + ctxt->handler.func_table = &hfuncs; + ctxt->ctrl.ctxt = ctxt; + ctxt->ctrl.detach = (void (*)(void *))decoder_detach; + ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; + ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned; + ctxt->client = cp; + ctxt->hdw = hdw; + ctxt->stale_mask = 1 << ((sizeof(decoder_ops)/ + sizeof(decoder_ops[0])) - 1); + hdw->decoder_ctrl = &ctxt->ctrl; + cp->handler = &ctxt->handler; + return !0; +} + + #endif /* PVR2_SUPPRESS_SAA711X */ |