diff options
Diffstat (limited to 'linux/drivers')
46 files changed, 2082 insertions, 2840 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c index 43b31ec2c..51fb82edc 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -52,6 +52,7 @@ static int dvb_shutdown_timeout; static int dvb_force_auto_inversion; static int dvb_override_tune_delay; static int dvb_powerdown_on_sleep = 1; +static int dvb_mfe_wait_time = 5; module_param_named(frontend_debug, dvb_frontend_debug, int, 0644); MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off)."); @@ -63,6 +64,8 @@ module_param(dvb_override_tune_delay, int, 0644); MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt"); module_param(dvb_powerdown_on_sleep, int, 0644); MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)"); +module_param(dvb_mfe_wait_time, int, 0644); +MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)"); #define dprintk if (dvb_frontend_debug) printk @@ -217,8 +220,9 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe, static void dvb_frontend_init(struct dvb_frontend *fe) { - dprintk ("DVB: initialising frontend %i (%s)...\n", + dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n", fe->dvb->num, + fe->id, fe->ops.info.name); if (fe->ops.init) @@ -697,7 +701,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe) mb(); fe_thread = kthread_run(dvb_frontend_thread, fe, - "kdvb-fe-%i", fe->dvb->num); + "kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id); if (IS_ERR(fe_thread)) { ret = PTR_ERR(fe_thread); printk("dvb_frontend_start: failed to start kthread (%d)\n", ret); @@ -721,8 +725,8 @@ static void dvb_frontend_get_frequeny_limits(struct dvb_frontend *fe, *freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max); if (*freq_min == 0 || *freq_max == 0) - printk(KERN_WARNING "DVB: frontend %u frequency limits undefined - fix the driver\n", - fe->dvb->num); + printk(KERN_WARNING "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n", + fe->dvb->num,fe->id); } static int dvb_frontend_check_parameters(struct dvb_frontend *fe, @@ -735,8 +739,8 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, dvb_frontend_get_frequeny_limits(fe, &freq_min, &freq_max); if ((freq_min && parms->frequency < freq_min) || (freq_max && parms->frequency > freq_max)) { - printk(KERN_WARNING "DVB: frontend %u frequency %u out of range (%u..%u)\n", - fe->dvb->num, parms->frequency, freq_min, freq_max); + printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n", + fe->dvb->num, fe->id, parms->frequency, freq_min, freq_max); return -EINVAL; } @@ -746,8 +750,8 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, parms->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) || (fe->ops.info.symbol_rate_max && parms->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) { - printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n", - fe->dvb->num, parms->u.qpsk.symbol_rate, + printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", + fe->dvb->num, fe->id, parms->u.qpsk.symbol_rate, fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); return -EINVAL; } @@ -757,8 +761,8 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, parms->u.qam.symbol_rate < fe->ops.info.symbol_rate_min) || (fe->ops.info.symbol_rate_max && parms->u.qam.symbol_rate > fe->ops.info.symbol_rate_max)) { - printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n", - fe->dvb->num, parms->u.qam.symbol_rate, + printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", + fe->dvb->num, fe->id, parms->u.qam.symbol_rate, fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); return -EINVAL; } @@ -1133,6 +1137,7 @@ void dtv_property_adv_params_sync(struct dvb_frontend *fe) switch(c->modulation) { case PSK_8: case APSK_16: + case APSK_32: case QPSK: p->u.qpsk.symbol_rate = c->symbol_rate; p->u.qpsk.fec_inner = c->fec_inner; @@ -1819,13 +1824,46 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) struct dvb_device *dvbdev = file->private_data; struct dvb_frontend *fe = dvbdev->priv; struct dvb_frontend_private *fepriv = fe->frontend_priv; + struct dvb_adapter *adapter = fe->dvb; + struct dvb_device *mfedev; + struct dvb_frontend *mfe; + struct dvb_frontend_private *mfepriv; + int mferetry; int ret; dprintk ("%s\n", __func__); + if (adapter->mfe_shared) { + mutex_lock (&adapter->mfe_lock); + if (adapter->mfe_dvbdev != dvbdev) { + if (adapter->mfe_dvbdev) { + mfedev = adapter->mfe_dvbdev; + mfe = mfedev->priv; + mfepriv = mfe->frontend_priv; + mutex_unlock (&adapter->mfe_lock); + mferetry = (dvb_mfe_wait_time << 1); + while (mferetry-- && (mfedev->users != -1 || mfepriv->thread != NULL)) { + if(msleep_interruptible(500)) { + if(signal_pending(current)) + return -EINTR; + } + } + mutex_lock (&adapter->mfe_lock); + mfedev = adapter->mfe_dvbdev; + mfe = mfedev->priv; + mfepriv = mfe->frontend_priv; + if (mfedev->users != -1 || mfepriv->thread != NULL) { + ret = -EBUSY; + goto err0; + } + } + adapter->mfe_dvbdev = dvbdev; + } + } + if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) { if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0) - return ret; + goto err0; } if ((ret = dvb_generic_open (inode, file)) < 0) @@ -1845,6 +1883,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) fepriv->events.eventr = fepriv->events.eventw = 0; } + if (adapter->mfe_shared) + mutex_unlock (&adapter->mfe_lock); return ret; err2: @@ -1852,6 +1892,9 @@ err2: err1: if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) fe->ops.ts_bus_ctrl(fe, 0); +err0: + if (adapter->mfe_shared) + mutex_unlock (&adapter->mfe_lock); return ret; } @@ -1921,8 +1964,9 @@ int dvb_register_frontend(struct dvb_adapter* dvb, fe->dvb = dvb; fepriv->inversion = INVERSION_OFF; - printk ("DVB: registering frontend %i (%s)...\n", + printk ("DVB: registering adapter %i frontend %i (%s)...\n", fe->dvb->num, + fe->id, fe->ops.info.name); dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h index a0c591b3b..569b72a96 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -236,6 +236,7 @@ struct dvb_frontend { struct dtv_frontend_properties dtv_property_cache; #define DVB_FRONTEND_COMPONENT_TUNER 0 int (*callback)(void *adapter_priv, int component, int cmd, int arg); + int id; }; extern int dvb_register_frontend(struct dvb_adapter *dvb, diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.c b/linux/drivers/media/dvb/dvb-core/dvbdev.c index 0820da504..422af5a0d 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.c +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c @@ -341,6 +341,9 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, adap->name = name; adap->module = module; adap->device = device; + adap->mfe_shared = 0; + adap->mfe_dvbdev = NULL; + mutex_init (&adap->mfe_lock); list_add_tail (&adap->list_head, &dvb_adapter_list); diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.h b/linux/drivers/media/dvb/dvb-core/dvbdev.h index 89d12dc47..574e336ba 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.h +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.h @@ -62,6 +62,10 @@ struct dvb_adapter { struct device *device; struct module *module; + + int mfe_shared; /* indicates mutually exclusive frontends */ + struct dvb_device *mfe_dvbdev; /* frontend device in use */ + struct mutex mfe_lock; /* access lock for thread creation */ }; diff --git a/linux/drivers/media/radio/Kconfig b/linux/drivers/media/radio/Kconfig index e51d707e5..04cd7c04b 100644 --- a/linux/drivers/media/radio/Kconfig +++ b/linux/drivers/media/radio/Kconfig @@ -359,7 +359,7 @@ config USB_SI470X computer's USB port. To compile this driver as a module, choose M here: the - module will be called radio-silabs. + module will be called radio-si470x. config USB_MR800 tristate "AverMedia MR 800 USB FM radio support" diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index 871a63a87..e332b3de5 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -104,6 +104,7 @@ * - hardware frequency seek support * - afc indication * - more safety checks, let si470x_get_freq return errno + * - vidioc behavior corrected according to v4l2 spec * * ToDo: * - add firmware download/update support @@ -142,9 +143,9 @@ /* USB Device ID List */ static struct usb_device_id si470x_usb_driver_id_table[] = { /* Silicon Labs USB FM Radio Reference Design */ - { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) }, /* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */ - { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) }, /* Terminating entry */ { } }; @@ -158,7 +159,7 @@ MODULE_DEVICE_TABLE(usb, si470x_usb_driver_id_table); /* Radio Nr */ static int radio_nr = -1; -module_param(radio_nr, int, 0); +module_param(radio_nr, int, 0444); MODULE_PARM_DESC(radio_nr, "Radio Nr"); /* Spacing (kHz) */ @@ -166,42 +167,42 @@ MODULE_PARM_DESC(radio_nr, "Radio Nr"); /* 1: 100 kHz (Europe, Japan) */ /* 2: 50 kHz */ static unsigned short space = 2; -module_param(space, ushort, 0); -MODULE_PARM_DESC(radio_nr, "Spacing: 0=200kHz 1=100kHz *2=50kHz*"); +module_param(space, ushort, 0444); +MODULE_PARM_DESC(space, "Spacing: 0=200kHz 1=100kHz *2=50kHz*"); /* Bottom of Band (MHz) */ /* 0: 87.5 - 108 MHz (USA, Europe)*/ /* 1: 76 - 108 MHz (Japan wide band) */ /* 2: 76 - 90 MHz (Japan) */ static unsigned short band = 1; -module_param(band, ushort, 0); -MODULE_PARM_DESC(radio_nr, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz"); +module_param(band, ushort, 0444); +MODULE_PARM_DESC(band, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz"); /* De-emphasis */ /* 0: 75 us (USA) */ /* 1: 50 us (Europe, Australia, Japan) */ static unsigned short de = 1; -module_param(de, ushort, 0); -MODULE_PARM_DESC(radio_nr, "De-emphasis: 0=75us *1=50us*"); +module_param(de, ushort, 0444); +MODULE_PARM_DESC(de, "De-emphasis: 0=75us *1=50us*"); /* USB timeout */ static unsigned int usb_timeout = 500; -module_param(usb_timeout, uint, 0); +module_param(usb_timeout, uint, 0644); MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*"); /* Tune timeout */ static unsigned int tune_timeout = 3000; -module_param(tune_timeout, uint, 0); +module_param(tune_timeout, uint, 0644); MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*"); /* Seek timeout */ static unsigned int seek_timeout = 5000; -module_param(seek_timeout, uint, 0); +module_param(seek_timeout, uint, 0644); MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*"); /* RDS buffer blocks */ static unsigned int rds_buf = 100; -module_param(rds_buf, uint, 0); +module_param(rds_buf, uint, 0444); MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*"); /* RDS maximum block errors */ @@ -210,7 +211,7 @@ static unsigned short max_rds_errors = 1; /* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */ /* 2 means 3-5 errors requiring correction */ /* 3 means 6+ errors or errors in checkword, correction not possible */ -module_param(max_rds_errors, ushort, 0); +module_param(max_rds_errors, ushort, 0644); MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); /* RDS poll frequency */ @@ -219,7 +220,7 @@ static unsigned int rds_poll_time = 40; /* 50 is used by radio-cadet */ /* 75 should be okay */ /* 80 is the usual RDS receive interval */ -module_param(rds_poll_time, uint, 0); +module_param(rds_poll_time, uint, 0644); MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*"); @@ -672,23 +673,29 @@ static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq) int retval; /* Spacing (kHz) */ - switch (space) { + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { /* 0: 200 kHz (USA, Australia) */ - case 0 : spacing = 0.200 * FREQ_MUL; break; + case 0: + spacing = 0.200 * FREQ_MUL; break; /* 1: 100 kHz (Europe, Japan) */ - case 1 : spacing = 0.100 * FREQ_MUL; break; + case 1: + spacing = 0.100 * FREQ_MUL; break; /* 2: 50 kHz */ - default: spacing = 0.050 * FREQ_MUL; break; + default: + spacing = 0.050 * FREQ_MUL; break; }; /* Bottom of Band (MHz) */ - switch (band) { + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { /* 0: 87.5 - 108 MHz (USA, Europe) */ - case 0 : band_bottom = 87.5 * FREQ_MUL; break; + case 0: + band_bottom = 87.5 * FREQ_MUL; break; /* 1: 76 - 108 MHz (Japan wide band) */ - default: band_bottom = 76 * FREQ_MUL; break; + default: + band_bottom = 76 * FREQ_MUL; break; /* 2: 76 - 90 MHz (Japan) */ - case 2 : band_bottom = 76 * FREQ_MUL; break; + case 2: + band_bottom = 76 * FREQ_MUL; break; }; /* read channel */ @@ -711,23 +718,29 @@ static int si470x_set_freq(struct si470x_device *radio, unsigned int freq) unsigned short chan; /* Spacing (kHz) */ - switch (space) { + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_SPACE) >> 4) { /* 0: 200 kHz (USA, Australia) */ - case 0 : spacing = 0.200 * FREQ_MUL; break; + case 0: + spacing = 0.200 * FREQ_MUL; break; /* 1: 100 kHz (Europe, Japan) */ - case 1 : spacing = 0.100 * FREQ_MUL; break; + case 1: + spacing = 0.100 * FREQ_MUL; break; /* 2: 50 kHz */ - default: spacing = 0.050 * FREQ_MUL; break; + default: + spacing = 0.050 * FREQ_MUL; break; }; /* Bottom of Band (MHz) */ - switch (band) { + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { /* 0: 87.5 - 108 MHz (USA, Europe) */ - case 0 : band_bottom = 87.5 * FREQ_MUL; break; + case 0: + band_bottom = 87.5 * FREQ_MUL; break; /* 1: 76 - 108 MHz (Japan wide band) */ - default: band_bottom = 76 * FREQ_MUL; break; + default: + band_bottom = 76 * FREQ_MUL; break; /* 2: 76 - 90 MHz (Japan) */ - case 2 : band_bottom = 76 * FREQ_MUL; break; + case 2: + band_bottom = 76 * FREQ_MUL; break; }; /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */ @@ -1169,7 +1182,6 @@ static const struct file_operations si470x_fops = { * si470x_v4l2_queryctrl - query control */ static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = { -/* HINT: the disabled controls are only here to satify kradio and such apps */ { .id = V4L2_CID_AUDIO_VOLUME, .type = V4L2_CTRL_TYPE_INTEGER, @@ -1180,18 +1192,6 @@ static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = { .default_value = 15, }, { - .id = V4L2_CID_AUDIO_BALANCE, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_BASS, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { - .id = V4L2_CID_AUDIO_TREBLE, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, - { .id = V4L2_CID_AUDIO_MUTE, .type = V4L2_CTRL_TYPE_BOOLEAN, .name = "Mute", @@ -1200,10 +1200,6 @@ static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = { .step = 1, .default_value = 1, }, - { - .id = V4L2_CID_AUDIO_LOUDNESS, - .flags = V4L2_CTRL_FLAG_DISABLED, - }, }; @@ -1225,56 +1221,34 @@ static int si470x_vidioc_querycap(struct file *file, void *priv, /* - * si470x_vidioc_g_input - get input - */ -static int si470x_vidioc_g_input(struct file *file, void *priv, - unsigned int *i) -{ - *i = 0; - - return 0; -} - - -/* - * si470x_vidioc_s_input - set input - */ -static int si470x_vidioc_s_input(struct file *file, void *priv, unsigned int i) -{ - int retval = 0; - - /* safety checks */ - if (i != 0) - retval = -EINVAL; - - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set input failed with %d\n", retval); - return retval; -} - - -/* * si470x_vidioc_queryctrl - enumerate control items */ static int si470x_vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - unsigned char i; + unsigned char i = 0; int retval = -EINVAL; - /* safety checks */ - if (!qc->id) + /* abort if qc->id is below V4L2_CID_BASE */ + if (qc->id < V4L2_CID_BASE) goto done; + /* search video control */ for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) { if (qc->id == si470x_v4l2_queryctrl[i].id) { memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc)); - retval = 0; + retval = 0; /* found */ break; } } + /* disable unsupported base controls */ + /* to satisfy kradio and such apps */ + if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) { + qc->flags = V4L2_CTRL_FLAG_DISABLED; + retval = 0; + } + done: if (retval < 0) printk(KERN_WARNING DRIVER_NAME @@ -1365,44 +1339,13 @@ done: static int si470x_vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *audio) { - int retval = 0; - - /* safety checks */ - if (audio->index != 0) { - retval = -EINVAL; - goto done; - } - + /* driver constants */ + audio->index = 0; strcpy(audio->name, "Radio"); audio->capability = V4L2_AUDCAP_STEREO; + audio->mode = 0; -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": get audio failed with %d\n", retval); - return retval; -} - - -/* - * si470x_vidioc_s_audio - set audio attributes - */ -static int si470x_vidioc_s_audio(struct file *file, void *priv, - struct v4l2_audio *audio) -{ - int retval = 0; - - /* safety checks */ - if (audio->index != 0) { - retval = -EINVAL; - goto done; - } - -done: - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME - ": set audio failed with %d\n", retval); - return retval; + return 0; } @@ -1420,7 +1363,7 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, retval = -EIO; goto done; } - if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) { + if (tuner->index != 0) { retval = -EINVAL; goto done; } @@ -1429,8 +1372,13 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, if (retval < 0) goto done; + /* driver constants */ strcpy(tuner->name, "FM"); - switch (band) { + tuner->type = V4L2_TUNER_RADIO; + tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; + + /* range limits */ + switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { /* 0: 87.5 - 108 MHz (USA, Europe, default) */ default: tuner->rangelow = 87.5 * FREQ_MUL; @@ -1447,14 +1395,18 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, tuner->rangehigh = 90 * FREQ_MUL; break; }; - tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; - tuner->capability = V4L2_TUNER_CAP_LOW; - /* Stereo indicator == Stereo (instead of Mono) */ + /* stereo indicator == stereo (instead of mono) */ if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 1) - tuner->audmode = V4L2_TUNER_MODE_STEREO; + tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; else + tuner->rxsubchans = V4L2_TUNER_SUB_MONO; + + /* mono/stereo selector */ + if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 1) tuner->audmode = V4L2_TUNER_MODE_MONO; + else + tuner->audmode = V4L2_TUNER_MODE_STEREO; /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */ tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI) @@ -1479,22 +1431,27 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *tuner) { struct si470x_device *radio = video_drvdata(file); - int retval = 0; + int retval = -EINVAL; /* safety checks */ if (radio->disconnected) { retval = -EIO; goto done; } - if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) { - retval = -EINVAL; + if (tuner->index != 0) goto done; - } - if (tuner->audmode == V4L2_TUNER_MODE_MONO) + /* mono/stereo selector */ + switch (tuner->audmode) { + case V4L2_TUNER_MODE_MONO: radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */ - else + break; + case V4L2_TUNER_MODE_STEREO: radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */ + break; + default: + goto done; + } retval = si470x_set_register(radio, POWERCFG); @@ -1520,11 +1477,12 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv, retval = -EIO; goto done; } - if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) { + if (freq->tuner != 0) { retval = -EINVAL; goto done; } + freq->type = V4L2_TUNER_RADIO; retval = si470x_get_freq(radio, &freq->frequency); done: @@ -1549,7 +1507,7 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv, retval = -EIO; goto done; } - if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) { + if (freq->tuner != 0) { retval = -EINVAL; goto done; } @@ -1578,7 +1536,7 @@ static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv, retval = -EIO; goto done; } - if ((seek->tuner != 0) && (seek->type != V4L2_TUNER_RADIO)) { + if (seek->tuner != 0) { retval = -EINVAL; goto done; } @@ -1593,15 +1551,16 @@ done: return retval; } + +/* + * si470x_ioctl_ops - video device ioctl operations + */ static const struct v4l2_ioctl_ops si470x_ioctl_ops = { .vidioc_querycap = si470x_vidioc_querycap, - .vidioc_g_input = si470x_vidioc_g_input, - .vidioc_s_input = si470x_vidioc_s_input, .vidioc_queryctrl = si470x_vidioc_queryctrl, .vidioc_g_ctrl = si470x_vidioc_g_ctrl, .vidioc_s_ctrl = si470x_vidioc_s_ctrl, .vidioc_g_audio = si470x_vidioc_g_audio, - .vidioc_s_audio = si470x_vidioc_s_audio, .vidioc_g_tuner = si470x_vidioc_g_tuner, .vidioc_s_tuner = si470x_vidioc_s_tuner, .vidioc_g_frequency = si470x_vidioc_g_frequency, @@ -1609,14 +1568,15 @@ static const struct v4l2_ioctl_ops si470x_ioctl_ops = { .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek, }; + /* - * si470x_viddev_tamples - video device interface + * si470x_viddev_template - video device interface */ static struct video_device si470x_viddev_template = { .fops = &si470x_fops, - .ioctl_ops = &si470x_ioctl_ops, .name = DRIVER_NAME, .release = video_device_release, + .ioctl_ops = &si470x_ioctl_ops, }; diff --git a/linux/drivers/media/video/adv7170.c b/linux/drivers/media/video/adv7170.c index 54ef7aa63..0a319ad8e 100644 --- a/linux/drivers/media/video/adv7170.c +++ b/linux/drivers/media/video/adv7170.c @@ -29,44 +29,25 @@ */ #include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/major.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/signal.h> #include <linux/types.h> -#include <linux/i2c.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/page.h> +#include <linux/ioctl.h> #include <asm/uaccess.h> - -#include "compat.h" +#include <linux/i2c.h> +#include <linux/i2c-id.h> #include <linux/videodev.h> #include <linux/video_encoder.h> +#include <media/v4l2-common.h> +#include <media/v4l2-i2c-drv-legacy.h> +#include "compat.h" MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver"); MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_LICENSE("GPL"); - -#define I2C_NAME(x) (x)->name - - static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#define dprintk(num, format, args...) \ - do { \ - if (debug >= num) \ - printk(format, ##args); \ - } while (0) - /* ----------------------------------------------------------------------- */ struct adv7170 { @@ -81,21 +62,12 @@ struct adv7170 { int sat; }; -#define I2C_ADV7170 0xd4 -#define I2C_ADV7171 0x54 - -static char adv7170_name[] = "adv7170"; -static char adv7171_name[] = "adv7171"; - static char *inputs[] = { "pass_through", "play_back" }; static char *norms[] = { "PAL", "NTSC" }; /* ----------------------------------------------------------------------- */ -static inline int -adv7170_write (struct i2c_client *client, - u8 reg, - u8 value) +static inline int adv7170_write(struct i2c_client *client, u8 reg, u8 value) { struct adv7170 *encoder = i2c_get_clientdata(client); @@ -103,17 +75,13 @@ adv7170_write (struct i2c_client *client, return i2c_smbus_write_byte_data(client, reg, value); } -static inline int -adv7170_read (struct i2c_client *client, - u8 reg) +static inline int adv7170_read(struct i2c_client *client, u8 reg) { return i2c_smbus_read_byte_data(client, reg); } -static int -adv7170_write_block (struct i2c_client *client, - const u8 *data, - unsigned int len) +static int adv7170_write_block(struct i2c_client *client, + const u8 *data, unsigned int len) { int ret = -1; u8 reg; @@ -134,33 +102,25 @@ adv7170_write_block (struct i2c_client *client, encoder->reg[reg++] = data[1]; len -= 2; data += 2; - } while (len >= 2 && data[0] == reg && - block_len < 32); - if ((ret = i2c_master_send(client, block_data, - block_len)) < 0) + } while (len >= 2 && data[0] == reg && block_len < 32); + ret = i2c_master_send(client, block_data, block_len); + if (ret < 0) break; } } else { /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - if ((ret = adv7170_write(client, reg, - *data++)) < 0) + ret = adv7170_write(client, reg, *data++); + if (ret < 0) break; len -= 2; } } - return ret; } /* ----------------------------------------------------------------------- */ -// Output filter: S-Video Composite - -#define MR050 0x11 //0x09 -#define MR060 0x14 //0x0c - -//--------------------------------------------------------------------------- #define TR0MODE 0x4c #define TR0RST 0x80 @@ -168,7 +128,6 @@ adv7170_write_block (struct i2c_client *client, #define TR1CAPT 0x00 #define TR1PLAY 0x00 - static const unsigned char init_NTSC[] = { 0x00, 0x10, // MR0 0x01, 0x20, // MR1 @@ -228,15 +187,11 @@ static const unsigned char init_PAL[] = { }; -static int -adv7170_command (struct i2c_client *client, - unsigned int cmd, - void * arg) +static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg) { struct adv7170 *encoder = i2c_get_clientdata(client); switch (cmd) { - case 0: #if 0 /* keep */ /* This is just for testing!!! */ @@ -255,18 +210,16 @@ adv7170_command (struct i2c_client *client, VIDEO_ENCODER_NTSC; cap->inputs = 2; cap->outputs = 1; - } break; + } case ENCODER_SET_NORM: { int iarg = *(int *) arg; - dprintk(1, KERN_DEBUG "%s_command: set norm %d", - I2C_NAME(client), iarg); + v4l_dbg(1, debug, client, "set norm %d\n", iarg); switch (iarg) { - case VIDEO_MODE_NTSC: adv7170_write_block(client, init_NTSC, sizeof(init_NTSC)); @@ -286,16 +239,13 @@ adv7170_command (struct i2c_client *client, break; default: - dprintk(1, KERN_ERR "%s: illegal norm: %d\n", - I2C_NAME(client), iarg); + v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg); return -EINVAL; - } - dprintk(1, KERN_DEBUG "%s: switched to %s\n", I2C_NAME(client), - norms[iarg]); + v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]); encoder->norm = iarg; - } break; + } case ENCODER_SET_INPUT: { @@ -305,19 +255,17 @@ adv7170_command (struct i2c_client *client, *iarg = 1: input is from ZR36060 *iarg = 2: color bar */ - dprintk(1, KERN_DEBUG "%s_command: set input from %s\n", - I2C_NAME(client), + v4l_dbg(1, debug, client, "set input from %s\n", iarg == 0 ? "decoder" : "ZR36060"); switch (iarg) { - case 0: adv7170_write(client, 0x01, 0x20); adv7170_write(client, 0x08, TR1CAPT); /* TR1 */ adv7170_write(client, 0x02, 0x0e); // Enable genlock adv7170_write(client, 0x07, TR0MODE | TR0RST); adv7170_write(client, 0x07, TR0MODE); - //udelay(10); + /* udelay(10); */ break; case 1: @@ -326,20 +274,17 @@ adv7170_command (struct i2c_client *client, adv7170_write(client, 0x02, 0x08); adv7170_write(client, 0x07, TR0MODE | TR0RST); adv7170_write(client, 0x07, TR0MODE); - //udelay(10); + /* udelay(10); */ break; default: - dprintk(1, KERN_ERR "%s: illegal input: %d\n", - I2C_NAME(client), iarg); + v4l_dbg(1, debug, client, "illegal input: %d\n", iarg); return -EINVAL; - } - dprintk(1, KERN_DEBUG "%s: switched to %s\n", I2C_NAME(client), - inputs[iarg]); + v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]); encoder->input = iarg; - } break; + } case ENCODER_SET_OUTPUT: { @@ -349,16 +294,16 @@ adv7170_command (struct i2c_client *client, if (*iarg != 0) { return -EINVAL; } - } break; + } case ENCODER_ENABLE_OUTPUT: { int *iarg = arg; encoder->enable = !!*iarg; - } break; + } default: return -EINVAL; @@ -369,149 +314,71 @@ adv7170_command (struct i2c_client *client, /* ----------------------------------------------------------------------- */ -/* - * Generic i2c probe - * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' - */ -static unsigned short normal_i2c[] = - { I2C_ADV7170 >> 1, (I2C_ADV7170 >> 1) + 1, - I2C_ADV7171 >> 1, (I2C_ADV7171 >> 1) + 1, +static unsigned short normal_i2c[] = { + 0xd4 >> 1, 0xd6 >> 1, /* adv7170 IDs */ + 0x54 >> 1, 0x56 >> 1, /* adv7171 IDs */ I2C_CLIENT_END }; -static unsigned short ignore = I2C_CLIENT_END; +I2C_CLIENT_INSMOD; -static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_i2c, - .probe = &ignore, - .ignore = &ignore, -}; - -static struct i2c_driver i2c_driver_adv7170; - -static int -adv7170_detect_client (struct i2c_adapter *adapter, - int address, - int kind) +static int adv7170_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - int i; - struct i2c_client *client; struct adv7170 *encoder; - char *dname; - - dprintk(1, - KERN_INFO - "adv7170.c: detecting adv7170 client on address 0x%x\n", - address << 1); + int i; /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) - return -ENOMEM; - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver_adv7170; - if ((client->addr == I2C_ADV7170 >> 1) || - (client->addr == (I2C_ADV7170 >> 1) + 1)) { - dname = adv7170_name; - } else if ((client->addr == I2C_ADV7171 >> 1) || - (client->addr == (I2C_ADV7171 >> 1) + 1)) { - dname = adv7171_name; - } else { - /* We should never get here!!! */ - kfree(client); - return 0; - } - strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client))); + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL); - if (encoder == NULL) { - kfree(client); + if (encoder == NULL) return -ENOMEM; - } encoder->norm = VIDEO_MODE_NTSC; encoder->input = 0; encoder->enable = 1; i2c_set_clientdata(client, encoder); - i = i2c_attach_client(client); - if (i) { - kfree(client); - kfree(encoder); - return i; - } - i = adv7170_write_block(client, init_NTSC, sizeof(init_NTSC)); if (i >= 0) { i = adv7170_write(client, 0x07, TR0MODE | TR0RST); i = adv7170_write(client, 0x07, TR0MODE); i = adv7170_read(client, 0x12); - dprintk(1, KERN_INFO "%s_attach: rev. %d at 0x%02x\n", - I2C_NAME(client), i & 1, client->addr << 1); - } - if (i < 0) { - dprintk(1, KERN_ERR "%s_attach: init error 0x%x\n", - I2C_NAME(client), i); + v4l_dbg(1, debug, client, "revision %d\n", i & 1); } - + if (i < 0) + v4l_dbg(1, debug, client, "init error 0x%x\n", i); return 0; } -static int -adv7170_attach_adapter (struct i2c_adapter *adapter) -{ - dprintk(1, - KERN_INFO - "adv7170.c: starting probe for adapter %s (0x%x)\n", - I2C_NAME(adapter), adapter->id); - return i2c_probe(adapter, &addr_data, &adv7170_detect_client); -} - -static int -adv7170_detach_client (struct i2c_client *client) +static int adv7170_remove(struct i2c_client *client) { - struct adv7170 *encoder = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - - kfree(encoder); - kfree(client); - + kfree(i2c_get_clientdata(client)); return 0; } /* ----------------------------------------------------------------------- */ -static struct i2c_driver i2c_driver_adv7170 = { - .driver = { - .name = "adv7170", /* name */ - }, - - .id = I2C_DRIVERID_ADV7170, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id adv7170_id[] = { + { "adv7170", 0 }, + { "adv7171", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adv7170_id); - .attach_adapter = adv7170_attach_adapter, - .detach_client = adv7170_detach_client, +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "adv7170", + .driverid = I2C_DRIVERID_ADV7170, .command = adv7170_command, + .probe = adv7170_probe, + .remove = adv7170_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = adv7170_id, +#endif }; - -static int __init -adv7170_init (void) -{ - return i2c_add_driver(&i2c_driver_adv7170); -} - -static void __exit -adv7170_exit (void) -{ - i2c_del_driver(&i2c_driver_adv7170); -} - -module_init(adv7170_init); -module_exit(adv7170_exit); diff --git a/linux/drivers/media/video/adv7175.c b/linux/drivers/media/video/adv7175.c index b8618c021..281a3f53c 100644 --- a/linux/drivers/media/video/adv7175.c +++ b/linux/drivers/media/video/adv7175.c @@ -25,44 +25,25 @@ */ #include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/major.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/signal.h> #include <linux/types.h> -#include <linux/i2c.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/page.h> +#include <linux/ioctl.h> #include <asm/uaccess.h> - +#include <linux/i2c.h> +#include <linux/i2c-id.h> #include <linux/videodev.h> #include <linux/video_encoder.h> +#include <media/v4l2-common.h> +#include <media/v4l2-i2c-drv-legacy.h> #include "compat.h" MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver"); MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); - -#define I2C_NAME(s) (s)->name - - static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#define dprintk(num, format, args...) \ - do { \ - if (debug >= num) \ - printk(format, ##args); \ - } while (0) - /* ----------------------------------------------------------------------- */ struct adv7175 { @@ -78,33 +59,23 @@ struct adv7175 { #define I2C_ADV7175 0xd4 #define I2C_ADV7176 0x54 -static char adv7175_name[] = "adv7175"; -static char adv7176_name[] = "adv7176"; - static char *inputs[] = { "pass_through", "play_back", "color_bar" }; static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" }; /* ----------------------------------------------------------------------- */ -static inline int -adv7175_write (struct i2c_client *client, - u8 reg, - u8 value) +static inline int adv7175_write(struct i2c_client *client, u8 reg, u8 value) { return i2c_smbus_write_byte_data(client, reg, value); } -static inline int -adv7175_read (struct i2c_client *client, - u8 reg) +static inline int adv7175_read(struct i2c_client *client, u8 reg) { return i2c_smbus_read_byte_data(client, reg); } -static int -adv7175_write_block (struct i2c_client *client, - const u8 *data, - unsigned int len) +static int adv7175_write_block(struct i2c_client *client, + const u8 *data, unsigned int len) { int ret = -1; u8 reg; @@ -124,18 +95,17 @@ adv7175_write_block (struct i2c_client *client, reg++; len -= 2; data += 2; - } while (len >= 2 && data[0] == reg && - block_len < 32); - if ((ret = i2c_master_send(client, block_data, - block_len)) < 0) + } while (len >= 2 && data[0] == reg && block_len < 32); + ret = i2c_master_send(client, block_data, block_len); + if (ret < 0) break; } } else { /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - if ((ret = adv7175_write(client, reg, - *data++)) < 0) + ret = adv7175_write(client, reg, *data++); + if (ret < 0) break; len -= 2; } @@ -144,13 +114,11 @@ adv7175_write_block (struct i2c_client *client, return ret; } -static void -set_subcarrier_freq (struct i2c_client *client, - int pass_through) +static void set_subcarrier_freq(struct i2c_client *client, int pass_through) { /* for some reason pass_through NTSC needs * a different sub-carrier freq to remain stable. */ - if(pass_through) + if (pass_through) adv7175_write(client, 0x02, 0x00); else adv7175_write(client, 0x02, 0x55); @@ -161,12 +129,12 @@ set_subcarrier_freq (struct i2c_client *client, } /* ----------------------------------------------------------------------- */ -// Output filter: S-Video Composite +/* Output filter: S-Video Composite */ -#define MR050 0x11 //0x09 -#define MR060 0x14 //0x0c +#define MR050 0x11 /* 0x09 */ +#define MR060 0x14 /* 0x0c */ -//--------------------------------------------------------------------------- +/* ----------------------------------------------------------------------- */ #define TR0MODE 0x46 #define TR0RST 0x80 @@ -217,15 +185,11 @@ static const unsigned char init_ntsc[] = { 0x06, 0x1a, /* subc. phase */ }; -static int -adv7175_command (struct i2c_client *client, - unsigned int cmd, - void *arg) +static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg) { struct adv7175 *encoder = i2c_get_clientdata(client); switch (cmd) { - case 0: /* This is just for testing!!! */ adv7175_write_block(client, init_common, @@ -243,15 +207,14 @@ adv7175_command (struct i2c_client *client, VIDEO_ENCODER_SECAM; /* well, hacky */ cap->inputs = 2; cap->outputs = 1; - } break; + } case ENCODER_SET_NORM: { int iarg = *(int *) arg; switch (iarg) { - case VIDEO_MODE_NTSC: adv7175_write_block(client, init_ntsc, sizeof(init_ntsc)); @@ -285,16 +248,13 @@ adv7175_command (struct i2c_client *client, adv7175_write(client, 0x07, TR0MODE); break; default: - dprintk(1, KERN_ERR "%s: illegal norm: %d\n", - I2C_NAME(client), iarg); + v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg); return -EINVAL; - } - dprintk(1, KERN_INFO "%s: switched to %s\n", I2C_NAME(client), - norms[iarg]); + v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]); encoder->norm = iarg; - } break; + } case ENCODER_SET_INPUT: { @@ -305,7 +265,6 @@ adv7175_command (struct i2c_client *client, *iarg = 2: color bar */ switch (iarg) { - case 0: adv7175_write(client, 0x01, 0x00); @@ -332,7 +291,7 @@ adv7175_command (struct i2c_client *client, adv7175_write(client, 0x0d, 0x49); adv7175_write(client, 0x07, TR0MODE | TR0RST); adv7175_write(client, 0x07, TR0MODE); - //udelay(10); + /* udelay(10); */ break; case 2: @@ -344,39 +303,35 @@ adv7175_command (struct i2c_client *client, adv7175_write(client, 0x0d, 0x49); adv7175_write(client, 0x07, TR0MODE | TR0RST); adv7175_write(client, 0x07, TR0MODE); - //udelay(10); + /* udelay(10); */ break; default: - dprintk(1, KERN_ERR "%s: illegal input: %d\n", - I2C_NAME(client), iarg); + v4l_dbg(1, debug, client, "illegal input: %d\n", iarg); return -EINVAL; - } - dprintk(1, KERN_INFO "%s: switched to %s\n", I2C_NAME(client), - inputs[iarg]); + v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]); encoder->input = iarg; - } break; + } case ENCODER_SET_OUTPUT: { int *iarg = arg; /* not much choice of outputs */ - if (*iarg != 0) { + if (*iarg != 0) return -EINVAL; - } - } break; + } case ENCODER_ENABLE_OUTPUT: { int *iarg = arg; encoder->enable = !!*iarg; - } break; + } default: return -EINVAL; @@ -391,145 +346,71 @@ adv7175_command (struct i2c_client *client, * Generic i2c probe * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */ -static unsigned short normal_i2c[] = - { I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1, +static unsigned short normal_i2c[] = { + I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1, I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1, I2C_CLIENT_END }; -static unsigned short ignore = I2C_CLIENT_END; - -static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_i2c, - .probe = &ignore, - .ignore = &ignore, -}; - -static struct i2c_driver i2c_driver_adv7175; +I2C_CLIENT_INSMOD; -static int -adv7175_detect_client (struct i2c_adapter *adapter, - int address, - int kind) +static int adv7175_probe(struct i2c_client *client, + const struct i2c_device_id *id) { int i; - struct i2c_client *client; struct adv7175 *encoder; - char *dname; - - dprintk(1, - KERN_INFO - "adv7175.c: detecting adv7175 client on address 0x%x\n", - address << 1); /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) - return -ENOMEM; - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver_adv7175; - if ((client->addr == I2C_ADV7175 >> 1) || - (client->addr == (I2C_ADV7175 >> 1) + 1)) { - dname = adv7175_name; - } else if ((client->addr == I2C_ADV7176 >> 1) || - (client->addr == (I2C_ADV7176 >> 1) + 1)) { - dname = adv7176_name; - } else { - /* We should never get here!!! */ - kfree(client); - return 0; - } - strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client))); + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL); - if (encoder == NULL) { - kfree(client); + if (encoder == NULL) return -ENOMEM; - } encoder->norm = VIDEO_MODE_PAL; encoder->input = 0; encoder->enable = 1; i2c_set_clientdata(client, encoder); - i = i2c_attach_client(client); - if (i) { - kfree(client); - kfree(encoder); - return i; - } - i = adv7175_write_block(client, init_common, sizeof(init_common)); if (i >= 0) { i = adv7175_write(client, 0x07, TR0MODE | TR0RST); i = adv7175_write(client, 0x07, TR0MODE); i = adv7175_read(client, 0x12); - dprintk(1, KERN_INFO "%s_attach: rev. %d at 0x%x\n", - I2C_NAME(client), i & 1, client->addr << 1); + v4l_dbg(1, debug, client, "revision %d\n", i & 1); } - if (i < 0) { - dprintk(1, KERN_ERR "%s_attach: init error 0x%x\n", - I2C_NAME(client), i); - } - + if (i < 0) + v4l_dbg(1, debug, client, "init error 0x%x\n", i); return 0; } -static int -adv7175_attach_adapter (struct i2c_adapter *adapter) -{ - dprintk(1, - KERN_INFO - "adv7175.c: starting probe for adapter %s (0x%x)\n", - I2C_NAME(adapter), adapter->id); - return i2c_probe(adapter, &addr_data, &adv7175_detect_client); -} - -static int -adv7175_detach_client (struct i2c_client *client) +static int adv7175_remove(struct i2c_client *client) { - struct adv7175 *encoder = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - - kfree(encoder); - kfree(client); - + kfree(i2c_get_clientdata(client)); return 0; } /* ----------------------------------------------------------------------- */ -static struct i2c_driver i2c_driver_adv7175 = { - .driver = { - .name = "adv7175", /* name */ - }, - - .id = I2C_DRIVERID_ADV7175, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id adv7175_id[] = { + { "adv7175", 0 }, + { "adv7176", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adv7175_id); +#endif - .attach_adapter = adv7175_attach_adapter, - .detach_client = adv7175_detach_client, +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "adv7175", + .driverid = I2C_DRIVERID_ADV7175, .command = adv7175_command, + .probe = adv7175_probe, + .remove = adv7175_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = adv7175_id, +#endif }; - -static int __init -adv7175_init (void) -{ - return i2c_add_driver(&i2c_driver_adv7175); -} - -static void __exit -adv7175_exit (void) -{ - i2c_del_driver(&i2c_driver_adv7175); -} - -module_init(adv7175_init); -module_exit(adv7175_exit); diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c index 90be239cc..201dd9277 100644 --- a/linux/drivers/media/video/bt819.c +++ b/linux/drivers/media/video/bt819.c @@ -29,45 +29,26 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/delay.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/major.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/signal.h> #include <linux/types.h> -#include <linux/i2c.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/page.h> +#include <linux/ioctl.h> #include <asm/uaccess.h> - +#include <linux/i2c.h> +#include <linux/i2c-id.h> #include <linux/videodev.h> #include <linux/video_decoder.h> - +#include <media/v4l2-common.h> +#include <media/v4l2-i2c-drv-legacy.h> #include "compat.h" MODULE_DESCRIPTION("Brooktree-819 video decoder driver"); MODULE_AUTHOR("Mike Bernson & Dave Perks"); MODULE_LICENSE("GPL"); - -#define I2C_NAME(s) (s)->name - - static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#define dprintk(num, format, args...) \ - do { \ - if (debug >= num) \ - printk(format, ##args); \ - } while (0) - /* ----------------------------------------------------------------------- */ struct bt819 { @@ -98,14 +79,9 @@ static struct timing timing_data[] = { {858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000}, }; -#define I2C_BT819 0x8a - /* ----------------------------------------------------------------------- */ -static inline int -bt819_write (struct i2c_client *client, - u8 reg, - u8 value) +static inline int bt819_write(struct i2c_client *client, u8 reg, u8 value) { struct bt819 *decoder = i2c_get_clientdata(client); @@ -113,24 +89,15 @@ bt819_write (struct i2c_client *client, return i2c_smbus_write_byte_data(client, reg, value); } -static inline int -bt819_setbit (struct i2c_client *client, - u8 reg, - u8 bit, - u8 value) +static inline int bt819_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value) { struct bt819 *decoder = i2c_get_clientdata(client); return bt819_write(client, reg, - (decoder-> - reg[reg] & ~(1 << bit)) | - (value ? (1 << bit) : 0)); + (decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0)); } -static int -bt819_write_block (struct i2c_client *client, - const u8 *data, - unsigned int len) +static int bt819_write_block(struct i2c_client *client, const u8 *data, unsigned int len) { int ret = -1; u8 reg; @@ -151,10 +118,9 @@ bt819_write_block (struct i2c_client *client, decoder->reg[reg++] = data[1]; len -= 2; data += 2; - } while (len >= 2 && data[0] == reg && - block_len < 32); - if ((ret = i2c_master_send(client, block_data, - block_len)) < 0) + } while (len >= 2 && data[0] == reg && block_len < 32); + ret = i2c_master_send(client, block_data, block_len); + if (ret < 0) break; } } else { @@ -170,20 +136,17 @@ bt819_write_block (struct i2c_client *client, return ret; } -static inline int -bt819_read (struct i2c_client *client, - u8 reg) +static inline int bt819_read(struct i2c_client *client, u8 reg) { return i2c_smbus_read_byte_data(client, reg); } -static int -bt819_init (struct i2c_client *client) +static int bt819_init(struct i2c_client *client) { struct bt819 *decoder = i2c_get_clientdata(client); static unsigned char init[] = { - //0x1f, 0x00, /* Reset */ + /*0x1f, 0x00,*/ /* Reset */ 0x01, 0x59, /* 0x01 input format */ 0x02, 0x00, /* 0x02 temporal decimation */ 0x03, 0x12, /* 0x03 Cropping msb */ @@ -219,12 +182,10 @@ bt819_init (struct i2c_client *client) struct timing *timing = &timing_data[decoder->norm]; init[0x03 * 2 - 1] = - (((timing->vdelay >> 8) & 0x03) << 6) | (((timing-> - vactive >> 8) & - 0x03) << 4) | - (((timing->hdelay >> 8) & 0x03) << 2) | ((timing-> - hactive >> 8) & - 0x03); + (((timing->vdelay >> 8) & 0x03) << 6) | + (((timing->vactive >> 8) & 0x03) << 4) | + (((timing->hdelay >> 8) & 0x03) << 2) | + ((timing->hactive >> 8) & 0x03); init[0x04 * 2 - 1] = timing->vdelay & 0xff; init[0x05 * 2 - 1] = timing->vactive & 0xff; init[0x06 * 2 - 1] = timing->hdelay & 0xff; @@ -239,27 +200,22 @@ bt819_init (struct i2c_client *client) /* init */ return bt819_write_block(client, init, sizeof(init)); - } /* ----------------------------------------------------------------------- */ -static int -bt819_command (struct i2c_client *client, - unsigned int cmd, - void *arg) +static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg) { int temp; struct bt819 *decoder = i2c_get_clientdata(client); - if (!decoder->initialized) { // First call to bt819_init could be - bt819_init(client); // without #FRST = 0 + if (!decoder->initialized) { /* First call to bt819_init could be */ + bt819_init(client); /* without #FRST = 0 */ decoder->initialized = 1; } switch (cmd) { - case 0: /* This is just for testing!!! */ bt819_init(client); @@ -275,8 +231,8 @@ bt819_command (struct i2c_client *client, VIDEO_DECODER_CCIR; cap->inputs = 8; cap->outputs = 1; - } break; + } case DECODER_GET_STATUS: { @@ -286,9 +242,9 @@ bt819_command (struct i2c_client *client, status = bt819_read(client, 0x00); res = 0; - if ((status & 0x80)) { + if ((status & 0x80)) res |= DECODER_STATUS_GOOD; - } + switch (decoder->norm) { case VIDEO_MODE_NTSC: res |= DECODER_STATUS_NTSC; @@ -298,28 +254,25 @@ bt819_command (struct i2c_client *client, break; default: case VIDEO_MODE_AUTO: - if ((status & 0x10)) { + if ((status & 0x10)) res |= DECODER_STATUS_PAL; - } else { + else res |= DECODER_STATUS_NTSC; - } break; } res |= DECODER_STATUS_COLOR; *iarg = res; - dprintk(1, KERN_INFO "%s: get status %x\n", I2C_NAME(client), - *iarg); - } + v4l_dbg(1, debug, client, "get status %x\n", *iarg); break; + } case DECODER_SET_NORM: { int *iarg = arg; struct timing *timing = NULL; - dprintk(1, KERN_INFO "%s: set norm %x\n", I2C_NAME(client), - *iarg); + v4l_dbg(1, debug, client, "set norm %x\n", *iarg); switch (*iarg) { case VIDEO_MODE_NTSC: @@ -328,7 +281,7 @@ bt819_command (struct i2c_client *client, bt819_setbit(client, 0x01, 5, 0); bt819_write(client, 0x18, 0x68); bt819_write(client, 0x19, 0x5d); - //bt819_setbit(client, 0x1a, 5, 1); + /* bt819_setbit(client, 0x1a, 5, 1); */ timing = &timing_data[VIDEO_MODE_NTSC]; break; case VIDEO_MODE_PAL: @@ -337,7 +290,7 @@ bt819_command (struct i2c_client *client, bt819_setbit(client, 0x01, 5, 1); bt819_write(client, 0x18, 0x7f); bt819_write(client, 0x19, 0x72); - //bt819_setbit(client, 0x1a, 5, 0); + /* bt819_setbit(client, 0x1a, 5, 0); */ timing = &timing_data[VIDEO_MODE_PAL]; break; case VIDEO_MODE_AUTO: @@ -345,10 +298,7 @@ bt819_command (struct i2c_client *client, bt819_setbit(client, 0x01, 1, 0); break; default: - dprintk(1, - KERN_ERR - "%s: unsupported norm %d\n", - I2C_NAME(client), *iarg); + v4l_dbg(1, debug, client, "unsupported norm %x\n", *iarg); return -EINVAL; } @@ -367,19 +317,17 @@ bt819_command (struct i2c_client *client, } decoder->norm = *iarg; - } break; + } case DECODER_SET_INPUT: { int *iarg = arg; - dprintk(1, KERN_INFO "%s: set input %x\n", I2C_NAME(client), - *iarg); + v4l_dbg(1, debug, client, "set input %x\n", *iarg); - if (*iarg < 0 || *iarg > 7) { + if (*iarg < 0 || *iarg > 7) return -EINVAL; - } if (decoder->input != *iarg) { decoder->input = *iarg; @@ -392,52 +340,42 @@ bt819_command (struct i2c_client *client, bt819_setbit(client, 0x1a, 1, 0); } } - } break; + } case DECODER_SET_OUTPUT: { int *iarg = arg; - dprintk(1, KERN_INFO "%s: set output %x\n", I2C_NAME(client), - *iarg); + v4l_dbg(1, debug, client, "set output %x\n", *iarg); /* not much choice of outputs */ - if (*iarg != 0) { + if (*iarg != 0) return -EINVAL; - } - } break; + } case DECODER_ENABLE_OUTPUT: { int *iarg = arg; int enable = (*iarg != 0); - dprintk(1, KERN_INFO "%s: enable output %x\n", - I2C_NAME(client), *iarg); + v4l_dbg(1, debug, client, "enable output %x\n", *iarg); if (decoder->enable != enable) { decoder->enable = enable; - - if (decoder->enable) { - bt819_setbit(client, 0x16, 7, 0); - } else { - bt819_setbit(client, 0x16, 7, 1); - } + bt819_setbit(client, 0x16, 7, !enable); } - } break; + } case DECODER_SET_PICTURE: { struct video_picture *pic = arg; - dprintk(1, - KERN_INFO - "%s: set picture brightness %d contrast %d colour %d\n", - I2C_NAME(client), pic->brightness, pic->contrast, - pic->colour); + v4l_dbg(1, debug, client, + "set picture brightness %d contrast %d colour %d\n", + pic->brightness, pic->contrast, pic->colour); if (decoder->bright != pic->brightness) { @@ -475,8 +413,8 @@ bt819_command (struct i2c_client *client, bt819_write(client, 0x0f, 128 - (decoder->hue >> 8)); } - } break; + } default: return -EINVAL; @@ -487,55 +425,44 @@ bt819_command (struct i2c_client *client, /* ----------------------------------------------------------------------- */ -/* - * Generic i2c probe - * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' - */ -static unsigned short normal_i2c[] = { - I2C_BT819 >> 1, - I2C_CLIENT_END, -}; - -static unsigned short ignore = I2C_CLIENT_END; - -static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_i2c, - .probe = &ignore, - .ignore = &ignore, -}; +static unsigned short normal_i2c[] = { 0x8a >> 1, I2C_CLIENT_END }; -static struct i2c_driver i2c_driver_bt819; +I2C_CLIENT_INSMOD; -static int -bt819_detect_client (struct i2c_adapter *adapter, - int address, - int kind) +static int bt819_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - int i, id; + int i, ver; struct bt819 *decoder; - struct i2c_client *client; - - dprintk(1, - KERN_INFO - "bt819: detecting bt819 client on address 0x%x\n", - address << 1); + const char *name; /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) - return -ENOMEM; - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver_bt819; + ver = bt819_read(client, 0x17); + switch (ver & 0xf0) { + case 0x70: + name = "bt819a"; + break; + case 0x60: + name = "bt817a"; + break; + case 0x20: + name = "bt815a"; + break; + default: + v4l_dbg(1, debug, client, + "unknown chip version 0x%02x\n", ver); + return -ENODEV; + } + + v4l_info(client, "%s found @ 0x%x (%s)\n", name, + client->addr << 1, client->adapter->name); decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL); - if (decoder == NULL) { - kfree(client); + if (decoder == NULL) return -ENOMEM; - } decoder->norm = VIDEO_MODE_NTSC; decoder->input = 0; decoder->enable = 1; @@ -546,97 +473,37 @@ bt819_detect_client (struct i2c_adapter *adapter, decoder->initialized = 0; i2c_set_clientdata(client, decoder); - id = bt819_read(client, 0x17); - switch (id & 0xf0) { - case 0x70: - strlcpy(I2C_NAME(client), "bt819a", sizeof(I2C_NAME(client))); - break; - case 0x60: - strlcpy(I2C_NAME(client), "bt817a", sizeof(I2C_NAME(client))); - break; - case 0x20: - strlcpy(I2C_NAME(client), "bt815a", sizeof(I2C_NAME(client))); - break; - default: - dprintk(1, - KERN_ERR - "bt819: unknown chip version 0x%x (ver 0x%x)\n", - id & 0xf0, id & 0x0f); - kfree(decoder); - kfree(client); - return 0; - } - - i = i2c_attach_client(client); - if (i) { - kfree(client); - kfree(decoder); - return i; - } - i = bt819_init(client); - if (i < 0) { - dprintk(1, KERN_ERR "%s_attach: init status %d\n", - I2C_NAME(client), i); - } else { - dprintk(1, - KERN_INFO - "%s_attach: chip version 0x%x at address 0x%x\n", - I2C_NAME(client), id & 0x0f, - client->addr << 1); - } - + if (i < 0) + v4l_dbg(1, debug, client, "init status %d\n", i); return 0; } -static int -bt819_attach_adapter (struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, &bt819_detect_client); -} - -static int -bt819_detach_client (struct i2c_client *client) +static int bt819_remove(struct i2c_client *client) { - struct bt819 *decoder = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - - kfree(decoder); - kfree(client); - + kfree(i2c_get_clientdata(client)); return 0; } /* ----------------------------------------------------------------------- */ -static struct i2c_driver i2c_driver_bt819 = { - .driver = { - .name = "bt819", - }, - - .id = I2C_DRIVERID_BT819, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id bt819_id[] = { + { "bt819a", 0 }, + { "bt817a", 0 }, + { "bt815a", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, bt819_id); - .attach_adapter = bt819_attach_adapter, - .detach_client = bt819_detach_client, +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "bt819", + .driverid = I2C_DRIVERID_BT819, .command = bt819_command, + .probe = bt819_probe, + .remove = bt819_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = bt819_id, +#endif }; - -static int __init -bt819_init_module (void) -{ - return i2c_add_driver(&i2c_driver_bt819); -} - -static void __exit -bt819_exit (void) -{ - i2c_del_driver(&i2c_driver_bt819); -} - -module_init(bt819_init_module); -module_exit(bt819_exit); diff --git a/linux/drivers/media/video/bt856.c b/linux/drivers/media/video/bt856.c index e31c9d4b9..89c4061c7 100644 --- a/linux/drivers/media/video/bt856.c +++ b/linux/drivers/media/video/bt856.c @@ -29,44 +29,25 @@ */ #include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/major.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/signal.h> #include <linux/types.h> +#include <linux/ioctl.h> +#include <asm/uaccess.h> #include <linux/i2c.h> +#include <linux/i2c-id.h> +#include <linux/videodev.h> #include <linux/video_encoder.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/page.h> -#include <asm/uaccess.h> - +#include <media/v4l2-common.h> +#include <media/v4l2-i2c-drv-legacy.h> #include "compat.h" -#include <linux/videodev.h> MODULE_DESCRIPTION("Brooktree-856A video encoder driver"); MODULE_AUTHOR("Mike Bernson & Dave Perks"); MODULE_LICENSE("GPL"); - -#define I2C_NAME(s) (s)->name - - static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#define dprintk(num, format, args...) \ - do { \ - if (debug >= num) \ - printk(format, ##args); \ - } while (0) - /* ----------------------------------------------------------------------- */ #define BT856_REG_OFFSET 0xDA @@ -79,14 +60,9 @@ struct bt856 { int enable; }; -#define I2C_BT856 0x88 - /* ----------------------------------------------------------------------- */ -static inline int -bt856_write (struct i2c_client *client, - u8 reg, - u8 value) +static inline int bt856_write(struct i2c_client *client, u8 reg, u8 value) { struct bt856 *encoder = i2c_get_clientdata(client); @@ -94,46 +70,36 @@ bt856_write (struct i2c_client *client, return i2c_smbus_write_byte_data(client, reg, value); } -static inline int -bt856_setbit (struct i2c_client *client, - u8 reg, - u8 bit, - u8 value) +static inline int bt856_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value) { struct bt856 *encoder = i2c_get_clientdata(client); return bt856_write(client, reg, - (encoder-> - reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) | - (value ? (1 << bit) : 0)); + (encoder->reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) | + (value ? (1 << bit) : 0)); } -static void -bt856_dump (struct i2c_client *client) +static void bt856_dump(struct i2c_client *client) { int i; struct bt856 *encoder = i2c_get_clientdata(client); - printk(KERN_INFO "%s: register dump:", I2C_NAME(client)); + v4l_info(client, "register dump:\n"); for (i = 0; i < BT856_NR_REG; i += 2) - printk(" %02x", encoder->reg[i]); - printk("\n"); + printk(KERN_CONT " %02x", encoder->reg[i]); + printk(KERN_CONT "\n"); } /* ----------------------------------------------------------------------- */ -static int -bt856_command (struct i2c_client *client, - unsigned int cmd, - void *arg) +static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg) { struct bt856 *encoder = i2c_get_clientdata(client); switch (cmd) { - case 0: /* This is just for testing!!! */ - dprintk(1, KERN_INFO "bt856: init\n"); + v4l_dbg(1, debug, client, "init\n"); bt856_write(client, 0xdc, 0x18); bt856_write(client, 0xda, 0); bt856_write(client, 0xde, 0); @@ -143,7 +109,6 @@ bt856_command (struct i2c_client *client, bt856_setbit(client, 0xdc, 4, 1); switch (encoder->norm) { - case VIDEO_MODE_NTSC: bt856_setbit(client, 0xdc, 2, 0); break; @@ -164,26 +129,23 @@ bt856_command (struct i2c_client *client, { struct video_encoder_capability *cap = arg; - dprintk(1, KERN_INFO "%s: get capabilities\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "get capabilities\n"); cap->flags = VIDEO_ENCODER_PAL | VIDEO_ENCODER_NTSC | VIDEO_ENCODER_CCIR; cap->inputs = 2; cap->outputs = 1; - } break; + } case ENCODER_SET_NORM: { int *iarg = arg; - dprintk(1, KERN_INFO "%s: set norm %d\n", I2C_NAME(client), - *iarg); + v4l_dbg(1, debug, client, "set norm %d\n", *iarg); switch (*iarg) { - case VIDEO_MODE_NTSC: bt856_setbit(client, 0xdc, 2, 0); break; @@ -196,27 +158,23 @@ bt856_command (struct i2c_client *client, default: return -EINVAL; - } encoder->norm = *iarg; if (debug != 0) bt856_dump(client); - } break; + } case ENCODER_SET_INPUT: { int *iarg = arg; - dprintk(1, KERN_INFO "%s: set input %d\n", I2C_NAME(client), - *iarg); + v4l_dbg(1, debug, client, "set input %d\n", *iarg); /* We only have video bus. * iarg = 0: input is from bt819 * iarg = 1: input is from ZR36060 */ - switch (*iarg) { - case 0: bt856_setbit(client, 0xde, 4, 0); bt856_setbit(client, 0xde, 3, 1); @@ -235,27 +193,24 @@ bt856_command (struct i2c_client *client, break; default: return -EINVAL; - } if (debug != 0) bt856_dump(client); - } break; + } case ENCODER_SET_OUTPUT: { int *iarg = arg; - dprintk(1, KERN_INFO "%s: set output %d\n", I2C_NAME(client), - *iarg); + v4l_dbg(1, debug, client, "set output %d\n", *iarg); /* not much choice of outputs */ - if (*iarg != 0) { + if (*iarg != 0) return -EINVAL; - } - } break; + } case ENCODER_ENABLE_OUTPUT: { @@ -263,10 +218,9 @@ bt856_command (struct i2c_client *client, encoder->enable = !!*iarg; - dprintk(1, KERN_INFO "%s: enable output %d\n", - I2C_NAME(client), encoder->enable); - } + v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable); break; + } default: return -EINVAL; @@ -277,64 +231,29 @@ bt856_command (struct i2c_client *client, /* ----------------------------------------------------------------------- */ -/* - * Generic i2c probe - * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' - */ -static unsigned short normal_i2c[] = { I2C_BT856 >> 1, I2C_CLIENT_END }; - -static unsigned short ignore = I2C_CLIENT_END; - -static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_i2c, - .probe = &ignore, - .ignore = &ignore, -}; +static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; -static struct i2c_driver i2c_driver_bt856; +I2C_CLIENT_INSMOD; -static int -bt856_detect_client (struct i2c_adapter *adapter, - int address, - int kind) +static int bt856_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - int i; - struct i2c_client *client; struct bt856 *encoder; - dprintk(1, - KERN_INFO - "bt856.c: detecting bt856 client on address 0x%x\n", - address << 1); - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) - return -ENOMEM; - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver_bt856; - strlcpy(I2C_NAME(client), "bt856", sizeof(I2C_NAME(client))); + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL); - if (encoder == NULL) { - kfree(client); + if (encoder == NULL) return -ENOMEM; - } encoder->norm = VIDEO_MODE_NTSC; encoder->enable = 1; i2c_set_clientdata(client, encoder); - i = i2c_attach_client(client); - if (i) { - kfree(client); - kfree(encoder); - return i; - } - bt856_write(client, 0xdc, 0x18); bt856_write(client, 0xda, 0); bt856_write(client, 0xde, 0); @@ -360,65 +279,30 @@ bt856_detect_client (struct i2c_adapter *adapter, if (debug != 0) bt856_dump(client); - - dprintk(1, KERN_INFO "%s_attach: at address 0x%x\n", I2C_NAME(client), - client->addr << 1); - return 0; } -static int -bt856_attach_adapter (struct i2c_adapter *adapter) +static int bt856_remove(struct i2c_client *client) { - dprintk(1, - KERN_INFO - "bt856.c: starting probe for adapter %s (0x%x)\n", - I2C_NAME(adapter), adapter->id); - return i2c_probe(adapter, &addr_data, &bt856_detect_client); -} - -static int -bt856_detach_client (struct i2c_client *client) -{ - struct bt856 *encoder = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - - kfree(encoder); - kfree(client); - + kfree(i2c_get_clientdata(client)); return 0; } -/* ----------------------------------------------------------------------- */ - -static struct i2c_driver i2c_driver_bt856 = { - .driver = { - .name = "bt856", - }, - - .id = I2C_DRIVERID_BT856, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id bt856_id[] = { + { "bt856", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, bt856_id); +#endif - .attach_adapter = bt856_attach_adapter, - .detach_client = bt856_detach_client, +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "bt856", + .driverid = I2C_DRIVERID_BT856, .command = bt856_command, + .probe = bt856_probe, + .remove = bt856_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = bt856_id, +#endif }; - -static int __init -bt856_init (void) -{ - return i2c_add_driver(&i2c_driver_bt856); -} - -static void __exit -bt856_exit (void) -{ - i2c_del_driver(&i2c_driver_bt856); -} - -module_init(bt856_init); -module_exit(bt856_exit); diff --git a/linux/drivers/media/video/bt866.c b/linux/drivers/media/video/bt866.c index 89161e867..aaa985c8e 100644 --- a/linux/drivers/media/video/bt866.c +++ b/linux/drivers/media/video/bt866.c @@ -29,43 +29,29 @@ */ #include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/major.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/signal.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/page.h> -#include <linux/sched.h> #include <linux/types.h> +#include <linux/ioctl.h> +#include <asm/uaccess.h> #include <linux/i2c.h> - -#include "compat.h" +#include <linux/i2c-id.h> #include <linux/videodev.h> -#include <asm/uaccess.h> - #include <linux/video_encoder.h> +#include <media/v4l2-common.h> +#include <media/v4l2-i2c-drv-legacy.h> +#include "compat.h" +MODULE_DESCRIPTION("Brooktree-866 video encoder driver"); +MODULE_AUTHOR("Mike Bernson & Dave Perks"); MODULE_LICENSE("GPL"); -#define BT866_DEVNAME "bt866" -#define I2C_BT866 0x88 - -MODULE_LICENSE("GPL"); - -#define DEBUG(x) /* Debug driver */ +static int debug; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0-1)"); /* ----------------------------------------------------------------------- */ struct bt866 { - struct i2c_client *i2c; - int addr; - unsigned char reg[256]; + u8 reg[256]; int norm; int enable; @@ -75,20 +61,45 @@ struct bt866 { int sat; }; -static int bt866_write(struct bt866 *dev, - unsigned char subaddr, unsigned char data); +static int bt866_write(struct i2c_client *client, u8 subaddr, u8 data) +{ + struct bt866 *encoder = i2c_get_clientdata(client); + u8 buffer[2]; + int err; + + buffer[0] = subaddr; + buffer[1] = data; + + encoder->reg[subaddr] = data; + + v4l_dbg(1, debug, client, "write 0x%02x = 0x%02x\n", subaddr, data); -static int bt866_do_command(struct bt866 *encoder, - unsigned int cmd, void *arg) + for (err = 0; err < 3;) { + if (i2c_master_send(client, buffer, 2) == 2) + break; + err++; + v4l_warn(client, "error #%d writing to 0x%02x\n", + err, subaddr); + schedule_timeout_interruptible(msecs_to_jiffies(100)); + } + if (err == 3) { + v4l_warn(client, "giving up\n"); + return -1; + } + + return 0; +} + +static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg) { + struct bt866 *encoder = i2c_get_clientdata(client); + switch (cmd) { case ENCODER_GET_CAPABILITIES: { struct video_encoder_capability *cap = arg; - DEBUG(printk - (KERN_INFO "%s: get capabilities\n", - encoder->i2c->name)); + v4l_dbg(1, debug, client, "get capabilities\n"); cap->flags = VIDEO_ENCODER_PAL @@ -96,18 +107,16 @@ static int bt866_do_command(struct bt866 *encoder, | VIDEO_ENCODER_CCIR; cap->inputs = 2; cap->outputs = 1; + break; } - break; case ENCODER_SET_NORM: { int *iarg = arg; - DEBUG(printk(KERN_INFO "%s: set norm %d\n", - encoder->i2c->name, *iarg)); + v4l_dbg(1, debug, client, "set norm %d\n", *iarg); switch (*iarg) { - case VIDEO_MODE_NTSC: break; @@ -116,11 +125,10 @@ static int bt866_do_command(struct bt866 *encoder, default: return -EINVAL; - } encoder->norm = *iarg; + break; } - break; case ENCODER_SET_INPUT: { @@ -156,7 +164,7 @@ static int bt866_do_command(struct bt866 *encoder, u8 val; for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2) - bt866_write(encoder, init[i], init[i+1]); + bt866_write(client, init[i], init[i+1]); val = encoder->reg[0xdc]; @@ -165,17 +173,16 @@ static int bt866_do_command(struct bt866 *encoder, else val &= ~0x40; /* !CBSWAP */ - bt866_write(encoder, 0xdc, val); + bt866_write(client, 0xdc, val); val = encoder->reg[0xcc]; if (*iarg == 2) val |= 0x01; /* OSDBAR */ else val &= ~0x01; /* !OSDBAR */ - bt866_write(encoder, 0xcc, val); + bt866_write(client, 0xcc, val); - DEBUG(printk(KERN_INFO "%s: set input %d\n", - encoder->i2c->name, *iarg)); + v4l_dbg(1, debug, client, "set input %d\n", *iarg); switch (*iarg) { case 0: @@ -184,48 +191,44 @@ static int bt866_do_command(struct bt866 *encoder, break; default: return -EINVAL; - } + break; } - break; case ENCODER_SET_OUTPUT: { int *iarg = arg; - DEBUG(printk(KERN_INFO "%s: set output %d\n", - encoder->i2c->name, *iarg)); + v4l_dbg(1, debug, client, "set output %d\n", *iarg); /* not much choice of outputs */ if (*iarg != 0) return -EINVAL; + break; } - break; case ENCODER_ENABLE_OUTPUT: { int *iarg = arg; encoder->enable = !!*iarg; - DEBUG(printk - (KERN_INFO "%s: enable output %d\n", - encoder->i2c->name, encoder->enable)); + v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable); + break; } - break; case 4711: { int *iarg = arg; __u8 val; - printk("bt866: square = %d\n", *iarg); + v4l_dbg(1, debug, client, "square %d\n", *iarg); val = encoder->reg[0xdc]; if (*iarg) val |= 1; /* SQUARE */ else val &= ~1; /* !SQUARE */ - bt866_write(encoder, 0xdc, val); + bt866_write(client, 0xdc, val); break; } @@ -236,141 +239,53 @@ static int bt866_do_command(struct bt866 *encoder, return 0; } -static int bt866_write(struct bt866 *encoder, - unsigned char subaddr, unsigned char data) -{ - unsigned char buffer[2]; - int err; - - buffer[0] = subaddr; - buffer[1] = data; - - encoder->reg[subaddr] = data; +static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; - DEBUG(printk - ("%s: write 0x%02X = 0x%02X\n", - encoder->i2c->name, subaddr, data)); +I2C_CLIENT_INSMOD; - for (err = 0; err < 3;) { - if (i2c_master_send(encoder->i2c, buffer, 2) == 2) - break; - err++; - printk(KERN_WARNING "%s: I/O error #%d " - "(write 0x%02x/0x%02x)\n", - encoder->i2c->name, err, encoder->addr, subaddr); - schedule_timeout_interruptible(msecs_to_jiffies(100)); - } - if (err == 3) { - printk(KERN_WARNING "%s: giving up\n", - encoder->i2c->name); - return -1; - } - - return 0; -} - -static int bt866_attach(struct i2c_adapter *adapter); -static int bt866_detach(struct i2c_client *client); -static int bt866_command(struct i2c_client *client, - unsigned int cmd, void *arg); - - -/* Addresses to scan */ -static unsigned short normal_i2c[] = {I2C_BT866>>1, I2C_CLIENT_END}; -static unsigned short probe[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; -static unsigned short ignore[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; - -static struct i2c_client_address_data addr_data = { - normal_i2c, - probe, - ignore, -}; - -static struct i2c_driver i2c_driver_bt866 = { - .driver.name = BT866_DEVNAME, - .id = I2C_DRIVERID_BT866, - .attach_adapter = bt866_attach, - .detach_client = bt866_detach, - .command = bt866_command -}; - - -static struct i2c_client bt866_client_tmpl = -{ - .name = "(nil)", - .addr = 0, - .adapter = NULL, - .driver = &i2c_driver_bt866, -}; - -static int bt866_found_proc(struct i2c_adapter *adapter, - int addr, int kind) +static int bt866_probe(struct i2c_client *client, + const struct i2c_device_id *id) { struct bt866 *encoder; - struct i2c_client *client; - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - memcpy(client, &bt866_client_tmpl, sizeof(*client)); + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); - if (encoder == NULL) { - kfree(client); + if (encoder == NULL) return -ENOMEM; - } i2c_set_clientdata(client, encoder); - client->adapter = adapter; - client->addr = addr; - sprintf(client->name, "%s-%02x", BT866_DEVNAME, adapter->id); - - encoder->i2c = client; - encoder->addr = addr; - //encoder->encoder_type = ENCODER_TYPE_UNKNOWN; - - /* initialize */ - - i2c_attach_client(client); - return 0; } -static int bt866_attach(struct i2c_adapter *adapter) +static int bt866_remove(struct i2c_client *client) { - if (adapter->id == I2C_HW_B_ZR36067) - return i2c_probe(adapter, &addr_data, bt866_found_proc); + kfree(i2c_get_clientdata(client)); return 0; } -static int bt866_detach(struct i2c_client *client) +static int bt866_legacy_probe(struct i2c_adapter *adapter) { - struct bt866 *encoder = i2c_get_clientdata(client); - - i2c_detach_client(client); - kfree(encoder); - kfree(client); - - return 0; + return adapter->id == I2C_HW_B_ZR36067; } -static int bt866_command(struct i2c_client *client, - unsigned int cmd, void *arg) -{ - struct bt866 *encoder = i2c_get_clientdata(client); - return bt866_do_command(encoder, cmd, arg); -} - -static int __devinit bt866_init(void) -{ - i2c_add_driver(&i2c_driver_bt866); - return 0; -} - -static void __devexit bt866_exit(void) -{ - i2c_del_driver(&i2c_driver_bt866); -} - -module_init(bt866_init); -module_exit(bt866_exit); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id bt866_id[] = { + { "bt866", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, bt866_id); +#endif + +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "bt866", + .driverid = I2C_DRIVERID_BT866, + .command = bt866_command, + .probe = bt866_probe, + .remove = bt866_remove, + .legacy_probe = bt866_legacy_probe, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = bt866_id, +#endif +}; diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index c050cd2ce..6fc69988a 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -644,6 +644,17 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p port->mpegq.timeout.data = (unsigned long)port; init_timer(&port->mpegq.timeout); + mutex_init(&port->frontends.lock); + INIT_LIST_HEAD(&port->frontends.frontend.felist); + port->frontends.active_fe_id = 0; + + /* This should be hardcoded allow a single frontend + * attachment to this tsport, keeping the -dvb.c + * code clean and safe. + */ + if(!port->num_frontends) + port->num_frontends = 1; + switch(portno) { case 1: port->reg_gpcnt = VID_B_GPCNT; diff --git a/linux/drivers/media/video/cx23885/cx23885-dvb.c b/linux/drivers/media/video/cx23885/cx23885-dvb.c index 1909ef6e3..9b96b0600 100644 --- a/linux/drivers/media/video/cx23885/cx23885-dvb.c +++ b/linux/drivers/media/video/cx23885/cx23885-dvb.c @@ -313,19 +313,25 @@ static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; struct cx23885_i2c *i2c_bus = NULL; + struct videobuf_dvb_frontend *fe0; + + /* Get the first frontend */ + fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); + if (!fe0) + return -EINVAL; /* init struct videobuf_dvb */ - port->dvb.name = dev->name; + fe0->dvb.name = dev->name; /* init frontend */ switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1250: i2c_bus = &dev->i2c_bus[0]; - port->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { - dvb_attach(mt2131_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + dvb_attach(mt2131_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_generic_tunerconfig, 0); } @@ -334,27 +340,27 @@ static int dvb_register(struct cx23885_tsport *port) i2c_bus = &dev->i2c_bus[0]; switch (alt_tuner) { case 1: - port->dvb.frontend = + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_ezqam_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { - dvb_attach(tda829x_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda829x_attach, fe0->dvb.frontend, &dev->i2c_bus[1].i2c_adap, 0x42, &tda829x_no_probe); - dvb_attach(tda18271_attach, port->dvb.frontend, + dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); } break; case 0: default: - port->dvb.frontend = + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) - dvb_attach(mt2131_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) + dvb_attach(mt2131_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_generic_tunerconfig, 0); break; @@ -362,42 +368,42 @@ static int dvb_register(struct cx23885_tsport *port) break; case CX23885_BOARD_HAUPPAUGE_HVR1800lp: i2c_bus = &dev->i2c_bus[0]; - port->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1800lp_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { - dvb_attach(mt2131_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + dvb_attach(mt2131_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_generic_tunerconfig, 0); } break; case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP: i2c_bus = &dev->i2c_bus[0]; - port->dvb.frontend = dvb_attach(lgdt330x_attach, + fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_express, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { - dvb_attach(simple_tuner_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF); } break; case CX23885_BOARD_HAUPPAUGE_HVR1500Q: i2c_bus = &dev->i2c_bus[1]; - port->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500q_config, &dev->i2c_bus[0].i2c_adap); - if (port->dvb.frontend != NULL) - dvb_attach(xc5000_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) + dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_hvr1500q_tunerconfig); break; case CX23885_BOARD_HAUPPAUGE_HVR1500: i2c_bus = &dev->i2c_bus[1]; - port->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500_config, &dev->i2c_bus[0].i2c_adap); - if (port->dvb.frontend != NULL) { + if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, @@ -410,7 +416,7 @@ static int dvb_register(struct cx23885_tsport *port) }; fe = dvb_attach(xc2028_attach, - port->dvb.frontend, &cfg); + fe0->dvb.frontend, &cfg); if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctl); } @@ -418,24 +424,24 @@ static int dvb_register(struct cx23885_tsport *port) case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: i2c_bus = &dev->i2c_bus[0]; - port->dvb.frontend = dvb_attach(tda10048_attach, + fe0->dvb.frontend = dvb_attach(tda10048_attach, &hauppauge_hvr1200_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { - dvb_attach(tda829x_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda829x_attach, fe0->dvb.frontend, &dev->i2c_bus[1].i2c_adap, 0x42, &tda829x_no_probe); - dvb_attach(tda18271_attach, port->dvb.frontend, + dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr1200_tuner_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1400: i2c_bus = &dev->i2c_bus[0]; - port->dvb.frontend = dvb_attach(dib7000p_attach, + fe0->dvb.frontend = dvb_attach(dib7000p_attach, &i2c_bus->i2c_adap, 0x12, &hauppauge_hvr1400_dib7000_config); - if (port->dvb.frontend != NULL) { + if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, @@ -450,7 +456,7 @@ static int dvb_register(struct cx23885_tsport *port) }; fe = dvb_attach(xc2028_attach, - port->dvb.frontend, &cfg); + fe0->dvb.frontend, &cfg); if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctl); } @@ -458,25 +464,25 @@ static int dvb_register(struct cx23885_tsport *port) case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: i2c_bus = &dev->i2c_bus[port->nr - 1]; - port->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &dvico_s5h1409_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend == NULL) - port->dvb.frontend = dvb_attach(s5h1411_attach, + if (fe0->dvb.frontend == NULL) + fe0->dvb.frontend = dvb_attach(s5h1411_attach, &dvico_s5h1411_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) - dvb_attach(xc5000_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) + dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &dvico_xc5000_tunerconfig); break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: { i2c_bus = &dev->i2c_bus[port->nr - 1]; - port->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { + if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, @@ -488,7 +494,7 @@ static int dvb_register(struct cx23885_tsport *port) .demod = XC3028_FE_ZARLINK456, }; - fe = dvb_attach(xc2028_attach, port->dvb.frontend, + fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg); if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctl); @@ -498,10 +504,10 @@ static int dvb_register(struct cx23885_tsport *port) case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: i2c_bus = &dev->i2c_bus[0]; - port->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { + if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, @@ -513,7 +519,7 @@ static int dvb_register(struct cx23885_tsport *port) .demod = XC3028_FE_ZARLINK456, }; - fe = dvb_attach(xc2028_attach, port->dvb.frontend, + fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg); if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctl); @@ -524,43 +530,70 @@ static int dvb_register(struct cx23885_tsport *port) dev->name); break; } - if (NULL == port->dvb.frontend) { + if (NULL == fe0->dvb.frontend) { printk("%s: frontend initialization failed\n", dev->name); return -1; } /* define general-purpose callback pointer */ - port->dvb.frontend->callback = cx23885_tuner_callback; + fe0->dvb.frontend->callback = cx23885_tuner_callback; /* Put the analog decoder in standby to keep it quiet */ cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL); - if (port->dvb.frontend->ops.analog_ops.standby) - port->dvb.frontend->ops.analog_ops.standby(port->dvb.frontend); + if (fe0->dvb.frontend->ops.analog_ops.standby) + fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); /* register everything */ - return videobuf_dvb_register(&port->dvb, THIS_MODULE, port, - &dev->pci->dev, adapter_nr); + return videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, + &dev->pci->dev, adapter_nr, 0); + } int cx23885_dvb_register(struct cx23885_tsport *port) { + + struct videobuf_dvb_frontend *fe0; struct cx23885_dev *dev = port->dev; - int err; + int err, i; + + /* Here we need to allocate the correct number of frontends, + * as reflected in the cards struct. The reality is that currrently + * no cx23885 boards support this - yet. But, if we don't modify this + * code then the second frontend would never be allocated (later) + * and fail with error before the attach in dvb_register(). + * Without these changes we risk an OOPS later. The changes here + * are for safety, and should provide a good foundation for the + * future addition of any multi-frontend cx23885 based boards. + */ + printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, + port->num_frontends); - dprintk(1, "%s\n", __func__); - dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", - dev->board, - dev->name, - dev->pci_bus, - dev->pci_slot); + for (i = 1; i <= port->num_frontends; i++) { + if (videobuf_dvb_alloc_frontend(dev, &port->frontends, i) == NULL) { + printk(KERN_ERR "%s() failed to alloc\n", __func__); + return -ENOMEM; + } - err = -ENODEV; + fe0 = videobuf_dvb_get_frontend(&port->frontends, i); + if (!fe0) + err = -EINVAL; - /* dvb stuff */ - printk("%s: cx23885 based dvb card\n", dev->name); - videobuf_queue_sg_init(&port->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock, + dprintk(1, "%s\n", __func__); + dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", + dev->board, + dev->name, + dev->pci_bus, + dev->pci_slot); + + err = -ENODEV; + + /* dvb stuff */ + /* We have to init the queue for each frontend on a port. */ + printk("%s: cx23885 based dvb card\n", dev->name); + videobuf_queue_sg_init(&fe0->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx23885_buffer), port); + } err = dvb_register(port); if (err != 0) printk("%s() dvb_register failed err = %d\n", __func__, err); @@ -570,9 +603,18 @@ int cx23885_dvb_register(struct cx23885_tsport *port) int cx23885_dvb_unregister(struct cx23885_tsport *port) { - /* dvb */ - if(port->dvb.frontend) - videobuf_dvb_unregister(&port->dvb); + struct videobuf_dvb_frontend *fe0; + + /* FIXME: in an error condition where the we have + * an expected number of frontends (attach problem) + * then this might not clean up correctly, if 1 + * is invalid. + * This comment only applies to future boards IF they + * implement MFE support. + */ + fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); + if(fe0->dvb.frontend) + videobuf_dvb_unregister_bus(&port->frontends); return 0; } diff --git a/linux/drivers/media/video/cx23885/cx23885.h b/linux/drivers/media/video/cx23885/cx23885.h index dea1798f7..2dde9e01a 100644 --- a/linux/drivers/media/video/cx23885/cx23885.h +++ b/linux/drivers/media/video/cx23885/cx23885.h @@ -226,7 +226,7 @@ struct cx23885_tsport { int nr; int sram_chno; - struct videobuf_dvb dvb; + struct videobuf_dvb_frontends frontends; /* dma queues */ struct cx23885_dmaqueue mpegq; @@ -263,6 +263,9 @@ struct cx23885_tsport { u32 src_sel_val; u32 vld_misc_val; u32 hw_sop_ctrl_val; + + /* Allow a single tsport to have multiple frontends */ + u32 num_frontends; }; struct cx23885_dev { diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c index a351a2220..eac3508d6 100644 --- a/linux/drivers/media/video/cx88/cx88-cards.c +++ b/linux/drivers/media/video/cx88/cx88-cards.c @@ -1303,27 +1303,36 @@ static const struct cx88_board cx88_boards[] = { .mpeg = CX88_MPEG_DVB, }, [CX88_BOARD_HAUPPAUGE_HVR3000] = { - /* FIXME: Add dvb & radio support */ .name = "Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T", .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .audio_chip = V4L2_IDENT_WM8775, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x84bf, + .audioroute = 1, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x84bf, + .audioroute = 2, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x84bf, + .audioroute = 2, }}, + /* FIXME Radio tunes but only noise is heard */ + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x84bf, + }, .mpeg = CX88_MPEG_DVB, + .num_frontends = 2, }, [CX88_BOARD_NORWOOD_MICRO] = { .name = "Norwood Micro TV Tuner", @@ -1749,6 +1758,7 @@ static const struct cx88_board cx88_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .audio_chip = V4L2_IDENT_WM8775, /* * GPIO0 (WINTV2000) * @@ -1762,7 +1772,7 @@ static const struct cx88_board cx88_boards[] = { * BIT VALUE FUNCTION GP{x}_IO * 0 1 I:? * 1 1 I:? - * 2 1 O:DVB-T DEMOD ENABLE LOW/ANALOG DEMOD ENABLE HIGH + * 2 1 O:MPEG PORT 0=DVB-T 1=DVB-S * 3 1 I:? * 4 1 I:? * 5 1 I:? @@ -1783,17 +1793,25 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0xc4bf, + .audioroute = 1, }, { .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0xc4bf, + .audioroute = 2, }, { .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0xc4bf, + .audioroute = 2, } }, - /* fixme: Add radio support */ + /* FIXME Radio tunes but only noise is heard */ + .radio = { + .type = CX88_RADIO, + .gpio0 = 0xc4bf, + }, .mpeg = CX88_MPEG_DVB, + .num_frontends = 2, }, [CX88_BOARD_HAUPPAUGE_HVR4000LITE] = { .name = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2", @@ -2695,10 +2713,13 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR4000: - case CX88_BOARD_HAUPPAUGE_HVR4000LITE: /* Init GPIO */ cx_write(MO_GP0_IO, core->board.input[0].gpio0); udelay(1000); + cx_clear(MO_GP0_IO, 0x00000080); + udelay(50); + cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */ + udelay(1000); break; } } @@ -3037,10 +3058,14 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board)); - info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + if (!core->board.num_frontends) + core->board.num_frontends=1; + + info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n", pci->subsystem_vendor, pci->subsystem_device, core->board.name, core->boardnr, card[core->nr] == core->boardnr ? - "insmod option" : "autodetected"); + "insmod option" : "autodetected", + core->board.num_frontends); if (tuner[core->nr] != UNSET) core->board.tuner_type = tuner[core->nr]; diff --git a/linux/drivers/media/video/cx88/cx88-dvb.c b/linux/drivers/media/video/cx88/cx88-dvb.c index 84f235ba0..1a0f971c6 100644 --- a/linux/drivers/media/video/cx88/cx88-dvb.c +++ b/linux/drivers/media/video/cx88/cx88-dvb.c @@ -117,13 +117,23 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) struct cx8802_dev *dev= fe->dvb->priv; struct cx8802_driver *drv = NULL; int ret = 0; + int fe_id; + + fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe); + if (!fe_id) { + printk(KERN_ERR "%s() No frontend found\n", __FUNCTION__); + return -EINVAL; + } drv = cx8802_get_driver(dev, CX88_MPEG_DVB); if (drv) { - if (acquire) + if (acquire){ + dev->frontends.active_fe_id = fe_id; ret = drv->request_acquire(drv); - else + } else { ret = drv->request_release(drv); + dev->frontends.active_fe_id = 0; + } } return ret; @@ -490,6 +500,7 @@ static struct xc5000_config dvico_fusionhdtv7_tuner_config = { static int attach_xc3028(u8 addr, struct cx8802_dev *dev) { struct dvb_frontend *fe; + struct videobuf_dvb_frontend *fe0 = NULL; struct xc2028_ctrl ctl; struct xc2028_config cfg = { .i2c_adap = &dev->core->i2c_adap, @@ -497,7 +508,12 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) .ctrl = &ctl, }; - if (!dev->dvb.frontend) { + /* Get the first frontend */ + fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); + if (!fe0) + return -EINVAL; + + if (!fe0->dvb.frontend) { printk(KERN_ERR "%s/2: dvb frontend not attached. " "Can't attach xc3028\n", dev->core->name); @@ -511,10 +527,13 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) */ cx88_setup_xc3028(dev->core, &ctl); - fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); + fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg); if (!fe) { printk(KERN_ERR "%s/2: xc3028 attach failed\n", dev->core->name); + dvb_frontend_detach(fe0->dvb.frontend); + dvb_unregister_frontend(fe0->dvb.frontend); + fe0->dvb.frontend = NULL; return -EINVAL; } @@ -539,8 +558,10 @@ static int cx24116_reset_device(struct dvb_frontend *fe) struct cx88_core *core = dev->core; /* Reset the part */ + /* Put the cx24116 into reset */ cx_write(MO_SRST_IO, 0); msleep(10); + /* Take the cx24116 out of reset */ cx_write(MO_SRST_IO, 1); msleep(10); @@ -581,19 +602,25 @@ static struct stv0288_config tevii_tuner_earda_config = { static int dvb_register(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; + struct videobuf_dvb_frontend *fe0, *fe1 = NULL; + int mfe_shared = 0; /* bus not shared by default */ - /* init struct videobuf_dvb */ - dev->dvb.name = core->name; - dev->ts_gen_cntrl = 0x0c; + /* Get the first frontend */ + fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); + if (!fe0) + return -EINVAL; - /* init frontend */ + /* multi-frontend gate control is undefined or defaults to fe0 */ + dev->frontends.gate = 0; + + /* init frontend(s) */ switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_DVB_T1: - dev->dvb.frontend = dvb_attach(cx22702_attach, + fe0->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, &core->i2c_adap, DVB_PLL_THOMSON_DTT759X)) goto frontend_detach; @@ -603,11 +630,11 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_CONEXANT_DVB_T1: case CX88_BOARD_KWORLD_DVB_T_CX22702: case CX88_BOARD_WINFAST_DTV1000: - dev->dvb.frontend = dvb_attach(cx22702_attach, + fe0->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, &core->i2c_adap, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; @@ -617,33 +644,67 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: case CX88_BOARD_HAUPPAUGE_HVR1300: - case CX88_BOARD_HAUPPAUGE_HVR3000: - dev->dvb.frontend = dvb_attach(cx22702_attach, + fe0->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_hvr_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) goto frontend_detach; } break; + case CX88_BOARD_HAUPPAUGE_HVR3000: + /* DVB-S init */ + fe0->dvb.frontend = dvb_attach(cx24123_attach, + &hauppauge_novas_config, + &dev->core->i2c_adap); + if (fe0->dvb.frontend) { + if (!dvb_attach(isl6421_attach, fe0->dvb.frontend, + &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) { + dprintk( 1, "%s(): HVR3000 - DVB-S LNB Init: failed\n", __FUNCTION__); + } + } else { + dprintk( 1, "%s(): HVR3000 - DVB-S Init: failed\n", __FUNCTION__); + } + /* DVB-T init */ + fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); + if (fe1) { + dev->frontends.gate = 2; + mfe_shared = 1; + fe1->dvb.frontend = dvb_attach(cx22702_attach, + &hauppauge_hvr_config, + &dev->core->i2c_adap); + if (fe1->dvb.frontend) { + fe1->dvb.frontend->id = 1; + if(!dvb_attach(simple_tuner_attach, fe1->dvb.frontend, + &dev->core->i2c_adap, 0x61, + TUNER_PHILIPS_FMD1216ME_MK3)) { + dprintk( 1, "%s(): HVR3000 - DVB-T misc Init: failed\n", __FUNCTION__); + } + } else { + dprintk( 1, "%s(): HVR3000 - DVB-T Init: failed\n", __FUNCTION__); + } + } else { + dprintk( 1, "%s(): HVR3000 - DVB-T Init: can't find frontend 2.\n", __FUNCTION__); + } + break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; break; } /* ZL10353 replaces MT352 on later cards */ - dev->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; } @@ -651,31 +712,31 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: /* The tin box says DEE1601, but it seems to be DTT7579 * compatible, with a slightly different MT352 AGC gain. */ - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_dual, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; break; } /* ZL10353 replaces MT352 on later cards */ - dev->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_LG_Z201)) goto frontend_detach; } @@ -683,11 +744,11 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_ADSTECH_DVB_T_PCI: - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_UNKNOWN_1)) goto frontend_detach; } @@ -695,10 +756,10 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: #if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) /* MT352 is on a secondary I2C bus made from some GPIO lines */ - dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, + fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, &dev->vp3054->adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) goto frontend_detach; @@ -709,22 +770,22 @@ static int dvb_register(struct cx8802_dev *dev) #endif break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: - dev->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_hybrid, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_FE6600)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: - dev->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &core->i2c_adap); - if (dev->dvb.frontend == NULL) - dev->dvb.frontend = dvb_attach(mt352_attach, + if (fe0->dvb.frontend == NULL) + fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_mt352_xc3028, &core->i2c_adap); /* @@ -732,16 +793,16 @@ static int dvb_register(struct cx8802_dev *dev) * We must not permit gate_ctrl to be performed, or * the xc3028 cannot communicate on the bus. */ - if (dev->dvb.frontend) - dev->dvb.frontend->ops.i2c_gate_ctrl = NULL; + if (fe0->dvb.frontend) + fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; if (attach_xc3028(0x61, dev) < 0) return -EINVAL; break; case CX88_BOARD_PCHDTV_HD3000: - dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, + fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) goto frontend_detach; @@ -758,11 +819,11 @@ static int dvb_register(struct cx8802_dev *dev) /* Select RF connector callback */ fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; - dev->dvb.frontend = dvb_attach(lgdt330x_attach, + fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_MICROTUNE_4042FI5)) goto frontend_detach; @@ -776,11 +837,11 @@ static int dvb_register(struct cx8802_dev *dev) mdelay(100); cx_set(MO_GP0_IO, 9); mdelay(200); - dev->dvb.frontend = dvb_attach(lgdt330x_attach, + fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) goto frontend_detach; @@ -794,15 +855,15 @@ static int dvb_register(struct cx8802_dev *dev) mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); - dev->dvb.frontend = dvb_attach(lgdt330x_attach, + fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_gold, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF)) goto frontend_detach; - if (!dvb_attach(tda9887_attach, dev->dvb.frontend, + if (!dvb_attach(tda9887_attach, fe0->dvb.frontend, &core->i2c_adap, 0x43)) goto frontend_detach; } @@ -815,25 +876,25 @@ static int dvb_register(struct cx8802_dev *dev) mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); - dev->dvb.frontend = dvb_attach(lgdt330x_attach, + fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &pchdtv_hd5500, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF)) goto frontend_detach; - if (!dvb_attach(tda9887_attach, dev->dvb.frontend, + if (!dvb_attach(tda9887_attach, fe0->dvb.frontend, &core->i2c_adap, 0x43)) goto frontend_detach; } break; case CX88_BOARD_ATI_HDTVWONDER: - dev->dvb.frontend = dvb_attach(nxt200x_attach, + fe0->dvb.frontend = dvb_attach(nxt200x_attach, &ati_hdtvwonder, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_PHILIPS_TUV1236D)) goto frontend_detach; @@ -841,49 +902,49 @@ static int dvb_register(struct cx8802_dev *dev) break; case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: - dev->dvb.frontend = dvb_attach(cx24123_attach, + fe0->dvb.frontend = dvb_attach(cx24123_attach, &hauppauge_novas_config, &core->i2c_adap); - if (dev->dvb.frontend) { - if (!dvb_attach(isl6421_attach, dev->dvb.frontend, + if (fe0->dvb.frontend) { + if (!dvb_attach(isl6421_attach, fe0->dvb.frontend, &core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) goto frontend_detach; } break; case CX88_BOARD_KWORLD_DVBS_100: - dev->dvb.frontend = dvb_attach(cx24123_attach, + fe0->dvb.frontend = dvb_attach(cx24123_attach, &kworld_dvbs_100_config, &core->i2c_adap); - if (dev->dvb.frontend) { - core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; - dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; + if (fe0->dvb.frontend) { + core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; } break; case CX88_BOARD_GENIATECH_DVBS: - dev->dvb.frontend = dvb_attach(cx24123_attach, + fe0->dvb.frontend = dvb_attach(cx24123_attach, &geniatech_dvbs_config, &core->i2c_adap); - if (dev->dvb.frontend) { - core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; - dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; + if (fe0->dvb.frontend) { + core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; } break; case CX88_BOARD_PINNACLE_PCTV_HD_800i: - dev->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &pinnacle_pctv_hd_800i_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(xc5000_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(xc5000_attach, fe0->dvb.frontend, &core->i2c_adap, &pinnacle_pctv_hd_800i_tuner_config)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: - dev->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &dvico_hdtv5_pci_nano_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { + if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &core->i2c_adap, @@ -896,17 +957,17 @@ static int dvb_register(struct cx8802_dev *dev) }; fe = dvb_attach(xc2028_attach, - dev->dvb.frontend, &cfg); + fe0->dvb.frontend, &cfg); if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctl); } break; case CX88_BOARD_PINNACLE_HYBRID_PCTV: - dev->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_pinnacle_hybrid_pctv, &core->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.i2c_gate_ctrl = NULL; + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; } @@ -914,85 +975,118 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_GENIATECH_X8000_MT: dev->ts_gen_cntrl = 0x00; - dev->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_geniatech_x8000_mt, &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; break; case CX88_BOARD_KWORLD_ATSC_120: - dev->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &kworld_atsc_120_config, &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; break; case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: - dev->dvb.frontend = dvb_attach(s5h1411_attach, + fe0->dvb.frontend = dvb_attach(s5h1411_attach, &dvico_fusionhdtv7_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(xc5000_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(xc5000_attach, fe0->dvb.frontend, &core->i2c_adap, &dvico_fusionhdtv7_tuner_config)) goto frontend_detach; } break; case CX88_BOARD_HAUPPAUGE_HVR4000: + /* DVB-S/S2 Init */ + fe0->dvb.frontend = dvb_attach(cx24116_attach, + &hauppauge_hvr4000_config, + &dev->core->i2c_adap); + if (fe0->dvb.frontend) { + if(!dvb_attach(isl6421_attach, fe0->dvb.frontend, + &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) { + dprintk( 1, "%s(): HVR4000 - DVB-S LNB Init: failed\n", __FUNCTION__); + } + } else { + dprintk( 1, "%s(): HVR4000 - DVB-S Init: failed\n", __FUNCTION__); + } + /* DVB-T Init */ + fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); + if (fe1) { + dev->frontends.gate = 2; + mfe_shared = 1; + fe1->dvb.frontend = dvb_attach(cx22702_attach, + &hauppauge_hvr_config, + &dev->core->i2c_adap); + if (fe1->dvb.frontend) { + fe1->dvb.frontend->id = 1; + if(!dvb_attach(simple_tuner_attach, fe1->dvb.frontend, + &dev->core->i2c_adap, 0x61, + TUNER_PHILIPS_FMD1216ME_MK3)) { + dprintk( 1, "%s(): HVR4000 - DVB-T misc Init: failed\n", __FUNCTION__); + } + } else { + dprintk( 1, "%s(): HVR4000 - DVB-T Init: failed\n", __FUNCTION__); + } + } else { + dprintk( 1, "%s(): HVR4000 - DVB-T Init: can't find frontend 2.\n", __FUNCTION__); + } + break; case CX88_BOARD_HAUPPAUGE_HVR4000LITE: - /* Support for DVB-S only, not DVB-T support */ - dev->dvb.frontend = dvb_attach(cx24116_attach, + fe0->dvb.frontend = dvb_attach(cx24116_attach, &hauppauge_hvr4000_config, &dev->core->i2c_adap); - if (dev->dvb.frontend) { - dvb_attach(isl6421_attach, dev->dvb.frontend, + if (fe0->dvb.frontend) { + dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00); } break; case CX88_BOARD_TEVII_S420: - dev->dvb.frontend = dvb_attach(stv0299_attach, + fe0->dvb.frontend = dvb_attach(stv0299_attach, &tevii_tuner_sharp_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, &core->i2c_adap, DVB_PLL_OPERA1)) goto frontend_detach; - core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; - dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; } else { - dev->dvb.frontend = dvb_attach(stv0288_attach, + fe0->dvb.frontend = dvb_attach(stv0288_attach, &tevii_tuner_earda_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(stb6000_attach, dev->dvb.frontend, 0x61, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61, &core->i2c_adap)) goto frontend_detach; - core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; - dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; } } break; case CX88_BOARD_TEVII_S460: - dev->dvb.frontend = dvb_attach(cx24116_attach, + fe0->dvb.frontend = dvb_attach(cx24116_attach, &tevii_s460_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; - dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + if (fe0->dvb.frontend != NULL) { + core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; } break; case CX88_BOARD_OMICOM_SS4_PCI: case CX88_BOARD_TBS_8920: case CX88_BOARD_PROF_7300: - dev->dvb.frontend = dvb_attach(cx24116_attach, + fe0->dvb.frontend = dvb_attach(cx24116_attach, &hauppauge_hvr4000_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; - dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + if (fe0->dvb.frontend != NULL) { + core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; } break; default: @@ -1000,29 +1094,32 @@ static int dvb_register(struct cx8802_dev *dev) core->name); break; } - if (NULL == dev->dvb.frontend) { + + if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) { printk(KERN_ERR "%s/2: frontend initialization failed\n", core->name); return -EINVAL; } /* define general-purpose callback pointer */ - dev->dvb.frontend->callback = cx88_tuner_callback; + fe0->dvb.frontend->callback = cx88_tuner_callback; /* Ensure all frontends negotiate bus access */ - dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; + fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; + if (fe1) + fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; /* Put the analog decoder in standby to keep it quiet */ cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL); /* register everything */ - return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, - &dev->pci->dev, adapter_nr); + return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, + &dev->pci->dev, adapter_nr, mfe_shared); frontend_detach: - if (dev->dvb.frontend) { - dvb_frontend_detach(dev->dvb.frontend); - dev->dvb.frontend = NULL; + if (fe0->dvb.frontend) { + dvb_frontend_detach(fe0->dvb.frontend); + fe0->dvb.frontend = NULL; } return -EINVAL; } @@ -1046,6 +1143,38 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) cx_clear(MO_GP0_IO, 0x00000004); udelay(1000); break; + + case CX88_BOARD_HAUPPAUGE_HVR3000: + case CX88_BOARD_HAUPPAUGE_HVR4000: + if(core->dvbdev->frontends.active_fe_id == 1) { + /* DVB-S/S2 Enabled */ + + /* Toggle reset on cx22702 leaving i2c active */ + cx_write(MO_GP0_IO, (core->board.input[0].gpio0 & 0x0000ff00) | 0x00000080); + udelay(1000); + cx_clear(MO_GP0_IO, 0x00000080); + udelay(50); + cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset */ + cx_set(MO_GP0_IO, 0x00000004); /* tri-state the cx22702 pins */ + udelay(1000); + + cx_write(MO_SRST_IO, 1); /* Take the cx24116/cx24123 out of reset */ + core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */ + } else + if (core->dvbdev->frontends.active_fe_id == 2) { + /* DVB-T Enabled */ + + /* Put the cx24116/cx24123 into reset */ + cx_write(MO_SRST_IO, 0); + + /* cx22702 out of reset and enable it */ + cx_set(MO_GP0_IO, 0x00000080); + cx_clear(MO_GP0_IO, 0x00000004); + core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */ + udelay(1000); + } + break; + default: err = -ENODEV; } @@ -1066,6 +1195,9 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv) cx_set(MO_GP0_IO, 0x00000004); #endif break; + case CX88_BOARD_HAUPPAUGE_HVR3000: + case CX88_BOARD_HAUPPAUGE_HVR4000: + break; default: err = -ENODEV; } @@ -1076,7 +1208,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; struct cx8802_dev *dev = drv->core->dvbdev; - int err; + int err, i; + struct videobuf_dvb_frontend *fe; dprintk( 1, "%s\n", __func__); dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", @@ -1096,18 +1229,28 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) /* dvb stuff */ printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); - videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops, + dev->ts_gen_cntrl = 0x0c; + + for (i = 1; i <= core->board.num_frontends; i++) { + fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i); + if (!fe) { + printk(KERN_ERR "%s() failed to get frontend(%d)\n", __FUNCTION__, i); + continue; + } + videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops, &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx88_buffer), dev); + /* init struct videobuf_dvb */ + fe->dvb.name = dev->core->name; + } err = dvb_register(dev); if (err != 0) printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n", core->name, err); - - fail_core: +fail_core: return err; } @@ -1115,9 +1258,7 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv) { struct cx8802_dev *dev = drv->core->dvbdev; - /* dvb */ - if (dev->dvb.frontend) - videobuf_dvb_unregister(&dev->dvb); + videobuf_dvb_unregister_bus(&dev->frontends); vp3054_i2c_remove(dev); diff --git a/linux/drivers/media/video/cx88/cx88-i2c.c b/linux/drivers/media/video/cx88/cx88-i2c.c index 8e74d64fd..01de23007 100644 --- a/linux/drivers/media/video/cx88/cx88-i2c.c +++ b/linux/drivers/media/video/cx88/cx88-i2c.c @@ -116,18 +116,25 @@ static int detach_inform(struct i2c_client *client) void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) { + struct videobuf_dvb_frontends *f = &core->dvbdev->frontends; + struct videobuf_dvb_frontend *fe = NULL; if (0 != core->i2c_rc) return; #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) - if ( (core->dvbdev) && (core->dvbdev->dvb.frontend) ) { - if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) - core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1); + if (core->dvbdev && f) { + if(f->gate <= 1) /* undefined or fe0 */ + fe = videobuf_dvb_get_frontend(f, 1); + else + fe = videobuf_dvb_get_frontend(f, f->gate); + + if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) + fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, 1); i2c_clients_command(&core->i2c_adap, cmd, arg); - if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) - core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0); + if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) + fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, 0); } else #endif i2c_clients_command(&core->i2c_adap, cmd, arg); diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c index 4af6604ec..88c237790 100644 --- a/linux/drivers/media/video/cx88/cx88-mpeg.c +++ b/linux/drivers/media/video/cx88/cx88-mpeg.c @@ -808,7 +808,8 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, { struct cx8802_dev *dev; struct cx88_core *core; - int err; + struct videobuf_dvb_frontend *demod; + int err,i; /* general setup */ core = cx88_core_get(pci_dev); @@ -821,6 +822,11 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, if (!core->board.mpeg) goto fail_core; + if (!core->board.num_frontends) { + printk(KERN_ERR "%s() .num_frontends should be non-zero, err = %d\n", __FUNCTION__, err); + goto fail_core; + } + err = -ENOMEM; dev = kzalloc(sizeof(*dev),GFP_KERNEL); if (NULL == dev) @@ -835,6 +841,20 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, INIT_LIST_HEAD(&dev->drvlist); list_add_tail(&dev->devlist,&cx8802_devlist); + mutex_init(&dev->frontends.lock); + INIT_LIST_HEAD(&dev->frontends.frontend.felist); + + printk(KERN_INFO "%s() allocating %d frontend(s)\n", __FUNCTION__, core->board.num_frontends); + + for (i = 1; i <= core->board.num_frontends; i++) { + demod = videobuf_dvb_alloc_frontend(dev, &dev->frontends, i); + if(demod == NULL) { + printk(KERN_ERR "%s() failed to alloc\n", __FUNCTION__); + err = -ENOMEM; + goto fail_free; + } + } + /* Maintain a reference so cx88-video can query the 8802 device. */ core->dvbdev = dev; diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h index 778e1f707..774c0b9b1 100644 --- a/linux/drivers/media/video/cx88/cx88.h +++ b/linux/drivers/media/video/cx88/cx88.h @@ -248,7 +248,7 @@ struct cx88_input { enum cx88_itype type; u32 gpio0, gpio1, gpio2, gpio3; unsigned int vmux:2; - unsigned int audioroute:2; + unsigned int audioroute:4; }; struct cx88_board { @@ -262,6 +262,7 @@ struct cx88_board { struct cx88_input radio; enum cx88_board_type mpeg; unsigned int audio_chip; + int num_frontends; }; struct cx88_subid { @@ -360,6 +361,7 @@ struct cx88_core { struct cx8802_dev *dvbdev; enum cx88_board_type active_type_id; int active_ref; + int active_fe_id; }; struct cx8800_dev; @@ -511,7 +513,7 @@ struct cx8802_dev { #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) /* for dvb only */ - struct videobuf_dvb dvb; + struct videobuf_dvb_frontends frontends; #endif #if defined(CONFIG_VIDEO_CX88_VP3054) || \ diff --git a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h index c786d7d3d..1a37ae4bc 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_bridge.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_bridge.h @@ -1,7 +1,7 @@ /* * USB Driver for ALi m5602 based webcams * - * Copyright (C) 2008 Erik Andren + * Copyright (C) 2008 Erik Andrén * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> * @@ -25,33 +25,6 @@ /*****************************************************************************/ -#undef PDEBUG -#undef info -#undef err - -#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \ - format "\n" , ## arg) -#define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \ - format "\n" , ## arg) - -/* Debug parameters */ -#define DBG_INIT 0x1 -#define DBG_PROBE 0x2 -#define DBG_V4L2 0x4 -#define DBG_TRACE 0x8 -#define DBG_DATA 0x10 -#define DBG_V4L2_CID 0x20 -#define DBG_GSPCA 0x40 - -#define PDEBUG(level, fmt, args...) \ - do { \ - if (m5602_debug & level) \ - info("[%s:%d] " fmt, __func__, __LINE__ , \ - ## args); \ - } while (0) - -/*****************************************************************************/ - #define M5602_XB_SENSOR_TYPE 0x00 #define M5602_XB_SENSOR_CTRL 0x01 #define M5602_XB_LINE_OF_FRAME_H 0x02 diff --git a/linux/drivers/media/video/gspca/m5602/m5602_core.c b/linux/drivers/media/video/gspca/m5602/m5602_core.c index 19d5e351c..fd6ce384b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_core.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_core.c @@ -1,7 +1,7 @@ -/* + /* * USB Driver for ALi m5602 based webcams * - * Copyright (C) 2008 Erik Andren + * Copyright (C) 2008 Erik Andrén * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> * @@ -26,7 +26,6 @@ int force_sensor; int dump_bridge; int dump_sensor; -unsigned int m5602_debug; static const __devinitdata struct usb_device_id m5602_table[] = { {USB_DEVICE(0x0402, 0x5602)}, @@ -48,7 +47,7 @@ int m5602_read_bridge(struct sd *sd, u8 address, u8 *i2c_data) 1, M5602_URB_MSG_TIMEOUT); *i2c_data = buf[0]; - PDEBUG(DBG_TRACE, "Reading bridge register 0x%x containing 0x%x", + PDEBUG(D_CONF, "Reading bridge register 0x%x containing 0x%x", address, *i2c_data); /* usb_control_msg(...) returns the number of bytes sent upon success, @@ -63,7 +62,7 @@ int m5602_write_bridge(struct sd *sd, u8 address, u8 i2c_data) struct usb_device *udev = sd->gspca_dev.dev; __u8 *buf = sd->gspca_dev.usb_buf; - PDEBUG(DBG_TRACE, "Writing bridge register 0x%x with 0x%x", + PDEBUG(D_CONF, "Writing bridge register 0x%x with 0x%x", address, i2c_data); memcpy(buf, bridge_urb_skeleton, @@ -91,7 +90,8 @@ static void m5602_dump_bridge(struct sd *sd) m5602_read_bridge(sd, i, &val); info("ALi m5602 address 0x%x contains 0x%x", i, val); } - info("Warning: The camera probably won't work until it's power cycled"); + info("Warning: The ALi m5602 webcam probably won't work " + "until it's power cycled"); } static int m5602_probe_sensor(struct sd *sd) @@ -135,7 +135,7 @@ static int m5602_init(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int err; - PDEBUG(DBG_TRACE, "Initializing ALi m5602 webcam"); + PDEBUG(D_CONF, "Initializing ALi m5602 webcam"); /* Run the init sequence */ err = sd->sensor->init(sd); @@ -146,16 +146,18 @@ static int m5602_start_transfer(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; __u8 *buf = sd->gspca_dev.usb_buf; + int err; /* Send start command to the camera */ const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01}; memcpy(buf, buffer, sizeof(buffer)); - usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), - 0x04, 0x40, 0x19, 0x0000, buf, - 4, M5602_URB_MSG_TIMEOUT); + err = usb_control_msg(gspca_dev->dev, + usb_sndctrlpipe(gspca_dev->dev, 0), + 0x04, 0x40, 0x19, 0x0000, buf, + 4, M5602_URB_MSG_TIMEOUT); - PDEBUG(DBG_V4L2, "Transfer started"); - return 0; + PDEBUG(D_STREAM, "Transfer started"); + return (err < 0) ? err : 0; } static void m5602_urb_complete(struct gspca_dev *gspca_dev, @@ -165,14 +167,14 @@ static void m5602_urb_complete(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; if (len < 6) { - PDEBUG(DBG_DATA, "Packet is less than 6 bytes"); + PDEBUG(D_PACK, "Packet is less than 6 bytes"); return; } /* Frame delimiter: ff xx xx xx ff ff */ if (data[0] == 0xff && data[4] == 0xff && data[5] == 0xff && data[2] != sd->frame_id) { - PDEBUG(DBG_DATA, "Frame delimiter detected"); + PDEBUG(D_FRAM, "Frame delimiter detected"); sd->frame_id = data[2]; /* Remove the extra fluff appended on each header */ @@ -187,7 +189,7 @@ static void m5602_urb_complete(struct gspca_dev *gspca_dev, /* Create a new frame */ gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len); - PDEBUG(DBG_V4L2, "Starting new frame %d", + PDEBUG(D_FRAM, "Starting new frame %d", sd->frame_count); } else { @@ -198,7 +200,7 @@ static void m5602_urb_complete(struct gspca_dev *gspca_dev, len -= 4; if (cur_frame_len + len <= frame->v4l2_buf.length) { - PDEBUG(DBG_DATA, "Continuing frame %d copying %d bytes", + PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes", sd->frame_count, len); gspca_frame_add(gspca_dev, INTER_PACKET, frame, @@ -234,8 +236,6 @@ static int m5602_configure(struct gspca_dev *gspca_dev, struct cam *cam; int err; - PDEBUG(DBG_GSPCA, "m5602_configure start"); - cam = &gspca_dev->cam; cam->epaddr = M5602_ISOC_ENDPOINT_ADDR; sd->desc = &sd_desc; @@ -248,11 +248,10 @@ static int m5602_configure(struct gspca_dev *gspca_dev, if (err) goto fail; - PDEBUG(DBG_GSPCA, "m5602_configure end"); return 0; fail: - PDEBUG(DBG_GSPCA, "m5602_configure failed"); + PDEBUG(D_ERR, "ALi m5602 webcam failed"); cam->cam_mode = NULL; cam->nmodes = 0; @@ -282,13 +281,13 @@ static int __init mod_m5602_init(void) { if (usb_register(&sd_driver) < 0) return -1; - PDEBUG(D_PROBE, "m5602 module registered"); + PDEBUG(D_PROBE, "registered"); return 0; } static void __exit mod_m5602_exit(void) { usb_deregister(&sd_driver); - PDEBUG(D_PROBE, "m5602 module deregistered"); + PDEBUG(D_PROBE, "deregistered"); } module_init(mod_m5602_init); @@ -297,9 +296,6 @@ module_exit(mod_m5602_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param_named(debug, m5602_debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "toggles debug on/off"); - module_param(force_sensor, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(force_sensor, "force detection of sensor, " diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 566d4925a..fb700c2d0 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.c @@ -1,7 +1,7 @@ /* * Driver for the mt9m111 sensor * - * Copyright (C) 2008 Erik Andren + * Copyright (C) 2008 Erik Andrén * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> * @@ -107,7 +107,7 @@ int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); *val = data[0] & MT9M111_RMB_MIRROR_ROWS; - PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val); + PDEBUG(D_V4L2, "Read vertical flip %d", *val); return (err < 0) ? err : 0; } @@ -118,7 +118,7 @@ int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val) u8 data[2] = {0x00, 0x00}; struct sd *sd = (struct sd *) gspca_dev; - PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val); + PDEBUG(D_V4L2, "Set vertical flip to %d", val); /* Set the correct page map */ err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); @@ -145,7 +145,7 @@ int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2); *val = data[0] & MT9M111_RMB_MIRROR_COLS; - PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val); + PDEBUG(D_V4L2, "Read horizontal flip %d", *val); return (err < 0) ? err : 0; } @@ -156,7 +156,7 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val) u8 data[2] = {0x00, 0x00}; struct sd *sd = (struct sd *) gspca_dev; - PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val); + PDEBUG(D_V4L2, "Set horizontal flip to %d", val); /* Set the correct page map */ err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2); @@ -188,7 +188,7 @@ int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val) ((tmp & (1 << 8)) * 2) | (tmp & 0x7f); - PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); + PDEBUG(D_V4L2, "Read gain %d", *val); return (err < 0) ? err : 0; } @@ -222,7 +222,7 @@ int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val) data[1] = (tmp & 0xff00) >> 8; data[0] = (tmp & 0xff); - PDEBUG(DBG_V4L2_CID, "tmp=%d, data[1]=%d, data[0]=%d", tmp, + PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp, data[1], data[0]); err = mt9m111_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN, @@ -257,7 +257,7 @@ int mt9m111_read_sensor(struct sd *sd, const u8 address, for (i = 0; i < len && !err; i++) { err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); - PDEBUG(DBG_TRACE, "Reading sensor register " + PDEBUG(D_CONF, "Reading sensor register " "0x%x contains 0x%x ", address, *i2c_data); } out: @@ -290,7 +290,7 @@ int mt9m111_write_sensor(struct sd *sd, const u8 address, memcpy(p, sensor_urb_skeleton + 16, 4); p[3] = i2c_data[i]; p += 4; - PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", + PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x", address, i2c_data[i]); } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h index 79a5d8878..07d224d01 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_mt9m111.h @@ -1,7 +1,7 @@ /* * Driver for the mt9m111 sensor * - * Copyright (C) 2008 Erik Andren + * Copyright (C) 2008 Erik Andrén * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> * @@ -82,7 +82,6 @@ /* Kernel module parameters */ extern int force_sensor; extern int dump_sensor; -extern unsigned int m5602_debug; int mt9m111_probe(struct sd *sd); int mt9m111_init(struct sd *sd); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c index 31c589625..837c7e476 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.c @@ -1,7 +1,7 @@ /* * Driver for the ov9650 sensor * - * Copyright (C) 2008 Erik Andren + * Copyright (C) 2008 Erik Andrén * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> * @@ -40,7 +40,7 @@ int ov9650_read_sensor(struct sd *sd, const u8 address, for (i = 0; i < len; i++) { err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); - PDEBUG(DBG_TRACE, "Reading sensor register " + PDEBUG(D_CONF, "Reading sensor register " "0x%x containing 0x%x ", address, *i2c_data); } return (err < 0) ? err : 0; @@ -72,7 +72,7 @@ int ov9650_write_sensor(struct sd *sd, const u8 address, memcpy(p, sensor_urb_skeleton + 16, 4); p[3] = i2c_data[i]; p += 4; - PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", + PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x", address, i2c_data[i]); } @@ -199,7 +199,7 @@ int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) goto out; *val |= (i2c_data & 0x3f) << 10; - PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val); + PDEBUG(D_V4L2, "Read exposure %d", *val); out: return (err < 0) ? err : 0; } @@ -210,7 +210,7 @@ int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val) u8 i2c_data; int err; - PDEBUG(DBG_V4L2_CID, "Set exposure to %d", + PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff); /* The 6 MSBs */ @@ -246,7 +246,7 @@ int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val) err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); *val |= i2c_data; - PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); + PDEBUG(D_V4L2, "Read gain %d", *val); return (err < 0) ? err : 0; } @@ -280,7 +280,7 @@ int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) err = ov9650_read_sensor(sd, OV9650_RED, &i2c_data, 1); *val = i2c_data; - PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val); + PDEBUG(D_V4L2, "Read red gain %d", *val); return (err < 0) ? err : 0; } @@ -291,7 +291,7 @@ int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - PDEBUG(DBG_V4L2_CID, "Set red gain to %d", + PDEBUG(D_V4L2, "Set red gain to %d", val & 0xff); i2c_data = val & 0xff; @@ -309,7 +309,7 @@ int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) err = ov9650_read_sensor(sd, OV9650_BLUE, &i2c_data, 1); *val = i2c_data; - PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val); + PDEBUG(D_V4L2, "Read blue gain %d", *val); return (err < 0) ? err : 0; } @@ -320,7 +320,7 @@ int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - PDEBUG(DBG_V4L2_CID, "Set blue gain to %d", + PDEBUG(D_V4L2, "Set blue gain to %d", val & 0xff); i2c_data = val & 0xff; @@ -340,7 +340,7 @@ int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) *val = ((i2c_data & OV9650_HFLIP) >> 5) ? 0 : 1; else *val = (i2c_data & OV9650_HFLIP) >> 5; - PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val); + PDEBUG(D_V4L2, "Read horizontal flip %d", *val); return (err < 0) ? err : 0; } @@ -351,7 +351,7 @@ int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", val); + PDEBUG(D_V4L2, "Set horizontal flip to %d", val); err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); if (err < 0) goto out; @@ -379,7 +379,7 @@ int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) *val = ((i2c_data & 0x10) >> 4) ? 0 : 1; else *val = (i2c_data & 0x10) >> 4; - PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val); + PDEBUG(D_V4L2, "Read vertical flip %d", *val); return (err < 0) ? err : 0; } @@ -390,7 +390,7 @@ int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val); + PDEBUG(D_V4L2, "Set vertical flip to %d", val); err = ov9650_read_sensor(sd, OV9650_MVFP, &i2c_data, 1); if (err < 0) goto out; @@ -420,7 +420,7 @@ int ov9650_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) err = ov9650_read_sensor(sd, OV9650_GAIN, &i2c_data, 1); *val |= i2c_data; - PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); + PDEBUG(D_V4L2, "Read gain %d", *val); out: return (err < 0) ? err : 0; } @@ -431,7 +431,7 @@ int ov9650_set_brightness(struct gspca_dev *gspca_dev, __s32 val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - PDEBUG(DBG_V4L2_CID, "Set gain to %d", val & 0x3ff); + PDEBUG(D_V4L2, "Set gain to %d", val & 0x3ff); /* Read the OV9650_VREF register first to avoid corrupting the VREF high and low bits */ @@ -461,7 +461,7 @@ int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev, __s32 *val) err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); *val = (i2c_data & OV9650_AWB_EN) >> 1; - PDEBUG(DBG_V4L2_CID, "Read auto white balance %d", *val); + PDEBUG(D_V4L2, "Read auto white balance %d", *val); return (err < 0) ? err : 0; } @@ -472,7 +472,7 @@ int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev, __s32 val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - PDEBUG(DBG_V4L2_CID, "Set auto white balance to %d", val); + PDEBUG(D_V4L2, "Set auto white balance to %d", val); err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); if (err < 0) goto out; @@ -491,7 +491,7 @@ int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val) err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); *val = (i2c_data & OV9650_AGC_EN) >> 2; - PDEBUG(DBG_V4L2_CID, "Read auto gain control %d", *val); + PDEBUG(D_V4L2, "Read auto gain control %d", *val); return (err < 0) ? err : 0; } @@ -502,7 +502,7 @@ int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val) u8 i2c_data; struct sd *sd = (struct sd *) gspca_dev; - PDEBUG(DBG_V4L2_CID, "Set auto gain control to %d", val); + PDEBUG(D_V4L2, "Set auto gain control to %d", val); err = ov9650_read_sensor(sd, OV9650_COM8, &i2c_data, 1); if (err < 0) goto out; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h index fb21e7ffb..e8ede47ce 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_ov9650.h @@ -1,7 +1,7 @@ /* * Driver for the ov9650 sensor * - * Copyright (C) 2008 Erik Andren + * Copyright (C) 2008 Erik Andrén * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> * @@ -121,7 +121,6 @@ /* Kernel module parameters */ extern int force_sensor; extern int dump_sensor; -extern unsigned int m5602_debug; int ov9650_probe(struct sd *sd); int ov9650_init(struct sd *sd); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c index 08c015bde..d17ac5256 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.c @@ -1,7 +1,7 @@ /* * Driver for the po1030 sensor * - * Copyright (c) 2008 Erik Andren + * Copyright (c) 2008 Erik Andrén * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> * @@ -82,7 +82,7 @@ int po1030_read_sensor(struct sd *sd, const u8 address, for (i = 0; i < len; i++) { err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); - PDEBUG(DBG_TRACE, "Reading sensor register " + PDEBUG(D_CONF, "Reading sensor register " "0x%x containing 0x%x ", address, *i2c_data); } return (err < 0) ? err : 0; @@ -112,7 +112,7 @@ int po1030_write_sensor(struct sd *sd, const u8 address, memcpy(p, sensor_urb_skeleton + 16, 4); p[3] = i2c_data[i]; p += 4; - PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", + PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x", address, i2c_data[i]); } @@ -185,7 +185,7 @@ int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) &i2c_data, 1); *val |= i2c_data; - PDEBUG(DBG_V4L2_CID, "Exposure read as %d", *val); + PDEBUG(D_V4L2, "Exposure read as %d", *val); out: return (err < 0) ? err : 0; } @@ -196,10 +196,10 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) u8 i2c_data; int err; - PDEBUG(DBG_V4L2, "Set exposure to %d", val & 0xffff); + PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff); i2c_data = ((val & 0xff00) >> 8); - PDEBUG(DBG_V4L2, "Set exposure to high byte to 0x%x", + PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x", i2c_data); err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_H, @@ -208,7 +208,7 @@ int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val) goto out; i2c_data = (val & 0xff); - PDEBUG(DBG_V4L2, "Set exposure to low byte to 0x%x", + PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x", i2c_data); err = po1030_write_sensor(sd, PO1030_REG_INTEGLINES_M, &i2c_data, 1); @@ -226,7 +226,71 @@ int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val) err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN, &i2c_data, 1); *val = i2c_data; - PDEBUG(DBG_V4L2_CID, "Read global gain %d", *val); + PDEBUG(D_V4L2, "Read global gain %d", *val); + + return (err < 0) ? err : 0; +} + +int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + + err = po1030_read_sensor(sd, PO1030_REG_CONTROL2, + &i2c_data, 1); + + *val = (i2c_data >> 7) & 0x01 ; + + PDEBUG(D_V4L2, "Read hflip %d", *val); + + return (err < 0) ? err : 0; +} + +int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + + PDEBUG(D_V4L2, "Set hflip %d", val); + + i2c_data = (val & 0x01) << 7; + + err = po1030_write_sensor(sd, PO1030_REG_CONTROL2, + &i2c_data, 1); + + return (err < 0) ? err : 0; +} + +int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + + err = po1030_read_sensor(sd, PO1030_REG_GLOBALGAIN, + &i2c_data, 1); + + *val = (i2c_data >> 6) & 0x01; + + PDEBUG(D_V4L2, "Read vflip %d", *val); + + return (err < 0) ? err : 0; +} + +int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + u8 i2c_data; + int err; + + PDEBUG(D_V4L2, "Set vflip %d", val); + + i2c_data = (val & 0x01) << 6; + + err = po1030_write_sensor(sd, PO1030_REG_CONTROL2, + &i2c_data, 1); return (err < 0) ? err : 0; } @@ -238,7 +302,7 @@ int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val) int err; i2c_data = val & 0xff; - PDEBUG(DBG_V4L2, "Set global gain to %d", i2c_data); + PDEBUG(D_V4L2, "Set global gain to %d", i2c_data); err = po1030_write_sensor(sd, PO1030_REG_GLOBALGAIN, &i2c_data, 1); return (err < 0) ? err : 0; @@ -253,7 +317,7 @@ int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val) err = po1030_read_sensor(sd, PO1030_REG_RED_GAIN, &i2c_data, 1); *val = i2c_data; - PDEBUG(DBG_V4L2_CID, "Read red gain %d", *val); + PDEBUG(D_V4L2, "Read red gain %d", *val); return (err < 0) ? err : 0; } @@ -264,7 +328,7 @@ int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val) int err; i2c_data = val & 0xff; - PDEBUG(DBG_V4L2, "Set red gain to %d", i2c_data); + PDEBUG(D_V4L2, "Set red gain to %d", i2c_data); err = po1030_write_sensor(sd, PO1030_REG_RED_GAIN, &i2c_data, 1); return (err < 0) ? err : 0; @@ -279,7 +343,7 @@ int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val) err = po1030_read_sensor(sd, PO1030_REG_BLUE_GAIN, &i2c_data, 1); *val = i2c_data; - PDEBUG(DBG_V4L2_CID, "Read blue gain %d", *val); + PDEBUG(D_V4L2, "Read blue gain %d", *val); return (err < 0) ? err : 0; } @@ -290,7 +354,7 @@ int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val) u8 i2c_data; int err; i2c_data = val & 0xff; - PDEBUG(DBG_V4L2, "Set blue gain to %d", i2c_data); + PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data); err = po1030_write_sensor(sd, PO1030_REG_BLUE_GAIN, &i2c_data, 1); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h index 68f34c97b..a0b75ff61 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_po1030.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_po1030.h @@ -1,8 +1,7 @@ /* * Driver for the po1030 sensor. - * This is probably a pixel plus sensor but we haven't identified it yet * - * Copyright (c) 2008 Erik Andren + * Copyright (c) 2008 Erik Andrén * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> * @@ -109,10 +108,13 @@ #define PO1030_REG_YCONTRAST 0x74 #define PO1030_REG_YSATURATION 0x75 +#define PO1030_HFLIP (1 << 7) +#define PO1030_VFLIP (1 << 6) + /*****************************************************************************/ #define PO1030_GLOBAL_GAIN_DEFAULT 0x12 -#define PO1030_EXPOSURE_DEFAULT 0xf0ff +#define PO1030_EXPOSURE_DEFAULT 0x0085 #define PO1030_BLUE_GAIN_DEFAULT 0x40 #define PO1030_RED_GAIN_DEFAULT 0x40 @@ -121,7 +123,6 @@ /* Kernel module parameters */ extern int force_sensor; extern int dump_sensor; -extern unsigned int m5602_debug; int po1030_probe(struct sd *sd); int po1030_init(struct sd *sd); @@ -142,6 +143,10 @@ int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val); int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val); int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val); int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val); +int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val); +int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val); +int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); +int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val); static struct m5602_sensor po1030 = { .name = "PO1030", @@ -152,7 +157,7 @@ static struct m5602_sensor po1030 = { .init = po1030_init, .power_down = po1030_power_down, - .nctrls = 4, + .nctrls = 6, .ctrls = { { { @@ -160,7 +165,7 @@ static struct m5602_sensor po1030 = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "gain", .minimum = 0x00, - .maximum = 0xff, + .maximum = 0x4f, .step = 0x1, .default_value = PO1030_GLOBAL_GAIN_DEFAULT, .flags = V4L2_CTRL_FLAG_SLIDER @@ -173,7 +178,7 @@ static struct m5602_sensor po1030 = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "exposure", .minimum = 0x00, - .maximum = 0xffff, + .maximum = 0x02ff, .step = 0x1, .default_value = PO1030_EXPOSURE_DEFAULT, .flags = V4L2_CTRL_FLAG_SLIDER @@ -206,8 +211,33 @@ static struct m5602_sensor po1030 = { }, .set = po1030_set_blue_balance, .get = po1030_get_blue_balance + }, { + { + .id = V4L2_CID_HFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "horizontal flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + .set = po1030_set_hflip, + .get = po1030_get_hflip + }, { + { + .id = V4L2_CID_VFLIP, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "vertical flip", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + .set = po1030_set_vflip, + .get = po1030_get_vflip } }, + .nmodes = 1, .modes = { { @@ -381,7 +411,7 @@ static const unsigned char init_po1030[][4] = /* Set the y window to 1 */ {SENSOR, PO1030_REG_WINDOWY_H, 0x00}, - {SENSOR, PO1030_REG_WINDOWX_L, 0x01}, + {SENSOR, PO1030_REG_WINDOWY_L, 0x01}, {SENSOR, PO1030_REG_WINDOWWIDTH_H, 0x02}, {SENSOR, PO1030_REG_WINDOWWIDTH_L, 0x87}, diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 682025653..14b1eac5b 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -1,7 +1,7 @@ /* * Driver for the s5k4aa sensor * - * Copyright (C) 2008 Erik Andren + * Copyright (C) 2008 Erik Andrén * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> * @@ -117,7 +117,7 @@ int s5k4aa_read_sensor(struct sd *sd, const u8 address, for (i = 0; (i < len) & !err; i++) { err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); - PDEBUG(DBG_TRACE, "Reading sensor register " + PDEBUG(D_CONF, "Reading sensor register " "0x%x containing 0x%x ", address, *i2c_data); } out: @@ -150,7 +150,7 @@ int s5k4aa_write_sensor(struct sd *sd, const u8 address, memcpy(p, sensor_urb_skeleton + 16, 4); p[3] = i2c_data[i]; p += 4; - PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", + PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x", address, i2c_data[i]); } @@ -248,7 +248,7 @@ int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) *val = data << 8; err = s5k4aa_read_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1); *val |= data; - PDEBUG(DBG_V4L2_CID, "Read exposure %d", *val); + PDEBUG(D_V4L2, "Read exposure %d", *val); out: return (err < 0) ? err : 0; } @@ -259,7 +259,7 @@ int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val) u8 data = S5K4AA_PAGE_MAP_2; int err; - PDEBUG(DBG_V4L2_CID, "Set exposure to %d", val); + PDEBUG(D_V4L2, "Set exposure to %d", val); err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) goto out; @@ -285,7 +285,7 @@ int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val) err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); *val = (data & S5K4AA_RM_V_FLIP) >> 7; - PDEBUG(DBG_V4L2_CID, "Read vertical flip %d", *val); + PDEBUG(D_V4L2, "Read vertical flip %d", *val); out: return (err < 0) ? err : 0; @@ -297,7 +297,7 @@ int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val) u8 data = S5K4AA_PAGE_MAP_2; int err; - PDEBUG(DBG_V4L2_CID, "Set vertical flip to %d", val); + PDEBUG(D_V4L2, "Set vertical flip to %d", val); err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) goto out; @@ -341,7 +341,7 @@ int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val) err = s5k4aa_read_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); *val = (data & S5K4AA_RM_H_FLIP) >> 6; - PDEBUG(DBG_V4L2_CID, "Read horizontal flip %d", *val); + PDEBUG(D_V4L2, "Read horizontal flip %d", *val); out: return (err < 0) ? err : 0; } @@ -352,7 +352,7 @@ int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val) u8 data = S5K4AA_PAGE_MAP_2; int err; - PDEBUG(DBG_V4L2_CID, "Set horizontal flip to %d", + PDEBUG(D_V4L2, "Set horizontal flip to %d", val); err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) @@ -397,7 +397,7 @@ int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val) err = s5k4aa_read_sensor(sd, S5K4AA_GAIN_2, &data, 1); *val = data; - PDEBUG(DBG_V4L2_CID, "Read gain %d", *val); + PDEBUG(D_V4L2, "Read gain %d", *val); out: return (err < 0) ? err : 0; @@ -409,7 +409,7 @@ int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val) u8 data = S5K4AA_PAGE_MAP_2; int err; - PDEBUG(DBG_V4L2_CID, "Set gain to %d", val); + PDEBUG(D_V4L2, "Set gain to %d", val); err = s5k4aa_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); if (err < 0) goto out; diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h index 48abc6c8b..87167fb92 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k4aa.h @@ -1,7 +1,7 @@ /* * Driver for the s5k4aa sensor * - * Copyright (C) 2008 Erik Andren + * Copyright (C) 2008 Erik Andrén * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> * @@ -63,7 +63,6 @@ /* Kernel module parameters */ extern int force_sensor; extern int dump_sensor; -extern unsigned int m5602_debug; int s5k4aa_probe(struct sd *sd); int s5k4aa_init(struct sd *sd); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c index b4b33c2d0..8988a728e 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.c @@ -1,7 +1,7 @@ /* * Driver for the s5k83a sensor * - * Copyright (C) 2008 Erik Andren + * Copyright (C) 2008 Erik Andrén * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> * @@ -101,7 +101,7 @@ int s5k83a_read_sensor(struct sd *sd, const u8 address, for (i = 0; i < len && !len; i++) { err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i])); - PDEBUG(DBG_TRACE, "Reading sensor register " + PDEBUG(D_CONF, "Reading sensor register " "0x%x containing 0x%x ", address, *i2c_data); } @@ -135,7 +135,7 @@ int s5k83a_write_sensor(struct sd *sd, const u8 address, memcpy(p, sensor_urb_skeleton + 16, 4); p[3] = i2c_data[i]; p += 4; - PDEBUG(DBG_TRACE, "Writing sensor register 0x%x with 0x%x", + PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x", address, i2c_data[i]); } diff --git a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h index 833708eb5..ee3ee9cfc 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_s5k83a.h @@ -1,7 +1,7 @@ /* * Driver for the s5k83a sensor * - * Copyright (C) 2008 Erik Andren + * Copyright (C) 2008 Erik Andrén * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> * @@ -41,8 +41,6 @@ /* Kernel module parameters */ extern int force_sensor; extern int dump_sensor; -extern unsigned int m5602_debug; - int s5k83a_probe(struct sd *sd); int s5k83a_init(struct sd *sd); diff --git a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h index 930fcaab4..60c9a48e0 100644 --- a/linux/drivers/media/video/gspca/m5602/m5602_sensor.h +++ b/linux/drivers/media/video/gspca/m5602/m5602_sensor.h @@ -1,7 +1,7 @@ /* * USB Driver for ALi m5602 based webcams * - * Copyright (C) 2008 Erik Andren + * Copyright (C) 2008 Erik Andrén * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project. * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br> * diff --git a/linux/drivers/media/video/ivtv/ivtv-fileops.c b/linux/drivers/media/video/ivtv/ivtv-fileops.c index b7457fc60..1c404e454 100644 --- a/linux/drivers/media/video/ivtv/ivtv-fileops.c +++ b/linux/drivers/media/video/ivtv/ivtv-fileops.c @@ -600,13 +600,14 @@ retry: since we may get here before the stream has been fully set-up */ if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) { while (count >= itv->dma_data_req_size) { - if (!ivtv_yuv_udma_stream_frame (itv, (void __user *)user_buf)) { - bytes_written += itv->dma_data_req_size; - user_buf += itv->dma_data_req_size; - count -= itv->dma_data_req_size; - } else { - break; - } + rc = ivtv_yuv_udma_stream_frame(itv, (void __user *)user_buf); + + if (rc < 0) + return rc; + + bytes_written += itv->dma_data_req_size; + user_buf += itv->dma_data_req_size; + count -= itv->dma_data_req_size; } if (count == 0) { IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused); diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index 8696527ab..208fb5484 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -509,7 +509,6 @@ static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_ static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) { struct ivtv_open_id *id = fh; - struct ivtv *itv = id->itv; s32 w = fmt->fmt.pix.width; s32 h = fmt->fmt.pix.height; int field = fmt->fmt.pix.field; @@ -517,7 +516,22 @@ static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format w = min(w, 720); w = max(w, 2); - h = min(h, itv->is_out_50hz ? 576 : 480); + /* Why can the height be 576 even when the output is NTSC? + + Internally the buffers of the PVR350 are always set to 720x576. The + decoded video frame will always be placed in the top left corner of + this buffer. For any video which is not 720x576, the buffer will + then be cropped to remove the unused right and lower areas, with + the remaining image being scaled by the hardware to fit the display + area. The video can be scaled both up and down, so a 720x480 video + can be displayed full-screen on PAL and a 720x576 video can be + displayed without cropping on NTSC. + + Note that the scaling only occurs on the video stream, the osd + resolution is locked to the broadcast standard and not scaled. + + Thanks to Ian Armstrong for this explanation. */ + h = min(h, 576); h = max(h, 2); if (id->type == IVTV_DEC_STREAM_TYPE_YUV) fmt->fmt.pix.field = field; diff --git a/linux/drivers/media/video/ks0127.c b/linux/drivers/media/video/ks0127.c index b21b6f097..16526165b 100644 --- a/linux/drivers/media/video/ks0127.c +++ b/linux/drivers/media/video/ks0127.c @@ -33,28 +33,21 @@ * V1.1 Gerard v.d. Horst Added some debugoutput, reset the video-standard */ -#ifndef __KERNEL__ -#define __KERNEL__ -#endif - #include <linux/init.h> #include <linux/module.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/proc_fs.h> -#include "ks0127.h" - #include <linux/i2c.h> #include <linux/video_decoder.h> +#include <media/v4l2-common.h> +#include <media/v4l2-i2c-drv-legacy.h> +#include "ks0127.h" #include "compat.h" -#define dprintk if (debug) printk - -/* i2c identification */ -#define I2C_KS0127_ADDON 0xD8 -#define I2C_KS0127_ONBOARD 0xDA +MODULE_DESCRIPTION("KS0127 video decoder driver"); +MODULE_AUTHOR("Ryan Drake"); +MODULE_LICENSE("GPL"); #define KS_TYPE_UNKNOWN 0 #define KS_TYPE_0122S 1 @@ -205,8 +198,6 @@ struct adjust { }; struct ks0127 { - struct i2c_client *client; - unsigned char addr; int format_width; int format_height; int cap_width; @@ -221,16 +212,18 @@ static int debug; /* insmod parameter */ module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug output"); -MODULE_LICENSE("GPL"); static u8 reg_defaults[64]; - - static void init_reg_defaults(void) { + static int initialized; u8 *table = reg_defaults; + if (initialized) + return; + initialized = 1; + table[KS_CMDA] = 0x2c; /* VSE=0, CCIR 601, autodetect standard */ table[KS_CMDB] = 0x12; /* VALIGN=0, AGC control and input */ table[KS_CMDC] = 0x00; /* Test options */ @@ -309,50 +302,53 @@ static void init_reg_defaults(void) * An explanation from kayork@mail.utexas.edu: * * During I2C reads, the KS0127 only samples for a stop condition - * during the place where the acknoledge bit should be. Any standard + * during the place where the acknowledge bit should be. Any standard * I2C implementation (correctly) throws in another clock transition * at the 9th bit, and the KS0127 will not recognize the stop condition * and will continue to clock out data. * * So we have to do the read ourself. Big deal. - workaround in i2c-algo-bit + * workaround in i2c-algo-bit */ -static u8 ks0127_read(struct ks0127 *ks, u8 reg) +static u8 ks0127_read(struct i2c_client *c, u8 reg) { - struct i2c_client *c = ks->client; char val = 0; struct i2c_msg msgs[] = { - {c->addr, 0, sizeof(reg), ®}, - {c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val}}; + { c->addr, 0, sizeof(reg), ® }, + { c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val } + }; int ret; ret = i2c_transfer(c->adapter, msgs, ARRAY_SIZE(msgs)); if (ret != ARRAY_SIZE(msgs)) - dprintk("ks0127_write error\n"); + v4l_dbg(1, debug, c, "read error\n"); return val; } -static void ks0127_write(struct ks0127 *ks, u8 reg, u8 val) +static void ks0127_write(struct i2c_client *c, u8 reg, u8 val) { - char msg[] = {reg, val}; + struct ks0127 *ks = i2c_get_clientdata(c); + char msg[] = { reg, val }; - if (i2c_master_send(ks->client, msg, sizeof(msg)) != sizeof(msg)) - dprintk("ks0127_write error\n"); + if (i2c_master_send(c, msg, sizeof(msg)) != sizeof(msg)) + v4l_dbg(1, debug, c, "write error\n"); ks->regs[reg] = val; } /* generic bit-twiddling */ -static void ks0127_and_or(struct ks0127 *ks, u8 reg, u8 and_v, u8 or_v) +static void ks0127_and_or(struct i2c_client *client, u8 reg, u8 and_v, u8 or_v) { + struct ks0127 *ks = i2c_get_clientdata(client); + u8 val = ks->regs[reg]; val = (val & and_v) | or_v; - ks0127_write(ks, reg, val); + ks0127_write(client, reg, val); } @@ -360,73 +356,69 @@ static void ks0127_and_or(struct ks0127 *ks, u8 reg, u8 and_v, u8 or_v) /**************************************************************************** * ks0127 private api ****************************************************************************/ -static void ks0127_reset(struct ks0127* ks) +static void ks0127_reset(struct i2c_client *c) { - int i; + struct ks0127 *ks = i2c_get_clientdata(c); u8 *table = reg_defaults; + int i; ks->ks_type = KS_TYPE_UNKNOWN; - dprintk("ks0127: reset\n"); + v4l_dbg(1, debug, c, "reset\n"); msleep(1); /* initialize all registers to known values */ /* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */ - for(i = 1; i < 33; i++) - ks0127_write(ks, i, table[i]); + for (i = 1; i < 33; i++) + ks0127_write(c, i, table[i]); - for(i = 35; i < 40; i++) - ks0127_write(ks, i, table[i]); + for (i = 35; i < 40; i++) + ks0127_write(c, i, table[i]); - for(i = 41; i < 56; i++) - ks0127_write(ks, i, table[i]); + for (i = 41; i < 56; i++) + ks0127_write(c, i, table[i]); - for(i = 58; i < 64; i++) - ks0127_write(ks, i, table[i]); + for (i = 58; i < 64; i++) + ks0127_write(c, i, table[i]); - if ((ks0127_read(ks, KS_STAT) & 0x80) == 0) { + if ((ks0127_read(c, KS_STAT) & 0x80) == 0) { ks->ks_type = KS_TYPE_0122S; - dprintk("ks0127: ks0122s Found\n"); + v4l_dbg(1, debug, c, "ks0122s found\n"); return; } - switch(ks0127_read(ks, KS_CMDE) & 0x0f) { - + switch (ks0127_read(c, KS_CMDE) & 0x0f) { case 0: ks->ks_type = KS_TYPE_0127; - dprintk("ks0127: ks0127 found\n"); + v4l_dbg(1, debug, c, "ks0127 found\n"); break; case 9: ks->ks_type = KS_TYPE_0127B; - dprintk("ks0127: ks0127B Revision A found\n"); + v4l_dbg(1, debug, c, "ks0127B Revision A found\n"); break; default: - dprintk("ks0127: unknown revision\n"); + v4l_dbg(1, debug, c, "unknown revision\n"); break; } } -static int ks0127_command(struct i2c_client *client, - unsigned int cmd, void *arg) +static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) { - struct ks0127 *ks = i2c_get_clientdata(client); - - int *iarg = (int*)arg; - + struct ks0127 *ks = i2c_get_clientdata(c); + int *iarg = (int *)arg; int status; if (!ks) return -ENODEV; switch (cmd) { - case DECODER_INIT: - dprintk("ks0127: command DECODER_INIT\n"); - ks0127_reset(ks); + v4l_dbg(1, debug, c, "DECODER_INIT\n"); + ks0127_reset(c); break; case DECODER_SET_INPUT: @@ -437,161 +429,160 @@ static int ks0127_command(struct i2c_client *client, case KS_INPUT_COMPOSITE_4: case KS_INPUT_COMPOSITE_5: case KS_INPUT_COMPOSITE_6: - dprintk("ks0127: command DECODER_SET_INPUT %d: " - "Composite\n", *iarg); + v4l_dbg(1, debug, c, + "DECODER_SET_INPUT %d: Composite\n", *iarg); /* autodetect 50/60 Hz */ - ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00); + ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); /* VSE=0 */ - ks0127_and_or(ks, KS_CMDA, ~0x40, 0x00); + ks0127_and_or(c, KS_CMDA, ~0x40, 0x00); /* set input line */ - ks0127_and_or(ks, KS_CMDB, 0xb0, *iarg); + ks0127_and_or(c, KS_CMDB, 0xb0, *iarg); /* non-freerunning mode */ - ks0127_and_or(ks, KS_CMDC, 0x70, 0x0a); + ks0127_and_or(c, KS_CMDC, 0x70, 0x0a); /* analog input */ - ks0127_and_or(ks, KS_CMDD, 0x03, 0x00); + ks0127_and_or(c, KS_CMDD, 0x03, 0x00); /* enable chroma demodulation */ - ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00); + ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00); /* chroma trap, HYBWR=1 */ - ks0127_and_or(ks, KS_LUMA, 0x00, + ks0127_and_or(c, KS_LUMA, 0x00, (reg_defaults[KS_LUMA])|0x0c); /* scaler fullbw, luma comb off */ - ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81); + ks0127_and_or(c, KS_VERTIA, 0x08, 0x81); /* manual chroma comb .25 .5 .25 */ - ks0127_and_or(ks, KS_VERTIC, 0x0f, 0x90); + ks0127_and_or(c, KS_VERTIC, 0x0f, 0x90); /* chroma path delay */ - ks0127_and_or(ks, KS_CHROMB, 0x0f, 0x90); + ks0127_and_or(c, KS_CHROMB, 0x0f, 0x90); - ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]); - ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]); - ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]); - ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]); + ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]); + ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]); + ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]); + ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]); break; case KS_INPUT_SVIDEO_1: case KS_INPUT_SVIDEO_2: case KS_INPUT_SVIDEO_3: - dprintk("ks0127: command DECODER_SET_INPUT %d: " - "S-Video\n", *iarg); + v4l_dbg(1, debug, c, + "DECODER_SET_INPUT %d: S-Video\n", *iarg); /* autodetect 50/60 Hz */ - ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00); + ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); /* VSE=0 */ - ks0127_and_or(ks, KS_CMDA, ~0x40, 0x00); + ks0127_and_or(c, KS_CMDA, ~0x40, 0x00); /* set input line */ - ks0127_and_or(ks, KS_CMDB, 0xb0, *iarg); + ks0127_and_or(c, KS_CMDB, 0xb0, *iarg); /* non-freerunning mode */ - ks0127_and_or(ks, KS_CMDC, 0x70, 0x0a); + ks0127_and_or(c, KS_CMDC, 0x70, 0x0a); /* analog input */ - ks0127_and_or(ks, KS_CMDD, 0x03, 0x00); + ks0127_and_or(c, KS_CMDD, 0x03, 0x00); /* enable chroma demodulation */ - ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00); - ks0127_and_or(ks, KS_LUMA, 0x00, + ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00); + ks0127_and_or(c, KS_LUMA, 0x00, reg_defaults[KS_LUMA]); /* disable luma comb */ - ks0127_and_or(ks, KS_VERTIA, 0x08, + ks0127_and_or(c, KS_VERTIA, 0x08, (reg_defaults[KS_VERTIA]&0xf0)|0x01); - ks0127_and_or(ks, KS_VERTIC, 0x0f, + ks0127_and_or(c, KS_VERTIC, 0x0f, reg_defaults[KS_VERTIC]&0xf0); - ks0127_and_or(ks, KS_CHROMB, 0x0f, + ks0127_and_or(c, KS_CHROMB, 0x0f, reg_defaults[KS_CHROMB]&0xf0); - ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]); - ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]); - ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]); - ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]); + ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]); + ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]); + ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]); + ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]); break; case KS_INPUT_YUV656: - dprintk("ks0127: command DECODER_SET_INPUT 15: " - "YUV656\n"); + v4l_dbg(1, debug, c, + "DECODER_SET_INPUT 15: YUV656\n"); if (ks->norm == VIDEO_MODE_NTSC || ks->norm == KS_STD_PAL_M) /* force 60 Hz */ - ks0127_and_or(ks, KS_CMDA, 0xfc, 0x03); + ks0127_and_or(c, KS_CMDA, 0xfc, 0x03); else /* force 50 Hz */ - ks0127_and_or(ks, KS_CMDA, 0xfc, 0x02); + ks0127_and_or(c, KS_CMDA, 0xfc, 0x02); - ks0127_and_or(ks, KS_CMDA, 0xff, 0x40); /* VSE=1 */ + ks0127_and_or(c, KS_CMDA, 0xff, 0x40); /* VSE=1 */ /* set input line and VALIGN */ - ks0127_and_or(ks, KS_CMDB, 0xb0, (*iarg | 0x40)); + ks0127_and_or(c, KS_CMDB, 0xb0, (*iarg | 0x40)); /* freerunning mode, */ /* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0 VMEM=1*/ - ks0127_and_or(ks, KS_CMDC, 0x70, 0x87); + ks0127_and_or(c, KS_CMDC, 0x70, 0x87); /* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */ - ks0127_and_or(ks, KS_CMDD, 0x03, 0x08); + ks0127_and_or(c, KS_CMDD, 0x03, 0x08); /* disable chroma demodulation */ - ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x30); + ks0127_and_or(c, KS_CTRACK, 0xcf, 0x30); /* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */ - ks0127_and_or(ks, KS_LUMA, 0x00, 0x71); - ks0127_and_or(ks, KS_VERTIC, 0x0f, + ks0127_and_or(c, KS_LUMA, 0x00, 0x71); + ks0127_and_or(c, KS_VERTIC, 0x0f, reg_defaults[KS_VERTIC]&0xf0); /* scaler fullbw, luma comb off */ - ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81); + ks0127_and_or(c, KS_VERTIA, 0x08, 0x81); - ks0127_and_or(ks, KS_CHROMB, 0x0f, + ks0127_and_or(c, KS_CHROMB, 0x0f, reg_defaults[KS_CHROMB]&0xf0); - ks0127_and_or(ks, KS_CON, 0x00, 0x00); - ks0127_and_or(ks, KS_BRT, 0x00, 32); /* spec: 34 */ + ks0127_and_or(c, KS_CON, 0x00, 0x00); + ks0127_and_or(c, KS_BRT, 0x00, 32); /* spec: 34 */ /* spec: 229 (e5) */ - ks0127_and_or(ks, KS_SAT, 0x00, 0xe8); - ks0127_and_or(ks, KS_HUE, 0x00, 0); + ks0127_and_or(c, KS_SAT, 0x00, 0xe8); + ks0127_and_or(c, KS_HUE, 0x00, 0); - ks0127_and_or(ks, KS_UGAIN, 0x00, 238); - ks0127_and_or(ks, KS_VGAIN, 0x00, 0x00); + ks0127_and_or(c, KS_UGAIN, 0x00, 238); + ks0127_and_or(c, KS_VGAIN, 0x00, 0x00); /*UOFF:0x30, VOFF:0x30, TSTCGN=1 */ - ks0127_and_or(ks, KS_UVOFFH, 0x00, 0x4f); - ks0127_and_or(ks, KS_UVOFFL, 0x00, 0x00); + ks0127_and_or(c, KS_UVOFFH, 0x00, 0x4f); + ks0127_and_or(c, KS_UVOFFL, 0x00, 0x00); break; default: - dprintk("ks0127: command DECODER_SET_INPUT: " - "Unknown input %d\n", *iarg); + v4l_dbg(1, debug, c, + "DECODER_SET_INPUT: Unknown input %d\n", *iarg); break; } /* hack: CDMLPF sometimes spontaneously switches on; */ /* force back off */ - ks0127_write(ks, KS_DEMOD, reg_defaults[KS_DEMOD]); + ks0127_write(c, KS_DEMOD, reg_defaults[KS_DEMOD]); break; case DECODER_SET_OUTPUT: switch(*iarg) { case KS_OUTPUT_YUV656E: - dprintk("ks0127: command DECODER_SET_OUTPUT: " - "OUTPUT_YUV656E (Missing)\n"); + v4l_dbg(1, debug, c, + "DECODER_SET_OUTPUT: OUTPUT_YUV656E (Missing)\n"); return -EINVAL; - break; case KS_OUTPUT_EXV: - dprintk("ks0127: command DECODER_SET_OUTPUT: " - "OUTPUT_EXV\n"); - ks0127_and_or(ks, KS_OFMTA, 0xf0, 0x09); + v4l_dbg(1, debug, c, + "DECODER_SET_OUTPUT: OUTPUT_EXV\n"); + ks0127_and_or(c, KS_OFMTA, 0xf0, 0x09); break; } break; - case DECODER_SET_NORM: //sam This block mixes old and new norm names... + case DECODER_SET_NORM: /* sam This block mixes old and new norm names... */ /* Set to automatic SECAM/Fsc mode */ - ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00); + ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00); ks->norm = *iarg; - switch(*iarg) - { + switch (*iarg) { /* this is untested !! */ /* It just detects PAL_N/NTSC_M (no special frequencies) */ /* And you have to set the standard a second time afterwards */ case VIDEO_MODE_AUTO: - dprintk("ks0127: command DECODER_SET_NORM: AUTO\n"); + v4l_dbg(1, debug, c, + "DECODER_SET_NORM: AUTO\n"); /* The chip determines the format */ /* based on the current field rate */ - ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00); - ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20); + ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); + ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); /* This is wrong for PAL ! As I said, */ /* you need to set the standard once again !! */ ks->format_height = 240; @@ -599,84 +590,86 @@ static int ks0127_command(struct i2c_client *client, break; case VIDEO_MODE_NTSC: - dprintk("ks0127: command DECODER_SET_NORM: NTSC_M\n"); - ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20); + v4l_dbg(1, debug, c, + "DECODER_SET_NORM: NTSC_M\n"); + ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); ks->format_height = 240; ks->format_width = 704; break; case KS_STD_NTSC_N: - dprintk("ks0127: command KS0127_SET_STANDARD: " - "NTSC_N (fixme)\n"); - ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40); + v4l_dbg(1, debug, c, + "KS0127_SET_NORM: NTSC_N (fixme)\n"); + ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40); ks->format_height = 240; ks->format_width = 704; break; case VIDEO_MODE_PAL: - dprintk("ks0127: command DECODER_SET_NORM: PAL_N\n"); - ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20); + v4l_dbg(1, debug, c, + "DECODER_SET_NORM: PAL_N\n"); + ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); ks->format_height = 290; ks->format_width = 704; break; case KS_STD_PAL_M: - dprintk("ks0127: command KS0127_SET_STANDARD: " - "PAL_M (fixme)\n"); - ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40); + v4l_dbg(1, debug, c, + "KS0127_SET_NORM: PAL_M (fixme)\n"); + ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40); ks->format_height = 290; ks->format_width = 704; break; case VIDEO_MODE_SECAM: - dprintk("ks0127: command KS0127_SET_STANDARD: " - "SECAM\n"); + v4l_dbg(1, debug, c, + "KS0127_SET_NORM: SECAM\n"); ks->format_height = 290; ks->format_width = 704; /* set to secam autodetection */ - ks0127_and_or(ks, KS_CHROMA, 0xdf, 0x20); - ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00); + ks0127_and_or(c, KS_CHROMA, 0xdf, 0x20); + ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00); schedule_timeout_interruptible(HZ/10+1); /* did it autodetect? */ - if (ks0127_read(ks, KS_DEMOD) & 0x40) + if (ks0127_read(c, KS_DEMOD) & 0x40) break; /* force to secam mode */ - ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x0f); + ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f); break; default: - dprintk("ks0127: command DECODER_SET_NORM: " - "Unknown norm %d\n", *iarg); + v4l_dbg(1, debug, c, + "DECODER_SET_NORM: Unknown norm %d\n", *iarg); break; } break; case DECODER_SET_PICTURE: - dprintk("ks0127: command DECODER_SET_PICTURE " - "not yet supported (fixme)\n"); + v4l_dbg(1, debug, c, + "DECODER_SET_PICTURE: not yet supported\n"); return -EINVAL; - //sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE - //sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE - //sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE? - //sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE - //sam todo: KS0127_SET_AGC_MODE: - //sam todo: KS0127_SET_AGC: - //sam todo: KS0127_SET_CHROMA_MODE: - //sam todo: KS0127_SET_PIXCLK_MODE: - //sam todo: KS0127_SET_GAMMA_MODE: - //sam todo: KS0127_SET_UGAIN: - //sam todo: KS0127_SET_VGAIN: - //sam todo: KS0127_SET_INVALY: - //sam todo: KS0127_SET_INVALU: - //sam todo: KS0127_SET_INVALV: - //sam todo: KS0127_SET_UNUSEY: - //sam todo: KS0127_SET_UNUSEU: - //sam todo: KS0127_SET_UNUSEV: - //sam todo: KS0127_SET_VSALIGN_MODE: + /* sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE */ + /* sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE */ + /* sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE? */ + /* sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE */ + /* sam todo: KS0127_SET_AGC_MODE: */ + /* sam todo: KS0127_SET_AGC: */ + /* sam todo: KS0127_SET_CHROMA_MODE: */ + /* sam todo: KS0127_SET_PIXCLK_MODE: */ + /* sam todo: KS0127_SET_GAMMA_MODE: */ + /* sam todo: KS0127_SET_UGAIN: */ + /* sam todo: KS0127_SET_VGAIN: */ + /* sam todo: KS0127_SET_INVALY: */ + /* sam todo: KS0127_SET_INVALU: */ + /* sam todo: KS0127_SET_INVALV: */ + /* sam todo: KS0127_SET_UNUSEY: */ + /* sam todo: KS0127_SET_UNUSEU: */ + /* sam todo: KS0127_SET_UNUSEV: */ + /* sam todo: KS0127_SET_VSALIGN_MODE: */ case DECODER_ENABLE_OUTPUT: { @@ -685,34 +678,32 @@ static int ks0127_command(struct i2c_client *client, iarg = arg; enable = (*iarg != 0); if (enable) { - dprintk("ks0127: command " - "DECODER_ENABLE_OUTPUT on " - "(%d)\n", enable); + v4l_dbg(1, debug, c, + "DECODER_ENABLE_OUTPUT on\n"); /* All output pins on */ - ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30); + ks0127_and_or(c, KS_OFMTA, 0xcf, 0x30); /* Obey the OEN pin */ - ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00); + ks0127_and_or(c, KS_CDEM, 0x7f, 0x00); } else { - dprintk("ks0127: command " - "DECODER_ENABLE_OUTPUT off " - "(%d)\n", enable); + v4l_dbg(1, debug, c, + "DECODER_ENABLE_OUTPUT off\n"); /* Video output pins off */ - ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00); + ks0127_and_or(c, KS_OFMTA, 0xcf, 0x00); /* Ignore the OEN pin */ - ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80); + ks0127_and_or(c, KS_CDEM, 0x7f, 0x80); } - } break; + } - //sam todo: KS0127_SET_OUTPUT_MODE: - //sam todo: KS0127_SET_WIDTH: - //sam todo: KS0127_SET_HEIGHT: - //sam todo: KS0127_SET_HSCALE: + /* sam todo: KS0127_SET_OUTPUT_MODE: */ + /* sam todo: KS0127_SET_WIDTH: */ + /* sam todo: KS0127_SET_HEIGHT: */ + /* sam todo: KS0127_SET_HSCALE: */ case DECODER_GET_STATUS: - dprintk("ks0127: command DECODER_GET_STATUS\n"); + v4l_dbg(1, debug, c, "DECODER_GET_STATUS\n"); *iarg = 0; - status = ks0127_read(ks, KS_STAT); + status = ks0127_read(c, KS_STAT); if (!(status & 0x20)) /* NOVID not set */ *iarg = (*iarg | DECODER_STATUS_GOOD); if ((status & 0x01)) /* CLOCK set */ @@ -723,124 +714,85 @@ static int ks0127_command(struct i2c_client *client, *iarg = (*iarg | DECODER_STATUS_NTSC); break; - //Catch any unknown command + /* Catch any unknown command */ default: - dprintk("ks0127: command unknown: %04X\n", cmd); + v4l_dbg(1, debug, c, "unknown: 0x%08x\n", cmd); return -EINVAL; } return 0; } - - -static int ks0127_probe(struct i2c_adapter *adapter); -static int ks0127_detach(struct i2c_client *client); -static int ks0127_command(struct i2c_client *client, - unsigned int cmd, void *arg); - - - /* Addresses to scan */ -static unsigned short normal_i2c[] = {I2C_KS0127_ADDON>>1, - I2C_KS0127_ONBOARD>>1, I2C_CLIENT_END}; -static unsigned short probe[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; -static unsigned short ignore[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; -static struct i2c_client_address_data addr_data = { - normal_i2c, - probe, - ignore, -}; +#define I2C_KS0127_ADDON 0xD8 +#define I2C_KS0127_ONBOARD 0xDA -static struct i2c_driver i2c_driver_ks0127 = { - .driver.name = "ks0127", - .id = I2C_DRIVERID_KS0127, - .attach_adapter = ks0127_probe, - .detach_client = ks0127_detach, - .command = ks0127_command +static unsigned short normal_i2c[] = { + I2C_KS0127_ADDON >> 1, + I2C_KS0127_ONBOARD >> 1, + I2C_CLIENT_END }; -static struct i2c_client ks0127_client_tmpl = -{ - .name = "(ks0127 unset)", - .addr = 0, - .adapter = NULL, - .driver = &i2c_driver_ks0127, -}; +I2C_CLIENT_INSMOD; -static int ks0127_found_proc(struct i2c_adapter *adapter, int addr, int kind) +static int ks0127_probe(struct i2c_client *c, const struct i2c_device_id *id) { struct ks0127 *ks; - struct i2c_client *client; - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (client == NULL) - return -ENOMEM; - memcpy(client, &ks0127_client_tmpl, sizeof(*client)); + v4l_info(c, "%s chip found @ 0x%x (%s)\n", + c->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board", + c->addr << 1, c->adapter->name); ks = kzalloc(sizeof(*ks), GFP_KERNEL); - if (ks == NULL) { - kfree(client); + if (ks == NULL) return -ENOMEM; - } - i2c_set_clientdata(client, ks); - client->adapter = adapter; - client->addr = addr; - sprintf(client->name, "ks0127-%02x", adapter->id); + i2c_set_clientdata(c, ks); - ks->client = client; - ks->addr = addr; ks->ks_type = KS_TYPE_UNKNOWN; /* power up */ - ks0127_write(ks, KS_CMDA, 0x2c); + init_reg_defaults(); + ks0127_write(c, KS_CMDA, 0x2c); mdelay(10); /* reset the device */ - ks0127_reset(ks); - printk(KERN_INFO "ks0127: attach: %s video decoder\n", - ks->addr==(I2C_KS0127_ADDON>>1) ? "addon" : "on-board"); - - i2c_attach_client(client); - return 0; -} - - -static int ks0127_probe(struct i2c_adapter *adapter) -{ - if (adapter->id == I2C_HW_B_ZR36067) - return i2c_probe(adapter, &addr_data, ks0127_found_proc); + ks0127_reset(c); return 0; } -static int ks0127_detach(struct i2c_client *client) +static int ks0127_remove(struct i2c_client *c) { - struct ks0127 *ks = i2c_get_clientdata(client); + struct ks0127 *ks = i2c_get_clientdata(c); - ks0127_write(ks, KS_OFMTA, 0x20); /*tristate*/ - ks0127_write(ks, KS_CMDA, 0x2c | 0x80); /* power down */ + ks0127_write(c, KS_OFMTA, 0x20); /* tristate */ + ks0127_write(c, KS_CMDA, 0x2c | 0x80); /* power down */ - i2c_detach_client(client); kfree(ks); - kfree(client); - - dprintk("ks0127: detach\n"); return 0; } - -static int __devinit ks0127_init_module(void) -{ - init_reg_defaults(); - return i2c_add_driver(&i2c_driver_ks0127); -} - -static void __devexit ks0127_cleanup_module(void) +static int ks0127_legacy_probe(struct i2c_adapter *adapter) { - i2c_del_driver(&i2c_driver_ks0127); + return adapter->id == I2C_HW_B_ZR36067; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id ks0127_id[] = { + { "ks0127", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ks0127_id); +#endif -module_init(ks0127_init_module); -module_exit(ks0127_cleanup_module); +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "ks0127", + .driverid = I2C_DRIVERID_KS0127, + .command = ks0127_command, + .probe = ks0127_probe, + .remove = ks0127_remove, + .legacy_probe = ks0127_legacy_probe, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = ks0127_id, +#endif +}; diff --git a/linux/drivers/media/video/saa7110.c b/linux/drivers/media/video/saa7110.c index 0692e4bef..15eb8bd7a 100644 --- a/linux/drivers/media/video/saa7110.c +++ b/linux/drivers/media/video/saa7110.c @@ -31,37 +31,25 @@ #include <linux/delay.h> #include <linux/slab.h> #include <linux/wait.h> -#include <asm/io.h> #include <asm/uaccess.h> +#include <linux/i2c.h> +#include <linux/videodev.h> +#include <linux/video_decoder.h> +#include <media/v4l2-common.h> +#include <media/v4l2-i2c-drv-legacy.h> +#include "compat.h" MODULE_DESCRIPTION("Philips SAA7110 video decoder driver"); MODULE_AUTHOR("Pauline Middelink"); MODULE_LICENSE("GPL"); -#include <linux/i2c.h> - -#define I2C_NAME(s) (s)->name - -#include "compat.h" -#include <linux/videodev.h> -#include <media/v4l2-common.h> -#include <linux/video_decoder.h> - static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#define dprintk(num, format, args...) \ - do { \ - if (debug >= num) \ - printk(format, ##args); \ - } while (0) - #define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */ #define SAA7110_MAX_OUTPUT 0 /* its a decoder only */ -#define I2C_SAA7110 0x9C /* or 0x9E */ - #define SAA7110_NR_REG 0x35 struct saa7110 { @@ -82,10 +70,7 @@ struct saa7110 { /* I2C support functions */ /* ----------------------------------------------------------------------- */ -static int -saa7110_write (struct i2c_client *client, - u8 reg, - u8 value) +static int saa7110_write(struct i2c_client *client, u8 reg, u8 value) { struct saa7110 *decoder = i2c_get_clientdata(client); @@ -93,10 +78,7 @@ saa7110_write (struct i2c_client *client, return i2c_smbus_write_byte_data(client, reg, value); } -static int -saa7110_write_block (struct i2c_client *client, - const u8 *data, - unsigned int len) +static int saa7110_write_block(struct i2c_client *client, const u8 *data, unsigned int len) { int ret = -1; u8 reg = *data; /* first register to write to */ @@ -116,8 +98,8 @@ saa7110_write_block (struct i2c_client *client, memcpy(decoder->reg + reg, data + 1, len - 1); } else { for (++data, --len; len; len--) { - if ((ret = saa7110_write(client, reg++, - *data++)) < 0) + ret = saa7110_write(client, reg++, *data++); + if (ret < 0) break; } } @@ -125,8 +107,7 @@ saa7110_write_block (struct i2c_client *client, return ret; } -static inline int -saa7110_read (struct i2c_client *client) +static inline int saa7110_read(struct i2c_client *client) { return i2c_smbus_read_byte(client); } @@ -139,9 +120,7 @@ saa7110_read (struct i2c_client *client) #define FRESP_06H_SVIDEO 0x83 //0xC0 -static int -saa7110_selmux (struct i2c_client *client, - int chan) +static int saa7110_selmux(struct i2c_client *client, int chan) { static const unsigned char modes[9][8] = { /* mode 0 */ @@ -198,8 +177,7 @@ static const unsigned char initseq[1 + SAA7110_NR_REG] = { /* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02 }; -static int -determine_norm (struct i2c_client *client) +static int determine_norm(struct i2c_client *client) { DEFINE_WAIT(wait); struct saa7110 *decoder = i2c_get_clientdata(client); @@ -213,29 +191,23 @@ determine_norm (struct i2c_client *client) finish_wait(&decoder->wq, &wait); status = saa7110_read(client); if (status & 0x40) { - dprintk(1, KERN_INFO "%s: status=0x%02x (no signal)\n", - I2C_NAME(client), status); + v4l_dbg(1, debug, client, "status=0x%02x (no signal)\n", status); return decoder->norm; // no change } if ((status & 3) == 0) { saa7110_write(client, 0x06, 0x83); if (status & 0x20) { - dprintk(1, - KERN_INFO - "%s: status=0x%02x (NTSC/no color)\n", - I2C_NAME(client), status); + v4l_dbg(1, debug, client, "status=0x%02x (NTSC/no color)\n", status); //saa7110_write(client,0x2E,0x81); return VIDEO_MODE_NTSC; } - dprintk(1, KERN_INFO "%s: status=0x%02x (PAL/no color)\n", - I2C_NAME(client), status); + v4l_dbg(1, debug, client, "status=0x%02x (PAL/no color)\n", status); //saa7110_write(client,0x2E,0x9A); return VIDEO_MODE_PAL; } //saa7110_write(client,0x06,0x03); if (status & 0x20) { /* 60Hz */ - dprintk(1, KERN_INFO "%s: status=0x%02x (NTSC)\n", - I2C_NAME(client), status); + v4l_dbg(1, debug, client, "status=0x%02x (NTSC)\n", status); saa7110_write(client, 0x0D, 0x86); saa7110_write(client, 0x0F, 0x50); saa7110_write(client, 0x11, 0x2C); @@ -255,13 +227,11 @@ determine_norm (struct i2c_client *client) status = saa7110_read(client); if ((status & 0x03) == 0x01) { - dprintk(1, KERN_INFO "%s: status=0x%02x (SECAM)\n", - I2C_NAME(client), status); + v4l_dbg(1, debug, client, "status=0x%02x (SECAM)\n", status); saa7110_write(client, 0x0D, 0x87); return VIDEO_MODE_SECAM; } - dprintk(1, KERN_INFO "%s: status=0x%02x (PAL)\n", I2C_NAME(client), - status); + v4l_dbg(1, debug, client, "status=0x%02x (PAL)\n", status); return VIDEO_MODE_PAL; } @@ -287,8 +257,8 @@ saa7110_command (struct i2c_client *client, VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO; dc->inputs = SAA7110_MAX_INPUT; dc->outputs = SAA7110_MAX_OUTPUT; - } break; + } case DECODER_GET_STATUS: { @@ -296,8 +266,8 @@ saa7110_command (struct i2c_client *client, int res = 0; status = saa7110_read(client); - dprintk(1, KERN_INFO "%s: status=0x%02x norm=%d\n", - I2C_NAME(client), status, decoder->norm); + v4l_dbg(1, debug, client, "status=0x%02x norm=%d\n", + status, decoder->norm); if (!(status & 0x40)) res |= DECODER_STATUS_GOOD; if (status & 0x03) @@ -315,8 +285,8 @@ saa7110_command (struct i2c_client *client, break; } *(int *) arg = res; - } break; + } case DECODER_SET_NORM: v = *(int *) arg; @@ -329,34 +299,24 @@ saa7110_command (struct i2c_client *client, saa7110_write(client, 0x0F, 0x50); saa7110_write(client, 0x11, 0x2C); //saa7110_write(client, 0x2E, 0x81); - dprintk(1, - KERN_INFO "%s: switched to NTSC\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "switched to NTSC\n"); break; case VIDEO_MODE_PAL: saa7110_write(client, 0x0D, 0x86); saa7110_write(client, 0x0F, 0x10); saa7110_write(client, 0x11, 0x59); //saa7110_write(client, 0x2E, 0x9A); - dprintk(1, - KERN_INFO "%s: switched to PAL\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "switched to PAL\n"); break; case VIDEO_MODE_SECAM: saa7110_write(client, 0x0D, 0x87); saa7110_write(client, 0x0F, 0x10); saa7110_write(client, 0x11, 0x59); //saa7110_write(client, 0x2E, 0x9A); - dprintk(1, - KERN_INFO - "%s: switched to SECAM\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "switched to SECAM\n"); break; case VIDEO_MODE_AUTO: - dprintk(1, - KERN_INFO - "%s: TV standard detection...\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "switched to AUTO\n"); decoder->norm = determine_norm(client); *(int *) arg = decoder->norm; break; @@ -369,15 +329,12 @@ saa7110_command (struct i2c_client *client, case DECODER_SET_INPUT: v = *(int *) arg; if (v < 0 || v > SAA7110_MAX_INPUT) { - dprintk(1, - KERN_INFO "%s: input=%d not available\n", - I2C_NAME(client), v); + v4l_dbg(1, debug, client, "input=%d not available\n", v); return -EINVAL; } if (decoder->input != v) { saa7110_selmux(client, v); - dprintk(1, KERN_INFO "%s: switched to input=%d\n", - I2C_NAME(client), v); + v4l_dbg(1, debug, client, "switched to input=%d\n", v); } break; @@ -393,8 +350,7 @@ saa7110_command (struct i2c_client *client, if (decoder->enable != v) { decoder->enable = v; saa7110_write(client, 0x0E, v ? 0x18 : 0x80); - dprintk(1, KERN_INFO "%s: YUV %s\n", I2C_NAME(client), - v ? "on" : "off"); + v4l_dbg(1, debug, client, "YUV %s\n", v ? "on" : "off"); } break; @@ -424,23 +380,23 @@ saa7110_command (struct i2c_client *client, saa7110_write(client, 0x07, (decoder->hue >> 8) - 128); } - } break; + } case DECODER_DUMP: + if (!debug) + break; for (v = 0; v < SAA7110_NR_REG; v += 16) { int j; - dprintk(1, KERN_DEBUG "%s: %02x:", I2C_NAME(client), - v); + v4l_dbg(1, debug, client, "%02x:", v); for (j = 0; j < 16 && v + j < SAA7110_NR_REG; j++) - dprintk(1, " %02x", decoder->reg[v + j]); - dprintk(1, "\n"); + printk(KERN_CONT " %02x", decoder->reg[v + j]); + printk(KERN_CONT "\n"); } break; default: - dprintk(1, KERN_INFO "unknown saa7110_command??(%d)\n", - cmd); + v4l_dbg(1, debug, client, "unknown command %08x\n", cmd); return -EINVAL; } return 0; @@ -452,55 +408,28 @@ saa7110_command (struct i2c_client *client, * Generic i2c probe * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' */ -static unsigned short normal_i2c[] = { - I2C_SAA7110 >> 1, - (I2C_SAA7110 >> 1) + 1, - I2C_CLIENT_END -}; -static unsigned short ignore = I2C_CLIENT_END; +static unsigned short normal_i2c[] = { 0x9c >> 1, 0x9e >> 1, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_i2c, - .probe = &ignore, - .ignore = &ignore, -}; +I2C_CLIENT_INSMOD; -static struct i2c_driver i2c_driver_saa7110; - -static int -saa7110_detect_client (struct i2c_adapter *adapter, - int address, - int kind) +static int saa7110_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client; struct saa7110 *decoder; int rv; - dprintk(1, - KERN_INFO - "saa7110.c: detecting saa7110 client on address 0x%x\n", - address << 1); - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality - (adapter, - I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) - return 0; + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) + return -ENODEV; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) - return -ENOMEM; - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver_saa7110; - strlcpy(I2C_NAME(client), "saa7110", sizeof(I2C_NAME(client))); + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL); - if (!decoder) { - kfree(client); + if (!decoder) return -ENOMEM; - } decoder->norm = VIDEO_MODE_PAL; decoder->input = 0; decoder->enable = 1; @@ -511,18 +440,10 @@ saa7110_detect_client (struct i2c_adapter *adapter, init_waitqueue_head(&decoder->wq); i2c_set_clientdata(client, decoder); - rv = i2c_attach_client(client); - if (rv) { - kfree(client); - kfree(decoder); - return rv; - } - rv = saa7110_write_block(client, initseq, sizeof(initseq)); - if (rv < 0) - dprintk(1, KERN_ERR "%s_attach: init status %d\n", - I2C_NAME(client), rv); - else { + if (rv < 0) { + v4l_dbg(1, debug, client, "init status %d\n", rv); + } else { int ver, status; saa7110_write(client, 0x21, 0x10); saa7110_write(client, 0x0e, 0x18); @@ -531,10 +452,8 @@ saa7110_detect_client (struct i2c_adapter *adapter, saa7110_write(client, 0x0D, 0x06); //mdelay(150); status = saa7110_read(client); - dprintk(1, - KERN_INFO - "%s_attach: SAA7110A version %x at 0x%02x, status=0x%02x\n", - I2C_NAME(client), ver, client->addr << 1, status); + v4l_dbg(1, debug, client, "version %x, status=0x%02x\n", + ver, status); saa7110_write(client, 0x0D, 0x86); saa7110_write(client, 0x0F, 0x10); saa7110_write(client, 0x11, 0x59); @@ -548,58 +467,29 @@ saa7110_detect_client (struct i2c_adapter *adapter, return 0; } -static int -saa7110_attach_adapter (struct i2c_adapter *adapter) +static int saa7110_remove(struct i2c_client *client) { - dprintk(1, - KERN_INFO - "saa7110.c: starting probe for adapter %s (0x%x)\n", - I2C_NAME(adapter), adapter->id); - return i2c_probe(adapter, &addr_data, &saa7110_detect_client); -} - -static int -saa7110_detach_client (struct i2c_client *client) -{ - struct saa7110 *decoder = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - - kfree(decoder); - kfree(client); - + kfree(i2c_get_clientdata(client)); return 0; } /* ----------------------------------------------------------------------- */ -static struct i2c_driver i2c_driver_saa7110 = { - .driver = { - .name = "saa7110", - }, - - .id = I2C_DRIVERID_SAA7110, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id saa7110_id[] = { + { "saa7110", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, saa7110_id); - .attach_adapter = saa7110_attach_adapter, - .detach_client = saa7110_detach_client, +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "saa7110", + .driverid = I2C_DRIVERID_SAA7110, .command = saa7110_command, + .probe = saa7110_probe, + .remove = saa7110_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = saa7110_id, +#endif }; - -static int __init -saa7110_init (void) -{ - return i2c_add_driver(&i2c_driver_saa7110); -} - -static void __exit -saa7110_exit (void) -{ - i2c_del_driver(&i2c_driver_saa7110); -} - -module_init(saa7110_init); -module_exit(saa7110_exit); diff --git a/linux/drivers/media/video/saa7111.c b/linux/drivers/media/video/saa7111.c index 917fb2553..94e5d0b4e 100644 --- a/linux/drivers/media/video/saa7111.c +++ b/linux/drivers/media/video/saa7111.c @@ -28,44 +28,25 @@ */ #include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/major.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/signal.h> #include <linux/types.h> -#include <linux/i2c.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/page.h> +#include <linux/ioctl.h> #include <asm/uaccess.h> - +#include <linux/i2c.h> +#include <linux/i2c-id.h> #include <linux/videodev.h> #include <linux/video_decoder.h> +#include <media/v4l2-common.h> +#include <media/v4l2-i2c-drv-legacy.h> #include "compat.h" MODULE_DESCRIPTION("Philips SAA7111 video decoder driver"); MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); - -#define I2C_NAME(s) (s)->name - - static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#define dprintk(num, format, args...) \ - do { \ - if (debug >= num) \ - printk(format, ##args); \ - } while (0) - /* ----------------------------------------------------------------------- */ #define SAA7111_NR_REG 0x18 @@ -78,14 +59,9 @@ struct saa7111 { int enable; }; -#define I2C_SAA7111 0x48 - /* ----------------------------------------------------------------------- */ -static inline int -saa7111_write (struct i2c_client *client, - u8 reg, - u8 value) +static inline int saa7111_write(struct i2c_client *client, u8 reg, u8 value) { struct saa7111 *decoder = i2c_get_clientdata(client); @@ -93,8 +69,7 @@ saa7111_write (struct i2c_client *client, return i2c_smbus_write_byte_data(client, reg, value); } -static inline void -saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value) +static inline void saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value) { struct saa7111 *decoder = i2c_get_clientdata(client); @@ -104,10 +79,7 @@ saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value) } } -static int -saa7111_write_block (struct i2c_client *client, - const u8 *data, - unsigned int len) +static int saa7111_write_block(struct i2c_client *client, const u8 *data, unsigned int len) { int ret = -1; u8 reg; @@ -128,18 +100,17 @@ saa7111_write_block (struct i2c_client *client, decoder->reg[reg++] = data[1]; len -= 2; data += 2; - } while (len >= 2 && data[0] == reg && - block_len < 32); - if ((ret = i2c_master_send(client, block_data, - block_len)) < 0) + } while (len >= 2 && data[0] == reg && block_len < 32); + ret = i2c_master_send(client, block_data, block_len); + if (ret < 0) break; } } else { /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - if ((ret = saa7111_write(client, reg, - *data++)) < 0) + ret = saa7111_write(client, reg, *data++); + if (ret < 0) break; len -= 2; } @@ -148,16 +119,13 @@ saa7111_write_block (struct i2c_client *client, return ret; } -static int -saa7111_init_decoder (struct i2c_client *client, - struct video_decoder_init *init) +static int saa7111_init_decoder(struct i2c_client *client, + struct video_decoder_init *init) { return saa7111_write_block(client, init->data, init->len); } -static inline int -saa7111_read (struct i2c_client *client, - u8 reg) +static inline int saa7111_read(struct i2c_client *client, u8 reg) { return i2c_smbus_read_byte_data(client, reg); } @@ -204,28 +172,23 @@ static const unsigned char saa7111_i2c_init[] = { 0x17, 0x00, /* 17 - VBI */ }; -static int -saa7111_command (struct i2c_client *client, - unsigned int cmd, - void *arg) +static int saa7111_command(struct i2c_client *client, unsigned cmd, void *arg) { struct saa7111 *decoder = i2c_get_clientdata(client); switch (cmd) { - case 0: break; case DECODER_INIT: { struct video_decoder_init *init = arg; + struct video_decoder_init vdi; + if (NULL != init) return saa7111_init_decoder(client, init); - else { - struct video_decoder_init vdi; - vdi.data = saa7111_i2c_init; - vdi.len = sizeof(saa7111_i2c_init); - return saa7111_init_decoder(client, &vdi); - } + vdi.data = saa7111_i2c_init; + vdi.len = sizeof(saa7111_i2c_init); + return saa7111_init_decoder(client, &vdi); } case DECODER_DUMP: @@ -235,15 +198,15 @@ saa7111_command (struct i2c_client *client, for (i = 0; i < SAA7111_NR_REG; i += 16) { int j; - printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i); + v4l_info(client, "%03x", i); for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) { - printk(" %02x", + printk(KERN_CONT " %02x", saa7111_read(client, i + j)); } - printk("\n"); + printk(KERN_CONT "\n"); } - } break; + } case DECODER_GET_CAPABILITIES: { @@ -256,8 +219,8 @@ saa7111_command (struct i2c_client *client, VIDEO_DECODER_CCIR; cap->inputs = 8; cap->outputs = 1; - } break; + } case DECODER_GET_STATUS: { @@ -266,8 +229,7 @@ saa7111_command (struct i2c_client *client, int res; status = saa7111_read(client, 0x1f); - dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client), - status); + v4l_dbg(1, debug, client, "status: 0x%02x\n", status); res = 0; if ((status & (1 << 6)) == 0) { res |= DECODER_STATUS_GOOD; @@ -295,8 +257,8 @@ saa7111_command (struct i2c_client *client, res |= DECODER_STATUS_COLOR; } *iarg = res; - } break; + } case DECODER_SET_GPIO: { @@ -363,8 +325,8 @@ saa7111_command (struct i2c_client *client, } decoder->norm = *iarg; - } break; + } case DECODER_SET_INPUT: { @@ -388,8 +350,8 @@ saa7111_command (struct i2c_client *client, 3) ? 0x80 : 0)); } - } break; + } case DECODER_SET_OUTPUT: { @@ -399,8 +361,8 @@ saa7111_command (struct i2c_client *client, if (*iarg != 0) { return -EINVAL; } - } break; + } case DECODER_ENABLE_OUTPUT: { @@ -440,8 +402,8 @@ saa7111_command (struct i2c_client *client, (decoder->reg[0x11] & 0xf3)); } } - } break; + } case DECODER_SET_PICTURE: { @@ -455,8 +417,8 @@ saa7111_command (struct i2c_client *client, saa7111_write(client, 0x0c, pic->colour >> 9); /* We want -128 to 127 we get 0-65535 */ saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8); - } break; + } default: return -EINVAL; @@ -467,48 +429,23 @@ saa7111_command (struct i2c_client *client, /* ----------------------------------------------------------------------- */ -/* - * Generic i2c probe - * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' - */ -static unsigned short normal_i2c[] = { I2C_SAA7111 >> 1, I2C_CLIENT_END }; - -static unsigned short ignore = I2C_CLIENT_END; - -static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_i2c, - .probe = &ignore, - .ignore = &ignore, -}; +static unsigned short normal_i2c[] = { 0x48 >> 1, I2C_CLIENT_END }; -static struct i2c_driver i2c_driver_saa7111; +I2C_CLIENT_INSMOD; -static int -saa7111_detect_client (struct i2c_adapter *adapter, - int address, - int kind) +static int saa7111_probe(struct i2c_client *client, + const struct i2c_device_id *id) { int i; - struct i2c_client *client; struct saa7111 *decoder; struct video_decoder_init vdi; - dprintk(1, - KERN_INFO - "saa7111.c: detecting saa7111 client on address 0x%x\n", - address << 1); - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) - return -ENOMEM; - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver_saa7111; - strlcpy(I2C_NAME(client), "saa7111", sizeof(I2C_NAME(client))); + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL); if (decoder == NULL) { @@ -520,82 +457,41 @@ saa7111_detect_client (struct i2c_adapter *adapter, decoder->enable = 1; i2c_set_clientdata(client, decoder); - i = i2c_attach_client(client); - if (i) { - kfree(client); - kfree(decoder); - return i; - } - vdi.data = saa7111_i2c_init; vdi.len = sizeof(saa7111_i2c_init); i = saa7111_init_decoder(client, &vdi); if (i < 0) { - dprintk(1, KERN_ERR "%s_attach error: init status %d\n", - I2C_NAME(client), i); + v4l_dbg(1, debug, client, "init status %d\n", i); } else { - dprintk(1, - KERN_INFO - "%s_attach: chip version %x at address 0x%x\n", - I2C_NAME(client), saa7111_read(client, 0x00) >> 4, - client->addr << 1); + v4l_dbg(1, debug, client, "revision %x\n", + saa7111_read(client, 0x00) >> 4); } - return 0; } -static int -saa7111_attach_adapter (struct i2c_adapter *adapter) +static int saa7111_remove(struct i2c_client *client) { - dprintk(1, - KERN_INFO - "saa7111.c: starting probe for adapter %s (0x%x)\n", - I2C_NAME(adapter), adapter->id); - return i2c_probe(adapter, &addr_data, &saa7111_detect_client); -} - -static int -saa7111_detach_client (struct i2c_client *client) -{ - struct saa7111 *decoder = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - - kfree(decoder); - kfree(client); - + kfree(i2c_get_clientdata(client)); return 0; } /* ----------------------------------------------------------------------- */ -static struct i2c_driver i2c_driver_saa7111 = { - .driver = { - .name = "saa7111", - }, - - .id = I2C_DRIVERID_SAA7111A, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id saa7111_id[] = { + { "saa7111_old", 0 }, /* "saa7111" maps to the saa7115 driver */ + { } +}; +MODULE_DEVICE_TABLE(i2c, saa7111_id); - .attach_adapter = saa7111_attach_adapter, - .detach_client = saa7111_detach_client, +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "saa7111", + .driverid = I2C_DRIVERID_SAA7111A, .command = saa7111_command, + .probe = saa7111_probe, + .remove = saa7111_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = saa7111_id, +#endif }; - -static int __init -saa7111_init (void) -{ - return i2c_add_driver(&i2c_driver_saa7111); -} - -static void __exit -saa7111_exit (void) -{ - i2c_del_driver(&i2c_driver_saa7111); -} - -module_init(saa7111_init); -module_exit(saa7111_exit); diff --git a/linux/drivers/media/video/saa7114.c b/linux/drivers/media/video/saa7114.c index 158bd123c..6d380e255 100644 --- a/linux/drivers/media/video/saa7114.c +++ b/linux/drivers/media/video/saa7114.c @@ -29,44 +29,25 @@ */ #include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/major.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/signal.h> #include <linux/types.h> -#include <linux/i2c.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/page.h> +#include <linux/ioctl.h> #include <asm/uaccess.h> - +#include <linux/i2c.h> +#include <linux/i2c-id.h> #include <linux/videodev.h> #include <linux/video_decoder.h> +#include <media/v4l2-common.h> +#include <media/v4l2-i2c-drv-legacy.h> #include "compat.h" MODULE_DESCRIPTION("Philips SAA7114H video decoder driver"); MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_LICENSE("GPL"); - -#define I2C_NAME(x) (x)->name - - static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#define dprintk(num, format, args...) \ - do { \ - if (debug >= num) \ - printk(format, ##args); \ - } while (0) - /* ----------------------------------------------------------------------- */ struct saa7114 { @@ -82,9 +63,6 @@ struct saa7114 { int playback; }; -#define I2C_SAA7114 0x42 -#define I2C_SAA7114A 0x40 - #define I2C_DELAY 10 @@ -130,18 +108,12 @@ struct saa7114 { /* ----------------------------------------------------------------------- */ -static inline int -saa7114_write (struct i2c_client *client, - u8 reg, - u8 value) +static inline int saa7114_write(struct i2c_client *client, u8 reg, u8 value) { return i2c_smbus_write_byte_data(client, reg, value); } -static int -saa7114_write_block (struct i2c_client *client, - const u8 *data, - unsigned int len) +static int saa7114_write_block(struct i2c_client *client, const u8 *data, unsigned int len) { int ret = -1; u8 reg; @@ -161,18 +133,17 @@ saa7114_write_block (struct i2c_client *client, reg++; len -= 2; data += 2; - } while (len >= 2 && data[0] == reg && - block_len < 32); - if ((ret = i2c_master_send(client, block_data, - block_len)) < 0) + } while (len >= 2 && data[0] == reg && block_len < 32); + ret = i2c_master_send(client, block_data, block_len); + if (ret < 0) break; } } else { /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - if ((ret = saa7114_write(client, reg, - *data++)) < 0) + ret = saa7114_write(client, reg, *data++); + if (ret < 0) break; len -= 2; } @@ -181,9 +152,7 @@ saa7114_write_block (struct i2c_client *client, return ret; } -static inline int -saa7114_read (struct i2c_client *client, - u8 reg) +static inline int saa7114_read(struct i2c_client *client, u8 reg) { return i2c_smbus_read_byte_data(client, reg); } @@ -453,15 +422,11 @@ static const unsigned char init[] = { 0xef, 0x00 }; -static int -saa7114_command (struct i2c_client *client, - unsigned int cmd, - void *arg) +static int saa7114_command(struct i2c_client *client, unsigned cmd, void *arg) { struct saa7114 *decoder = i2c_get_clientdata(client); switch (cmd) { - case 0: //dprintk(1, KERN_INFO "%s: writing init\n", I2C_NAME(client)); //saa7114_write_block(client, init, sizeof(init)); @@ -471,27 +436,28 @@ saa7114_command (struct i2c_client *client, { int i; - dprintk(1, KERN_INFO "%s: decoder dump\n", I2C_NAME(client)); + if (!debug) + break; + v4l_info(client, "decoder dump\n"); for (i = 0; i < 32; i += 16) { int j; - printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i); + v4l_info(client, "%03x", i); for (j = 0; j < 16; ++j) { - printk(" %02x", + printk(KERN_CONT " %02x", saa7114_read(client, i + j)); } - printk("\n"); + printk(KERN_CONT "\n"); } - } break; + } case DECODER_GET_CAPABILITIES: { struct video_decoder_capability *cap = arg; - dprintk(1, KERN_DEBUG "%s: decoder get capabilities\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "get capabilities\n"); cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | @@ -499,8 +465,8 @@ saa7114_command (struct i2c_client *client, VIDEO_DECODER_CCIR; cap->inputs = 8; cap->outputs = 1; - } break; + } case DECODER_GET_STATUS: { @@ -510,8 +476,7 @@ saa7114_command (struct i2c_client *client, status = saa7114_read(client, 0x1f); - dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client), - status); + v4l_dbg(1, debug, client, "status: 0x%02x\n", status); res = 0; if ((status & (1 << 6)) == 0) { res |= DECODER_STATUS_GOOD; @@ -539,8 +504,8 @@ saa7114_command (struct i2c_client *client, res |= DECODER_STATUS_COLOR; } *iarg = res; - } break; + } case DECODER_SET_NORM: { @@ -548,12 +513,11 @@ saa7114_command (struct i2c_client *client, short int hoff = 0, voff = 0, w = 0, h = 0; - dprintk(1, KERN_DEBUG "%s: decoder set norm ", - I2C_NAME(client)); - switch (*iarg) { + v4l_dbg(1, debug, client, "set norm\n"); + switch (*iarg) { case VIDEO_MODE_NTSC: - dprintk(1, "NTSC\n"); + v4l_dbg(1, debug, client, "NTSC\n"); decoder->reg[REG_ADDR(0x06)] = SAA_7114_NTSC_HSYNC_START; decoder->reg[REG_ADDR(0x07)] = @@ -572,7 +536,7 @@ saa7114_command (struct i2c_client *client, break; case VIDEO_MODE_PAL: - dprintk(1, "PAL\n"); + v4l_dbg(1, debug, client, "PAL\n"); decoder->reg[REG_ADDR(0x06)] = SAA_7114_PAL_HSYNC_START; decoder->reg[REG_ADDR(0x07)] = @@ -591,9 +555,8 @@ saa7114_command (struct i2c_client *client, break; default: - dprintk(1, " Unknown video mode!!!\n"); + v4l_dbg(1, debug, client, "Unknown video mode\n"); return -EINVAL; - } @@ -645,22 +608,20 @@ saa7114_command (struct i2c_client *client, saa7114_write(client, 0x80, 0x36); // i-port and scaler back end clock selection decoder->norm = *iarg; - } break; + } case DECODER_SET_INPUT: { int *iarg = arg; - dprintk(1, KERN_DEBUG "%s: decoder set input (%d)\n", - I2C_NAME(client), *iarg); + v4l_dbg(1, debug, client, "set input (%d)\n", *iarg); if (*iarg < 0 || *iarg > 7) { return -EINVAL; } if (decoder->input != *iarg) { - dprintk(1, KERN_DEBUG "%s: now setting %s input\n", - I2C_NAME(client), + v4l_dbg(1, debug, client, "now setting %s input\n", *iarg >= 6 ? "S-Video" : "Composite"); decoder->input = *iarg; @@ -691,30 +652,29 @@ saa7114_command (struct i2c_client *client, saa7114_write(client, 0x0e, decoder->reg[REG_ADDR(0x0e)]); } - } break; + } case DECODER_SET_OUTPUT: { int *iarg = arg; - dprintk(1, KERN_DEBUG "%s: decoder set output\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "set output\n"); /* not much choice of outputs */ if (*iarg != 0) { return -EINVAL; } - } break; + } case DECODER_ENABLE_OUTPUT: { int *iarg = arg; int enable = (*iarg != 0); - dprintk(1, KERN_DEBUG "%s: decoder %s output\n", - I2C_NAME(client), enable ? "enable" : "disable"); + v4l_dbg(1, debug, client, "%s output\n", + enable ? "enable" : "disable"); decoder->playback = !enable; @@ -755,18 +715,16 @@ saa7114_command (struct i2c_client *client, saa7114_write(client, 0x80, 0x36); } - } break; + } case DECODER_SET_PICTURE: { struct video_picture *pic = arg; - dprintk(1, - KERN_DEBUG - "%s: decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n", - I2C_NAME(client), pic->brightness, pic->contrast, - pic->colour, pic->hue); + v4l_dbg(1, debug, client, + "decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n", + pic->brightness, pic->contrast, pic->colour, pic->hue); if (decoder->bright != pic->brightness) { /* We want 0 to 255 we get 0-65535 */ @@ -790,8 +748,8 @@ saa7114_command (struct i2c_client *client, saa7114_write(client, 0x0d, (decoder->hue - 32768) >> 8); } - } break; + } default: return -EINVAL; @@ -802,58 +760,30 @@ saa7114_command (struct i2c_client *client, /* ----------------------------------------------------------------------- */ -/* - * Generic i2c probe - * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' - */ -static unsigned short normal_i2c[] = - { I2C_SAA7114 >> 1, I2C_SAA7114A >> 1, I2C_CLIENT_END }; - -static unsigned short ignore = I2C_CLIENT_END; - -static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_i2c, - .probe = &ignore, - .ignore = &ignore, -}; +static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END }; -static struct i2c_driver i2c_driver_saa7114; +I2C_CLIENT_INSMOD; -static int -saa7114_detect_client (struct i2c_adapter *adapter, - int address, - int kind) +static int saa7114_probe(struct i2c_client *client, + const struct i2c_device_id *id) { int i, err[30]; short int hoff = SAA_7114_NTSC_HOFFSET; short int voff = SAA_7114_NTSC_VOFFSET; short int w = SAA_7114_NTSC_WIDTH; short int h = SAA_7114_NTSC_HEIGHT; - struct i2c_client *client; struct saa7114 *decoder; - dprintk(1, - KERN_INFO - "saa7114.c: detecting saa7114 client on address 0x%x\n", - address << 1); - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) - return -ENOMEM; - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver_saa7114; - strlcpy(I2C_NAME(client), "saa7114", sizeof(I2C_NAME(client))); + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); decoder = kzalloc(sizeof(struct saa7114), GFP_KERNEL); - if (decoder == NULL) { - kfree(client); + if (decoder == NULL) return -ENOMEM; - } decoder->norm = VIDEO_MODE_NTSC; decoder->input = -1; decoder->enable = 1; @@ -938,8 +868,7 @@ saa7114_detect_client (struct i2c_adapter *adapter, decoder->reg[REG_ADDR(0x0e)] |= 1; // combfilter on - dprintk(1, KERN_DEBUG "%s_attach: starting decoder init\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "starting init\n"); err[0] = saa7114_write_block(client, decoder->reg + (0x20 << 1), @@ -963,28 +892,23 @@ saa7114_detect_client (struct i2c_adapter *adapter, for (i = 0; i <= 5; i++) { if (err[i] < 0) { - dprintk(1, - KERN_ERR - "%s_attach: init error %d at stage %d, leaving attach.\n", - I2C_NAME(client), i, err[i]); + v4l_dbg(1, debug, client, + "init error %d at stage %d, leaving attach.\n", + i, err[i]); kfree(decoder); - kfree(client); - return 0; + return -EIO; } } for (i = 6; i < 8; i++) { - dprintk(1, - KERN_DEBUG - "%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n", - I2C_NAME(client), i, saa7114_read(client, i), + v4l_dbg(1, debug, client, + "reg[0x%02x] = 0x%02x (0x%02x)\n", + i, saa7114_read(client, i), decoder->reg[REG_ADDR(i)]); } - dprintk(1, - KERN_DEBUG - "%s_attach: performing decoder reset sequence\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, + "performing decoder reset sequence\n"); err[6] = saa7114_write(client, 0x80, 0x06); // i-port and scaler backend clock selection, task A&B off err[7] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler @@ -992,19 +916,15 @@ saa7114_detect_client (struct i2c_adapter *adapter, for (i = 6; i <= 8; i++) { if (err[i] < 0) { - dprintk(1, - KERN_ERR - "%s_attach: init error %d at stage %d, leaving attach.\n", - I2C_NAME(client), i, err[i]); + v4l_dbg(1, debug, client, + "init error %d at stage %d, leaving attach.\n", + i, err[i]); kfree(decoder); - kfree(client); - return 0; + return -EIO; } } - dprintk(1, KERN_INFO "%s_attach: performing the rest of init\n", - I2C_NAME(client)); - + v4l_dbg(1, debug, client, "performing the rest of init\n"); err[9] = saa7114_write(client, 0x01, decoder->reg[REG_ADDR(0x01)]); err[10] = saa7114_write_block(client, decoder->reg + (0x03 << 1), (0x1e + 1 - 0x03) << 1); // big seq @@ -1040,37 +960,32 @@ saa7114_detect_client (struct i2c_adapter *adapter, for (i = 9; i <= 18; i++) { if (err[i] < 0) { - dprintk(1, - KERN_ERR - "%s_attach: init error %d at stage %d, leaving attach.\n", - I2C_NAME(client), i, err[i]); + v4l_dbg(1, debug, client, + "init error %d at stage %d, leaving attach.\n", + i, err[i]); kfree(decoder); - kfree(client); - return 0; + return -EIO; } } for (i = 6; i < 8; i++) { - dprintk(1, - KERN_DEBUG - "%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n", - I2C_NAME(client), i, saa7114_read(client, i), + v4l_dbg(1, debug, client, + "reg[0x%02x] = 0x%02x (0x%02x)\n", + i, saa7114_read(client, i), decoder->reg[REG_ADDR(i)]); } for (i = 0x11; i <= 0x13; i++) { - dprintk(1, - KERN_DEBUG - "%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n", - I2C_NAME(client), i, saa7114_read(client, i), + v4l_dbg(1, debug, client, + "reg[0x%02x] = 0x%02x (0x%02x)\n", + i, saa7114_read(client, i), decoder->reg[REG_ADDR(i)]); } - dprintk(1, KERN_DEBUG "%s_attach: setting video input\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "setting video input\n"); err[19] = saa7114_write(client, 0x02, decoder->reg[REG_ADDR(0x02)]); @@ -1081,20 +996,15 @@ saa7114_detect_client (struct i2c_adapter *adapter, for (i = 19; i <= 21; i++) { if (err[i] < 0) { - dprintk(1, - KERN_ERR - "%s_attach: init error %d at stage %d, leaving attach.\n", - I2C_NAME(client), i, err[i]); + v4l_dbg(1, debug, client, + "init error %d at stage %d, leaving attach.\n", + i, err[i]); kfree(decoder); - kfree(client); - return 0; + return -EIO; } } - dprintk(1, - KERN_DEBUG - "%s_attach: performing decoder reset sequence\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "performing decoder reset sequence\n"); err[22] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler err[23] = saa7114_write(client, 0x88, 0xf8); // sw reset scaler release @@ -1103,13 +1013,11 @@ saa7114_detect_client (struct i2c_adapter *adapter, for (i = 22; i <= 24; i++) { if (err[i] < 0) { - dprintk(1, - KERN_ERR - "%s_attach: init error %d at stage %d, leaving attach.\n", - I2C_NAME(client), i, err[i]); + v4l_dbg(1, debug, client, + "init error %d at stage %d, leaving attach.\n", + i, err[i]); kfree(decoder); - kfree(client); - return 0; + return -EIO; } } @@ -1117,101 +1025,49 @@ saa7114_detect_client (struct i2c_adapter *adapter, err[26] = saa7114_write(client, 0x07, init[REG_ADDR(0x07)]); err[27] = saa7114_write(client, 0x10, init[REG_ADDR(0x10)]); - dprintk(1, - KERN_INFO - "%s_attach: chip version %x, decoder status 0x%02x\n", - I2C_NAME(client), saa7114_read(client, 0x00) >> 4, + v4l_dbg(1, debug, client, "chip version %x, decoder status 0x%02x\n", + saa7114_read(client, 0x00) >> 4, saa7114_read(client, 0x1f)); - dprintk(1, - KERN_DEBUG - "%s_attach: power save control: 0x%02x, scaler status: 0x%02x\n", - I2C_NAME(client), saa7114_read(client, 0x88), + v4l_dbg(1, debug, client, + "power save control: 0x%02x, scaler status: 0x%02x\n", + saa7114_read(client, 0x88), saa7114_read(client, 0x8f)); for (i = 0x94; i < 0x96; i++) { - dprintk(1, - KERN_DEBUG - "%s_attach: reg[0x%02x] = 0x%02x (0x%02x)\n", - I2C_NAME(client), i, saa7114_read(client, i), + v4l_dbg(1, debug, client, + "reg[0x%02x] = 0x%02x (0x%02x)\n", + i, saa7114_read(client, i), decoder->reg[REG_ADDR(i)]); } - i = i2c_attach_client(client); - if (i) { - kfree(client); - kfree(decoder); - return i; - } - //i = saa7114_write_block(client, init, sizeof(init)); - i = 0; - if (i < 0) { - dprintk(1, KERN_ERR "%s_attach error: init status %d\n", - I2C_NAME(client), i); - } else { - dprintk(1, - KERN_INFO - "%s_attach: chip version %x at address 0x%x\n", - I2C_NAME(client), saa7114_read(client, 0x00) >> 4, - client->addr << 1); - } - return 0; } -static int -saa7114_attach_adapter (struct i2c_adapter *adapter) -{ - dprintk(1, - KERN_INFO - "saa7114.c: starting probe for adapter %s (0x%x)\n", - I2C_NAME(adapter), adapter->id); - return i2c_probe(adapter, &addr_data, &saa7114_detect_client); -} - -static int -saa7114_detach_client (struct i2c_client *client) +static int saa7114_remove(struct i2c_client *client) { - struct saa7114 *decoder = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - - kfree(decoder); - kfree(client); - + kfree(i2c_get_clientdata(client)); return 0; } /* ----------------------------------------------------------------------- */ -static struct i2c_driver i2c_driver_saa7114 = { - .driver = { - .name = "saa7114", - }, - - .id = I2C_DRIVERID_SAA7114, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id saa7114_id[] = { + { "saa7114_old", 0 }, /* "saa7114" maps to the saa7115 driver */ + { } +}; +MODULE_DEVICE_TABLE(i2c, saa7114_id); - .attach_adapter = saa7114_attach_adapter, - .detach_client = saa7114_detach_client, +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "saa7114", + .driverid = I2C_DRIVERID_SAA7114, .command = saa7114_command, + .probe = saa7114_probe, + .remove = saa7114_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = saa7114_id, +#endif }; - -static int __init -saa7114_init (void) -{ - return i2c_add_driver(&i2c_driver_saa7114); -} - -static void __exit -saa7114_exit (void) -{ - i2c_del_driver(&i2c_driver_saa7114); -} - -module_init(saa7114_init); -module_exit(saa7114_exit); diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c index c84895fca..11a7c76bc 100644 --- a/linux/drivers/media/video/saa7134/saa7134-dvb.c +++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c @@ -535,11 +535,16 @@ static int configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *cdec_conf, struct tda827x_config *tuner_conf) { - dev->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap); - if (dev->dvb.frontend) { + struct videobuf_dvb_frontend *fe0; + + /* Get the first frontend */ + fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); + + fe0->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap); + if (fe0->dvb.frontend) { if (cdec_conf->i2c_gate) - dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; - if (dvb_attach(tda827x_attach, dev->dvb.frontend, + fe0->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; + if (dvb_attach(tda827x_attach, fe0->dvb.frontend, cdec_conf->tuner_address, &dev->i2c_adap, tuner_conf)) return 0; @@ -944,12 +949,30 @@ static int dvb_init(struct saa7134_dev *dev) { int ret; int attach_xc3028 = 0; + struct videobuf_dvb_frontend *fe0; + + /* FIXME: add support for multi-frontend */ + mutex_init(&dev->frontends.lock); + INIT_LIST_HEAD(&dev->frontends.frontend.felist); + dev->frontends.active_fe_id = 0; + + printk(KERN_INFO "%s() allocating 1 frontend\n", __func__); + + if (videobuf_dvb_alloc_frontend(dev, &dev->frontends, 1) == NULL) { + printk(KERN_ERR "%s() failed to alloc\n", __func__); + return -ENOMEM; + } + + /* Get the first frontend */ + fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); + if (!fe0) + return -EINVAL; /* init struct videobuf_dvb */ dev->ts.nr_bufs = 32; dev->ts.nr_packets = 32*4; - dev->dvb.name = dev->name; - videobuf_queue_sg_init(&dev->dvb.dvbq, &saa7134_ts_qops, + fe0->dvb.name = dev->name; + videobuf_queue_sg_init(&fe0->dvb.dvbq, &saa7134_ts_qops, &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_ALTERNATE, @@ -959,47 +982,47 @@ static int dvb_init(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL: dprintk("pinnacle 300i dvb setup\n"); - dev->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i, + fe0->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i, &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params; + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params; } break; case SAA7134_BOARD_AVERMEDIA_777: case SAA7134_BOARD_AVERMEDIA_A16AR: dprintk("avertv 777 dvb setup\n"); - dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777, + fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777, &dev->i2c_adap); - if (dev->dvb.frontend) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend) { + dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x61, TUNER_PHILIPS_TD1316); } break; case SAA7134_BOARD_AVERMEDIA_A16D: dprintk("AverMedia A16D dvb setup\n"); - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_xc3028_mt352_dev, &dev->i2c_adap); attach_xc3028 = 1; break; case SAA7134_BOARD_MD7134: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &medion_cardbus, &dev->i2c_adap); - if (dev->dvb.frontend) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend) { + dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &dev->i2c_adap, medion_cardbus.tuner_address, TUNER_PHILIPS_FMD1216ME_MK3); } break; case SAA7134_BOARD_PHILIPS_TOUGH: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &philips_tu1216_60_config, &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set; + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init; + fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set; } break; case SAA7134_BOARD_FLYDVBTDUO: @@ -1010,24 +1033,24 @@ static int dvb_init(struct saa7134_dev *dev) break; case SAA7134_BOARD_PHILIPS_EUROPA: case SAA7134_BOARD_VIDEOMATE_DVBT_300: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &philips_europa_config, &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->original_demod_sleep = dev->dvb.frontend->ops.sleep; - dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep; - dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init; - dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; + if (fe0->dvb.frontend) { + dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep; + fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep; + fe0->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init; + fe0->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep; + fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; } break; case SAA7134_BOARD_VIDEOMATE_DVBT_200: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &philips_tu1216_61_config, &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set; + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init; + fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set; } break; case SAA7134_BOARD_KWORLD_DVBT_210: @@ -1066,14 +1089,14 @@ static int dvb_init(struct saa7134_dev *dev) &tda827x_cfg_0) < 0) goto dettach_frontend; } else { /* satellite */ - dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); - if (dev->dvb.frontend) { - if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63, + fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); + if (fe0->dvb.frontend) { + if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x63, &dev->i2c_adap, 0) == NULL) { wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__); goto dettach_frontend; } - if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap, + if (dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x08, 0, 0) == NULL) { wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__); goto dettach_frontend; @@ -1083,11 +1106,11 @@ static int dvb_init(struct saa7134_dev *dev) break; case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &ads_tech_duo_config, &dev->i2c_adap); - if (dev->dvb.frontend) { - if (dvb_attach(tda827x_attach,dev->dvb.frontend, + if (fe0->dvb.frontend) { + if (dvb_attach(tda827x_attach,fe0->dvb.frontend, ads_tech_duo_config.tuner_address, &dev->i2c_adap, &ads_duo_cfg) == NULL) { wprintk("no tda827x tuner found at addr: %02x\n", @@ -1108,15 +1131,15 @@ static int dvb_init(struct saa7134_dev *dev) &tda827x_cfg_0) < 0) goto dettach_frontend; } else { /* satellite */ - dev->dvb.frontend = dvb_attach(tda10086_attach, + fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); - if (dev->dvb.frontend) { - struct dvb_frontend *fe = dev->dvb.frontend; + if (fe0->dvb.frontend) { + struct dvb_frontend *fe = fe0->dvb.frontend; u8 dev_id = dev->eedata[2]; u8 data = 0xc4; struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1}; - if (dvb_attach(tda826x_attach, dev->dvb.frontend, + if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) { wprintk("%s: Medion Quadro, no tda826x " "found !\n", __func__); @@ -1150,31 +1173,31 @@ static int dvb_init(struct saa7134_dev *dev) } break; case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: - dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180, + fe0->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180, &dev->i2c_adap); - if (dev->dvb.frontend) - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, + if (fe0->dvb.frontend) + dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_TDHU2); break; case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: case SAA7134_BOARD_KWORLD_ATSC110: - dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, + fe0->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, &dev->i2c_adap); - if (dev->dvb.frontend) - dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend) + dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x61, TUNER_PHILIPS_TUV1236D); break; case SAA7134_BOARD_FLYDVBS_LR300: - dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, + fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); - if (dev->dvb.frontend) { - if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, + if (fe0->dvb.frontend) { + if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) { wprintk("%s: No tda826x found!\n", __func__); goto dettach_frontend; } - if (dvb_attach(isl6421_attach, dev->dvb.frontend, + if (dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x08, 0, 0) == NULL) { wprintk("%s: No ISL6421 found!\n", __func__); goto dettach_frontend; @@ -1182,25 +1205,25 @@ static int dvb_init(struct saa7134_dev *dev) } break; case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &medion_cardbus, &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->original_demod_sleep = dev->dvb.frontend->ops.sleep; - dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep; + if (fe0->dvb.frontend) { + dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep; + fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep; - dvb_attach(simple_tuner_attach, dev->dvb.frontend, + dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &dev->i2c_adap, medion_cardbus.tuner_address, TUNER_PHILIPS_FMD1216ME_MK3); } break; case SAA7134_BOARD_VIDEOMATE_DVBT_200A: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &philips_europa_config, &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init; + fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; } break; case SAA7134_BOARD_CINERGY_HT_PCMCIA: @@ -1239,15 +1262,15 @@ static int dvb_init(struct saa7134_dev *dev) goto dettach_frontend; break; case SAA7134_BOARD_PHILIPS_SNAKE: - dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, + fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); - if (dev->dvb.frontend) { - if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, + if (fe0->dvb.frontend) { + if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) { wprintk("%s: No tda826x found!\n", __func__); goto dettach_frontend; } - if (dvb_attach(lnbp21_attach, dev->dvb.frontend, + if (dvb_attach(lnbp21_attach, fe0->dvb.frontend, &dev->i2c_adap, 0, 0) == NULL) { wprintk("%s: No lnbp21 found!\n", __func__); goto dettach_frontend; @@ -1269,7 +1292,7 @@ static int dvb_init(struct saa7134_dev *dev) saa7134_set_gpio(dev, 25, 0); msleep(10); saa7134_set_gpio(dev, 25, 1); - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_xc3028_mt352_dev, &dev->i2c_adap); attach_xc3028 = 1; @@ -1279,18 +1302,18 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_T750: #endif case SAA7134_BOARD_MD7134_BRIDGE_2: - dev->dvb.frontend = dvb_attach(tda10086_attach, + fe0->dvb.frontend = dvb_attach(tda10086_attach, &sd1878_4m, &dev->i2c_adap); - if (dev->dvb.frontend) { + if (fe0->dvb.frontend) { struct dvb_frontend *fe; - if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, + if (dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) { wprintk("%s: MD7134 DVB-S, no SD1878 " "found !\n", __func__); goto dettach_frontend; } /* we need to open the i2c gate (we know it exists) */ - fe = dev->dvb.frontend; + fe = fe0->dvb.frontend; fe->ops.i2c_gate_ctrl(fe, 1); if (dvb_attach(isl6405_attach, fe, &dev->i2c_adap, 0x08, 0, 0) == NULL) { @@ -1309,7 +1332,7 @@ static int dvb_init(struct saa7134_dev *dev) saa7134_set_gpio(dev, 25, 0); msleep(10); saa7134_set_gpio(dev, 25, 1); - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_xc3028_mt352_dev, &dev->i2c_adap); attach_xc3028 = 1; @@ -1320,17 +1343,17 @@ static int dvb_init(struct saa7134_dev *dev) &tda827x_cfg_2) < 0) goto dettach_frontend; } else { /* satellite */ - dev->dvb.frontend = dvb_attach(tda10086_attach, + fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); - if (dev->dvb.frontend) { + if (fe0->dvb.frontend) { if (dvb_attach(tda826x_attach, - dev->dvb.frontend, 0x60, + fe0->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) { wprintk("%s: Asus Tiger 3in1, no " "tda826x found!\n", __func__); goto dettach_frontend; } - if (dvb_attach(lnbp21_attach, dev->dvb.frontend, + if (dvb_attach(lnbp21_attach, fe0->dvb.frontend, &dev->i2c_adap, 0, 0) == NULL) { wprintk("%s: Asus Tiger 3in1, no lnbp21" " found!\n", __func__); @@ -1356,10 +1379,10 @@ static int dvb_init(struct saa7134_dev *dev) .i2c_addr = 0x61, }; - if (!dev->dvb.frontend) + if (!fe0->dvb.frontend) return -1; - fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); + fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg); if (!fe) { printk(KERN_ERR "%s/2: xc3028 attach failed\n", dev->name); @@ -1367,40 +1390,47 @@ static int dvb_init(struct saa7134_dev *dev) } } - if (NULL == dev->dvb.frontend) { + if (NULL == fe0->dvb.frontend) { printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name); return -1; } /* define general-purpose callback pointer */ - dev->dvb.frontend->callback = saa7134_tuner_callback; + fe0->dvb.frontend->callback = saa7134_tuner_callback; /* register everything else */ - ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev, - adapter_nr); + ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, + &dev->pci->dev, adapter_nr, 0); /* this sequence is necessary to make the tda1004x load its firmware * and to enter analog mode of hybrid boards */ if (!ret) { - if (dev->dvb.frontend->ops.init) - dev->dvb.frontend->ops.init(dev->dvb.frontend); - if (dev->dvb.frontend->ops.sleep) - dev->dvb.frontend->ops.sleep(dev->dvb.frontend); - if (dev->dvb.frontend->ops.tuner_ops.sleep) - dev->dvb.frontend->ops.tuner_ops.sleep(dev->dvb.frontend); + if (fe0->dvb.frontend->ops.init) + fe0->dvb.frontend->ops.init(fe0->dvb.frontend); + if (fe0->dvb.frontend->ops.sleep) + fe0->dvb.frontend->ops.sleep(fe0->dvb.frontend); + if (fe0->dvb.frontend->ops.tuner_ops.sleep) + fe0->dvb.frontend->ops.tuner_ops.sleep(fe0->dvb.frontend); } return ret; dettach_frontend: - if (dev->dvb.frontend) - dvb_frontend_detach(dev->dvb.frontend); - dev->dvb.frontend = NULL; + if (fe0->dvb.frontend) + dvb_frontend_detach(fe0->dvb.frontend); + fe0->dvb.frontend = NULL; return -1; } static int dvb_fini(struct saa7134_dev *dev) { + struct videobuf_dvb_frontend *fe0; + + /* Get the first frontend */ + fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); + if (!fe0) + return -EINVAL; + /* FIXME: I suspect that this code is bogus, since the entry for Pinnacle 300I DVB-T PAL already defines the proper init to allow the detection of mt2032 (TDA9887_PORT2_INACTIVE) @@ -1420,7 +1450,7 @@ static int dvb_fini(struct saa7134_dev *dev) u8 data = 0x80; struct i2c_msg msg = {.addr = 0x08, .buf = &data, .flags = 0, .len = 1}; struct dvb_frontend *fe; - fe = dev->dvb.frontend; + fe = fe0->dvb.frontend; if (fe->ops.i2c_gate_ctrl) { fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &msg, 1); @@ -1428,8 +1458,8 @@ static int dvb_fini(struct saa7134_dev *dev) } } } - if (dev->dvb.frontend) - videobuf_dvb_unregister(&dev->dvb); + if (fe0->dvb.frontend) + videobuf_dvb_unregister_bus(&dev->frontends); return 0; } diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 502cbe60c..837fc5424 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -586,7 +586,7 @@ struct saa7134_dev { #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE) /* SAA7134_MPEG_DVB only */ - struct videobuf_dvb dvb; + struct videobuf_dvb_frontends frontends; int (*original_demod_sleep)(struct dvb_frontend *fe); int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg); diff --git a/linux/drivers/media/video/saa7185.c b/linux/drivers/media/video/saa7185.c index 7a6c9c1fb..195e2f415 100644 --- a/linux/drivers/media/video/saa7185.c +++ b/linux/drivers/media/video/saa7185.c @@ -25,24 +25,15 @@ */ #include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/major.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/signal.h> #include <linux/types.h> -#include <linux/i2c.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/page.h> +#include <linux/ioctl.h> #include <asm/uaccess.h> - +#include <linux/i2c.h> +#include <linux/i2c-id.h> #include <linux/videodev.h> #include <linux/video_encoder.h> +#include <media/v4l2-common.h> +#include <media/v4l2-i2c-drv-legacy.h> #include "compat.h" MODULE_DESCRIPTION("Philips SAA7185 video encoder driver"); @@ -50,19 +41,10 @@ MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); -#define I2C_NAME(s) (s)->name - - static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#define dprintk(num, format, args...) \ - do { \ - if (debug >= num) \ - printk(format, ##args); \ - } while (0) - /* ----------------------------------------------------------------------- */ struct saa7185 { @@ -76,32 +58,24 @@ struct saa7185 { int sat; }; -#define I2C_SAA7185 0x88 - /* ----------------------------------------------------------------------- */ -static inline int -saa7185_read (struct i2c_client *client) +static inline int saa7185_read(struct i2c_client *client) { return i2c_smbus_read_byte(client); } -static int -saa7185_write (struct i2c_client *client, - u8 reg, - u8 value) +static int saa7185_write(struct i2c_client *client, u8 reg, u8 value) { struct saa7185 *encoder = i2c_get_clientdata(client); - dprintk(1, KERN_DEBUG "SAA7185: %02x set to %02x\n", reg, value); + v4l_dbg(1, debug, client, "%02x set to %02x\n", reg, value); encoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } -static int -saa7185_write_block (struct i2c_client *client, - const u8 *data, - unsigned int len) +static int saa7185_write_block(struct i2c_client *client, + const u8 *data, unsigned int len) { int ret = -1; u8 reg; @@ -122,18 +96,17 @@ saa7185_write_block (struct i2c_client *client, encoder->reg[reg++] = data[1]; len -= 2; data += 2; - } while (len >= 2 && data[0] == reg && - block_len < 32); - if ((ret = i2c_master_send(client, block_data, - block_len)) < 0) + } while (len >= 2 && data[0] == reg && block_len < 32); + ret = i2c_master_send(client, block_data, block_len); + if (ret < 0) break; } } else { /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; - if ((ret = saa7185_write(client, reg, - *data++)) < 0) + ret = saa7185_write(client, reg, *data++); + if (ret < 0) break; len -= 2; } @@ -241,15 +214,11 @@ static const unsigned char init_ntsc[] = { 0x66, 0x21, /* FSC3 */ }; -static int -saa7185_command (struct i2c_client *client, - unsigned int cmd, - void *arg) +static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) { struct saa7185 *encoder = i2c_get_clientdata(client); switch (cmd) { - case 0: saa7185_write_block(client, init_common, sizeof(init_common)); @@ -265,7 +234,6 @@ saa7185_command (struct i2c_client *client, sizeof(init_pal)); break; } - break; case ENCODER_GET_CAPABILITIES: @@ -277,8 +245,8 @@ saa7185_command (struct i2c_client *client, VIDEO_ENCODER_SECAM | VIDEO_ENCODER_CCIR; cap->inputs = 1; cap->outputs = 1; - } break; + } case ENCODER_SET_NORM: { @@ -287,7 +255,6 @@ saa7185_command (struct i2c_client *client, //saa7185_write_block(client, init_common, sizeof(init_common)); switch (*iarg) { - case VIDEO_MODE_NTSC: saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); @@ -301,11 +268,10 @@ saa7185_command (struct i2c_client *client, case VIDEO_MODE_SECAM: default: return -EINVAL; - } encoder->norm = *iarg; - } break; + } case ENCODER_SET_INPUT: { @@ -315,7 +281,6 @@ saa7185_command (struct i2c_client *client, *iarg = 1: input is from ZR36060 */ switch (*iarg) { - case 0: /* Switch RTCE to 1 */ saa7185_write(client, 0x61, @@ -333,21 +298,19 @@ saa7185_command (struct i2c_client *client, default: return -EINVAL; - } - } break; + } case ENCODER_SET_OUTPUT: { int *iarg = arg; /* not much choice of outputs */ - if (*iarg != 0) { + if (*iarg != 0) return -EINVAL; - } - } break; + } case ENCODER_ENABLE_OUTPUT: { @@ -357,8 +320,8 @@ saa7185_command (struct i2c_client *client, saa7185_write(client, 0x61, (encoder->reg[0x61] & 0xbf) | (encoder->enable ? 0x00 : 0x40)); - } break; + } default: return -EINVAL; @@ -369,138 +332,69 @@ saa7185_command (struct i2c_client *client, /* ----------------------------------------------------------------------- */ -/* - * Generic i2c probe - * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' - */ -static unsigned short normal_i2c[] = { I2C_SAA7185 >> 1, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; -static unsigned short ignore = I2C_CLIENT_END; +I2C_CLIENT_INSMOD; -static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_i2c, - .probe = &ignore, - .ignore = &ignore, -}; - -static struct i2c_driver i2c_driver_saa7185; - -static int -saa7185_detect_client (struct i2c_adapter *adapter, - int address, - int kind) +static int saa7185_probe(struct i2c_client *client, + const struct i2c_device_id *id) { int i; - struct i2c_client *client; struct saa7185 *encoder; - dprintk(1, - KERN_INFO - "saa7185.c: detecting saa7185 client on address 0x%x\n", - address << 1); - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return 0; + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) - return -ENOMEM; - client->addr = address; - client->adapter = adapter; - client->driver = &i2c_driver_saa7185; - strlcpy(I2C_NAME(client), "saa7185", sizeof(I2C_NAME(client))); + v4l_info(client, "chip found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL); - if (encoder == NULL) { - kfree(client); + if (encoder == NULL) return -ENOMEM; - } encoder->norm = VIDEO_MODE_NTSC; encoder->enable = 1; i2c_set_clientdata(client, encoder); - i = i2c_attach_client(client); - if (i) { - kfree(client); - kfree(encoder); - return i; - } - i = saa7185_write_block(client, init_common, sizeof(init_common)); - if (i >= 0) { - i = saa7185_write_block(client, init_ntsc, - sizeof(init_ntsc)); - } - if (i < 0) { - dprintk(1, KERN_ERR "%s_attach: init error %d\n", - I2C_NAME(client), i); - } else { - dprintk(1, - KERN_INFO - "%s_attach: chip version %d at address 0x%x\n", - I2C_NAME(client), saa7185_read(client) >> 5, - client->addr << 1); - } - + if (i >= 0) + i = saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); + if (i < 0) + v4l_dbg(1, debug, client, "init error %d\n", i); + else + v4l_dbg(1, debug, client, "revision 0x%x\n", + saa7185_read(client) >> 5); return 0; } -static int -saa7185_attach_adapter (struct i2c_adapter *adapter) -{ - dprintk(1, - KERN_INFO - "saa7185.c: starting probe for adapter %s (0x%x)\n", - I2C_NAME(adapter), adapter->id); - return i2c_probe(adapter, &addr_data, &saa7185_detect_client); -} - -static int -saa7185_detach_client (struct i2c_client *client) +static int saa7185_remove(struct i2c_client *client) { struct saa7185 *encoder = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } saa7185_write(client, 0x61, (encoder->reg[0x61]) | 0x40); /* SW: output off is active */ //saa7185_write(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */ kfree(encoder); - kfree(client); - return 0; } /* ----------------------------------------------------------------------- */ -static struct i2c_driver i2c_driver_saa7185 = { - .driver = { - .name = "saa7185", /* name */ - }, - - .id = I2C_DRIVERID_SAA7185B, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id saa7185_id[] = { + { "saa7185", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, saa7185_id); +#endif - .attach_adapter = saa7185_attach_adapter, - .detach_client = saa7185_detach_client, +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "saa7185", + .driverid = I2C_DRIVERID_SAA7185B, .command = saa7185_command, + .probe = saa7185_probe, + .remove = saa7185_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = saa7185_id, +#endif }; - -static int __init -saa7185_init (void) -{ - return i2c_add_driver(&i2c_driver_saa7185); -} - -static void __exit -saa7185_exit (void) -{ - i2c_del_driver(&i2c_driver_saa7185); -} - -module_init(saa7185_init); -module_exit(saa7185_exit); diff --git a/linux/drivers/media/video/stk-webcam.c b/linux/drivers/media/video/stk-webcam.c index 8c1817a47..f606300e8 100644 --- a/linux/drivers/media/video/stk-webcam.c +++ b/linux/drivers/media/video/stk-webcam.c @@ -27,7 +27,6 @@ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/slab.h> -#include <linux/kref.h> #include <linux/usb.h> #include <linux/mm.h> @@ -561,7 +560,7 @@ static void stk_clean_iso(struct stk_camera *dev) urb = dev->isobufs[i].urb; if (urb) { - if (atomic_read(&dev->urbs_used)) + if (atomic_read(&dev->urbs_used) && is_present(dev)) usb_kill_urb(urb); usb_free_urb(urb); } @@ -690,18 +689,14 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) { struct stk_camera *dev = fp->private_data; - if (dev->owner != fp) { - usb_autopm_put_interface(dev->interface); - return 0; + if (dev->owner == fp) { + stk_stop_stream(dev); + stk_free_buffers(dev); + dev->owner = NULL; } - stk_stop_stream(dev); - - stk_free_buffers(dev); - - dev->owner = NULL; - - usb_autopm_put_interface(dev->interface); + if(is_present(dev)) + usb_autopm_put_interface(dev->interface); return 0; } @@ -715,9 +710,6 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, struct stk_sio_buffer *sbuf; struct stk_camera *dev = fp->private_data; - if (dev == NULL) - return -EIO; - if (!is_present(dev)) return -EIO; if (dev->owner && dev->owner != fp) @@ -774,9 +766,6 @@ static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait) { struct stk_camera *dev = fp->private_data; - if (dev == NULL) - return -ENODEV; - poll_wait(fp, &dev->wait_frame, wait); if (!is_present(dev)) @@ -1437,7 +1426,7 @@ static void stk_camera_disconnect(struct usb_interface *interface) wake_up_interruptible(&dev->wait_frame); stk_remove_sysfs_files(&dev->vdev); - STK_INFO("Syntek USB2.0 Camera release resources" + STK_INFO("Syntek USB2.0 Camera release resources " "video device /dev/video%d\n", dev->vdev.minor); video_unregister_device(&dev->vdev); diff --git a/linux/drivers/media/video/stk-webcam.h b/linux/drivers/media/video/stk-webcam.h index 084a85bdd..9f6736637 100644 --- a/linux/drivers/media/video/stk-webcam.h +++ b/linux/drivers/media/video/stk-webcam.h @@ -122,7 +122,6 @@ struct stk_camera { #define vdev_to_camera(d) container_of(d, struct stk_camera, vdev) -void stk_camera_delete(struct kref *); int stk_camera_write_reg(struct stk_camera *, u16, u8); int stk_camera_read_reg(struct stk_camera *, u16, int *); diff --git a/linux/drivers/media/video/videobuf-dvb.c b/linux/drivers/media/video/videobuf-dvb.c index d9979ab26..33e2f2b2b 100644 --- a/linux/drivers/media/video/videobuf-dvb.c +++ b/linux/drivers/media/video/videobuf-dvb.c @@ -140,29 +140,78 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed) } /* ------------------------------------------------------------------ */ +/* Register a single adapter and one or more frontends */ +int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f, + struct module *module, + void *adapter_priv, + struct device *device, + short *adapter_nr, + int mfe_shared) +{ + struct list_head *list, *q; + struct videobuf_dvb_frontend *fe; + int res = -EINVAL; + + fe = videobuf_dvb_get_frontend(f, 1); + if (!fe) { + printk(KERN_WARNING "Unable to register the adapter which has no frontends\n"); + goto err; + } + + /* Bring up the adapter */ + res = videobuf_dvb_register_adapter(f, module, adapter_priv, device, fe->dvb.name, adapter_nr, mfe_shared); + if (res < 0) { + printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res); + goto err; + } -int videobuf_dvb_register(struct videobuf_dvb *dvb, + /* Attach all of the frontends to the adapter */ + mutex_lock(&f->lock); + list_for_each_safe(list, q, &f->frontend.felist) { + fe = list_entry(list, struct videobuf_dvb_frontend, felist); + + res = videobuf_dvb_register_frontend(&f->adapter, &fe->dvb); + if (res < 0) { + printk(KERN_WARNING "%s: videobuf_dvb_register_frontend failed (errno = %d)\n", + fe->dvb.name, res); + } + } + mutex_unlock(&f->lock); + +err: + return res; +} + +int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe, struct module *module, void *adapter_priv, struct device *device, - short *adapter_nr) + char *adapter_name, + short *adapter_nr, + int mfe_shared) { int result; - mutex_init(&dvb->lock); + mutex_init(&fe->lock); /* register adapter */ - result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device, - adapter_nr); + result = dvb_register_adapter(&fe->adapter, adapter_name, module, device, adapter_nr); if (result < 0) { printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", - dvb->name, result); - goto fail_adapter; + adapter_name, result); } - dvb->adapter.priv = adapter_priv; + fe->adapter.priv = adapter_priv; + fe->adapter.mfe_shared = mfe_shared; + + return result; +} + +int videobuf_dvb_register_frontend(struct dvb_adapter *adapter, struct videobuf_dvb *dvb) +{ + int result; /* register frontend */ - result = dvb_register_frontend(&dvb->adapter, dvb->frontend); + result = dvb_register_frontend(adapter, dvb->frontend); if (result < 0) { printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", dvb->name, result); @@ -188,7 +237,8 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb, dvb->dmxdev.filternum = 256; dvb->dmxdev.demux = &dvb->demux.dmx; dvb->dmxdev.capabilities = 0; - result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); + result = dvb_dmxdev_init(&dvb->dmxdev, adapter); + if (result < 0) { printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", dvb->name, result); @@ -219,7 +269,7 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb, } /* register network adapter */ - dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); + dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx); return 0; fail_fe_conn: @@ -234,25 +284,102 @@ fail_dmx: dvb_unregister_frontend(dvb->frontend); fail_frontend: dvb_frontend_detach(dvb->frontend); - dvb_unregister_adapter(&dvb->adapter); -fail_adapter: + dvb_unregister_adapter(adapter); + return result; } -void videobuf_dvb_unregister(struct videobuf_dvb *dvb) +void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f) { - dvb_net_release(&dvb->net); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); - dvb_dmxdev_release(&dvb->dmxdev); - dvb_dmx_release(&dvb->demux); - dvb_unregister_frontend(dvb->frontend); - dvb_frontend_detach(dvb->frontend); - dvb_unregister_adapter(&dvb->adapter); + struct list_head *list, *q; + struct videobuf_dvb_frontend *fe; + + mutex_lock(&f->lock); + list_for_each_safe(list, q, &f->frontend.felist) { + fe = list_entry(list, struct videobuf_dvb_frontend, felist); + + dvb_net_release(&fe->dvb.net); + fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, &fe->dvb.fe_mem); + fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, &fe->dvb.fe_hw); + dvb_dmxdev_release(&fe->dvb.dmxdev); + dvb_dmx_release(&fe->dvb.demux); + dvb_unregister_frontend(fe->dvb.frontend); + dvb_frontend_detach(fe->dvb.frontend); + + list_del(list); + kfree(fe); + } + mutex_unlock(&f->lock); + + dvb_unregister_adapter(&f->adapter); +} + +struct videobuf_dvb_frontend * videobuf_dvb_get_frontend(struct videobuf_dvb_frontends *f, int id) +{ + struct list_head *list, *q; + struct videobuf_dvb_frontend *fe, *ret = NULL; + + mutex_lock(&f->lock); + + list_for_each_safe(list, q, &f->frontend.felist) { + fe = list_entry(list, struct videobuf_dvb_frontend, felist); + if (fe->id == id) { + ret = fe; + break; + } + } + + mutex_unlock(&f->lock); + + return ret; +} + +int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f, struct dvb_frontend *p) +{ + struct list_head *list, *q; + struct videobuf_dvb_frontend *fe = NULL; + int ret = 0; + + mutex_lock(&f->lock); + + list_for_each_safe(list, q, &f->frontend.felist) { + fe = list_entry(list, struct videobuf_dvb_frontend, felist); + if (fe->dvb.frontend == p) { + ret = fe->id; + break; + } + } + + mutex_unlock(&f->lock); + + return ret; +} + +struct videobuf_dvb_frontend * videobuf_dvb_alloc_frontend(void *private, struct videobuf_dvb_frontends *f, int id) +{ + struct videobuf_dvb_frontend *fe; + + fe = kzalloc(sizeof(struct videobuf_dvb_frontend),GFP_KERNEL); + if (fe == NULL) + goto fail_alloc; + + fe->dev = private; + fe->id = id; + mutex_init(&fe->dvb.lock); + + mutex_lock(&f->lock); + list_add_tail(&fe->felist,&f->frontend.felist); + mutex_unlock(&f->lock); + +fail_alloc: + return fe; } -EXPORT_SYMBOL(videobuf_dvb_register); -EXPORT_SYMBOL(videobuf_dvb_unregister); +EXPORT_SYMBOL(videobuf_dvb_register_bus); +EXPORT_SYMBOL(videobuf_dvb_unregister_bus); +EXPORT_SYMBOL(videobuf_dvb_alloc_frontend); +EXPORT_SYMBOL(videobuf_dvb_get_frontend); +EXPORT_SYMBOL(videobuf_dvb_find_frontend); /* ------------------------------------------------------------------ */ /* diff --git a/linux/drivers/media/video/vpx3220.c b/linux/drivers/media/video/vpx3220.c index 896af1a12..5f368a1be 100644 --- a/linux/drivers/media/video/vpx3220.c +++ b/linux/drivers/media/video/vpx3220.c @@ -22,33 +22,22 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/types.h> -#include <linux/slab.h> - -#include <asm/io.h> #include <asm/uaccess.h> - #include <linux/i2c.h> - -#define I2C_NAME(x) (x)->name - -#include "compat.h" -#include <linux/videodev.h> #include <media/v4l2-common.h> +#include <media/v4l2-i2c-drv-legacy.h> +#include <linux/videodev.h> #include <linux/video_decoder.h> +#include "compat.h" -#define I2C_VPX3220 0x86 -#define VPX3220_DEBUG KERN_DEBUG "vpx3220: " +MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver"); +MODULE_AUTHOR("Laurent Pinchart"); +MODULE_LICENSE("GPL"); static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -#define dprintk(num, format, args...) \ - do { \ - if (debug >= num) \ - printk(format, ##args); \ - } while (0) - #define VPX_TIMEOUT_COUNT 10 /* ----------------------------------------------------------------------- */ @@ -68,10 +57,8 @@ struct vpx3220 { static char *inputs[] = { "internal", "composite", "svideo" }; /* ----------------------------------------------------------------------- */ -static inline int -vpx3220_write (struct i2c_client *client, - u8 reg, - u8 value) + +static inline int vpx3220_write(struct i2c_client *client, u8 reg, u8 value) { struct vpx3220 *decoder = i2c_get_clientdata(client); @@ -79,15 +66,12 @@ vpx3220_write (struct i2c_client *client, return i2c_smbus_write_byte_data(client, reg, value); } -static inline int -vpx3220_read (struct i2c_client *client, - u8 reg) +static inline int vpx3220_read(struct i2c_client *client, u8 reg) { return i2c_smbus_read_byte_data(client, reg); } -static int -vpx3220_fp_status (struct i2c_client *client) +static int vpx3220_fp_status(struct i2c_client *client) { unsigned char status; unsigned int i; @@ -107,14 +91,11 @@ vpx3220_fp_status (struct i2c_client *client) return -1; } -static int -vpx3220_fp_write (struct i2c_client *client, - u8 fpaddr, - u16 data) +static int vpx3220_fp_write(struct i2c_client *client, u8 fpaddr, u16 data) { /* Write the 16-bit address to the FPWR register */ if (i2c_smbus_write_word_data(client, 0x27, swab16(fpaddr)) == -1) { - dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__); + v4l_dbg(1, debug, client, "%s: failed\n", __func__); return -1; } @@ -123,22 +104,20 @@ vpx3220_fp_write (struct i2c_client *client, /* Write the 16-bit data to the FPDAT register */ if (i2c_smbus_write_word_data(client, 0x28, swab16(data)) == -1) { - dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__); + v4l_dbg(1, debug, client, "%s: failed\n", __func__); return -1; } return 0; } -static u16 -vpx3220_fp_read (struct i2c_client *client, - u16 fpaddr) +static u16 vpx3220_fp_read(struct i2c_client *client, u16 fpaddr) { s16 data; /* Write the 16-bit address to the FPRD register */ if (i2c_smbus_write_word_data(client, 0x26, swab16(fpaddr)) == -1) { - dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__); + v4l_dbg(1, debug, client, "%s: failed\n", __func__); return -1; } @@ -148,25 +127,22 @@ vpx3220_fp_read (struct i2c_client *client, /* Read the 16-bit data from the FPDAT register */ data = i2c_smbus_read_word_data(client, 0x28); if (data == -1) { - dprintk(1, VPX3220_DEBUG "%s: failed\n", __func__); + v4l_dbg(1, debug, client, "%s: failed\n", __func__); return -1; } return swab16(data); } -static int -vpx3220_write_block (struct i2c_client *client, - const u8 *data, - unsigned int len) +static int vpx3220_write_block(struct i2c_client *client, const u8 *data, unsigned int len) { u8 reg; int ret = -1; while (len >= 2) { reg = *data++; - if ((ret = - vpx3220_write(client, reg, *data++)) < 0) + ret = vpx3220_write(client, reg, *data++); + if (ret < 0) break; len -= 2; } @@ -174,10 +150,8 @@ vpx3220_write_block (struct i2c_client *client, return ret; } -static int -vpx3220_write_fp_block (struct i2c_client *client, - const u16 *data, - unsigned int len) +static int vpx3220_write_fp_block(struct i2c_client *client, + const u16 *data, unsigned int len) { u8 reg; int ret = 0; @@ -286,25 +260,20 @@ static const unsigned short init_fp[] = { 0x4b, 0x298, /* PLL gain */ }; -static void -vpx3220_dump_i2c (struct i2c_client *client) +static void vpx3220_dump_i2c(struct i2c_client *client) { int len = sizeof(init_common); const unsigned char *data = init_common; while (len > 1) { - dprintk(1, - KERN_DEBUG "vpx3216b i2c reg 0x%02x data 0x%02x\n", + v4l_dbg(1, debug, client, "i2c reg 0x%02x data 0x%02x\n", *data, vpx3220_read(client, *data)); data += 2; len -= 2; } } -static int -vpx3220_command (struct i2c_client *client, - unsigned int cmd, - void *arg) +static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) { struct vpx3220 *decoder = i2c_get_clientdata(client); @@ -316,7 +285,6 @@ vpx3220_command (struct i2c_client *client, vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1); switch (decoder->norm) { - case VIDEO_MODE_NTSC: vpx3220_write_fp_block(client, init_ntsc, sizeof(init_ntsc) >> 1); @@ -335,21 +303,20 @@ vpx3220_command (struct i2c_client *client, sizeof(init_pal) >> 1); break; } - } break; + } case DECODER_DUMP: { vpx3220_dump_i2c(client); - } break; + } case DECODER_GET_CAPABILITIES: { struct video_decoder_capability *cap = arg; - dprintk(1, KERN_DEBUG "%s: DECODER_GET_CAPABILITIES\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "DECODER_GET_CAPABILITIES\n"); cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | @@ -358,20 +325,18 @@ vpx3220_command (struct i2c_client *client, VIDEO_DECODER_CCIR; cap->inputs = 3; cap->outputs = 1; - } break; + } case DECODER_GET_STATUS: { int res = 0, status; - dprintk(1, KERN_INFO "%s: DECODER_GET_STATUS\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "DECODER_GET_STATUS\n"); status = vpx3220_fp_read(client, 0x0f3); - dprintk(1, KERN_INFO "%s: status: 0x%04x\n", I2C_NAME(client), - status); + v4l_dbg(1, debug, client, "status: 0x%04x\n", status); if (status < 0) return status; @@ -380,7 +345,6 @@ vpx3220_command (struct i2c_client *client, res |= DECODER_STATUS_GOOD | DECODER_STATUS_COLOR; switch (status & 0x18) { - case 0x00: case 0x10: case 0x14: @@ -401,8 +365,8 @@ vpx3220_command (struct i2c_client *client, } *(int *) arg = res; - } break; + } case DECODER_SET_NORM: { @@ -414,50 +378,43 @@ vpx3220_command (struct i2c_client *client, choosen video norm */ temp_input = vpx3220_fp_read(client, 0xf2); - dprintk(1, KERN_DEBUG "%s: DECODER_SET_NORM %d\n", - I2C_NAME(client), *iarg); + v4l_dbg(1, debug, client, "DECODER_SET_NORM %d\n", *iarg); switch (*iarg) { - case VIDEO_MODE_NTSC: vpx3220_write_fp_block(client, init_ntsc, sizeof(init_ntsc) >> 1); - dprintk(1, KERN_INFO "%s: norm switched to NTSC\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "norm switched to NTSC\n"); break; case VIDEO_MODE_PAL: vpx3220_write_fp_block(client, init_pal, sizeof(init_pal) >> 1); - dprintk(1, KERN_INFO "%s: norm switched to PAL\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "norm switched to PAL\n"); break; case VIDEO_MODE_SECAM: vpx3220_write_fp_block(client, init_secam, sizeof(init_secam) >> 1); - dprintk(1, KERN_INFO "%s: norm switched to SECAM\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "norm switched to SECAM\n"); break; case VIDEO_MODE_AUTO: /* FIXME This is only preliminary support */ data = vpx3220_fp_read(client, 0xf2) & 0x20; vpx3220_fp_write(client, 0xf2, 0x00c0 | data); - dprintk(1, KERN_INFO "%s: norm switched to Auto\n", - I2C_NAME(client)); + v4l_dbg(1, debug, client, "norm switched to AUTO\n"); break; default: return -EINVAL; - } decoder->norm = *iarg; /* And here we set the backed up video input again */ vpx3220_fp_write(client, 0xf2, temp_input | 0x0010); udelay(10); - } break; + } case DECODER_SET_INPUT: { @@ -476,8 +433,7 @@ vpx3220_command (struct i2c_client *client, if (*iarg < 0 || *iarg > 2) return -EINVAL; - dprintk(1, KERN_INFO "%s: input switched to %s\n", - I2C_NAME(client), inputs[*iarg]); + v4l_dbg(1, debug, client, "input switched to %s\n", inputs[*iarg]); vpx3220_write(client, 0x33, input[*iarg][0]); @@ -489,8 +445,8 @@ vpx3220_command (struct i2c_client *client, data | (input[*iarg][1] << 5) | 0x0010); udelay(10); - } break; + } case DECODER_SET_OUTPUT: { @@ -500,19 +456,18 @@ vpx3220_command (struct i2c_client *client, if (*iarg != 0) { return -EINVAL; } - } break; + } case DECODER_ENABLE_OUTPUT: { int *iarg = arg; - dprintk(1, KERN_DEBUG "%s: DECODER_ENABLE_OUTPUT %d\n", - I2C_NAME(client), *iarg); + v4l_dbg(1, debug, client, "DECODER_ENABLE_OUTPUT %d\n", *iarg); vpx3220_write(client, 0xf2, (*iarg ? 0x1b : 0x00)); - } break; + } case DECODER_SET_PICTURE: { @@ -543,8 +498,8 @@ vpx3220_command (struct i2c_client *client, vpx3220_fp_write(client, 0x1c, ((decoder->hue - 32768) >> 6) & 0xFFF); } - } break; + } default: return -EINVAL; @@ -553,8 +508,7 @@ vpx3220_command (struct i2c_client *client, return 0; } -static int -vpx3220_init_client (struct i2c_client *client) +static int vpx3220_init_client(struct i2c_client *client) { vpx3220_write_block(client, init_common, sizeof(init_common)); vpx3220_write_fp_block(client, init_fp, sizeof(init_fp) >> 1); @@ -568,115 +522,26 @@ vpx3220_init_client (struct i2c_client *client) * Client management code */ -/* - * Generic i2c probe - * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' - */ -static unsigned short normal_i2c[] = - { I2C_VPX3220 >> 1, (I2C_VPX3220 >> 1) + 4, - I2C_CLIENT_END -}; +static unsigned short normal_i2c[] = { 0x86 >> 1, 0x8e >> 1, I2C_CLIENT_END }; -static unsigned short ignore = I2C_CLIENT_END; - -static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_i2c, - .probe = &ignore, - .ignore = &ignore, -}; - -static struct i2c_driver vpx3220_i2c_driver; - -static int -vpx3220_detach_client (struct i2c_client *client) -{ - struct vpx3220 *decoder = i2c_get_clientdata(client); - int err; - - err = i2c_detach_client(client); - if (err) { - return err; - } - - kfree(decoder); - kfree(client); - - return 0; -} +I2C_CLIENT_INSMOD; -static int -vpx3220_detect_client (struct i2c_adapter *adapter, - int address, - int kind) +static int vpx3220_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - int err; - struct i2c_client *client; struct vpx3220 *decoder; - - dprintk(1, VPX3220_DEBUG "%s\n", __func__); + const char *name = NULL; + u8 ver; + u16 pn; /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality - (adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) - return 0; - - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (client == NULL) { - return -ENOMEM; - } - - client->addr = address; - client->adapter = adapter; - client->driver = &vpx3220_i2c_driver; - - /* Check for manufacture ID and part number */ - if (kind < 0) { - u8 id; - u16 pn; - - id = vpx3220_read(client, 0x00); - if (id != 0xec) { - dprintk(1, - KERN_INFO - "vpx3220_attach: Wrong manufacturer ID (0x%02x)\n", - id); - kfree(client); - return 0; - } - - pn = (vpx3220_read(client, 0x02) << 8) + - vpx3220_read(client, 0x01); - switch (pn) { - case 0x4680: - strlcpy(I2C_NAME(client), "vpx3220a", - sizeof(I2C_NAME(client))); - break; - case 0x4260: - strlcpy(I2C_NAME(client), "vpx3216b", - sizeof(I2C_NAME(client))); - break; - case 0x4280: - strlcpy(I2C_NAME(client), "vpx3214c", - sizeof(I2C_NAME(client))); - break; - default: - dprintk(1, - KERN_INFO - "%s: Wrong part number (0x%04x)\n", - __func__, pn); - kfree(client); - return 0; - } - } else { - strlcpy(I2C_NAME(client), "forced vpx32xx", - sizeof(I2C_NAME(client))); - } + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL); - if (decoder == NULL) { - kfree(client); + if (decoder == NULL) return -ENOMEM; - } decoder->norm = VIDEO_MODE_PAL; decoder->input = 0; decoder->enable = 1; @@ -686,63 +551,56 @@ vpx3220_detect_client (struct i2c_adapter *adapter, decoder->sat = 32768; i2c_set_clientdata(client, decoder); - err = i2c_attach_client(client); - if (err) { - kfree(client); - kfree(decoder); - return err; + ver = i2c_smbus_read_byte_data(client, 0x00); + pn = (i2c_smbus_read_byte_data(client, 0x02) << 8) + + i2c_smbus_read_byte_data(client, 0x01); + if (ver == 0xec) { + switch (pn) { + case 0x4680: + name = "vpx3220a"; + break; + case 0x4260: + name = "vpx3216b"; + break; + case 0x4280: + name = "vpx3214c"; + break; + } } - - dprintk(1, KERN_INFO "%s: vpx32xx client found at address 0x%02x\n", - I2C_NAME(client), client->addr << 1); + if (name) + v4l_info(client, "%s found @ 0x%x (%s)\n", name, + client->addr << 1, client->adapter->name); + else + v4l_info(client, "chip (%02x:%04x) found @ 0x%x (%s)\n", + ver, pn, client->addr << 1, client->adapter->name); vpx3220_init_client(client); - return 0; } -static int -vpx3220_attach_adapter (struct i2c_adapter *adapter) +static int vpx3220_remove(struct i2c_client *client) { - int ret; - - ret = i2c_probe(adapter, &addr_data, &vpx3220_detect_client); - dprintk(1, VPX3220_DEBUG "%s: i2c_probe returned %d\n", - __func__, ret); - return ret; + kfree(i2c_get_clientdata(client)); + return 0; } -/* ----------------------------------------------------------------------- - * Driver initialization and cleanup code - */ - -static struct i2c_driver vpx3220_i2c_driver = { - .driver = { - .name = "vpx3220", - }, - - .id = I2C_DRIVERID_VPX3220, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id vpx3220_id[] = { + { "vpx3220a", 0 }, + { "vpx3216b", 0 }, + { "vpx3214c", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, vpx3220_id); +#endif - .attach_adapter = vpx3220_attach_adapter, - .detach_client = vpx3220_detach_client, +static struct v4l2_i2c_driver_data v4l2_i2c_data = { + .name = "vpx3220", + .driverid = I2C_DRIVERID_VPX3220, .command = vpx3220_command, + .probe = vpx3220_probe, + .remove = vpx3220_remove, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = vpx3220_id, +#endif }; - -static int __init -vpx3220_init (void) -{ - return i2c_add_driver(&vpx3220_i2c_driver); -} - -static void __exit -vpx3220_cleanup (void) -{ - i2c_del_driver(&vpx3220_i2c_driver); -} - -module_init(vpx3220_init); -module_exit(vpx3220_cleanup); - -MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver"); -MODULE_AUTHOR("Laurent Pinchart"); -MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/video/zoran/zoran_card.c b/linux/drivers/media/video/zoran/zoran_card.c index 081b72a45..d5026ae51 100644 --- a/linux/drivers/media/video/zoran/zoran_card.c +++ b/linux/drivers/media/video/zoran/zoran_card.c @@ -818,6 +818,7 @@ zoran_register_i2c (struct zoran *zr) memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template, sizeof(struct i2c_algo_bit_data)); zr->i2c_algo.data = zr; + zr->i2c_adapter.class = I2C_CLASS_TV_ANALOG; zr->i2c_adapter.id = I2C_HW_B_ZR36067; zr->i2c_adapter.client_register = zoran_i2c_client_register; zr->i2c_adapter.client_unregister = zoran_i2c_client_unregister; |