diff options
Diffstat (limited to 'v4l_experimental/pvrusb2/pvrusb2-tuner.c')
-rw-r--r-- | v4l_experimental/pvrusb2/pvrusb2-tuner.c | 168 |
1 files changed, 61 insertions, 107 deletions
diff --git a/v4l_experimental/pvrusb2/pvrusb2-tuner.c b/v4l_experimental/pvrusb2/pvrusb2-tuner.c index c84200ab6..232f083fd 100644 --- a/v4l_experimental/pvrusb2/pvrusb2-tuner.c +++ b/v4l_experimental/pvrusb2/pvrusb2-tuner.c @@ -1,6 +1,6 @@ /* * - * $Id: pvrusb2-tuner.c,v 1.6 2005/12/07 06:53:52 mcisely Exp $ + * $Id: pvrusb2-tuner.c,v 1.7 2006/01/01 08:26:03 mcisely Exp $ * * Copyright (C) 2005 Mike Isely <isely@pobox.com> * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> @@ -24,137 +24,91 @@ #include "pvrusb2-util.h" #include "pvrusb2-tuner.h" #include "pvrusb2-hdw-internal.h" -#include "pvrusb2-i2c.h" #include "pvrusb2-debug.h" #include "compat.h" #include <linux/videodev.h> #include <media/tuner.h> -#define PVR_STD_I2C_ADDR 0x43 -static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 }; - -module_param_array(tuner, int, NULL, 0444); -MODULE_PARM_DESC(tuner,"specify installed tuner type"); - -static u32 pvr_tbl_standard[] = { - [PVR2_CVAL_VIDEOSTANDARD_PAL_BG] = 0x00d47009, /* PVR_STD_PAL_BG */ - [PVR2_CVAL_VIDEOSTANDARD_PAL_I] = 0x00d4700a, /* PVR_STD_PAL_I */ - [PVR2_CVAL_VIDEOSTANDARD_PAL_DK] = 0x00d4700b, /* PVR_STD_PAL_DK */ - [PVR2_CVAL_VIDEOSTANDARD_SECAM_L] = 0x00c4100b, /* PVR_STD_SECAM */ - [PVR2_CVAL_VIDEOSTANDARD_NTSC_M] = 0x00163044, /* PVR_STD_NTSC */ - [PVR2_CVAL_VIDEOSTANDARD_PAL_M] = 0x00163044 /* PVR_STD_PAL_M */ +struct pvr2_tuner_handler { + struct pvr2_hdw *hdw; + struct pvr2_i2c_client *client; + struct pvr2_i2c_handler i2c_handler; + int type_update_fl; }; -#define trace_tuner(...) pvr2_trace(PVR2_TRACE_TUNER,__VA_ARGS__) - -int pvr2_tuner_get_default_type(struct pvr2_hdw *hdw) -{ - int unit_number = hdw->unit_number; - int tp = -1; - if ((unit_number >= 0) && (unit_number < PVR_NUM)) { - tp = tuner[unit_number]; - } - if (tp < 0) return -EINVAL; - hdw->tuner_type = tp; - return 0; -} - -int pvr2_tuner_set_freq(struct pvr2_hdw *hdw) -{ - int stat; - struct v4l2_frequency freq; - memset(&freq,0,sizeof(freq)); - freq.frequency = hdw->controls[PVR2_CID_FREQUENCY].value / 62500; - freq.tuner = 0; - freq.type = V4L2_TUNER_ANALOG_TV; - trace_tuner("pvr2_tuner_set_freq(%d)",freq.frequency); - stat = pvr2_i2c_tuner_cmd(hdw,VIDIOC_S_FREQUENCY,&freq); - if (stat < 0) return stat; - /* This kicks the audio controller... */ - stat = pvr2_i2c_msp3400_cmd(hdw,VIDIOCSFREQ,0); - if (stat < 0) return stat; - /* Smack around tda9887 as well, if it is lurking nearby */ - if (hdw->i2c_ifhandler_client) { - pvr2_i2c_ifhandler_cmd(hdw,VIDIOC_S_FREQUENCY,&freq); - } - hdw->subsys_enabled_mask |= PVR2_SUBSYS_TUNER_CFG_FREQ; - return 0; -} -int pvr2_tuner_set_type(struct pvr2_hdw *hdw) +static void set_type(struct pvr2_tuner_handler *ctxt) { + struct pvr2_hdw *hdw = ctxt->hdw; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) struct tuner_setup setup; #endif - trace_tuner("pvr2_tuner_set_type(%d)",hdw->tuner_type); - if (((int)(hdw->tuner_type)) < 0) { - trace_tuner("tuner type not set yet"); - return 0; - } + pvr2_trace(PVR2_TRACE_CHIPS,"i2c tuner set_type(%d)",hdw->tuner_type); + if (((int)(hdw->tuner_type)) < 0) return; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) setup.addr = ADDR_UNSET; setup.type = hdw->tuner_type; setup.mode_mask = T_RADIO | T_ANALOG_TV; /* We may really want mode_mask to be T_ANALOG_TV for now */ - return pvr2_i2c_tuner_cmd(hdw,TUNER_SET_TYPE_ADDR,&setup); + pvr2_i2c_client_cmd(ctxt->client,TUNER_SET_TYPE_ADDR,&setup); #else - return pvr2_i2c_tuner_cmd(hdw,TUNER_SET_TYPE,&hdw->tuner_type); + pvr2_i2c_tuner_cmd(ctxt->client,TUNER_SET_TYPE,&hdw->tuner_type); #endif + ctxt->type_update_fl = 0; +} + + +static int tuner_check(struct pvr2_tuner_handler *ctxt) +{ + struct pvr2_hdw *hdw = ctxt->hdw; + if (hdw->tuner_updated) ctxt->type_update_fl = !0; + return ctxt->type_update_fl != 0; +} + + +static void tuner_update(struct pvr2_tuner_handler *ctxt) +{ + if (ctxt->type_update_fl) set_type(ctxt); } -int pvr2_tuner_set_standard(struct pvr2_hdw *hdw) + +static void pvr2_tuner_detach(struct pvr2_tuner_handler *ctxt) { - struct i2c_msg msg[1]; - u8 buff [4]; - v4l2_std_id vs; - int cvstd = hdw->controls[PVR2_CID_VIDEOSTANDARD].value; - - trace_tuner("pvr2_tuner_set_standard(%d)", - hdw->controls[PVR2_CID_VIDEOSTANDARD].value); - - /* FIXME: Might be tuner dependant ? Need more hardware info... */ - /* MCI 15-May-2005: I have absolutely no idea what this is doing - or who it is talking to. */ - PVR2_DECOMPOSE_BE( - buff, 0,pvr_tbl_standard[cvstd]); - msg[0].addr = PVR_STD_I2C_ADDR; - msg[0].flags = 0; - msg[0].len = sizeof(buff); - msg[0].buf = buff; - i2c_transfer(&hdw->i2c_adap,msg,sizeof(msg)/sizeof(msg[0])); - - /* Also tell tuner.ko about the video standard. */ - switch (cvstd) { - default: - case PVR2_CVAL_VIDEOSTANDARD_NTSC_M: - vs = V4L2_STD_NTSC_M; - break; - case PVR2_CVAL_VIDEOSTANDARD_SECAM_L: - vs = V4L2_STD_SECAM; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_BG: - vs = V4L2_STD_PAL_BG; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_I: - vs = V4L2_STD_PAL_I; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_DK: - vs = V4L2_STD_PAL_DK; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_M: - vs = V4L2_STD_PAL_M; - break; - } - pvr2_i2c_tuner_cmd(hdw,VIDIOC_S_STD,&vs); - if (hdw->i2c_ifhandler_client) { - pvr2_i2c_ifhandler_cmd(hdw,VIDIOC_S_STD,&vs); - } - - hdw->subsys_enabled_mask |= PVR2_SUBSYS_TUNER_CFG_STD; - return 0; + ctxt->client->handler = 0; + kfree(ctxt); } + +const static struct pvr2_i2c_handler_functions tuner_funcs = { + .detach = (void (*)(void *))pvr2_tuner_detach, + .check = (int (*)(void *))tuner_check, + .update = (void (*)(void *))tuner_update, +}; + + +int pvr2_i2c_tuner_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) +{ + struct pvr2_tuner_handler *ctxt; + if (cp->handler) return 0; + + ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); + if (!ctxt) return 0; + memset(ctxt,0,sizeof(*ctxt)); + + ctxt->i2c_handler.func_data = ctxt; + ctxt->i2c_handler.func_table = &tuner_funcs; + ctxt->type_update_fl = !0; + ctxt->client = cp; + ctxt->hdw = hdw; + cp->handler = &ctxt->i2c_handler; + return !0; +} + + + + /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** |