From b590fcfdc57bf6463013c041449c69751049fda5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 29 Jan 2009 22:24:01 -0500 Subject: dib0700: add data debug to dib0700_i2c_xfer_new From: Michael Krufky Data debug for i2c transactions was provided by the functions called by dib0700_i2c_xfer_legacy, but not dib0700_i2c_xfer_new. This patch adds the missing data debug dumps to dib0700_i2c_xfer_new. Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/dvb-usb/dib0700_core.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c index 46c425643..ef5c89c82 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -158,6 +158,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, err("i2c read error (status = %d)\n", result); break; } + + deb_data("<<< "); + debug_dump(msg[i].buf, msg[i].len, deb_data); + } else { /* Write request */ buf[0] = REQUEST_NEW_I2C_WRITE; @@ -169,6 +173,9 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, /* The Actual i2c payload */ memcpy(&buf[4], msg[i].buf, msg[i].len); + deb_data(">>> "); + debug_dump(buf, msg[i].len + 4, deb_data); + result = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), REQUEST_NEW_I2C_WRITE, -- cgit v1.2.3 From 564916a52c7355ed4408de16431f67d66461363f Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 6 Jan 2009 12:10:59 -0500 Subject: tveeprom: update to include Hauppauge tuners 151-155 From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/video/tveeprom.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/video/tveeprom.c b/linux/drivers/media/video/tveeprom.c index de93ac3b5..acd601a52 100644 --- a/linux/drivers/media/video/tveeprom.c +++ b/linux/drivers/media/video/tveeprom.c @@ -263,6 +263,11 @@ hauppauge_tuner[] = { TUNER_PHILIPS_TDA8290, "Philips 18271_8295"}, /* 150-159 */ { TUNER_ABSENT, "Xceive XC5000"}, + { TUNER_ABSENT, "Xceive XC3028L"}, + { TUNER_ABSENT, "NXP 18271C2_716x"}, + { TUNER_ABSENT, "Xceive XC4000"}, + { TUNER_ABSENT, "Dibcom 7070"}, + { TUNER_PHILIPS_TDA8290, "NXP 18271C2"}, }; /* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are -- cgit v1.2.3 From 2d4f2fbb05799ae2c5d8cd0c001364ab3f3dbf24 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 11 Jan 2009 09:12:43 +0000 Subject: dvb: constify VFTs From: Jan Engelhardt dvb: constify VFTs Signed-off-by: Jan Engelhardt Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/bt8xx/dst_ca.c | 2 +- linux/drivers/media/dvb/dvb-core/dmxdev.c | 2 +- linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c | 2 +- linux/drivers/media/dvb/dvb-core/dvb_frontend.c | 2 +- linux/drivers/media/dvb/dvb-core/dvb_net.c | 2 +- linux/drivers/media/dvb/dvb-core/dvbdev.c | 4 ++-- linux/drivers/media/dvb/dvb-core/dvbdev.h | 2 +- linux/drivers/media/dvb/ttpci/av7110.c | 2 +- linux/drivers/media/dvb/ttpci/av7110_av.c | 4 ++-- linux/drivers/media/dvb/ttpci/av7110_ca.c | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/bt8xx/dst_ca.c b/linux/drivers/media/dvb/bt8xx/dst_ca.c index 0b462e7bb..68aef6786 100644 --- a/linux/drivers/media/dvb/bt8xx/dst_ca.c +++ b/linux/drivers/media/dvb/bt8xx/dst_ca.c @@ -778,7 +778,7 @@ static ssize_t dst_ca_write(struct file *file, const char __user *buffer, size_t return 0; } -static struct file_operations dst_ca_fops = { +static const struct file_operations dst_ca_fops = { .owner = THIS_MODULE, .ioctl = dst_ca_ioctl, .open = dst_ca_open, diff --git a/linux/drivers/media/dvb/dvb-core/dmxdev.c b/linux/drivers/media/dvb/dvb-core/dmxdev.c index 0c733c66a..cc143929a 100644 --- a/linux/drivers/media/dvb/dvb-core/dmxdev.c +++ b/linux/drivers/media/dvb/dvb-core/dmxdev.c @@ -1026,7 +1026,7 @@ static int dvb_demux_release(struct inode *inode, struct file *file) return ret; } -static struct file_operations dvb_demux_fops = { +static const struct file_operations dvb_demux_fops = { .owner = THIS_MODULE, .read = dvb_demux_read, .ioctl = dvb_demux_ioctl, diff --git a/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index 19965a055..02a4e94cb 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c @@ -1608,7 +1608,7 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait) EXPORT_SYMBOL(dvb_ca_en50221_init); -static struct file_operations dvb_ca_fops = { +static const struct file_operations dvb_ca_fops = { .owner = THIS_MODULE, .read = dvb_ca_en50221_io_read, .write = dvb_ca_en50221_io_write, diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c index 01a9ceb37..05b327403 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1989,7 +1989,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file) return ret; } -static struct file_operations dvb_frontend_fops = { +static const struct file_operations dvb_frontend_fops = { .owner = THIS_MODULE, .ioctl = dvb_generic_ioctl, .poll = dvb_frontend_poll, diff --git a/linux/drivers/media/dvb/dvb-core/dvb_net.c b/linux/drivers/media/dvb/dvb-core/dvb_net.c index f0cd3b8ed..5f4856c6d 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_net.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_net.c @@ -1526,7 +1526,7 @@ static int dvb_net_close(struct inode *inode, struct file *file) } -static struct file_operations dvb_net_fops = { +static const struct file_operations dvb_net_fops = { .owner = THIS_MODULE, .ioctl = dvb_net_ioctl, .open = dvb_generic_open, diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.c b/linux/drivers/media/dvb/dvb-core/dvbdev.c index 940114768..4609e3ebd 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.c +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c @@ -237,8 +237,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, dvbdev->fops = dvbdevfops; init_waitqueue_head (&dvbdev->wait_queue); - memcpy(dvbdev->fops, template->fops, sizeof(struct file_operations)); - dvbdev->fops->owner = adap->module; + memcpy(dvbdevfops, template->fops, sizeof(struct file_operations)); + dvbdevfops->owner = adap->module; list_add_tail (&dvbdev->list_head, &adap->device_list); diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.h b/linux/drivers/media/dvb/dvb-core/dvbdev.h index dca49cf96..79927305e 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.h +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.h @@ -71,7 +71,7 @@ struct dvb_adapter { struct dvb_device { struct list_head list_head; - struct file_operations *fops; + const struct file_operations *fops; struct dvb_adapter *adapter; int type; int minor; diff --git a/linux/drivers/media/dvb/ttpci/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c index b99057a68..841590ed5 100644 --- a/linux/drivers/media/dvb/ttpci/av7110.c +++ b/linux/drivers/media/dvb/ttpci/av7110.c @@ -728,7 +728,7 @@ static int dvb_osd_ioctl(struct inode *inode, struct file *file, } -static struct file_operations dvb_osd_fops = { +static const struct file_operations dvb_osd_fops = { .owner = THIS_MODULE, .ioctl = dvb_generic_ioctl, .open = dvb_generic_open, diff --git a/linux/drivers/media/dvb/ttpci/av7110_av.c b/linux/drivers/media/dvb/ttpci/av7110_av.c index bdc62acf2..e4d0900d5 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_av.c +++ b/linux/drivers/media/dvb/ttpci/av7110_av.c @@ -1456,7 +1456,7 @@ static int dvb_audio_release(struct inode *inode, struct file *file) * driver registration ******************************************************************************/ -static struct file_operations dvb_video_fops = { +static const struct file_operations dvb_video_fops = { .owner = THIS_MODULE, .write = dvb_video_write, .ioctl = dvb_generic_ioctl, @@ -1474,7 +1474,7 @@ static struct dvb_device dvbdev_video = { .kernel_ioctl = dvb_video_ioctl, }; -static struct file_operations dvb_audio_fops = { +static const struct file_operations dvb_audio_fops = { .owner = THIS_MODULE, .write = dvb_audio_write, .ioctl = dvb_generic_ioctl, diff --git a/linux/drivers/media/dvb/ttpci/av7110_ca.c b/linux/drivers/media/dvb/ttpci/av7110_ca.c index 261135ded..c7a65b154 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_ca.c +++ b/linux/drivers/media/dvb/ttpci/av7110_ca.c @@ -345,7 +345,7 @@ static ssize_t dvb_ca_read(struct file *file, char __user *buf, return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos); } -static struct file_operations dvb_ca_fops = { +static const struct file_operations dvb_ca_fops = { .owner = THIS_MODULE, .read = dvb_ca_read, .write = dvb_ca_write, -- cgit v1.2.3 From 6c4ccc0cd8e4160824698caa2bf36b96716a6a04 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 14 Jan 2009 16:17:59 +0000 Subject: lnbp21: documentation about the system register From: Hans Werner Here is a patch which adds some documentation about meanings of the the lnbp21 system register bits. Signed-off-by: Hans Werner Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/lnbp21.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/frontends/lnbp21.h b/linux/drivers/media/dvb/frontends/lnbp21.h index 8fe094bd9..b87458874 100644 --- a/linux/drivers/media/dvb/frontends/lnbp21.h +++ b/linux/drivers/media/dvb/frontends/lnbp21.h @@ -28,14 +28,14 @@ #define _LNBP21_H /* system register bits */ -#define LNBP21_OLF 0x01 -#define LNBP21_OTF 0x02 -#define LNBP21_EN 0x04 -#define LNBP21_VSEL 0x08 -#define LNBP21_LLC 0x10 -#define LNBP21_TEN 0x20 -#define LNBP21_ISEL 0x40 -#define LNBP21_PCL 0x80 +#define LNBP21_OLF 0x01 /* [R-only] 0=OK; 1=over current limit flag*/ +#define LNBP21_OTF 0x02 /* [R-only] 0=OK; 1=over temperature flag (150degC typ) */ +#define LNBP21_EN 0x04 /* [RW] 0=disable LNB power, enable loopthrough; 1=enable LNB power, disable loopthrough*/ +#define LNBP21_VSEL 0x08 /* [RW] 0=low voltage (13/14V, vert pol); 1=high voltage (18/19V,horiz pol) */ +#define LNBP21_LLC 0x10 /* [RW] increase LNB voltage by 1V: 0=13/18V; 1=14/19V */ +#define LNBP21_TEN 0x20 /* [RW] 0=tone controlled by DSQIN pin; 1=tone enable, disable DSQIN */ +#define LNBP21_ISEL 0x40 /* [RW] current limit select 0:Iout=500-650mA,Isc=300mA ; 1:Iout=400-550mA,Isc=200mA*/ +#define LNBP21_PCL 0x80 /* [RW] short-circuit prot: 0=pulsed (dynamic) curr limiting; 1=static curr limiting*/ #include -- cgit v1.2.3 From 7987027f994d1a996d966798c87d222c639cb911 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 18 Jan 2009 23:31:26 +0000 Subject: DVB: negative internal->sub_range won't get noticed From: Roel Kluin internal->sub_range is unsigned, a negative won't get noticed. Signed-off-by: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/stb0899_algo.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/frontends/stb0899_algo.c b/linux/drivers/media/dvb/frontends/stb0899_algo.c index 3d13968a7..71037dc67 100644 --- a/linux/drivers/media/dvb/frontends/stb0899_algo.c +++ b/linux/drivers/media/dvb/frontends/stb0899_algo.c @@ -467,13 +467,14 @@ static void next_sub_range(struct stb0899_state *state) if (internal->sub_dir > 0) { old_sub_range = internal->sub_range; - internal->sub_range = MIN((internal->srch_range / 2) - + if (internal->tuner_offst + internal->sub_range / 2 >= + internal->srch_range / 2) + internal->sub_range = 0; + else + internal->sub_range = MIN((internal->srch_range / 2) - (internal->tuner_offst + internal->sub_range / 2), internal->sub_range); - if (internal->sub_range < 0) - internal->sub_range = 0; - internal->tuner_offst += (old_sub_range + internal->sub_range) / 2; } -- cgit v1.2.3 From e2dece7b3a29cf172128e7a3481940322ca5df20 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 19 Jan 2009 11:01:24 +0000 Subject: KWorld ATSC 115 all static From: Mauro Carvalho Chehab saa7134: Fix tuner access on Kworld ATSC110 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 46 +++++++++++++++-------- linux/drivers/media/video/saa7134/saa7134.h | 23 ++++++++++-- 2 files changed, 49 insertions(+), 20 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 7740c1601..9ad47eba4 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -5995,6 +5995,32 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) /* ----------------------------------------------------------- */ +static void nxt200x_gate_ctrl(struct saa7134_dev *dev, int open) +{ + /* enable tuner */ + int i; + static const u8 buffer [][2] = { + { 0x10, 0x12 }, + { 0x13, 0x04 }, + { 0x16, 0x00 }, + { 0x14, 0x04 }, + { 0x17, 0x00 }, + }; + + dev->i2c_client.addr = 0x0a; + + /* FIXME: don't know how to close the i2c gate on NXT200x */ + if (!open) + return; + + for (i = 0; i < ARRAY_SIZE(buffer); i++) + if (2 != i2c_master_send(&dev->i2c_client, + &buffer[i][0], ARRAY_SIZE(buffer[0]))) + printk(KERN_WARNING + "%s: Unable to enable tuner(%i).\n", + dev->name, i); +} + int saa7134_board_init1(struct saa7134_dev *dev) { /* Always print gpio, often manufacturers encode tuner type and other info. */ @@ -6192,6 +6218,10 @@ int saa7134_board_init1(struct saa7134_dev *dev) "are supported for now.\n", dev->name, card(dev).name, dev->name); break; + case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: + case SAA7134_BOARD_KWORLD_ATSC110: + dev->gate_ctrl = nxt200x_gate_ctrl; + break; } return 0; } @@ -6453,22 +6483,6 @@ int saa7134_board_init2(struct saa7134_dev *dev) i2c_transfer(&dev->i2c_adap, &msg, 1); break; } - case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: - case SAA7134_BOARD_KWORLD_ATSC110: - { - /* enable tuner */ - int i; - static const u8 buffer [] = { 0x10, 0x12, 0x13, 0x04, 0x16, - 0x00, 0x14, 0x04, 0x17, 0x00 }; - dev->i2c_client.addr = 0x0a; - for (i = 0; i < 5; i++) - if (2 != i2c_master_send(&dev->i2c_client, - &buffer[i*2], 2)) - printk(KERN_WARNING - "%s: Unable to enable tuner(%i).\n", - dev->name, i); - break; - } case SAA7134_BOARD_VIDEOMATE_DVBT_200: case SAA7134_BOARD_VIDEOMATE_DVBT_200A: /* The T200 and the T200A share the same pci id. Consequently, diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 9e3b37c73..040f447c6 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -594,6 +594,7 @@ struct saa7134_dev { int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg); #endif + void (*gate_ctrl)(struct saa7134_dev *dev, int open); }; /* ----------------------------------------------------------- */ @@ -623,10 +624,24 @@ struct saa7134_dev { V4L2_STD_PAL_60) #define GRP_EMPRESS (1) -#define saa_call_all(dev, o, f, args...) \ - v4l2_device_call_all(&(dev)->v4l2_dev, 0, o, f , ##args) -#define saa_call_empress(dev, o, f, args...) \ - v4l2_device_call_until_err(&(dev)->v4l2_dev, GRP_EMPRESS, o, f , ##args) +#define saa_call_all(dev, o, f, args...) do { \ + if (dev->gate_ctrl) \ + dev->gate_ctrl(dev, 1); \ + v4l2_device_call_all(&(dev)->v4l2_dev, 0, o, f , ##args); \ + if (dev->gate_ctrl) \ + dev->gate_ctrl(dev, 0); \ +} while (0) + +#define saa_call_empress(dev, o, f, args...) ({ \ + long _rc; \ + if (dev->gate_ctrl) \ + dev->gate_ctrl(dev, 1); \ + _rc = v4l2_device_call_until_err(&(dev)->v4l2_dev, \ + GRP_EMPRESS, o, f , ##args); \ + if (dev->gate_ctrl) \ + dev->gate_ctrl(dev, 0); \ + _rc; \ +}) /* ----------------------------------------------------------- */ /* saa7134-core.c */ -- cgit v1.2.3 From fd237d0264b616b7a22369b14e56952e2bc306c5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 23 Jan 2009 13:28:10 -0500 Subject: sms1xxx: add missing usb id 2040:2011 From: Michael Krufky Priority: normal Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/siano/sms-cards.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c index 4307e4e8a..79f5715c0 100644 --- a/linux/drivers/media/dvb/siano/sms-cards.c +++ b/linux/drivers/media/dvb/siano/sms-cards.c @@ -46,6 +46,8 @@ struct usb_device_id smsusb_id_table[] = { .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, { USB_DEVICE(0x2040, 0x2010), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, + { USB_DEVICE(0x2040, 0x2011), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, { USB_DEVICE(0x2040, 0x2019), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD }, { USB_DEVICE(0x2040, 0x5500), -- cgit v1.2.3 From 32ff0a94de197313d0c1838ab4ad3a051064b292 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 25 Jan 2009 23:00:16 +0000 Subject: struct device - replace bus_id with dev_name(), dev_set_name() From: Kay Sievers Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/radio/radio-tea5764.c | 3 ++- linux/drivers/media/video/v4l2-device.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-tea5764.c b/linux/drivers/media/radio/radio-tea5764.c index 328fa50ca..9194a70aa 100644 --- a/linux/drivers/media/radio/radio-tea5764.c +++ b/linux/drivers/media/radio/radio-tea5764.c @@ -302,7 +302,8 @@ static int vidioc_querycap(struct file *file, void *priv, strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver)); strlcpy(v->card, dev->name, sizeof(v->card)); - snprintf(v->bus_info, sizeof(v->bus_info), "I2C:%s", dev->dev.bus_id); + snprintf(v->bus_info, sizeof(v->bus_info), + "I2C:%s", dev_name(&dev->dev)); v->version = RADIO_VERSION; v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; diff --git a/linux/drivers/media/video/v4l2-device.c b/linux/drivers/media/video/v4l2-device.c index cf9d4c7f5..8a4b74f31 100644 --- a/linux/drivers/media/video/v4l2-device.c +++ b/linux/drivers/media/video/v4l2-device.c @@ -34,7 +34,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) spin_lock_init(&v4l2_dev->lock); v4l2_dev->dev = dev; snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s", - dev->driver->name, dev->bus_id); + dev->driver->name, dev_name(dev)); dev_set_drvdata(dev, v4l2_dev); return 0; } -- cgit v1.2.3 From b1d07a100a489df3cd03e3dc629d76bebce559f7 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Mon, 26 Jan 2009 01:07:59 -0500 Subject: s5h1409: Perform s5h1409 soft reset after tuning From: Devin Heitmueller Just like with the s5h1411, the s5h1409 needs a soft-reset in order for it to know that the tuner has been told to change frequencies. This change changes the behavior from "random tuning times between 500ms to complete tuning lock failures" to "tuning lock consistently within 700ms". Thanks to Robert Krakora for doing initial testing of the patch on the KWorld 330U. Thanks to Andy Walls for doing testing of the patch on the HVR-1600. Thanks to Michael Krufky for doing additional testing. Signed-off-by: Devin Heitmueller Signed-off-by: Michael Krufky --- linux/drivers/media/dvb/frontends/s5h1409.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/frontends/s5h1409.c b/linux/drivers/media/dvb/frontends/s5h1409.c index cf4d8936b..3e08d985d 100644 --- a/linux/drivers/media/dvb/frontends/s5h1409.c +++ b/linux/drivers/media/dvb/frontends/s5h1409.c @@ -545,9 +545,6 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe, s5h1409_enable_modulation(fe, p->u.vsb.modulation); - /* Allow the demod to settle */ - msleep(100); - if (fe->ops.tuner_ops.set_params) { if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -562,6 +559,10 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe, s5h1409_set_qam_interleave_mode(fe); } + /* Issue a reset to the demod so it knows to resync against the + newly tuned frequency */ + s5h1409_softreset(fe); + return 0; } -- cgit v1.2.3 From 2ce6b1f573b3b082749e3559d5cc6becff654172 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 29 Jan 2009 08:02:15 -0200 Subject: v4l2-device.c: Fix compilation with older kernels From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-device.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux') diff --git a/linux/drivers/media/video/v4l2-device.c b/linux/drivers/media/video/v4l2-device.c index 8a4b74f31..e84925976 100644 --- a/linux/drivers/media/video/v4l2-device.c +++ b/linux/drivers/media/video/v4l2-device.c @@ -23,6 +23,7 @@ #include #include #include +#include "compat.h" int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) { -- cgit v1.2.3 From 9cbec50918322f2de1c4b1879c4d5fc5e5064be9 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 29 Jan 2009 08:59:45 +0100 Subject: gspca - sonixj: Sensor mt9v111 added. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 223 +++++++++++++++++++++++++++---- 1 file changed, 196 insertions(+), 27 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index abe26dc7f..33cbd7945 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -46,7 +46,7 @@ struct sd { u8 red; u8 gamma; u8 vflip; /* ov7630 only */ - u8 infrared; /* mi0360 only */ + u8 infrared; /* mt9v111 only */ s8 ag_cnt; #define AG_CNT_START 13 @@ -61,10 +61,11 @@ struct sd { #define SENSOR_HV7131R 0 #define SENSOR_MI0360 1 #define SENSOR_MO4000 2 -#define SENSOR_OM6802 3 -#define SENSOR_OV7630 4 -#define SENSOR_OV7648 5 -#define SENSOR_OV7660 6 +#define SENSOR_MT9V111 3 +#define SENSOR_OM6802 4 +#define SENSOR_OV7630 5 +#define SENSOR_OV7648 6 +#define SENSOR_OV7660 7 u8 i2c_base; }; @@ -206,7 +207,7 @@ static struct ctrl sd_ctrls[] = { .set = sd_setvflip, .get = sd_getvflip, }, -/* mi0360 only */ +/* mt9v111 only */ #define INFRARED_IDX 7 { { @@ -228,18 +229,20 @@ static struct ctrl sd_ctrls[] = { static __u32 ctrl_dis[] = { (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_HV7131R 0 */ - (1 << VFLIP_IDX), + (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_MI0360 1 */ (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_MO4000 2 */ + (1 << AUTOGAIN_IDX), + /* SENSOR_MT9V111 3 */ (1 << INFRARED_IDX) | (1 << VFLIP_IDX), - /* SENSOR_OM6802 3 */ + /* SENSOR_OM6802 4 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX), - /* SENSOR_OV7630 4 */ + /* SENSOR_OV7630 5 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), - /* SENSOR_OV7648 5 */ + /* SENSOR_OV7648 6 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), - /* SENSOR_OV7660 6 */ + /* SENSOR_OV7660 7 */ }; static const struct v4l2_pix_format vga_mode[] = { @@ -294,6 +297,17 @@ static const u8 sn_mo4000[0x1c] = { 0x08, 0x00, 0x00, 0x00 }; +static const u8 sn_mt9v111[0x1c] = { +/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ + 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20, +/* reg8 reg9 rega regb regc regd rege regf */ + 0x81, 0x5c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, +/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ + 0x03, 0x00, 0x00, 0x02, 0x1c, 0x28, 0x1e, 0x40, +/* reg18 reg19 reg1a reg1b */ + 0x06, 0x00, 0x00, 0x00 +}; + static const u8 sn_om6802[0x1c] = { /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20, @@ -343,6 +357,7 @@ static const u8 *sn_tb[] = { sn_hv7131, sn_mi0360, sn_mo4000, + sn_mt9v111, sn_om6802, sn_ov7630, sn_ov7648, @@ -355,7 +370,7 @@ static const u8 gamma_def[17] = { }; #if 0 -static const u8 gamma_hv7131[17] = { +static const u8 gamma_hv7131r[17] = { 0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d, 0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5 }; @@ -402,7 +417,7 @@ static const u8 hv7131r_sensor_init[][8] = { static const u8 mi0360_sensor_init[][8] = { {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, - {0xb1, 0x5d, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10}, {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10}, {0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10}, @@ -476,6 +491,38 @@ static const u8 mo4000_sensor_init[][8] = { {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10}, {} }; +static const u8 mt9v111_sensor_init[][8] = { + {0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */ + /* delay 20 ms */ + {0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */ + {0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */ + {0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */ + {0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */ + {0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */ + {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */ + {0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */ + {0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */ + {0xb1, 0x5c, 0x07, 0x30, 0x02, 0x00, 0x00, 0x10}, /* output ctrl */ + {0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, /* shutter delay */ + {0xb1, 0x5c, 0x12, 0x00, 0xb0, 0x00, 0x00, 0x10}, /* zoom col start */ + {0xb1, 0x5c, 0x13, 0x00, 0x7c, 0x00, 0x00, 0x10}, /* zoom row start */ + {0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */ + {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */ + {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, + /*******/ + {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10}, /* shutter width */ + {0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10}, /* green1 gain */ + {0xd1, 0x5c, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10}, /* red gain */ + /*******/ + {0xb1, 0x5c, 0x06, 0x00, 0x1e, 0x00, 0x00, 0x10}, /* vert blanking */ + {0xb1, 0x5c, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10}, /* horiz blanking */ + {0xd1, 0x5c, 0x2c, 0x00, 0xad, 0x00, 0xad, 0x10}, /* blue gain */ + {0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */ + {} +}; static const u8 om6802_sensor_init[][8] = { {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10}, {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10}, @@ -742,7 +789,7 @@ static void reg_w1(struct gspca_dev *gspca_dev, u16 value, u8 data) { - PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data); + PDEBUG(D_USBO, "reg_w1 [%04x] = %02x", value, data); gspca_dev->usb_buf[0] = data; usb_control_msg(gspca_dev->dev, usb_sndctrlpipe(gspca_dev->dev, 0), @@ -758,7 +805,7 @@ static void reg_w(struct gspca_dev *gspca_dev, const u8 *buffer, int len) { - PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..", + PDEBUG(D_USBO, "reg_w [%04x] = %02x %02x ..", value, buffer[0], buffer[1]); #ifdef GSPCA_DEBUG if (len > USB_BUF_SZ) { @@ -838,7 +885,7 @@ static void i2c_r5(struct gspca_dev *gspca_dev, u8 reg) reg_r(gspca_dev, 0x0a, 5); } -static int probesensor(struct gspca_dev *gspca_dev) +static int hv7131r_probe(struct gspca_dev *gspca_dev) { i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */ msleep(10); @@ -860,6 +907,52 @@ static int probesensor(struct gspca_dev *gspca_dev) return -ENODEV; } +static int mi0360_probe(struct gspca_dev *gspca_dev) +{ + int i, j; + u16 val; + static const u8 probe_tb[][4][8] = { + { + {0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, + {0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10} + }, + { + {0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, + {0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, + {} + }, + }; + + for (i = 0; i < ARRAY_SIZE(probe_tb); i++) { + reg_w1(gspca_dev, 0x17, 0x62); + reg_w1(gspca_dev, 0x01, 0x08); + for (j = 0; j < 3; j++) + i2c_w8(gspca_dev, probe_tb[i][j]); + msleep(2); + reg_r(gspca_dev, 0x0a, 5); + val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; + if (probe_tb[i][3][0] != 0) + i2c_w8(gspca_dev, probe_tb[i][3]); + reg_w1(gspca_dev, 0x01, 0x29); + reg_w1(gspca_dev, 0x17, 0x42); + if (val != 0xffff) + break; + } + switch (val) { + case 0x823a: + PDEBUG(D_PROBE, "Sensor mt9v111"); + return SENSOR_MT9V111; + case 0x8243: + PDEBUG(D_PROBE, "Sensor mi0360"); + return SENSOR_MI0360; + } + PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val); + return SENSOR_MI0360; +} + static int configure_gpio(struct gspca_dev *gspca_dev, const u8 *sn9c1xx) { @@ -897,6 +990,12 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); switch (sd->sensor) { + case SENSOR_MT9V111: + reg_w1(gspca_dev, 0x01, 0x61); + reg_w1(gspca_dev, 0x17, 0x61); + reg_w1(gspca_dev, 0x01, 0x60); + reg_w1(gspca_dev, 0x01, 0x40); + break; case SENSOR_OM6802: reg_w1(gspca_dev, 0x02, 0x71); reg_w1(gspca_dev, 0x01, 0x42); @@ -934,7 +1033,7 @@ static int configure_gpio(struct gspca_dev *gspca_dev, reg_w1(gspca_dev, 0x17, 0x61); reg_w1(gspca_dev, 0x01, 0x42); if (sd->sensor == SENSOR_HV7131R) { - if (probesensor(gspca_dev) < 0) + if (hv7131r_probe(gspca_dev) < 0) return -ENODEV; } break; @@ -975,6 +1074,19 @@ static void mo4000_InitSensor(struct gspca_dev *gspca_dev) } } +static void mt9v111_InitSensor(struct gspca_dev *gspca_dev) +{ + int i = 0; + + i2c_w8(gspca_dev, mt9v111_sensor_init[i]); + i++; + msleep(20); + while (mt9v111_sensor_init[i][0]) { + i2c_w8(gspca_dev, mt9v111_sensor_init[i]); + i++; + } +} + static void om6802_InitSensor(struct gspca_dev *gspca_dev) { int i = 0; @@ -1092,11 +1204,21 @@ static int sd_init(struct gspca_dev *gspca_dev) case BRIDGE_SN9C105: if (regF1 != 0x11) return -ENODEV; + if (sd->sensor == SENSOR_MI0360) { + sd->sensor = mi0360_probe(gspca_dev); + if (sd->sensor == SENSOR_MT9V111) + sd->i2c_base = 0x5c; + } reg_w(gspca_dev, 0x01, regGpio, 2); break; case BRIDGE_SN9C120: if (regF1 != 0x12) return -ENODEV; + if (sd->sensor == SENSOR_MI0360) { + sd->sensor = mi0360_probe(gspca_dev); + if (sd->sensor == SENSOR_MT9V111) + sd->i2c_base = 0x5c; + } regGpio[1] = 0x70; reg_w(gspca_dev, 0x01, regGpio, 2); break; @@ -1131,7 +1253,7 @@ static u32 setexposure(struct gspca_dev *gspca_dev, break; } case SENSOR_MI0360: { - u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */ + u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */ { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 }; static const u8 doit[] = /* update sensor */ { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 }; @@ -1167,12 +1289,35 @@ static u32 setexposure(struct gspca_dev *gspca_dev, | ((expo & 0x0003) << 4); i2c_w8(gspca_dev, expoMo10); i2c_w8(gspca_dev, gainMo); - PDEBUG(D_CONF, "set exposure %d", + PDEBUG(D_FRAM, "set exposure %d", ((expoMo10[3] & 0x07) << 10) | (expoMof[3] << 2) | ((expoMo10[3] & 0x30) >> 4)); break; } + case SENSOR_MT9V111: { + u8 expo_c1[] = + { 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 }; +#if 0 + static const u8 c2[] = + { 0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10 }; + static const u8 c3[] = + { 0xd1, 0x5c, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10 }; +#endif + + if (expo > 0x0280) + expo = 0x0280; + else if (expo < 0x0040) + expo = 0x0040; + expo_c1[3] = expo >> 8; + expo_c1[4] = expo; + i2c_w8(gspca_dev, expo_c1); +#if 0 + i2c_w8(gspca_dev, expo_c2); + i2c_w8(gspca_dev, expo_c3); +#endif + break; + } case SENSOR_OM6802: { u8 gainOm[] = { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 }; @@ -1184,7 +1329,7 @@ static u32 setexposure(struct gspca_dev *gspca_dev, gainOm[3] = expo >> 2; i2c_w8(gspca_dev, gainOm); reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f); - PDEBUG(D_CONF, "set exposure %d", gainOm[3]); + PDEBUG(D_FRAM, "set exposure %d", gainOm[3]); break; } } @@ -1212,6 +1357,10 @@ static void setbrightness(struct gspca_dev *gspca_dev) expo = sd->brightness >> 4; sd->exposure = setexposure(gspca_dev, expo); break; + case SENSOR_MT9V111: + expo = sd->brightness >> 8; + sd->exposure = setexposure(gspca_dev, expo); + break; case SENSOR_OM6802: expo = sd->brightness >> 6; sd->exposure = setexposure(gspca_dev, expo); @@ -1219,7 +1368,8 @@ static void setbrightness(struct gspca_dev *gspca_dev) break; } - reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */ + if (sd->sensor != SENSOR_MT9V111) + reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */ } static void setcontrast(struct gspca_dev *gspca_dev) @@ -1342,6 +1492,9 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0xc9, 0x3c); reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); switch (sd->sensor) { + case SENSOR_MT9V111: + reg17 = 0xe0; + break; case SENSOR_OV7630: reg17 = 0xe2; break; @@ -1368,14 +1521,18 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); #if 0 - if (sd->sensor == SENSOR_HV7131R) - reg_w(gspca_dev, 0x20, gamma_hv7131, sizeof gamma_hv7131); + if (sd->sensor == SENSOR_HV7131R || sd->sensor == SENSOR_MT9V111) + reg_w(gspca_dev, 0x20, gamma_hv7131r, sizeof gamma_hv7131r); else #endif setgamma(gspca_dev); for (i = 0; i < 8; i++) reg_w(gspca_dev, 0x84, reg84, sizeof reg84); switch (sd->sensor) { + case SENSOR_MT9V111: + reg_w1(gspca_dev, 0x9a, 0x07); + reg_w1(gspca_dev, 0x99, 0x59); + break; case SENSOR_OV7648: reg_w1(gspca_dev, 0x9a, 0x0a); reg_w1(gspca_dev, 0x99, 0x60); @@ -1415,6 +1572,14 @@ static int sd_start(struct gspca_dev *gspca_dev) /* reg1 = 0x06; * 640 clk 24Mz (done) */ } break; + case SENSOR_MT9V111: + mt9v111_InitSensor(gspca_dev); + if (mode) { + reg1 = 0x04; /* 320 clk 48Mhz */ + } else { +/* reg1 = 0x06; * 640 clk 24Mz (done) */ + reg17 = 0xe2; + } case SENSOR_OM6802: om6802_InitSensor(gspca_dev); reg17 = 0x64; /* 640 MCKSIZE */ @@ -1463,17 +1628,19 @@ static int sd_start(struct gspca_dev *gspca_dev) reg18 = sn9c1xx[0x18] | (mode << 4); reg_w1(gspca_dev, 0x18, reg18 | 0x40); - reg_w(gspca_dev, 0x100, qtable4, 0x40); - reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40); + reg_w(gspca_dev, 0x0100, qtable4, 0x40); + reg_w(gspca_dev, 0x0140, qtable4 + 0x40, 0x40); reg_w1(gspca_dev, 0x18, reg18); reg_w1(gspca_dev, 0x17, reg17); reg_w1(gspca_dev, 0x01, reg1); switch (sd->sensor) { - case SENSOR_MI0360: +#if 0 + case SENSOR_MT9V111: setinfrared(sd); break; +#endif case SENSOR_OV7630: setvflip(sd); break; @@ -1509,6 +1676,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev) case SENSOR_OV7648: i2c_w8(gspca_dev, stopov7648); /* fall thru */ + case SENSOR_MT9V111: case SENSOR_OV7630: data = 0x29; break; @@ -1556,6 +1724,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) default: /* case SENSOR_MO4000: */ /* case SENSOR_MI0360: */ +/* case SENSOR_MT9V111: */ /* case SENSOR_OM6802: */ expotimes = sd->exposure; expotimes += (luma_mean - delta) >> 6; @@ -1812,7 +1981,7 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */ {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)}, /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */ - {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)}, + {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MT9V111, 0x5c)}, /* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)}, -- cgit v1.2.3 From a8eaa7e616a35998734938d8fe45740de2a40644 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 29 Jan 2009 09:32:23 +0100 Subject: gspca - vc032x: Webcam 041e:405b added and mi1310_soc updated. From: Jean-Francois Moine The mi1310_soc sequences come from the ms-win driver C0130Dev.inf. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 479 +++++++++++++++++++------------ 1 file changed, 296 insertions(+), 183 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index a615cc402..01d886d06 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -400,92 +400,208 @@ static const __u8 mi0360_initQVGA_JPG[][4] = { static const __u8 mi1310_socinitVGA_JPG[][4] = { {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x64, 0xcc}, - {0xb3, 0x00, 0x65, 0xcc}, - {0xb3, 0x05, 0x00, 0xcc}, - {0xb3, 0x06, 0x00, 0xcc}, + {0xb3, 0x00, 0x24, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x03, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc}, - {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, + {0xb3, 0x04, 0x0d, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, - {0xb3, 0x22, 0x03, 0xcc}, - {0xb3, 0x23, 0xc0, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, - {0xb3, 0x16, 0x04, 0xcc}, - {0xb3, 0x17, 0xff, 0xcc}, - {0xb3, 0x00, 0x65, 0xcc}, - {0xb8, 0x00, 0x00, 0xcc}, - {0xbc, 0x00, 0xd0, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, - {0xf0, 0x00, 0x02, 0xbb}, - {0xc8, 0x9f, 0x0b, 0xbb}, - {0x5b, 0x00, 0x01, 0xbb}, - {0x2f, 0xde, 0x20, 0xbb}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb8, 0x01, 0x7d, 0xcc}, + {0xb8, 0x81, 0x09, 0xcc}, + {0xb8, 0x27, 0x20, 0xcc}, + {0xb8, 0x26, 0x80, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb8, 0x00, 0x13, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xb8, 0x81, 0x01, 0xcc}, + {0xb8, 0x2c, 0x5a, 0xcc}, + {0xb8, 0x2d, 0xff, 0xcc}, + {0xb8, 0x2e, 0xee, 0xcc}, + {0xb8, 0x2f, 0xfb, 0xcc}, + {0xb8, 0x30, 0x52, 0xcc}, + {0xb8, 0x31, 0xf8, 0xcc}, + {0xb8, 0x32, 0xf1, 0xcc}, + {0xb8, 0x33, 0xff, 0xcc}, + {0xb8, 0x34, 0x54, 0xcc}, + {0xb8, 0x35, 0x00, 0xcc}, + {0xb8, 0x36, 0x00, 0xcc}, + {0xb8, 0x37, 0x00, 0xcc}, {0xf0, 0x00, 0x00, 0xbb}, - {0x20, 0x03, 0x02, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x0d, 0x00, 0x09, 0xbb}, + {0x0d, 0x00, 0x08, 0xbb}, {0xf0, 0x00, 0x01, 0xbb}, - {0x05, 0x00, 0x07, 0xbb}, - {0x34, 0x00, 0x00, 0xbb}, - {0x35, 0xff, 0x00, 0xbb}, - {0xdc, 0x07, 0x02, 0xbb}, - {0xdd, 0x3c, 0x18, 0xbb}, - {0xde, 0x92, 0x6d, 0xbb}, - {0xdf, 0xcd, 0xb1, 0xbb}, - {0xe0, 0xff, 0xe7, 0xbb}, - {0x06, 0xf0, 0x0d, 0xbb}, - {0x06, 0x70, 0x0e, 0xbb}, - {0x4c, 0x00, 0x01, 0xbb}, - {0x4d, 0x00, 0x01, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x2e, 0x0c, 0x55, 0xbb}, - {0x21, 0xb6, 0x6e, 0xbb}, - {0x36, 0x30, 0x10, 0xbb}, - {0x37, 0x00, 0xc1, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x06, 0x00, 0x14, 0xbb}, + {0x3a, 0x10, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x9b, 0x10, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, {0xf0, 0x00, 0x00, 0xbb}, - {0x07, 0x00, 0x84, 0xbb}, - {0x08, 0x02, 0x4a, 0xbb}, - {0x05, 0x01, 0x10, 0xbb}, - {0x06, 0x00, 0x39, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x58, 0x02, 0x67, 0xbb}, - {0x57, 0x02, 0x00, 0xbb}, - {0x5a, 0x02, 0x67, 0xbb}, - {0x59, 0x02, 0x00, 0xbb}, - {0x5c, 0x12, 0x0d, 0xbb}, - {0x5d, 0x16, 0x11, 0xbb}, - {0x39, 0x06, 0x18, 0xbb}, - {0x3a, 0x06, 0x18, 0xbb}, - {0x3b, 0x06, 0x18, 0xbb}, - {0x3c, 0x06, 0x18, 0xbb}, - {0x64, 0x7b, 0x5b, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x36, 0x30, 0x10, 0xbb}, - {0x37, 0x00, 0xc0, 0xbb}, - {0xbc, 0x0e, 0x00, 0xcc}, - {0xbc, 0x0f, 0x05, 0xcc}, - {0xbc, 0x10, 0xc0, 0xcc}, - {0xbc, 0x11, 0x03, 0xcc}, + {0x00, 0x01, 0x00, 0xdd}, + {0x2b, 0x00, 0x28, 0xbb}, + {0x2c, 0x00, 0x30, 0xbb}, + {0x2d, 0x00, 0x30, 0xbb}, + {0x2e, 0x00, 0x28, 0xbb}, + {0x41, 0x00, 0xd7, 0xbb}, + {0x09, 0x02, 0x3a, 0xbb}, + {0x0c, 0x00, 0x00, 0xbb}, + {0x20, 0x00, 0x00, 0xbb}, + {0x05, 0x00, 0x8c, 0xbb}, + {0x06, 0x00, 0x32, 0xbb}, + {0x07, 0x00, 0xc6, 0xbb}, + {0x08, 0x00, 0x19, 0xbb}, + {0x24, 0x80, 0x6f, 0xbb}, + {0xc8, 0x00, 0x0f, 0xbb}, + {0x20, 0x00, 0x0f, 0xbb}, {0xb6, 0x00, 0x00, 0xcc}, {0xb6, 0x03, 0x02, 0xcc}, {0xb6, 0x02, 0x80, 0xcc}, {0xb6, 0x05, 0x01, 0xcc}, {0xb6, 0x04, 0xe0, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, - {0xb6, 0x13, 0x25, 0xcc}, + {0xb6, 0x12, 0x78, 0xcc}, {0xb6, 0x18, 0x02, 0xcc}, {0xb6, 0x17, 0x58, 0xcc}, {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, {0xb6, 0x23, 0x0b, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, {0xbf, 0xc1, 0x04, 0xcc}, - {0xbf, 0xcc, 0x00, 0xcc}, + {0xbf, 0xcc, 0x10, 0xcc}, + {0xb9, 0x12, 0x00, 0xcc}, + {0xb9, 0x13, 0x0a, 0xcc}, + {0xb9, 0x14, 0x0a, 0xcc}, + {0xb9, 0x15, 0x0a, 0xcc}, + {0xb9, 0x16, 0x0a, 0xcc}, + {0xb9, 0x18, 0x00, 0xcc}, + {0xb9, 0x19, 0x0f, 0xcc}, + {0xb9, 0x1a, 0x0f, 0xcc}, + {0xb9, 0x1b, 0x0f, 0xcc}, + {0xb9, 0x1c, 0x0f, 0xcc}, + {0xb8, 0x8e, 0x00, 0xcc}, + {0xb8, 0x8f, 0xff, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0x03, 0x03, 0xc0, 0xbb}, + {0x06, 0x00, 0x10, 0xbb}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb8, 0x0c, 0x20, 0xcc}, + {0xb8, 0x0d, 0x70, 0xcc}, + {0xb6, 0x13, 0x13, 0xcc}, + {0x2f, 0x00, 0xC0, 0xbb}, + {0xb8, 0xa0, 0x12, 0xcc}, + {}, +}; +static const __u8 mi1310_socinitQVGA_JPG[][4] = { + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0xb3, 0x00, 0x24, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb3, 0x05, 0x01, 0xcc}, + {0xb3, 0x06, 0x03, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xdd, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x0d, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x01, 0xcc}, + {0xb3, 0x23, 0xe0, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x02, 0xcc}, + {0xb3, 0x17, 0x7f, 0xcc}, + {0xb8, 0x01, 0x7d, 0xcc}, + {0xb8, 0x81, 0x09, 0xcc}, + {0xb8, 0x27, 0x20, 0xcc}, + {0xb8, 0x26, 0x80, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb8, 0x00, 0x13, 0xcc}, + {0xbc, 0x00, 0xd1, 0xcc}, + {0xb8, 0x81, 0x01, 0xcc}, + {0xb8, 0x2c, 0x5a, 0xcc}, + {0xb8, 0x2d, 0xff, 0xcc}, + {0xb8, 0x2e, 0xee, 0xcc}, + {0xb8, 0x2f, 0xfb, 0xcc}, + {0xb8, 0x30, 0x52, 0xcc}, + {0xb8, 0x31, 0xf8, 0xcc}, + {0xb8, 0x32, 0xf1, 0xcc}, + {0xb8, 0x33, 0xff, 0xcc}, + {0xb8, 0x34, 0x54, 0xcc}, + {0xb8, 0x35, 0x00, 0xcc}, + {0xb8, 0x36, 0x00, 0xcc}, + {0xb8, 0x37, 0x00, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x0d, 0x00, 0x09, 0xbb}, + {0x0d, 0x00, 0x08, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x06, 0x00, 0x14, 0xbb}, + {0x3a, 0x10, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x9b, 0x10, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x2b, 0x00, 0x28, 0xbb}, + {0x2c, 0x00, 0x30, 0xbb}, + {0x2d, 0x00, 0x30, 0xbb}, + {0x2e, 0x00, 0x28, 0xbb}, + {0x41, 0x00, 0xd7, 0xbb}, + {0x09, 0x02, 0x3a, 0xbb}, + {0x0c, 0x00, 0x00, 0xbb}, + {0x20, 0x00, 0x00, 0xbb}, + {0x05, 0x00, 0x8c, 0xbb}, + {0x06, 0x00, 0x32, 0xbb}, + {0x07, 0x00, 0xc6, 0xbb}, + {0x08, 0x00, 0x19, 0xbb}, + {0x24, 0x80, 0x6f, 0xbb}, + {0xc8, 0x00, 0x0f, 0xbb}, + {0x20, 0x00, 0x0f, 0xbb}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x01, 0xcc}, + {0xb6, 0x02, 0x40, 0xcc}, + {0xb6, 0x05, 0x00, 0xcc}, + {0xb6, 0x04, 0xf0, 0xcc}, + {0xb6, 0x12, 0x78, 0xcc}, + {0xb6, 0x18, 0x00, 0xcc}, + {0xb6, 0x17, 0x96, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x10, 0xcc}, + {0xb9, 0x12, 0x00, 0xcc}, + {0xb9, 0x13, 0x0a, 0xcc}, + {0xb9, 0x14, 0x0a, 0xcc}, + {0xb9, 0x15, 0x0a, 0xcc}, + {0xb9, 0x16, 0x0a, 0xcc}, + {0xb9, 0x18, 0x00, 0xcc}, + {0xb9, 0x19, 0x0f, 0xcc}, + {0xb9, 0x1a, 0x0f, 0xcc}, + {0xb9, 0x1b, 0x0f, 0xcc}, + {0xb9, 0x1c, 0x0f, 0xcc}, + {0xb8, 0x8e, 0x00, 0xcc}, + {0xb8, 0x8f, 0xff, 0xcc}, {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc}, {0xbc, 0x04, 0x18, 0xcc}, @@ -496,132 +612,126 @@ static const __u8 mi1310_socinitVGA_JPG[][4] = { {0xbc, 0x0a, 0x10, 0xcc}, {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x80, 0x00, 0x03, 0xbb}, - {0x81, 0xc7, 0x14, 0xbb}, - {0x82, 0xeb, 0xe8, 0xbb}, - {0x83, 0xfe, 0xf4, 0xbb}, - {0x84, 0xcd, 0x10, 0xbb}, - {0x85, 0xf3, 0xee, 0xbb}, - {0x86, 0xff, 0xf1, 0xbb}, - {0x87, 0xcd, 0x10, 0xbb}, - {0x88, 0xf3, 0xee, 0xbb}, - {0x89, 0x01, 0xf1, 0xbb}, - {0x8a, 0xe5, 0x17, 0xbb}, - {0x8b, 0xe8, 0xe2, 0xbb}, - {0x8c, 0xf7, 0xed, 0xbb}, - {0x8d, 0x00, 0xff, 0xbb}, - {0x8e, 0xec, 0x10, 0xbb}, - {0x8f, 0xf0, 0xed, 0xbb}, - {0x90, 0xf9, 0xf2, 0xbb}, - {0x91, 0x00, 0x00, 0xbb}, - {0x92, 0xe9, 0x0d, 0xbb}, - {0x93, 0xf4, 0xf2, 0xbb}, - {0x94, 0xfb, 0xf5, 0xbb}, - {0x95, 0x00, 0xff, 0xbb}, - {0xb6, 0x0f, 0x08, 0xbb}, - {0xb7, 0x3d, 0x16, 0xbb}, - {0xb8, 0x0c, 0x04, 0xbb}, - {0xb9, 0x1c, 0x07, 0xbb}, - {0xba, 0x0a, 0x03, 0xbb}, - {0xbb, 0x1b, 0x09, 0xbb}, - {0xbc, 0x17, 0x0d, 0xbb}, - {0xbd, 0x23, 0x1d, 0xbb}, - {0xbe, 0x00, 0x28, 0xbb}, - {0xbf, 0x11, 0x09, 0xbb}, - {0xc0, 0x16, 0x15, 0xbb}, - {0xc1, 0x00, 0x1b, 0xbb}, - {0xc2, 0x0e, 0x07, 0xbb}, - {0xc3, 0x14, 0x10, 0xbb}, - {0xc4, 0x00, 0x17, 0xbb}, - {0x06, 0x74, 0x8e, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, - {0x06, 0xf4, 0x8e, 0xbb}, - {0x00, 0x00, 0x50, 0xdd}, - {0x06, 0x74, 0x8e, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x24, 0x50, 0x20, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, - {0x34, 0x0c, 0x50, 0xbb}, {0xb3, 0x01, 0x41, 0xcc}, - {0xf0, 0x00, 0x00, 0xbb}, {0x03, 0x03, 0xc0, 0xbb}, + {0x06, 0x00, 0x10, 0xbb}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb8, 0x0c, 0x20, 0xcc}, + {0xb8, 0x0d, 0x70, 0xcc}, + {0xb6, 0x13, 0x13, 0xcc}, + {0x2f, 0x00, 0xC0, 0xbb}, + {0xb8, 0xa0, 0x12, 0xcc}, {}, }; -static const __u8 mi1310_socinitQVGA_JPG[][4] = { - {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, - {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc}, - {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x00, 0xcc}, - {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, - {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc}, - {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc}, - {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc}, - {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x03, 0xcc}, - {0xb3, 0x23, 0xc0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc}, - {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x04, 0xcc}, - {0xb3, 0x17, 0xff, 0xcc}, {0xb3, 0x00, 0x65, 0xcc}, - {0xb8, 0x00, 0x00, 0xcc}, {0xbc, 0x00, 0xf0, 0xcc}, - {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x02, 0xbb}, - {0xc8, 0x9f, 0x0b, 0xbb}, {0x5b, 0x00, 0x01, 0xbb}, - {0x2f, 0xde, 0x20, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x20, 0x03, 0x02, 0xbb}, {0xf0, 0x00, 0x01, 0xbb}, - {0x05, 0x00, 0x07, 0xbb}, {0x34, 0x00, 0x00, 0xbb}, - {0x35, 0xff, 0x00, 0xbb}, {0xdc, 0x07, 0x02, 0xbb}, - {0xdd, 0x3c, 0x18, 0xbb}, {0xde, 0x92, 0x6d, 0xbb}, - {0xdf, 0xcd, 0xb1, 0xbb}, {0xe0, 0xff, 0xe7, 0xbb}, - {0x06, 0xf0, 0x0d, 0xbb}, {0x06, 0x70, 0x0e, 0xbb}, - {0x4c, 0x00, 0x01, 0xbb}, {0x4d, 0x00, 0x01, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x2e, 0x0c, 0x55, 0xbb}, - {0x21, 0xb6, 0x6e, 0xbb}, {0x36, 0x30, 0x10, 0xbb}, - {0x37, 0x00, 0xc1, 0xbb}, {0xf0, 0x00, 0x00, 0xbb}, - {0x07, 0x00, 0x84, 0xbb}, {0x08, 0x02, 0x4a, 0xbb}, - {0x05, 0x01, 0x10, 0xbb}, {0x06, 0x00, 0x39, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x58, 0x02, 0x67, 0xbb}, - {0x57, 0x02, 0x00, 0xbb}, {0x5a, 0x02, 0x67, 0xbb}, - {0x59, 0x02, 0x00, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb}, - {0x5d, 0x16, 0x11, 0xbb}, {0x39, 0x06, 0x18, 0xbb}, - {0x3a, 0x06, 0x18, 0xbb}, {0x3b, 0x06, 0x18, 0xbb}, - {0x3c, 0x06, 0x18, 0xbb}, {0x64, 0x7b, 0x5b, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x30, 0x10, 0xbb}, - {0x37, 0x00, 0xc0, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc}, - {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc}, - {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc}, - {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc}, - {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc}, - {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x25, 0xcc}, - {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc}, - {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc}, - {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc}, - {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc}, - {0xb3, 0x5c, 0x01, 0xcc}, {0xf0, 0x00, 0x01, 0xbb}, - {0x80, 0x00, 0x03, 0xbb}, {0x81, 0xc7, 0x14, 0xbb}, - {0x82, 0xeb, 0xe8, 0xbb}, {0x83, 0xfe, 0xf4, 0xbb}, - {0x84, 0xcd, 0x10, 0xbb}, {0x85, 0xf3, 0xee, 0xbb}, - {0x86, 0xff, 0xf1, 0xbb}, {0x87, 0xcd, 0x10, 0xbb}, - {0x88, 0xf3, 0xee, 0xbb}, {0x89, 0x01, 0xf1, 0xbb}, - {0x8a, 0xe5, 0x17, 0xbb}, {0x8b, 0xe8, 0xe2, 0xbb}, - {0x8c, 0xf7, 0xed, 0xbb}, {0x8d, 0x00, 0xff, 0xbb}, - {0x8e, 0xec, 0x10, 0xbb}, {0x8f, 0xf0, 0xed, 0xbb}, - {0x90, 0xf9, 0xf2, 0xbb}, {0x91, 0x00, 0x00, 0xbb}, - {0x92, 0xe9, 0x0d, 0xbb}, {0x93, 0xf4, 0xf2, 0xbb}, - {0x94, 0xfb, 0xf5, 0xbb}, {0x95, 0x00, 0xff, 0xbb}, - {0xb6, 0x0f, 0x08, 0xbb}, {0xb7, 0x3d, 0x16, 0xbb}, - {0xb8, 0x0c, 0x04, 0xbb}, {0xb9, 0x1c, 0x07, 0xbb}, - {0xba, 0x0a, 0x03, 0xbb}, {0xbb, 0x1b, 0x09, 0xbb}, - {0xbc, 0x17, 0x0d, 0xbb}, {0xbd, 0x23, 0x1d, 0xbb}, - {0xbe, 0x00, 0x28, 0xbb}, {0xbf, 0x11, 0x09, 0xbb}, - {0xc0, 0x16, 0x15, 0xbb}, {0xc1, 0x00, 0x1b, 0xbb}, - {0xc2, 0x0e, 0x07, 0xbb}, {0xc3, 0x14, 0x10, 0xbb}, - {0xc4, 0x00, 0x17, 0xbb}, {0x06, 0x74, 0x8e, 0xbb}, - {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0xf4, 0x8e, 0xbb}, - {0x00, 0x00, 0x50, 0xdd}, {0x06, 0x74, 0x8e, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x24, 0x50, 0x20, 0xbb}, - {0xf0, 0x00, 0x02, 0xbb}, {0x34, 0x0c, 0x50, 0xbb}, - {0xb3, 0x01, 0x41, 0xcc}, {0xf0, 0x00, 0x00, 0xbb}, - {0x03, 0x03, 0xc0, 0xbb}, - {}, +#if 0 +static const u8 mi1310_soc_InitSXGA_JPG[][4] = { + {0xb0, 0x03, 0x19, 0xcc}, + {0xb0, 0x04, 0x02, 0xcc}, + {0xb3, 0x00, 0x24, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb3, 0x05, 0x00, 0xcc}, + {0xb3, 0x06, 0x01, 0xcc}, + {0xb3, 0x5c, 0x01, 0xcc}, + {0xb3, 0x08, 0x01, 0xcc}, + {0xb3, 0x09, 0x0c, 0xcc}, + {0xb3, 0x34, 0x02, 0xcc}, + {0xb3, 0x35, 0xdd, 0xcc}, + {0xb3, 0x03, 0x0a, 0xcc}, + {0xb3, 0x04, 0x0d, 0xcc}, + {0xb3, 0x20, 0x00, 0xcc}, + {0xb3, 0x21, 0x00, 0xcc}, + {0xb3, 0x22, 0x04, 0xcc}, + {0xb3, 0x23, 0x00, 0xcc}, + {0xb3, 0x14, 0x00, 0xcc}, + {0xb3, 0x15, 0x00, 0xcc}, + {0xb3, 0x16, 0x04, 0xcc}, + {0xb3, 0x17, 0xff, 0xcc}, + {0xb8, 0x01, 0x7d, 0xcc}, + {0xb8, 0x81, 0x09, 0xcc}, + {0xb8, 0x27, 0x20, 0xcc}, + {0xb8, 0x26, 0x80, 0xcc}, + {0xb8, 0x06, 0x00, 0xcc}, + {0xb8, 0x07, 0x05, 0xcc}, + {0xb8, 0x08, 0x00, 0xcc}, + {0xb8, 0x09, 0x04, 0xcc}, + {0xb3, 0x00, 0x25, 0xcc}, + {0xb8, 0x00, 0x11, 0xcc}, + {0xbc, 0x00, 0x71, 0xcc}, + {0xb8, 0x81, 0x01, 0xcc}, + {0xb8, 0x2c, 0x5a, 0xcc}, + {0xb8, 0x2d, 0xff, 0xcc}, + {0xb8, 0x2e, 0xee, 0xcc}, + {0xb8, 0x2f, 0xfb, 0xcc}, + {0xb8, 0x30, 0x52, 0xcc}, + {0xb8, 0x31, 0xf8, 0xcc}, + {0xb8, 0x32, 0xf1, 0xcc}, + {0xb8, 0x33, 0xff, 0xcc}, + {0xb8, 0x34, 0x54, 0xcc}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x0d, 0x00, 0x09, 0xbb}, + {0x0d, 0x00, 0x08, 0xbb}, + {0xf0, 0x00, 0x01, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x06, 0x00, 0x14, 0xbb}, + {0x3a, 0x10, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0x9b, 0x10, 0x00, 0xbb}, + {0x00, 0x00, 0x10, 0xdd}, + {0xf0, 0x00, 0x00, 0xbb}, + {0x00, 0x01, 0x00, 0xdd}, + {0x2b, 0x00, 0x28, 0xbb}, + {0x2c, 0x00, 0x30, 0xbb}, + {0x2d, 0x00, 0x30, 0xbb}, + {0x2e, 0x00, 0x28, 0xbb}, + {0x41, 0x00, 0xd7, 0xbb}, + {0x09, 0x02, 0x3a, 0xbb}, + {0x0c, 0x00, 0x00, 0xbb}, + {0x20, 0x00, 0x00, 0xbb}, + {0x05, 0x00, 0x8c, 0xbb}, + {0x06, 0x00, 0x32, 0xbb}, + {0x07, 0x00, 0xc6, 0xbb}, + {0x08, 0x00, 0x19, 0xbb}, + {0x24, 0x80, 0x6f, 0xbb}, + {0xc8, 0x00, 0x0f, 0xbb}, + {0x20, 0x00, 0x03, 0xbb}, + {0xb6, 0x00, 0x00, 0xcc}, + {0xb6, 0x03, 0x05, 0xcc}, + {0xb6, 0x02, 0x00, 0xcc}, + {0xb6, 0x05, 0x04, 0xcc}, + {0xb6, 0x04, 0x00, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb6, 0x18, 0x0a, 0xcc}, + {0xb6, 0x17, 0x00, 0xcc}, + {0xb6, 0x16, 0x00, 0xcc}, + {0xb6, 0x22, 0x12, 0xcc}, + {0xb6, 0x23, 0x0b, 0xcc}, + {0xb3, 0x02, 0x02, 0xcc}, + {0xbf, 0xc0, 0x39, 0xcc}, + {0xbf, 0xc1, 0x04, 0xcc}, + {0xbf, 0xcc, 0x10, 0xcc}, + {0xb9, 0x12, 0x00, 0xcc}, + {0xb9, 0x13, 0x14, 0xcc}, + {0xb9, 0x14, 0x14, 0xcc}, + {0xb9, 0x15, 0x14, 0xcc}, + {0xb9, 0x16, 0x14, 0xcc}, + {0xb9, 0x18, 0x00, 0xcc}, + {0xb9, 0x19, 0x1e, 0xcc}, + {0xb9, 0x1a, 0x1e, 0xcc}, + {0xb9, 0x1b, 0x1e, 0xcc}, + {0xb9, 0x1c, 0x1e, 0xcc}, + {0xb3, 0x01, 0x41, 0xcc}, + {0xb8, 0x8e, 0x00, 0xcc}, + {0xb8, 0x8f, 0xff, 0xcc}, + {0xb6, 0x12, 0xf8, 0xcc}, + {0xb8, 0x0c, 0x20, 0xcc}, + {0xb8, 0x0d, 0x70, 0xcc}, + {0xb6, 0x13, 0x13, 0xcc}, + {0x2f, 0x00, 0xC0, 0xbb}, + {0xb8, 0xa0, 0x12, 0xcc}, + {} }; +#endif static const __u8 mi1320_gamma[17] = { 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, @@ -2208,6 +2318,8 @@ static int sd_start(struct gspca_dev *gspca_dev) } break; case SENSOR_MI1310_SOC: + GammaT = mi1320_gamma; + MatrixT = mi0360_matrix; if (mode) { /* 320x240 */ usb_exchange(gspca_dev, mi1310_socinitQVGA_JPG); @@ -2449,6 +2561,7 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x041e, 0x405b), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x046d, 0x0892), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x046d, 0x0896), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x046d, 0x0897), .driver_info = BRIDGE_VC0321}, -- cgit v1.2.3 From 10a9a21ccf74b5ff6c15d4e15f929fc5d08377a7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 29 Jan 2009 10:02:37 +0100 Subject: gspca - documentation: Add the webcam 041e:405b. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/Documentation/video4linux/gspca.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'linux') diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt index 3136c8028..12c8ff705 100644 --- a/linux/Documentation/video4linux/gspca.txt +++ b/linux/Documentation/video4linux/gspca.txt @@ -32,6 +32,7 @@ spca561 041e:403b Creative Webcam Vista (VF0010) zc3xx 041e:4051 Creative Live!Cam Notebook Pro (VF0250) ov519 041e:4052 Creative Live! VISTA IM zc3xx 041e:4053 Creative Live!Cam Video IM +vc032x 041e:405b Creative Live! Cam Notebook Ultra (VC0130) ov519 041e:405f Creative Live! VISTA VF0330 ov519 041e:4060 Creative Live! VISTA VF0350 ov519 041e:4061 Creative Live! VISTA VF0400 -- cgit v1.2.3 From 1ce2c6a963dd54733741c029136430693485f8cd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 29 Jan 2009 10:23:18 +0100 Subject: gspca: fix compiler warning From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/gspca/t613.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c index 9c777381a..adec0767c 100644 --- a/linux/drivers/media/video/gspca/t613.c +++ b/linux/drivers/media/video/gspca/t613.c @@ -635,7 +635,7 @@ static int sd_init(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int i; u16 sensor_id; - u8 test_byte; + u8 test_byte = 0; u16 reg80, reg8e; static const u8 read_indexs[] = -- cgit v1.2.3 From 68a6fa1ae421b7c28eb6b8365f3adfd08007e7b7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 29 Jan 2009 09:11:45 -0200 Subject: backport changes on files not maintained here From: Mauro Carvalho Chehab kernel-sync: Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/firmware/Makefile | 5 +++- linux/include/linux/i2c-id.h | 61 -------------------------------------------- 2 files changed, 4 insertions(+), 62 deletions(-) (limited to 'linux') diff --git a/linux/firmware/Makefile b/linux/firmware/Makefile index 205f822a3..6b398f25c 100644 --- a/linux/firmware/Makefile +++ b/linux/firmware/Makefile @@ -37,6 +37,8 @@ fw-shipped-$(CONFIG_CHELSIO_T3) += cxgb3/t3b_psram-1.1.0.bin \ cxgb3/t3c_psram-1.1.0.bin \ cxgb3/t3fw-7.0.0.bin fw-shipped-$(CONFIG_DVB_TTUSB_BUDGET) += ttusb-budget/dspbootcode.bin +fw-shipped-$(CONFIG_E100) += e100/d101m_ucode.bin e100/d101s_ucode.bin \ + e100/d102e_ucode.bin fw-shipped-$(CONFIG_SMCTR) += tr_smctr.bin fw-shipped-$(CONFIG_SND_KORG1212) += korg/k1212.dsp fw-shipped-$(CONFIG_SND_MAESTRO3) += ess/maestro3_assp_kernel.fw \ @@ -76,7 +78,8 @@ fw-shipped- += keyspan/mpr.fw keyspan/usa18x.fw keyspan/usa19.fw \ keyspan/usa28.fw keyspan/usa28xa.fw keyspan/usa28xb.fw \ keyspan/usa28x.fw keyspan/usa49w.fw keyspan/usa49wlc.fw endif -fw-shipped-$(CONFIG_USB_SERIAL_TI) += ti_3410.fw ti_5052.fw +fw-shipped-$(CONFIG_USB_SERIAL_TI) += ti_3410.fw ti_5052.fw \ + mts_cdma.fw mts_gsm.fw mts_edge.fw fw-shipped-$(CONFIG_USB_SERIAL_EDGEPORT) += edgeport/boot.fw edgeport/boot2.fw \ edgeport/down.fw edgeport/down2.fw fw-shipped-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += edgeport/down3.bin diff --git a/linux/include/linux/i2c-id.h b/linux/include/linux/i2c-id.h index 01d67ba9e..1ffc23bc5 100644 --- a/linux/include/linux/i2c-id.h +++ b/linux/include/linux/i2c-id.h @@ -40,9 +40,7 @@ #define I2C_DRIVERID_SAA7185B 13 /* video encoder */ #define I2C_DRIVERID_SAA7110 22 /* video decoder */ #define I2C_DRIVERID_SAA5249 24 /* SAA5249 and compatibles */ -#define I2C_DRIVERID_PCF8583 25 /* real time clock */ #define I2C_DRIVERID_TDA7432 27 /* Stereo sound processor */ -#define I2C_DRIVERID_TVMIXER 28 /* Mixer driver for tv cards */ #define I2C_DRIVERID_TVAUDIO 29 /* Generic TV sound driver */ #define I2C_DRIVERID_TDA9875 32 /* TV sound decoder chip */ #define I2C_DRIVERID_BT819 40 /* video decoder */ @@ -54,7 +52,6 @@ #define I2C_DRIVERID_SAA7191 57 /* video decoder */ #define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */ #define I2C_DRIVERID_OVCAMCHIP 61 /* OmniVision CMOS image sens. */ -#define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */ #define I2C_DRIVERID_SAA6752HS 67 /* MPEG2 encoder */ #define I2C_DRIVERID_TVEEPROM 68 /* TV EEPROM */ #define I2C_DRIVERID_WM8775 69 /* wm8775 audio processor */ @@ -62,23 +59,16 @@ #define I2C_DRIVERID_CX25840 71 /* cx2584x video encoder */ #define I2C_DRIVERID_SAA7127 72 /* saa7127 video encoder */ #define I2C_DRIVERID_SAA711X 73 /* saa711x video encoders */ -#define I2C_DRIVERID_AKITAIOEXP 74 /* IO Expander on Sharp SL-C1000 */ #define I2C_DRIVERID_INFRARED 75 /* I2C InfraRed on Video boards */ #define I2C_DRIVERID_TVP5150 76 /* TVP5150 video decoder */ #define I2C_DRIVERID_WM8739 77 /* wm8739 audio processor */ #define I2C_DRIVERID_UPD64083 78 /* upd64083 video processor */ #define I2C_DRIVERID_UPD64031A 79 /* upd64031a video processor */ #define I2C_DRIVERID_SAA717X 80 /* saa717x video encoder */ -#define I2C_DRIVERID_DS1672 81 /* Dallas/Maxim DS1672 RTC */ #define I2C_DRIVERID_BT866 85 /* Conexant bt866 video encoder */ #define I2C_DRIVERID_KS0127 86 /* Samsung ks0127 video decoder */ #define I2C_DRIVERID_TLV320AIC23B 87 /* TI TLV320AIC23B audio codec */ -#define I2C_DRIVERID_WM8731 89 /* Wolfson WM8731 audio codec */ -#define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */ -#define I2C_DRIVERID_WM8753 91 /* Wolfson WM8753 audio codec */ -#define I2C_DRIVERID_LM4857 92 /* LM4857 Audio Amplifier */ #define I2C_DRIVERID_VP27SMPX 93 /* Panasonic VP27s tuner internal MPX */ -#define I2C_DRIVERID_CS4270 94 /* Cirrus Logic 4270 audio codec */ #define I2C_DRIVERID_M52790 95 /* Mitsubishi M52790SP/FP AV switch */ #define I2C_DRIVERID_CS5345 96 /* cs5345 audio processor */ @@ -89,74 +79,23 @@ */ /* --- Bit algorithm adapters */ -#define I2C_HW_B_LP 0x010000 /* Parallel port Philips style */ #define I2C_HW_B_BT848 0x010005 /* BT848 video boards */ -#define I2C_HW_B_VIA 0x010007 /* Via vt82c586b */ -#define I2C_HW_B_HYDRA 0x010008 /* Apple Hydra Mac I/O */ -#define I2C_HW_B_I810 0x01000a /* Intel I810 */ -#define I2C_HW_B_VOO 0x01000b /* 3dfx Voodoo 3 / Banshee */ -#define I2C_HW_B_SCX200 0x01000e /* Nat'l Semi SCx200 I2C */ #define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */ -#define I2C_HW_B_IOC 0x010011 /* IOC bit-wiggling */ -#define I2C_HW_B_IXP2000 0x010016 /* GPIO on IXP2000 systems */ #define I2C_HW_B_ZR36067 0x010019 /* Zoran-36057/36067 based boards */ -#define I2C_HW_B_PCILYNX 0x01001a /* TI PCILynx I2C adapter */ #define I2C_HW_B_CX2388x 0x01001b /* connexant 2388x based tv cards */ -#define I2C_HW_B_NVIDIA 0x01001c /* nvidia framebuffer driver */ -#define I2C_HW_B_SAVAGE 0x01001d /* savage framebuffer driver */ -#define I2C_HW_B_RADEON 0x01001e /* radeon framebuffer driver */ #define I2C_HW_B_EM28XX 0x01001f /* em28xx video capture cards */ #define I2C_HW_B_CX2341X 0x010020 /* Conexant CX2341X MPEG encoder cards */ -#define I2C_HW_B_INTELFB 0x010021 /* intel framebuffer driver */ #define I2C_HW_B_CX23885 0x010022 /* conexant 23885 based tv cards (bus1) */ #define I2C_HW_B_AU0828 0x010023 /* auvitek au0828 usb bridge */ -/* --- PCF 8584 based algorithms */ -#define I2C_HW_P_ELEK 0x020002 /* Elektor ISA Bus inteface card */ - -/* --- PCA 9564 based algorithms */ -#define I2C_HW_A_ISA 0x1a0000 /* generic ISA Bus interface card */ - -/* --- PowerPC on-chip adapters */ -#define I2C_HW_OCP 0x120000 /* IBM on-chip I2C adapter */ - -/* --- Broadcom SiByte adapters */ -#define I2C_HW_SIBYTE 0x150000 - /* --- SGI adapters */ #define I2C_HW_SGI_VINO 0x160000 -/* --- XSCALE on-chip adapters */ -#define I2C_HW_IOP3XX 0x140000 - -/* --- Au1550 PSC adapters adapters */ -#define I2C_HW_AU1550_PSC 0x1b0000 - /* --- SMBus only adapters */ -#define I2C_HW_SMBUS_PIIX4 0x040000 -#define I2C_HW_SMBUS_ALI15X3 0x040001 -#define I2C_HW_SMBUS_VIA2 0x040002 -#define I2C_HW_SMBUS_I801 0x040004 -#define I2C_HW_SMBUS_AMD756 0x040005 -#define I2C_HW_SMBUS_SIS5595 0x040006 -#define I2C_HW_SMBUS_ALI1535 0x040007 -#define I2C_HW_SMBUS_SIS630 0x040008 -#define I2C_HW_SMBUS_SIS96X 0x040009 -#define I2C_HW_SMBUS_AMD8111 0x04000a -#define I2C_HW_SMBUS_SCX200 0x04000b -#define I2C_HW_SMBUS_NFORCE2 0x04000c #define I2C_HW_SMBUS_W9968CF 0x04000d #define I2C_HW_SMBUS_OV511 0x04000e /* OV511(+) USB 1.1 webcam ICs */ #define I2C_HW_SMBUS_OV518 0x04000f /* OV518(+) USB 1.1 webcam ICs */ #define I2C_HW_SMBUS_CAFE 0x040012 /* Marvell 88ALP01 "CAFE" cam */ -#define I2C_HW_SMBUS_ALI1563 0x040013 - -/* --- MCP107 adapter */ -#define I2C_HW_MPC107 0x0d0000 - -/* --- Embedded adapters */ -#define I2C_HW_MV64XXX 0x190000 -#define I2C_HW_BLACKFIN 0x190001 /* ADI Blackfin I2C TWI driver */ /* --- Miscellaneous adapters */ #define I2C_HW_SAA7146 0x060000 /* SAA7146 video decoder bus */ -- cgit v1.2.3 From b1ccf703c9015bc3257716ffccd33ca147f7a1a8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 29 Jan 2009 09:30:59 -0200 Subject: gspca: version.h is needed in order to compile upstream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Mauro Carvalho Chehab drivers/media/video/gspca/gspca.c: In function ‘vidioc_querycap’: drivers/media/video/gspca/gspca.c:963: error: implicit declaration of function ‘KERNEL_VERSION’ kernel-sync: CC: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/gspca/gspca.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c index a68b1a969..1a6c61f71 100644 --- a/linux/drivers/media/video/gspca/gspca.c +++ b/linux/drivers/media/video/gspca/gspca.c @@ -21,6 +21,7 @@ #define MODULE_NAME "gspca" #include +#include #include #include #include -- cgit v1.2.3 From 27b887c94f4f9a8e646d1915fe86783153b01f80 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 29 Jan 2009 10:56:56 -0200 Subject: backport changes on stb0899_algo per request From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/stb0899_algo.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/frontends/stb0899_algo.c b/linux/drivers/media/dvb/frontends/stb0899_algo.c index 71037dc67..3d13968a7 100644 --- a/linux/drivers/media/dvb/frontends/stb0899_algo.c +++ b/linux/drivers/media/dvb/frontends/stb0899_algo.c @@ -467,14 +467,13 @@ static void next_sub_range(struct stb0899_state *state) if (internal->sub_dir > 0) { old_sub_range = internal->sub_range; - if (internal->tuner_offst + internal->sub_range / 2 >= - internal->srch_range / 2) - internal->sub_range = 0; - else - internal->sub_range = MIN((internal->srch_range / 2) - + internal->sub_range = MIN((internal->srch_range / 2) - (internal->tuner_offst + internal->sub_range / 2), internal->sub_range); + if (internal->sub_range < 0) + internal->sub_range = 0; + internal->tuner_offst += (old_sub_range + internal->sub_range) / 2; } -- cgit v1.2.3 From bc9c580f08d66911d5f49c0c0627f69b06a169d7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 29 Jan 2009 20:03:19 +0100 Subject: gspca - sonixj: Bad sensor definition of the webcams 0c45:60c0. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 33cbd7945..a16f21be3 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -1981,7 +1981,7 @@ static const __devinitdata struct usb_device_id device_table[] = { /* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */ {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)}, /* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */ - {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MT9V111, 0x5c)}, + {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)}, /* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */ /* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */ {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)}, -- cgit v1.2.3 From 5d9421a2aa921a698637f5c8fc09b473a19eb075 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 29 Jan 2009 20:09:13 +0100 Subject: v4l2: fix incorrect hue range check From: Hans Verkuil A hue of -128 was rejected due to an incorrect range check, which was faithfully copy-and-pasted into four drivers... Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx18/cx18-av-core.c | 2 +- linux/drivers/media/video/cx25840/cx25840-core.c | 2 +- linux/drivers/media/video/saa7115.c | 2 +- linux/drivers/media/video/saa717x.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index 0b1c84b4d..780125002 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -548,7 +548,7 @@ static int set_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl) break; case V4L2_CID_HUE: - if (ctrl->value < -127 || ctrl->value > 127) { + if (ctrl->value < -128 || ctrl->value > 127) { CX18_ERR("invalid hue setting %d\n", ctrl->value); return -ERANGE; } diff --git a/linux/drivers/media/video/cx25840/cx25840-core.c b/linux/drivers/media/video/cx25840/cx25840-core.c index 57e80717f..d70dcd028 100644 --- a/linux/drivers/media/video/cx25840/cx25840-core.c +++ b/linux/drivers/media/video/cx25840/cx25840-core.c @@ -782,7 +782,7 @@ static int cx25840_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) break; case V4L2_CID_HUE: - if (ctrl->value < -127 || ctrl->value > 127) { + if (ctrl->value < -128 || ctrl->value > 127) { v4l_err(client, "invalid hue setting %d\n", ctrl->value); return -ERANGE; } diff --git a/linux/drivers/media/video/saa7115.c b/linux/drivers/media/video/saa7115.c index 40b0196e6..9fbb93775 100644 --- a/linux/drivers/media/video/saa7115.c +++ b/linux/drivers/media/video/saa7115.c @@ -779,7 +779,7 @@ static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) break; case V4L2_CID_HUE: - if (ctrl->value < -127 || ctrl->value > 127) { + if (ctrl->value < -128 || ctrl->value > 127) { v4l2_err(sd, "invalid hue setting %d\n", ctrl->value); return -ERANGE; } diff --git a/linux/drivers/media/video/saa717x.c b/linux/drivers/media/video/saa717x.c index 2fdac2e5c..b53ede210 100644 --- a/linux/drivers/media/video/saa717x.c +++ b/linux/drivers/media/video/saa717x.c @@ -937,7 +937,7 @@ static int saa717x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) break; case V4L2_CID_HUE: - if (ctrl->value < -127 || ctrl->value > 127) { + if (ctrl->value < -128 || ctrl->value > 127) { v4l2_err(sd, "invalid hue setting %d\n", ctrl->value); return -ERANGE; } -- cgit v1.2.3 From b0dced387dcc08db2201c56536a7c1799ba2bb53 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 29 Jan 2009 20:21:12 +0100 Subject: v4l: remove unused I2C_DRIVERIDs. From: Hans Verkuil I2C_DRIVERIDs are phased out. Remove those that are unused at the moment. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cs53l32a.c | 1 - linux/drivers/media/video/m52790.c | 1 - linux/drivers/media/video/saa5246a.c | 1 - linux/drivers/media/video/saa5249.c | 1 - linux/drivers/media/video/saa717x.c | 1 - linux/drivers/media/video/tda7432.c | 1 - linux/drivers/media/video/tda9840.c | 1 - linux/drivers/media/video/tda9875.c | 1 - linux/drivers/media/video/tea6415c.c | 1 - linux/drivers/media/video/tea6420.c | 1 - linux/drivers/media/video/tlv320aic23b.c | 1 - linux/drivers/media/video/tvmixer.c | 1 - linux/drivers/media/video/tvp5150.c | 1 - linux/drivers/media/video/upd64031a.c | 1 - linux/drivers/media/video/upd64083.c | 1 - linux/drivers/media/video/vp27smpx.c | 1 - linux/drivers/media/video/wm8739.c | 1 - 17 files changed, 17 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cs53l32a.c b/linux/drivers/media/video/cs53l32a.c index 842a8e4ed..c8b5fa157 100644 --- a/linux/drivers/media/video/cs53l32a.c +++ b/linux/drivers/media/video/cs53l32a.c @@ -225,7 +225,6 @@ MODULE_DEVICE_TABLE(i2c, cs53l32a_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "cs53l32a", - .driverid = I2C_DRIVERID_CS53L32A, .command = cs53l32a_command, .remove = cs53l32a_remove, .probe = cs53l32a_probe, diff --git a/linux/drivers/media/video/m52790.c b/linux/drivers/media/video/m52790.c index af179cf4b..982ab4268 100644 --- a/linux/drivers/media/video/m52790.c +++ b/linux/drivers/media/video/m52790.c @@ -222,7 +222,6 @@ MODULE_DEVICE_TABLE(i2c, m52790_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "m52790", - .driverid = I2C_DRIVERID_M52790, .command = m52790_command, .probe = m52790_probe, .remove = m52790_remove, diff --git a/linux/drivers/media/video/saa5246a.c b/linux/drivers/media/video/saa5246a.c index cb8a92e5f..be23b5bd5 100644 --- a/linux/drivers/media/video/saa5246a.c +++ b/linux/drivers/media/video/saa5246a.c @@ -1101,7 +1101,6 @@ MODULE_DEVICE_TABLE(i2c, saa5246a_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa5246a", - .driverid = I2C_DRIVERID_SAA5249, .probe = saa5246a_probe, .remove = saa5246a_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/saa5249.c b/linux/drivers/media/video/saa5249.c index 9102c6cea..eeb0edea4 100644 --- a/linux/drivers/media/video/saa5249.c +++ b/linux/drivers/media/video/saa5249.c @@ -627,7 +627,6 @@ MODULE_DEVICE_TABLE(i2c, saa5249_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa5249", - .driverid = I2C_DRIVERID_SAA5249, .probe = saa5249_probe, .remove = saa5249_remove, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) diff --git a/linux/drivers/media/video/saa717x.c b/linux/drivers/media/video/saa717x.c index b53ede210..3ad43f6b3 100644 --- a/linux/drivers/media/video/saa717x.c +++ b/linux/drivers/media/video/saa717x.c @@ -1539,7 +1539,6 @@ MODULE_DEVICE_TABLE(i2c, saa717x_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa717x", - .driverid = I2C_DRIVERID_SAA717X, .command = saa717x_command, .probe = saa717x_probe, .remove = saa717x_remove, diff --git a/linux/drivers/media/video/tda7432.c b/linux/drivers/media/video/tda7432.c index 64a90a71b..30f6f8a38 100644 --- a/linux/drivers/media/video/tda7432.c +++ b/linux/drivers/media/video/tda7432.c @@ -501,7 +501,6 @@ MODULE_DEVICE_TABLE(i2c, tda7432_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda7432", - .driverid = I2C_DRIVERID_TDA7432, .command = tda7432_command, .probe = tda7432_probe, .remove = tda7432_remove, diff --git a/linux/drivers/media/video/tda9840.c b/linux/drivers/media/video/tda9840.c index 62e257161..d2178ad78 100644 --- a/linux/drivers/media/video/tda9840.c +++ b/linux/drivers/media/video/tda9840.c @@ -265,7 +265,6 @@ MODULE_DEVICE_TABLE(i2c, tda9840_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda9840", - .driverid = I2C_DRIVERID_TDA9840, .command = tda9840_command, .probe = tda9840_probe, .remove = tda9840_remove, diff --git a/linux/drivers/media/video/tda9875.c b/linux/drivers/media/video/tda9875.c index 8e9c905e4..892d25a40 100644 --- a/linux/drivers/media/video/tda9875.c +++ b/linux/drivers/media/video/tda9875.c @@ -417,7 +417,6 @@ MODULE_DEVICE_TABLE(i2c, tda9875_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda9875", - .driverid = I2C_DRIVERID_TDA9875, .command = tda9875_command, .probe = tda9875_probe, .remove = tda9875_remove, diff --git a/linux/drivers/media/video/tea6415c.c b/linux/drivers/media/video/tea6415c.c index 0f589842c..2e57dd281 100644 --- a/linux/drivers/media/video/tea6415c.c +++ b/linux/drivers/media/video/tea6415c.c @@ -194,7 +194,6 @@ MODULE_DEVICE_TABLE(i2c, tea6415c_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tea6415c", - .driverid = I2C_DRIVERID_TEA6415C, .command = tea6415c_command, .probe = tea6415c_probe, .remove = tea6415c_remove, diff --git a/linux/drivers/media/video/tea6420.c b/linux/drivers/media/video/tea6420.c index b5f8342e0..023952ae7 100644 --- a/linux/drivers/media/video/tea6420.c +++ b/linux/drivers/media/video/tea6420.c @@ -174,7 +174,6 @@ MODULE_DEVICE_TABLE(i2c, tea6420_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tea6420", - .driverid = I2C_DRIVERID_TEA6420, .command = tea6420_command, .probe = tea6420_probe, .remove = tea6420_remove, diff --git a/linux/drivers/media/video/tlv320aic23b.c b/linux/drivers/media/video/tlv320aic23b.c index ecc3a4ef6..46671fb87 100644 --- a/linux/drivers/media/video/tlv320aic23b.c +++ b/linux/drivers/media/video/tlv320aic23b.c @@ -211,7 +211,6 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23b_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tlv320aic23b", - .driverid = I2C_DRIVERID_TLV320AIC23B, .command = tlv320aic23b_command, .probe = tlv320aic23b_probe, .remove = tlv320aic23b_remove, diff --git a/linux/drivers/media/video/tvmixer.c b/linux/drivers/media/video/tvmixer.c index fd2e902ea..ae25f0d16 100644 --- a/linux/drivers/media/video/tvmixer.c +++ b/linux/drivers/media/video/tvmixer.c @@ -223,7 +223,6 @@ static struct i2c_driver driver = { .driver = { .name = "tvmixer", }, - .id = I2C_DRIVERID_TVMIXER, #ifndef I2C_DF_DUMMY .detach_adapter = tvmixer_adapters, #endif diff --git a/linux/drivers/media/video/tvp5150.c b/linux/drivers/media/video/tvp5150.c index f968e8941..e1046ed3f 100644 --- a/linux/drivers/media/video/tvp5150.c +++ b/linux/drivers/media/video/tvp5150.c @@ -1195,7 +1195,6 @@ MODULE_DEVICE_TABLE(i2c, tvp5150_id); #endif static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tvp5150", - .driverid = I2C_DRIVERID_TVP5150, .command = tvp5150_command, .probe = tvp5150_probe, .remove = tvp5150_remove, diff --git a/linux/drivers/media/video/upd64031a.c b/linux/drivers/media/video/upd64031a.c index 9d20ff69d..0fd1c9312 100644 --- a/linux/drivers/media/video/upd64031a.c +++ b/linux/drivers/media/video/upd64031a.c @@ -275,7 +275,6 @@ MODULE_DEVICE_TABLE(i2c, upd64031a_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "upd64031a", - .driverid = I2C_DRIVERID_UPD64031A, .command = upd64031a_command, .probe = upd64031a_probe, .remove = upd64031a_remove, diff --git a/linux/drivers/media/video/upd64083.c b/linux/drivers/media/video/upd64083.c index a897d0856..aed167493 100644 --- a/linux/drivers/media/video/upd64083.c +++ b/linux/drivers/media/video/upd64083.c @@ -247,7 +247,6 @@ MODULE_DEVICE_TABLE(i2c, upd64083_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "upd64083", - .driverid = I2C_DRIVERID_UPD64083, .command = upd64083_command, .probe = upd64083_probe, .remove = upd64083_remove, diff --git a/linux/drivers/media/video/vp27smpx.c b/linux/drivers/media/video/vp27smpx.c index b3b3ee61d..3104d0e1f 100644 --- a/linux/drivers/media/video/vp27smpx.c +++ b/linux/drivers/media/video/vp27smpx.c @@ -217,7 +217,6 @@ MODULE_DEVICE_TABLE(i2c, vp27smpx_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "vp27smpx", - .driverid = I2C_DRIVERID_VP27SMPX, .command = vp27smpx_command, .probe = vp27smpx_probe, .remove = vp27smpx_remove, diff --git a/linux/drivers/media/video/wm8739.c b/linux/drivers/media/video/wm8739.c index ac81c6442..df7d6a094 100644 --- a/linux/drivers/media/video/wm8739.c +++ b/linux/drivers/media/video/wm8739.c @@ -351,7 +351,6 @@ MODULE_DEVICE_TABLE(i2c, wm8739_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "wm8739", - .driverid = I2C_DRIVERID_WM8739, .command = wm8739_command, .probe = wm8739_probe, .remove = wm8739_remove, -- cgit v1.2.3 From b34bef7d48726a37eea205ac8fafccadd6c23b67 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 29 Jan 2009 20:34:25 +0100 Subject: gspca - vc032x: Add resolution 1280x1024 for sensor mi1310_soc. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 108 ++++++++++++++----------------- 1 file changed, 50 insertions(+), 58 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 01d886d06..45ece4a45 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -149,6 +149,11 @@ static const struct v4l2_pix_format vc0323_mode[] = { .sizeimage = 640 * 480 * 3 / 8 + 590, .colorspace = V4L2_COLORSPACE_JPEG, .priv = 0}, + {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi1310_soc only */ + .bytesperline = 1280, + .sizeimage = 1280 * 1024 * 1 / 4 + 590, + .colorspace = V4L2_COLORSPACE_JPEG, + .priv = 2}, }; static const struct v4l2_pix_format svga_mode[] = { @@ -623,7 +628,6 @@ static const __u8 mi1310_socinitQVGA_JPG[][4] = { {0xb8, 0xa0, 0x12, 0xcc}, {}, }; -#if 0 static const u8 mi1310_soc_InitSXGA_JPG[][4] = { {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc}, @@ -731,7 +735,6 @@ static const u8 mi1310_soc_InitSXGA_JPG[][4] = { {0xb8, 0xa0, 0x12, 0xcc}, {} }; -#endif static const __u8 mi1320_gamma[17] = { 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, @@ -2157,7 +2160,10 @@ static int sd_config(struct gspca_dev *gspca_dev, } else { if (sensor != SENSOR_PO1200) { cam->cam_mode = vc0323_mode; - cam->nmodes = ARRAY_SIZE(vc0323_mode); + if (sd->sensor != SENSOR_MI1310_SOC) + cam->nmodes = ARRAY_SIZE(vc0323_mode); + else /* no SXGA */ + cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1; } else { cam->cam_mode = svga_mode; cam->nmodes = ARRAY_SIZE(svga_mode); @@ -2259,6 +2265,7 @@ static void setsharpness(struct gspca_dev *gspca_dev) static int sd_start(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + const __u8 (*init)[4]; const __u8 *GammaT = NULL; const __u8 *MatrixT = NULL; int mode; @@ -2276,96 +2283,81 @@ static int sd_start(struct gspca_dev *gspca_dev) case SENSOR_HV7131R: GammaT = hv7131r_gamma; MatrixT = hv7131r_matrix; - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, hv7131r_initQVGA_data); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, hv7131r_initVGA_data); - } + if (mode) + init = hv7131r_initQVGA_data; /* 320x240 */ + else + init = hv7131r_initVGA_data; /* 640x480 */ break; case SENSOR_OV7660: GammaT = ov7660_gamma; MatrixT = ov7660_matrix; - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, ov7660_initQVGA_data); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, ov7660_initVGA_data); - } + if (mode) + init = ov7660_initQVGA_data; /* 320x240 */ + else + init = ov7660_initVGA_data; /* 640x480 */ break; case SENSOR_OV7670: /*GammaT = ov7660_gamma; */ /*MatrixT = ov7660_matrix; */ - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, ov7670_initQVGA_JPG); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, ov7670_initVGA_JPG); - } + if (mode) + init = ov7670_initQVGA_JPG; /* 320x240 */ + else + init = ov7670_initVGA_JPG; /* 640x480 */ break; case SENSOR_MI0360: GammaT = mi1320_gamma; MatrixT = mi0360_matrix; - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, mi0360_initQVGA_JPG); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, mi0360_initVGA_JPG); - } + if (mode) + init = mi0360_initQVGA_JPG; /* 320x240 */ + else + init = mi0360_initVGA_JPG; /* 640x480 */ break; case SENSOR_MI1310_SOC: GammaT = mi1320_gamma; MatrixT = mi0360_matrix; - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, mi1310_socinitQVGA_JPG); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, mi1310_socinitVGA_JPG); + switch (mode) { + case 1: + init = mi1310_socinitQVGA_JPG; /* 320x240 */ + break; + case 0: + init = mi1310_socinitVGA_JPG; /* 640x480 */ + break; + default: + init = mi1310_soc_InitSXGA_JPG; /* 1280xq024 */ + break; } break; case SENSOR_MI1320: GammaT = mi1320_gamma; MatrixT = mi1320_matrix; - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, mi1320_initQVGA_data); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, mi1320_initVGA_data); - } + if (mode) + init = mi1320_initQVGA_data; /* 320x240 */ + else + init = mi1320_initVGA_data; /* 640x480 */ break; case SENSOR_PO3130NC: GammaT = po3130_gamma; MatrixT = po3130_matrix; - if (mode) { - /* 320x240 */ - usb_exchange(gspca_dev, po3130_initQVGA_data); - } else { - /* 640x480 */ - usb_exchange(gspca_dev, po3130_initVGA_data); - } - usb_exchange(gspca_dev, po3130_rundata); + if (mode) + init = po3130_initQVGA_data; /* 320x240 */ + else + init = po3130_initVGA_data; /* 640x480 */ + usb_exchange(gspca_dev, init); + init = po3130_rundata; break; - case SENSOR_PO1200: + default: +/* case SENSOR_PO1200: */ GammaT = po1200_gamma; MatrixT = po1200_matrix; - usb_exchange(gspca_dev, po1200_initVGA_data); + init = po1200_initVGA_data; break; - default: - PDEBUG(D_PROBE, "Damned !! no sensor found Bye"); - return -EMEDIUMTYPE; } + usb_exchange(gspca_dev, init); if (GammaT && MatrixT) { put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a); put_tab_to_reg(gspca_dev, GammaT, 17, 0xb85b); put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c); put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c); - /* Seem SHARPNESS */ /* reg_w(gspca_dev->dev, 0xa0, 0x80, 0xb80a); -- cgit v1.2.3 From f1ee371d5b7780d8c85202d55a6602f61abb50b6 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Fri, 30 Jan 2009 02:57:07 +0200 Subject: Bug fix: Restore HVR-4000 tuning. From: Igor M. Liplianin Some cards uses cx24116 LNB_DC pin for LNB power control, some not uses, some uses it different way, like HVR-4000. Signed-off-by: Igor M. Liplianin Tested-by : Edgar Hucek --- linux/drivers/media/dvb/frontends/cx24116.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/frontends/cx24116.c b/linux/drivers/media/dvb/frontends/cx24116.c index db1e1e4ea..8301a9865 100644 --- a/linux/drivers/media/dvb/frontends/cx24116.c +++ b/linux/drivers/media/dvb/frontends/cx24116.c @@ -1184,7 +1184,12 @@ static int cx24116_initfe(struct dvb_frontend *fe) if (ret != 0) return ret; - return cx24116_diseqc_init(fe); + ret = cx24116_diseqc_init(fe); + if (ret != 0) + return ret; + + /* HVR-4000 needs this */ + return cx24116_set_voltage(fe, SEC_VOLTAGE_13); } /* -- cgit v1.2.3 From 173b6c4977dc5d99c1273fe0e139dc6d5d6f7d6e Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 30 Jan 2009 16:14:02 +0100 Subject: gspca - sonixj: Bad initialization of sensor mt9v111. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index a16f21be3..5b5e526d8 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -1580,6 +1580,7 @@ static int sd_start(struct gspca_dev *gspca_dev) /* reg1 = 0x06; * 640 clk 24Mz (done) */ reg17 = 0xe2; } + break; case SENSOR_OM6802: om6802_InitSensor(gspca_dev); reg17 = 0x64; /* 640 MCKSIZE */ -- cgit v1.2.3 From 1a68aa3086f7f370d97adff8c3de35669c02f6f5 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 30 Jan 2009 20:21:45 -0500 Subject: cx18: Defer A/V core initialization until a valid cx18_av_cmd arrives From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-core.c | 40 ++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 7 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index 0b1c84b4d..50979d333 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -680,19 +680,45 @@ static int set_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt) /* ----------------------------------------------------------------------- */ +static int valid_av_cmd(unsigned int cmd) +{ + switch (cmd) { + /* All commands supported by cx18_av_cmd() */ + case VIDIOC_INT_DECODE_VBI_LINE: + case VIDIOC_INT_AUDIO_CLOCK_FREQ: + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: + case VIDIOC_LOG_STATUS: + case VIDIOC_G_CTRL: + case VIDIOC_S_CTRL: + case VIDIOC_QUERYCTRL: + case VIDIOC_G_STD: + case VIDIOC_S_STD: + case AUDC_SET_RADIO: + case VIDIOC_INT_G_VIDEO_ROUTING: + case VIDIOC_INT_S_VIDEO_ROUTING: + case VIDIOC_INT_G_AUDIO_ROUTING: + case VIDIOC_INT_S_AUDIO_ROUTING: + case VIDIOC_S_FREQUENCY: + case VIDIOC_G_TUNER: + case VIDIOC_S_TUNER: + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_INT_RESET: + return 1; + default: + return 0; + } + return 0; +} + int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg) { struct cx18_av_state *state = &cx->av_state; struct v4l2_tuner *vt = arg; struct v4l2_routing *route = arg; - /* ignore these commands */ - switch (cmd) { - case TUNER_SET_TYPE_ADDR: - return 0; - } - - if (!state->is_initialized) { + if (!state->is_initialized && valid_av_cmd(cmd)) { CX18_DEBUG_INFO("cmd %08x triggered fw load\n", cmd); /* initialize on first use */ state->is_initialized = 1; -- cgit v1.2.3 From bb9067ce37544bf82eebcee5ce959dcef1720113 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 30 Jan 2009 20:39:26 -0500 Subject: cx18: Smarter verification of CX18_AUDIO_ENABLE register writes From: Andy Walls The CX18_AUDIO_ENABLE register usually never reads back what was just written under normal circumstances. Perform better checking that a write went to the register as expected with a specification of what bits to verify. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-audio.c | 3 +-- linux/drivers/media/video/cx18/cx18-av-firmware.c | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-audio.c b/linux/drivers/media/video/cx18/cx18-audio.c index 57beddf0a..d19bd778c 100644 --- a/linux/drivers/media/video/cx18/cx18-audio.c +++ b/linux/drivers/media/video/cx18/cx18-audio.c @@ -64,8 +64,7 @@ int cx18_audio_set_io(struct cx18 *cx) val = cx18_read_reg(cx, CX18_AUDIO_ENABLE) & ~0x30; val |= (audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 : (audio_input << 4); - cx18_write_reg(cx, val | 0xb00, CX18_AUDIO_ENABLE); - cx18_vapi(cx, CX18_APU_RESETAI, 1, 0); + cx18_write_reg_expect(cx, val | 0xb00, CX18_AUDIO_ENABLE, val, 0x30); return 0; } diff --git a/linux/drivers/media/video/cx18/cx18-av-firmware.c b/linux/drivers/media/video/cx18/cx18-av-firmware.c index b374c74d3..940ea9352 100644 --- a/linux/drivers/media/video/cx18/cx18-av-firmware.c +++ b/linux/drivers/media/video/cx18/cx18-av-firmware.c @@ -131,7 +131,8 @@ int cx18_av_loadfw(struct cx18 *cx) v = cx18_read_reg(cx, CX18_AUDIO_ENABLE); /* If bit 11 is 1, clear bit 10 */ if (v & 0x800) - cx18_write_reg(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); + cx18_write_reg_expect(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE, + 0, 0x400); /* Enable WW auto audio standard detection */ v = cx18_av_read4(cx, CXADEC_STD_DET_CTL); -- cgit v1.2.3 From a5bbba89bd5698bdbde479d385a44a7b9bdecb70 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 30 Jan 2009 20:48:40 -0500 Subject: cx18: Normalize APU after second APU firmware load From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index fe2324ef2..f48d18f69 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -1085,6 +1085,19 @@ int cx18_init_on_first_open(struct cx18 *cx) return -ENXIO; } + /* + * The second firmware load requires us to normalize the APU state, + * or the audio for the first analog capture will be badly incorrect. + * + * I can't seem to call APU_RESETAI and have it succeed without the + * APU capturing audio, so we start and stop it here to do the reset + */ + + /* MPEG Encoding, 224 kbps, MPEG Layer II, 48 ksps */ + cx18_vapi(cx, CX18_APU_START, 2, CX18_APU_ENCODING_METHOD_MPEG|0xb9, 0); + cx18_vapi(cx, CX18_APU_RESETAI, 0); + cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG); + vf.tuner = 0; vf.type = V4L2_TUNER_ANALOG_TV; vf.frequency = 6400; /* the tuner 'baseline' frequency */ -- cgit v1.2.3 From adbc75d3cf3691d649c8dac1f32ee21f332f0f4c Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 30 Jan 2009 22:33:02 -0500 Subject: cx18: Clean-up and enable sliced VBI handling From: Andy Walls Removed legacy ivtv state variables, added comments, and cleaned up sliced VBI related code. Enabled sliced VBI. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-core.c | 11 +- linux/drivers/media/video/cx18/cx18-av-vbi.c | 92 ++++++++++++---- linux/drivers/media/video/cx18/cx18-cards.c | 8 +- linux/drivers/media/video/cx18/cx18-cards.h | 3 +- linux/drivers/media/video/cx18/cx18-controls.c | 4 +- linux/drivers/media/video/cx18/cx18-driver.c | 49 +-------- linux/drivers/media/video/cx18/cx18-driver.h | 142 ++++++++++++++++++------- linux/drivers/media/video/cx18/cx18-fileops.c | 54 +++++++--- linux/drivers/media/video/cx18/cx18-ioctl.c | 23 +--- linux/drivers/media/video/cx18/cx18-streams.c | 45 ++++++-- linux/drivers/media/video/cx18/cx18-vbi.c | 58 +++++++--- 11 files changed, 311 insertions(+), 178 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index 0b1c84b4d..5279b8e45 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -169,9 +169,14 @@ static void cx18_av_initialize(struct cx18 *cx) /* Set VGA_TRACK_RANGE to 0x20 */ cx18_av_and_or4(cx, CXADEC_DFE_CTRL2, 0xFFFF00FF, 0x00002000); - /* Enable VBI capture */ - cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253F); - /* cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253E); */ + /* + * Initial VBI setup + * VIP-1.1, 10 bit mode, enable Raw, disable sliced, + * don't clamp raw samples when codes are in use, 4 byte user D-words, + * programmed IDID, RP code V bit transition on VBLANK, data during + * blanking intervals + */ + cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010252e); /* Set the video input. The setting in MODE_CTRL gets lost when we do the above setup */ diff --git a/linux/drivers/media/video/cx18/cx18-av-vbi.c b/linux/drivers/media/video/cx18/cx18-av-vbi.c index 1527ea4f6..72325d774 100644 --- a/linux/drivers/media/video/cx18/cx18-av-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-av-vbi.c @@ -24,6 +24,52 @@ #include "cx18-driver.h" +/* + * For sliced VBI output, we set up to use VIP-1.1, 10-bit mode, + * NN counts 4 bytes Dwords, an IDID of 0x00 0x80 or one with the VBI line #. + * Thus, according to the VIP-2 Spec, our VBI ancillary data lines + * (should!) look like: + * 4 byte EAV code: 0xff 0x00 0x00 0xRP + * unknown number of possible idle bytes + * 3 byte Anc data preamble: 0x00 0xff 0xff + * 1 byte data identifier: ne010iii (parity bits, 010, DID bits) + * 1 byte secondary data id: nessssss (parity bits, SDID bits) + * 1 byte data word count: necccccc (parity bits, NN Dword count) + * 2 byte Internal DID: 0x00 0x80 (programmed value) + * 4*NN data bytes + * 1 byte checksum + * Fill bytes needed to fil out to 4*NN bytes of payload + * + * The RP codes for EAVs when in VIP-1.1 mode, not in raw mode, & + * in the vertical blanking interval are: + * 0xb0 (Task 0 VerticalBlank HorizontalBlank 0 0 0 0) + * 0xf0 (Task EvenField VerticalBlank HorizontalBlank 0 0 0 0) + * + * Since the V bit is only allowed to toggle in the EAV RP code, just + * before the first active region line and for active lines, they are: + * 0x90 (Task 0 0 HorizontalBlank 0 0 0 0) + * 0xd0 (Task EvenField 0 HorizontalBlank 0 0 0 0) + * + * The user application DID bytes we care about are: + * 0x91 (1 0 010 0 !ActiveLine AncDataPresent) + * 0x55 (0 1 010 2ndField !ActiveLine AncDataPresent) + * + */ +static const u8 sliced_vbi_did[2] = { 0x91, 0x55 }; + +struct vbi_anc_data { + /* u8 eav[4]; */ + /* u8 idle[]; Variable number of idle bytes */ + u8 preamble[3]; + u8 did; + u8 sdid; + u8 data_count; + u8 idid[2]; + u8 payload[1]; /* 4*data_count of payload */ + /* u8 checksum; */ + /* u8 fill[]; Variable number of fill bytes */ +}; + static int odd_parity(u8 c) { c ^= (c >> 4); @@ -96,7 +142,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ 0, V4L2_SLICED_WSS_625, 0, /* 4 */ V4L2_SLICED_CAPTION_525, /* 6 */ - 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ + V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 - unlike cx25840 */ 0, 0, 0, 0 }; int is_pal = !(state->std & V4L2_STD_525_60); @@ -220,47 +266,53 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) case VIDIOC_INT_DECODE_VBI_LINE: { struct v4l2_decode_vbi_line *vbi = arg; - u8 *p = vbi->p; - int id1, id2, l, err = 0; - - if (p[0] || p[1] != 0xff || p[2] != 0xff || - (p[3] != 0x55 && p[3] != 0x91)) { + u8 *p; + struct vbi_anc_data *anc = (struct vbi_anc_data *) vbi->p; + int did, sdid, l, err = 0; + + /* + * Check for the ancillary data header for sliced VBI + */ + if (anc->preamble[0] || + anc->preamble[1] != 0xff || anc->preamble[2] != 0xff || + (anc->did != sliced_vbi_did[0] && + anc->did != sliced_vbi_did[1])) { vbi->line = vbi->type = 0; break; } - p += 4; - id1 = p[-1]; - id2 = p[0] & 0xf; - l = p[2] & 0x3f; + did = anc->did; + sdid = anc->sdid & 0xf; + l = anc->idid[0] & 0x3f; l += state->vbi_line_offset; - p += 4; + p = anc->payload; - switch (id2) { + /* Decode the SDID set by the slicer */ + switch (sdid) { case 1: - id2 = V4L2_SLICED_TELETEXT_B; + sdid = V4L2_SLICED_TELETEXT_B; break; case 4: - id2 = V4L2_SLICED_WSS_625; + sdid = V4L2_SLICED_WSS_625; break; case 6: - id2 = V4L2_SLICED_CAPTION_525; + sdid = V4L2_SLICED_CAPTION_525; err = !odd_parity(p[0]) || !odd_parity(p[1]); break; - case 9: - id2 = V4L2_SLICED_VPS; + case 7: /* Differs from cx25840 */ + sdid = V4L2_SLICED_VPS; if (decode_vps(p, p) != 0) err = 1; break; default: - id2 = 0; + sdid = 0; err = 1; break; } - vbi->type = err ? 0 : id2; + vbi->type = err ? 0 : sdid; vbi->line = err ? 0 : l; - vbi->is_second_field = err ? 0 : (id1 == 0x55); + vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]); vbi->p = p; break; } diff --git a/linux/drivers/media/video/cx18/cx18-cards.c b/linux/drivers/media/video/cx18/cx18-cards.c index 53217cf45..c0177ce39 100644 --- a/linux/drivers/media/video/cx18/cx18-cards.c +++ b/linux/drivers/media/video/cx18/cx18-cards.c @@ -51,7 +51,7 @@ static struct cx18_card_tuner_i2c cx18_i2c_std = { static const struct cx18_card cx18_card_hvr1600_esmt = { .type = CX18_CARD_HVR_1600_ESMT, .name = "Hauppauge HVR-1600", - .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", + .comment = "Simultaneous Digital and Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_muxer = CX18_HW_CS5345, @@ -97,7 +97,7 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { static const struct cx18_card cx18_card_hvr1600_samsung = { .type = CX18_CARD_HVR_1600_SAMSUNG, .name = "Hauppauge HVR-1600 (Preproduction)", - .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", + .comment = "Simultaneous Digital and Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_muxer = CX18_HW_CS5345, @@ -152,7 +152,7 @@ static const struct cx18_card_pci_info cx18_pci_h900[] = { static const struct cx18_card cx18_card_h900 = { .type = CX18_CARD_COMPRO_H900, .name = "Compro VideoMate H900", - .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", + .comment = "Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_all = CX18_HW_TUNER, @@ -249,7 +249,7 @@ static const struct cx18_card_pci_info cx18_pci_cnxt_raptor_pal[] = { static const struct cx18_card cx18_card_cnxt_raptor_pal = { .type = CX18_CARD_CNXT_RAPTOR_PAL, .name = "Conexant Raptor PAL/SECAM", - .comment = "Raw VBI supported; Sliced VBI is not yet supported\n", + .comment = "Analog TV capture supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_muxer = CX18_HW_GPIO, diff --git a/linux/drivers/media/video/cx18/cx18-cards.h b/linux/drivers/media/video/cx18/cx18-cards.h index 6fa7bcb42..f8ee29f10 100644 --- a/linux/drivers/media/video/cx18/cx18-cards.h +++ b/linux/drivers/media/video/cx18/cx18-cards.h @@ -49,8 +49,7 @@ /* V4L2 capability aliases */ #define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | \ - V4L2_CAP_VBI_CAPTURE) -/* | V4L2_CAP_SLICED_VBI_CAPTURE) not yet */ + V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE) struct cx18_card_video_input { u8 video_type; /* video input type */ diff --git a/linux/drivers/media/video/cx18/cx18-controls.c b/linux/drivers/media/video/cx18/cx18-controls.c index 17edf305d..6af4d5c19 100644 --- a/linux/drivers/media/video/cx18/cx18-controls.c +++ b/linux/drivers/media/video/cx18/cx18-controls.c @@ -178,8 +178,8 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt int i; for (i = 0; i < CX18_VBI_FRAMES; i++) { - /* Yuck, hardcoded. Needs to be a define */ - cx->vbi.sliced_mpeg_data[i] = kmalloc(2049, GFP_KERNEL); + cx->vbi.sliced_mpeg_data[i] = + kmalloc(CX18_SLICED_MPEG_DATA_BUFSZ, GFP_KERNEL); if (cx->vbi.sliced_mpeg_data[i] == NULL) { while (--i >= 0) { kfree(cx->vbi.sliced_mpeg_data[i]); diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index fe2324ef2..f3a50f673 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -593,7 +593,8 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) (cx->params.video_temporal_filter_mode << 1) | (cx->params.video_median_filter_type << 2); cx->params.port = CX2341X_PORT_MEMORY; - cx->params.capabilities = CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_AC3; + cx->params.capabilities = + CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_AC3 | CX2341X_CAP_HAS_SLICED_VBI; init_waitqueue_head(&cx->cap_w); init_waitqueue_head(&cx->mb_apu_waitq); init_waitqueue_head(&cx->mb_cpu_waitq); @@ -603,49 +604,6 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced; - /* - * The VBI line sizes depend on the pixel clock and the horiz rate - * - * (1/Fh)*(2*Fp) = Samples/line - * = 4 bytes EAV + Anc data in hblank + 4 bytes SAV + active samples - * - * Sliced VBI is sent as ancillary data during horizontal blanking - * Raw VBI is sent as active video samples during vertcal blanking - * - * We use a BT.656 pxiel clock of 13.5 MHz and a BT.656 active line - * length of 720 pixels @ 4:2:2 sampling. Thus... - * - * For systems that use a 15.734 kHz horizontal rate, such as - * NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have: - * - * (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line = - * 4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples - * - * For systems that use a 15.625 kHz horizontal rate, such as - * PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have: - * - * (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line = - * 4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples - * - */ - - /* FIXME: init these based on tuner std & modify when std changes */ - /* CX18-AV-Core number of VBI samples output per horizontal line */ - cx->vbi.raw_decoder_line_size = 1444; /* 4 byte SAV + 2 * 720 */ - cx->vbi.sliced_decoder_line_size = 272; /* 60 Hz: 268+4, 50 Hz: 280+4 */ - - /* CX18-AV-Core VBI samples/line possibly rounded up */ - cx->vbi.raw_size = 1444; /* Real max size is 1444 */ - cx->vbi.sliced_size = 284; /* Real max size is 284 */ - - /* - * CX18-AV-Core SAV/EAV RP codes in VIP 1.x mode - * Task Field VerticalBlank HorizontalBlank 0 0 0 0 - */ - cx->vbi.raw_decoder_sav_odd_field = 0x20; /* V */ - cx->vbi.raw_decoder_sav_even_field = 0x60; /* FV */ - cx->vbi.sliced_decoder_sav_odd_field = 0xB0; /* T VH - actually EAV */ - cx->vbi.sliced_decoder_sav_even_field = 0xF0; /* TFVH - actually EAV */ return 0; } @@ -678,7 +636,6 @@ static void __devinit cx18_init_struct2(struct cx18 *cx) cx->av_state.aud_input = CX18_AV_AUDIO8; cx->av_state.audclk_freq = 48000; cx->av_state.audmode = V4L2_TUNER_MODE_LANG1; - /* FIXME - 8 is NTSC value, investigate */ cx->av_state.vbi_line_offset = 8; } @@ -943,7 +900,7 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, * suboptimal, as the CVBS and SVideo inputs could use a different std * and the buffer could end up being too small in that case. */ - vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2; + vbi_buf_size = vbi_active_samples * (cx->is_60hz ? 24 : 36) / 2; cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size; if (cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] < 0) diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index 3a21013cd..d2829f576 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -319,59 +319,121 @@ struct cx18_open_id { /* forward declaration of struct defined in cx18-cards.h */ struct cx18_card; +/* + * A note about "sliced" VBI data as implemented in this driver: + * + * Currently we collect the sliced VBI in the form of Ancillary Data + * packets, inserted by the AV core decoder/digitizer/slicer in the + * horizontal blanking region of the VBI lines, in "raw" mode as far as + * the Encoder is concerned. We don't ever tell the Encoder itself + * to provide sliced VBI. (AV Core: sliced mode - Encoder: raw mode) + * + * We then process the ancillary data ourselves to send the sliced data + * to the user application directly or build up MPEG-2 private stream 1 + * packets to splice into (only!) MPEG-2 PS streams for the user app. + * + * (That's how ivtv essentially does it.) + * + * The Encoder should be able to extract certain sliced VBI data for + * us and provide it in a separate stream or splice it into any type of + * MPEG PS or TS stream, but this isn't implemented yet. + */ + +/* + * Number of "raw" VBI samples per horizontal line we tell the Encoder to + * grab from the decoder/digitizer/slicer output for raw or sliced VBI. + * It depends on the pixel clock and the horiz rate: + * + * (1/Fh)*(2*Fp) = Samples/line + * = 4 bytes EAV + Anc data in hblank + 4 bytes SAV + active samples + * + * Sliced VBI data is sent as ancillary data during horizontal blanking + * Raw VBI is sent as active video samples during vertcal blanking + * + * We use a BT.656 pxiel clock of 13.5 MHz and a BT.656 active line + * length of 720 pixels @ 4:2:2 sampling. Thus... + * + * For systems that use a 15.734 kHz horizontal rate, such as + * NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have: + * + * (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line = + * 4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples + * + * For systems that use a 15.625 kHz horizontal rate, such as + * PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have: + * + * (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line = + * 4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples + */ +static const u32 vbi_active_samples = 1444; /* 4 byte SAV + 720 Y + 720 U/V */ +static const u32 vbi_hblank_samples_60Hz = 272; /* 4 byte EAV + 268 anc/fill */ +static const u32 vbi_hblank_samples_50Hz = 284; /* 4 byte EAV + 280 anc/fill */ #define CX18_VBI_FRAMES 32 -/* VBI data */ struct vbi_info { - u32 enc_size; - u32 frame; - u8 cc_data_odd[256]; - u8 cc_data_even[256]; - int cc_pos; - u8 cc_no_update; - u8 vps[5]; - u8 vps_found; - int wss; - u8 wss_found; - u8 wss_no_update; - u32 raw_decoder_line_size; - u8 raw_decoder_sav_odd_field; - u8 raw_decoder_sav_even_field; - u32 sliced_decoder_line_size; - u8 sliced_decoder_sav_odd_field; - u8 sliced_decoder_sav_even_field; + /* Current state of v4l2 VBI settings for this device */ struct v4l2_format in; - /* convenience pointer to sliced struct in vbi_in union */ - struct v4l2_sliced_vbi_format *sliced_in; - u32 service_set_in; - int insert_mpeg; + struct v4l2_sliced_vbi_format *sliced_in; /* pointer to in.fmt.sliced */ + u32 count; /* Count of VBI data lines: 60 Hz: 12 or 50 Hz: 18 */ + u32 start[2]; /* First VBI data line per field: 10 & 273 or 6 & 318 */ - /* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines. - One for /dev/vbi0 and one for /dev/vbi8 */ - struct v4l2_sliced_vbi_data sliced_data[36]; + u32 frame; /* Count of VBI buffers/frames received from Encoder */ - /* Buffer for VBI data inserted into MPEG stream. - The first byte is a dummy byte that's never used. - The next 16 bytes contain the MPEG header for the VBI data, - the remainder is the actual VBI data. - The max size accepted by the MPEG VBI reinsertion turns out - to be 1552 bytes, which happens to be 4 + (1 + 42) * (2 * 18) bytes, - where 4 is a four byte header, 42 is the max sliced VBI payload, 1 is - a single line header byte and 2 * 18 is the number of VBI lines per frame. + /* + * Vars for creation and insertion of MPEG Private Stream 1 packets + * of sliced VBI data into an MPEG PS + */ - However, it seems that the data must be 1K aligned, so we have to - pad the data until the 1 or 2 K boundary. + /* Boolean: create and insert Private Stream 1 packets into the PS */ + int insert_mpeg; + + /* + * Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines. + * Used in cx18-vbi.c only for collecting sliced data, and as a source + * during conversion of sliced VBI data into MPEG Priv Stream 1 packets. + * We don't need to save state here, but the array may have been a bit + * too big (2304 bytes) to alloc from the stack. + */ + struct v4l2_sliced_vbi_data sliced_data[36]; - This pointer array will allocate 2049 bytes to store each VBI frame. */ + /* + * A ring buffer of driver-generated MPEG-2 PS + * Program Pack/Private Stream 1 packets for sliced VBI data insertion + * into the MPEG PS stream. + * + * In each sliced_mpeg_data[] buffer is: + * 16 byte MPEG-2 PS Program Pack Header + * 16 byte MPEG-2 Private Stream 1 PES Header + * 4 byte magic number: "itv0" or "ITV0" + * 4 byte first field line mask, if "itv0" + * 4 byte second field line mask, if "itv0" + * 36 lines, if "ITV0"; or <36 lines, if "itv0"; of sliced VBI data + * + * Each line in the payload is + * 1 byte line header derived from the SDID (WSS, CC, VPS, etc.) + * 42 bytes of line data + * + * That's a maximum 1552 bytes of payload in the Private Stream 1 packet + * which is the payload size a PVR-350 (CX23415) MPEG decoder will + * accept for VBI data. So, including the headers, it's a maximum 1584 + * bytes total. + */ +#define CX18_SLICED_MPEG_DATA_MAXSZ 1584 + /* copy_vbi_buf() needs 8 temp bytes on the end for the worst case */ +#define CX18_SLICED_MPEG_DATA_BUFSZ (CX18_SLICED_MPEG_DATA_MAXSZ+8) u8 *sliced_mpeg_data[CX18_VBI_FRAMES]; u32 sliced_mpeg_size[CX18_VBI_FRAMES]; - struct cx18_buffer sliced_mpeg_buf; + + /* Count of Program Pack/Program Stream 1 packets inserted into PS */ u32 inserted_frame; - u32 start[2], count; - u32 raw_size; - u32 sliced_size; + /* + * A dummy driver stream transfer buffer with a copy of the next + * sliced_mpeg_data[] buffer for output to userland apps. + * Only used in cx18-fileops.c, but its state needs to persist at times. + */ + struct cx18_buffer sliced_mpeg_buf; }; /* Per cx23418, per I2C bus private algo callback data */ diff --git a/linux/drivers/media/video/cx18/cx18-fileops.c b/linux/drivers/media/video/cx18/cx18-fileops.c index 36c380b66..7d979ea28 100644 --- a/linux/drivers/media/video/cx18/cx18-fileops.c +++ b/linux/drivers/media/video/cx18/cx18-fileops.c @@ -209,9 +209,9 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, *err = 0; while (1) { if (s->type == CX18_ENC_STREAM_TYPE_MPG) { -#if 0 /* Process pending program info updates and pending VBI data */ +#if 0 cx18_update_pgm_info(cx); #endif @@ -298,6 +298,20 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, len = ucount; if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG && !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) { + /* + * Try to find a good splice point in the PS, just before + * an MPEG-2 Program Pack start code, and provide only + * up to that point to the user, so it's easy to insert VBI data + * the next time around. + */ + /* FIXME - This only works for an MPEG-2 PS, not a TS */ + /* + * An MPEG-2 Program Stream (PS) is a series of + * MPEG-2 Program Packs terminated by an + * MPEG Program End Code after the last Program Pack. + * A Program Pack may hold a PS System Header packet and any + * number of Program Elementary Stream (PES) Packets + */ const char *start = buf->buf + buf->readpos; const char *p = start + 1; const u8 *q; @@ -305,38 +319,54 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, int stuffing, i; while (start + len > p) { + /* Scan for a 0 to find a potential MPEG-2 start code */ q = memchr(p, 0, start + len - p); if (q == NULL) break; p = q + 1; + /* + * Keep looking if not a + * MPEG-2 Pack header start code: 0x00 0x00 0x01 0xba + * or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0 + */ if ((char *)q + 15 >= buf->buf + buf->bytesused || q[1] != 0 || q[2] != 1 || q[3] != ch) continue; + + /* If expecting the primary video PES */ if (!cx->search_pack_header) { + /* Continue if it couldn't be a PES packet */ if ((q[6] & 0xc0) != 0x80) continue; - if (((q[7] & 0xc0) == 0x80 && - (q[9] & 0xf0) == 0x20) || - ((q[7] & 0xc0) == 0xc0 && - (q[9] & 0xf0) == 0x30)) { - ch = 0xba; + /* Check if a PTS or PTS & DTS follow */ + if (((q[7] & 0xc0) == 0x80 && /* PTS only */ + (q[9] & 0xf0) == 0x20) || /* PTS only */ + ((q[7] & 0xc0) == 0xc0 && /* PTS & DTS */ + (q[9] & 0xf0) == 0x30)) { /* DTS follows */ + /* Assume we found the video PES hdr */ + ch = 0xba; /* next want a Program Pack*/ cx->search_pack_header = 1; - p = q + 9; + p = q + 9; /* Skip this video PES hdr */ } continue; } + + /* We may have found a Program Pack start code */ + + /* Get the count of stuffing bytes & verify them */ stuffing = q[13] & 7; /* all stuffing bytes must be 0xff */ for (i = 0; i < stuffing; i++) if (q[14 + i] != 0xff) break; - if (i == stuffing && - (q[4] & 0xc4) == 0x44 && - (q[12] & 3) == 3 && - q[14 + stuffing] == 0 && + if (i == stuffing && /* right number of stuffing bytes*/ + (q[4] & 0xc4) == 0x44 && /* marker check */ + (q[12] & 3) == 3 && /* marker check */ + q[14 + stuffing] == 0 && /* PES Pack or Sys Hdr */ q[15 + stuffing] == 0 && q[16 + stuffing] == 1) { - cx->search_pack_header = 0; + /* We declare we actually found a Program Pack*/ + cx->search_pack_header = 0; /* expect vid PES */ len = (char *)q - start; cx18_setup_sliced_vbi_buf(cx); break; diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index 4a49b0819..645c41937 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -102,7 +102,6 @@ void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) } } -#if 0 static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) { int f, l; @@ -116,7 +115,6 @@ static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) } return set != 0; } -#endif u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt) { @@ -165,7 +163,7 @@ static int cx18_g_fmt_vbi_cap(struct file *file, void *fh, vbifmt->sampling_rate = 27000000; vbifmt->offset = 248; - vbifmt->samples_per_line = cx->vbi.raw_decoder_line_size - 4; + vbifmt->samples_per_line = vbi_active_samples - 4; vbifmt->sample_format = V4L2_PIX_FMT_GREY; vbifmt->start[0] = cx->vbi.start[0]; vbifmt->start[1] = cx->vbi.start[1]; @@ -179,8 +177,6 @@ static int cx18_g_fmt_vbi_cap(struct file *file, void *fh, static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { -#if 0 - /* Supported by the cx23418 but not yet implemented. */ struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; @@ -192,9 +188,6 @@ static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, cx18_av_cmd(cx, VIDIOC_G_FMT, fmt); vbifmt->service_set = cx18_get_service_set(vbifmt); return 0; -#else - return -EINVAL; -#endif } static int cx18_try_fmt_vid_cap(struct file *file, void *fh, @@ -224,8 +217,6 @@ static int cx18_try_fmt_vbi_cap(struct file *file, void *fh, static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { -#if 0 - /* Supported by the cx23418 but not yet implemented. */ struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; @@ -238,9 +229,6 @@ static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh, check_service_set(vbifmt, cx->is_50hz); vbifmt->service_set = cx18_get_service_set(vbifmt); return 0; -#else - return -EINVAL; -#endif } static int cx18_s_fmt_vid_cap(struct file *file, void *fh, @@ -296,8 +284,6 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) { -#if 0 - /* Supported by the cx23418 but not yet implemented. */ struct cx18_open_id *id = fh; struct cx18 *cx = id->cx; int ret; @@ -320,9 +306,6 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in)); return 0; -#else - return -EINVAL; -#endif } static int cx18_g_chip_ident(struct file *file, void *fh, @@ -620,7 +603,6 @@ int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std) cx->vbi.count = cx->is_50hz ? 18 : 12; cx->vbi.start[0] = cx->is_50hz ? 6 : 10; cx->vbi.start[1] = cx->is_50hz ? 318 : 273; - cx->vbi.sliced_decoder_line_size = cx->is_60hz ? 272 : 284; CX18_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long) cx->std); @@ -671,8 +653,6 @@ static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) static int cx18_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap) { -#if 0 - /* Supported by the cx23418 but not yet implemented. */ struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; int f, l; @@ -686,7 +666,6 @@ static int cx18_g_sliced_vbi_cap(struct file *file, void *fh, } return 0; } -#endif return -EINVAL; } diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index 88b101401..bcd786988 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -349,10 +349,6 @@ static void cx18_vbi_setup(struct cx18_stream *s) /* setup VBI registers */ cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in); - /* determine number of lines and total number of VBI bytes. - A raw line takes 1444 bytes: 4 byte SAV code + 2 * 720 - A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal - header, 42 data bytes + checksum (to be confirmed) */ if (raw) { lines = cx->vbi.count * 2; } else { @@ -361,24 +357,53 @@ static void cx18_vbi_setup(struct cx18_stream *s) lines += 2; } - cx->vbi.enc_size = lines * - (raw ? cx->vbi.raw_size : cx->vbi.sliced_size); - data[0] = s->handle; /* Lines per field */ data[1] = (lines / 2) | ((lines / 2) << 16); /* bytes per line */ - data[2] = (raw ? cx->vbi.raw_decoder_line_size - : cx->vbi.sliced_decoder_line_size); + data[2] = (raw ? vbi_active_samples + : (cx->is_60hz ? vbi_hblank_samples_60Hz + : vbi_hblank_samples_50Hz)); /* Every X number of frames a VBI interrupt arrives (frames as in 25 or 30 fps) */ data[3] = 1; - /* Setup VBI for the cx25840 digitizer */ + /* + * Set the SAV/EAV RP codes to look for as start/stop points + * when in VIP-1.1 mode + */ if (raw) { + /* + * Start codes for beginning of "active" line in vertical blank + * 0x20 ( VerticalBlank ) + * 0x60 ( EvenField VerticalBlank ) + */ data[4] = 0x20602060; + /* + * End codes for end of "active" raw lines and regular lines + * 0x30 ( VerticalBlank HorizontalBlank) + * 0x70 ( EvenField VerticalBlank HorizontalBlank) + * 0x90 (Task HorizontalBlank) + * 0xd0 (Task EvenField HorizontalBlank) + */ data[5] = 0x307090d0; } else { + /* + * End codes for active video, we want data in the hblank region + * 0xb0 (Task 0 VerticalBlank HorizontalBlank) + * 0xf0 (Task EvenField VerticalBlank HorizontalBlank) + * + * Since the V bit is only allowed to toggle in the EAV RP code, + * just before the first active region line, these two + * are problematic and we have to ignore them: + * 0x90 (Task HorizontalBlank) + * 0xd0 (Task EvenField HorizontalBlank) + */ data[4] = 0xB0F0B0F0; + /* + * Start codes for beginning of active line in vertical blank + * 0xa0 (Task VerticalBlank ) + * 0xe0 (Task EvenField VerticalBlank ) + */ data[5] = 0xA0E0A0E0; } diff --git a/linux/drivers/media/video/cx18/cx18-vbi.c b/linux/drivers/media/video/cx18/cx18-vbi.c index fb595bd54..38d26c42e 100644 --- a/linux/drivers/media/video/cx18/cx18-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-vbi.c @@ -27,6 +27,16 @@ #include "cx18-queue.h" #include "cx18-av-core.h" +/* + * Raster Reference/Protection (RP) bytes, used in Start/End Active + * Video codes emitted from the digitzer in VIP 1.x mode, that flag the start + * of VBI sample or VBI ancilliary data regions in the digitial ratser line. + * + * Task FieldEven VerticalBlank HorizontalBlank 0 0 0 0 + */ +static const u8 raw_vbi_sav_rp[2] = { 0x20, 0x60 }; /* __V_, _FV_ */ +static const u8 sliced_vbi_eav_rp[2] = { 0xb0, 0xf0 }; /* T_VH, TFVH */ + static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) { int line = 0; @@ -34,10 +44,17 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) u32 linemask[2] = { 0, 0 }; unsigned short size; static const u8 mpeg_hdr_data[] = { - 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66, - 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff, - 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80, - 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff + /* MPEG-2 Program Pack */ + 0x00, 0x00, 0x01, 0xba, /* Prog Pack start code */ + 0x44, 0x00, 0x0c, 0x66, 0x24, 0x01, /* SCR, SCR Ext, markers */ + 0x01, 0xd1, 0xd3, /* Mux Rate, markers */ + 0xfa, 0xff, 0xff, /* Res, Suff cnt, Stuff */ + /* MPEG-2 Private Stream 1 PES Packet */ + 0x00, 0x00, 0x01, 0xbd, /* Priv Stream 1 start */ + 0x00, 0x1a, /* length */ + 0x84, 0x80, 0x07, /* flags, hdr data len */ + 0x21, 0x00, 0x5d, 0x63, 0xa7, /* PTS, markers */ + 0xff, 0xff /* stuffing */ }; const int sd = sizeof(mpeg_hdr_data); /* start of vbi data */ int idx = cx->vbi.frame % CX18_VBI_FRAMES; @@ -71,7 +88,7 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) memcpy(dst + sd + 4, dst + sd + 12, line * 43); size = 4 + ((43 * line + 3) & ~3); } else { - memcpy(dst + sd, "cx0", 4); + memcpy(dst + sd, "itv0", 4); memcpy(dst + sd + 4, &linemask[0], 8); size = 12 + ((43 * line + 3) & ~3); } @@ -90,10 +107,10 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) Returns new compressed size. */ static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size) { - u32 line_size = cx->vbi.raw_decoder_line_size; + u32 line_size = vbi_active_samples; u32 lines = cx->vbi.count; - u8 sav1 = cx->vbi.raw_decoder_sav_odd_field; - u8 sav2 = cx->vbi.raw_decoder_sav_even_field; + u8 sav1 = raw_vbi_sav_rp[0]; + u8 sav2 = raw_vbi_sav_rp[1]; u8 *q = buf; u8 *p; int i; @@ -115,15 +132,16 @@ static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size) /* Compressed VBI format, all found sliced blocks put next to one another Returns new compressed size */ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, - u32 size, u8 sav) + u32 size, u8 eav) { - u32 line_size = cx->vbi.sliced_decoder_line_size; struct v4l2_decode_vbi_line vbi; int i; + u32 line_size = cx->is_60hz ? vbi_hblank_samples_60Hz + : vbi_hblank_samples_50Hz; /* find the first valid line */ for (i = 0; i < size; i++, buf++) { - if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav) + if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == eav) break; } @@ -133,8 +151,8 @@ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, for (i = 0; i < size / line_size; i++) { u8 *p = buf + i * line_size; - /* Look for SAV code */ - if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) + /* Look for EAV code */ + if (p[0] != 0xff || p[1] || p[2] || p[3] != eav) continue; vbi.p = p + 4; cx18_av_cmd(cx, VIDIOC_INT_DECODE_VBI_LINE, &vbi); @@ -159,6 +177,12 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, if (streamtype != CX18_ENC_STREAM_TYPE_VBI) return; + /* + * Note the CX23418 provides a 12 byte header, in it's raw VBI + * buffers to us, that we currently throw away: + * 0x3fffffff [4 bytes of something] [4 byte timestamp] + */ + /* Raw VBI data */ if (cx18_raw_vbi(cx)) { u8 type; @@ -173,7 +197,7 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, size = buf->bytesused = compress_raw_buf(cx, p, size); /* second field of the frame? */ - if (type == cx->vbi.raw_decoder_sav_even_field) { + if (type == raw_vbi_sav_rp[1]) { /* Dirty hack needed for backwards compatibility of old VBI software. */ p += size - 4; @@ -187,14 +211,14 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, cx18_buf_swap(buf); /* first field */ - lines = compress_sliced_buf(cx, 0, p, size / 2, - cx->vbi.sliced_decoder_sav_odd_field); + /* compress_sliced_buf() will skip the 12 bytes of header */ + lines = compress_sliced_buf(cx, 0, p, size / 2, sliced_vbi_eav_rp[0]); /* second field */ /* experimentation shows that the second half does not always begin at the exact address. So start a bit earlier (hence 32). */ lines = compress_sliced_buf(cx, lines, p + size / 2 - 32, - size / 2 + 32, cx->vbi.sliced_decoder_sav_even_field); + size / 2 + 32, sliced_vbi_eav_rp[1]); /* always return at least one empty line */ if (lines == 0) { cx->vbi.sliced_data[0].id = 0; -- cgit v1.2.3 From b091f9b9e1a7c7b1485a6bef42a0af1587c59646 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 31 Jan 2009 09:09:33 -0200 Subject: saa7134-alsa: saa7130 doesn't support digital audio From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-alsa.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/saa7134/saa7134-alsa.c b/linux/drivers/media/video/saa7134/saa7134-alsa.c index 5182d958c..eaa03fc07 100644 --- a/linux/drivers/media/video/saa7134/saa7134-alsa.c +++ b/linux/drivers/media/video/saa7134/saa7134-alsa.c @@ -1094,7 +1094,11 @@ static int saa7134_alsa_init(void) list_for_each(list,&saa7134_devlist) { dev = list_entry(list, struct saa7134_dev, devlist); - alsa_device_init(dev); + if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130) + printk(KERN_INFO "%s/alsa: %s doesn't support digital audio\n", + dev->name, saa7134_boards[dev->board].name); + else + alsa_device_init(dev); } if (dev == NULL) -- cgit v1.2.3 From c486f5a8bc4d8eac66b2017d78ce2466c32d1ff9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 31 Jan 2009 09:10:49 -0200 Subject: saa7134-core: remove oss option, since saa7134-oss doesn't exist anymore From: Mauro Carvalho Chehab Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-core.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index 1ba80210e..527c25087 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -58,10 +58,6 @@ static unsigned int alsa; module_param(alsa, int, 0644); MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]"); -static unsigned int oss; -module_param(oss, int, 0644); -MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]"); - static unsigned int latency = UNSET; module_param(latency, int, 0444); MODULE_PARM_DESC(latency,"pci latency timer"); @@ -203,8 +199,6 @@ static void request_module_async(struct work_struct *work){ request_module("saa7134-dvb"); if (alsa) request_module("saa7134-alsa"); - if (oss) - request_module("saa7134-oss"); } static void request_submodules(struct saa7134_dev *dev) -- cgit v1.2.3 From 3f7305a1eb510b65eddf1867e6696f56a102b508 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 31 Jan 2009 09:14:24 -0200 Subject: saa7134-core: loading saa7134-alsa is now the default From: Mauro Carvalho Chehab Most boards nowadays supports saa7134-alsa. Even some of they doesn't have any option to wire an audio cable. So, lets load saa7134-alsa by default, if the board is not based on saa7130 and if saa7134-alsa is compiled. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index 527c25087..6e98c992c 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -54,9 +54,9 @@ static unsigned int gpio_tracking; module_param(gpio_tracking, int, 0644); MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); -static unsigned int alsa; +static unsigned int alsa = 1; module_param(alsa, int, 0644); -MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]"); +MODULE_PARM_DESC(alsa,"enable/disable ALSA DMA sound [dmasound]"); static unsigned int latency = UNSET; module_param(latency, int, 0444); @@ -197,8 +197,10 @@ static void request_module_async(struct work_struct *work){ request_module("saa7134-empress"); if (card_is_dvb(dev)) request_module("saa7134-dvb"); - if (alsa) - request_module("saa7134-alsa"); + if (alsa) { + if (dev->pci->device != PCI_DEVICE_ID_PHILIPS_SAA7130) + request_module("saa7134-alsa"); + } } static void request_submodules(struct saa7134_dev *dev) -- cgit v1.2.3 From 29e4b3115eccc5374834648d7c8c19e67a4e1095 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 1 Feb 2009 17:59:42 +0100 Subject: gspca - sonixj: Sensor sp80708 added for webcam 0c45:6143. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 145 +++++++++++++++++++++++++++++-- 1 file changed, 140 insertions(+), 5 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 5b5e526d8..eeedcbc72 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -66,6 +66,7 @@ struct sd { #define SENSOR_OV7630 5 #define SENSOR_OV7648 6 #define SENSOR_OV7660 7 +#define SENSOR_SP80708 8 u8 i2c_base; }; @@ -243,6 +244,8 @@ static __u32 ctrl_dis[] = { /* SENSOR_OV7648 6 */ (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_OV7660 7 */ + (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), + /* SENSOR_SP80708 8 */ }; static const struct v4l2_pix_format vga_mode[] = { @@ -352,6 +355,17 @@ static const u8 sn_ov7660[0x1c] = { 0x07, 0x00, 0x00, 0x00 }; +static const u8 sn_sp80708[0x1c] = { +/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ + 0x00, 0x63, 0x60, 0x00, 0x1a, 0x20, 0x20, 0x20, +/* reg8 reg9 rega regb regc regd rege regf */ + 0x81, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, +/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ + 0x03, 0x00, 0x00, 0x03, 0x04, 0x28, 0x1e, 0x00, +/* reg18 reg19 reg1a reg1b */ + 0x07, 0x00, 0x00, 0x00 +}; + /* sequence specific to the sensors - !! index = SENSOR_xxx */ static const u8 *sn_tb[] = { sn_hv7131, @@ -361,7 +375,8 @@ static const u8 *sn_tb[] = { sn_om6802, sn_ov7630, sn_ov7648, - sn_ov7660 + sn_ov7660, + sn_sp80708 }; static const u8 gamma_def[17] = { @@ -746,6 +761,89 @@ static const u8 ov7660_sensor_init[][8] = { {} }; +static const u8 sp80708_sensor_init[][8] = { + {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x10, 0x40, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x11, 0x4e, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x12, 0x53, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x15, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x19, 0x18, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x1c, 0x28, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x26, 0x04, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x27, 0x1e, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x28, 0x5a, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x29, 0x28, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x2a, 0x78, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x2c, 0xf7, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x2d, 0x2d, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x2e, 0xd5, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x39, 0x42, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x3a, 0x67, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x3b, 0x87, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x3c, 0xa3, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x3d, 0xb0, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x3e, 0xbc, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x3f, 0xc8, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x40, 0xd4, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x41, 0xdf, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x42, 0xea, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x43, 0xf5, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x45, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x46, 0x60, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x47, 0x50, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x48, 0x30, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x49, 0x01, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x4d, 0xae, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x4e, 0x03, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x4f, 0x66, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x50, 0x1c, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x4a, 0x30, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x51, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x52, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x53, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x54, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x55, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x56, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x57, 0xe0, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x58, 0xc0, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x59, 0xab, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x5a, 0xa0, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x5b, 0x99, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x5c, 0x90, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x5e, 0x24, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x61, 0x73, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x63, 0x42, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x64, 0x42, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x65, 0x42, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x66, 0x24, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10}, + /********/ + {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x14, 0x3f, 0x00, 0x00, 0x00, 0x10}, + {0xa1, 0x18, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10}, + {0xb1, 0x18, 0x11, 0x40, 0x40, 0x00, 0x00, 0x10}, + {} +}; + static const u8 qtable4[] = { 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06, 0x06, 0x08, 0x0a, 0x11, @@ -1028,6 +1126,14 @@ static int configure_gpio(struct gspca_dev *gspca_dev, } /* fall thru */ #endif + case SENSOR_SP80708: + reg_w1(gspca_dev, 0x01, 0x63); + reg_w1(gspca_dev, 0x17, 0x20); + reg_w1(gspca_dev, 0x01, 0x62); + reg_w1(gspca_dev, 0x01, 0x42); + mdelay(100); + reg_w1(gspca_dev, 0x02, 0x62); + break; default: reg_w1(gspca_dev, 0x01, 0x43); reg_w1(gspca_dev, 0x17, 0x61); @@ -1151,6 +1257,19 @@ static void ov7660_InitSensor(struct gspca_dev *gspca_dev) } } +static void sp80708_InitSensor(struct gspca_dev *gspca_dev) +{ + int i = 0; + + i2c_w8(gspca_dev, sp80708_sensor_init[i]); /* reset SCCB */ + i++; + msleep(20); + while (sp80708_sensor_init[i][0]) { + i2c_w8(gspca_dev, sp80708_sensor_init[i]); + i++; + } +} + /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -1424,6 +1543,7 @@ static void setgamma(struct gspca_dev *gspca_dev) 0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00 }; + for (i = 0; i < sizeof gamma; i++) gamma[i] = gamma_def[i] + delta[i] * (sd->gamma - GAMMA_DEF) / 32; @@ -1525,7 +1645,8 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x20, gamma_hv7131r, sizeof gamma_hv7131r); else #endif - setgamma(gspca_dev); + setgamma(gspca_dev); + for (i = 0; i < 8; i++) reg_w(gspca_dev, 0x84, reg84, sizeof reg84); switch (sd->sensor) { @@ -1537,6 +1658,10 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x9a, 0x0a); reg_w1(gspca_dev, 0x99, 0x60); break; + case SENSOR_SP80708: + reg_w1(gspca_dev, 0x9a, 0x05); + reg_w1(gspca_dev, 0x99, 0x59); + break; case SENSOR_OV7660: if (sd->bridge == BRIDGE_SN9C120) { reg_w1(gspca_dev, 0x9a, 0x05); @@ -1596,8 +1721,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg17 = 0x21; /* reg1 = 0x42; * 42 - 46? */ break; - default: -/* case SENSOR_OV7660: */ + case SENSOR_OV7660: ov7660_InitSensor(gspca_dev); if (sd->bridge == BRIDGE_SN9C120) { if (mode) { /* 320x240 - 160x120 */ @@ -1610,6 +1734,17 @@ static int sd_start(struct gspca_dev *gspca_dev) * inverse power down */ } break; + default: +/* case SENSOR_SP80708: */ + sp80708_InitSensor(gspca_dev); + if (mode) { +/*?? reg1 = 0x04; * 320 clk 48Mhz */ + ; + } else { + reg1 = 0x46; /* 640 clk 48Mz */ + reg17 = 0xa2; + } + break; } reg_w(gspca_dev, 0xc0, C0, 6); reg_w(gspca_dev, 0xca, CA, 4); @@ -2012,7 +2147,7 @@ static const __devinitdata struct usb_device_id device_table[] = { {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)}, /* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */ #endif - {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)}, + {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, {} }; MODULE_DEVICE_TABLE(usb, device_table); -- cgit v1.2.3 From 588027051d313c56ef5cea88111f5c16aed595b2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 1 Feb 2009 18:20:07 +0100 Subject: gspca - sonixj: Specific gamma tables per sensor. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 34 +++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index eeedcbc72..0a96d6cdc 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -379,17 +379,21 @@ static const u8 *sn_tb[] = { sn_sp80708 }; +/* default gamma table */ static const u8 gamma_def[17] = { 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99, 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff }; - -#if 0 -static const u8 gamma_hv7131r[17] = { +/* gamma for sensors HV7131R and MT9V111 */ +static const u8 gamma_spec_1[17] = { 0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d, 0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5 }; -#endif +/* gamma for sensor SP80708 */ +static const u8 gamma_spec_2[17] = { + 0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab, + 0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6 +}; /* color matrix and offsets */ static const u8 reg84[] = { @@ -1538,14 +1542,27 @@ static void setgamma(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; int i; u8 gamma[17]; + const u8 *gamma_base; static const u8 delta[17] = { 0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a, 0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00 }; + switch (sd->sensor) { + case SENSOR_HV7131R: + case SENSOR_MT9V111: + gamma_base = gamma_spec_1; + break; + case SENSOR_SP80708: + gamma_base = gamma_spec_2; + break; + default: + gamma_base = gamma_def; + break; + } for (i = 0; i < sizeof gamma; i++) - gamma[i] = gamma_def[i] + gamma[i] = gamma_base[i] + delta[i] * (sd->gamma - GAMMA_DEF) / 32; reg_w(gspca_dev, 0x20, gamma, sizeof gamma); } @@ -1640,11 +1657,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */ reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); -#if 0 - if (sd->sensor == SENSOR_HV7131R || sd->sensor == SENSOR_MT9V111) - reg_w(gspca_dev, 0x20, gamma_hv7131r, sizeof gamma_hv7131r); - else -#endif + setgamma(gspca_dev); for (i = 0; i < 8; i++) @@ -1739,7 +1752,6 @@ static int sd_start(struct gspca_dev *gspca_dev) sp80708_InitSensor(gspca_dev); if (mode) { /*?? reg1 = 0x04; * 320 clk 48Mhz */ - ; } else { reg1 = 0x46; /* 640 clk 48Mz */ reg17 = 0xa2; -- cgit v1.2.3 From e659d45f04c7de45057e9c86a93c7ca906027026 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 1 Feb 2009 18:26:51 +0100 Subject: gspca - sonixj: Simplify the probe of the sensors mi0360/mt9v111. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 0a96d6cdc..1d33e80a1 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -1009,18 +1009,19 @@ static int hv7131r_probe(struct gspca_dev *gspca_dev) return -ENODEV; } -static int mi0360_probe(struct gspca_dev *gspca_dev) +static void mi0360_probe(struct gspca_dev *gspca_dev) { + struct sd *sd = (struct sd *) gspca_dev; int i, j; u16 val; static const u8 probe_tb[][4][8] = { - { + { /* mi0360 */ {0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, {0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10} }, - { + { /* mt9v111 */ {0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, {0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, @@ -1046,13 +1047,16 @@ static int mi0360_probe(struct gspca_dev *gspca_dev) switch (val) { case 0x823a: PDEBUG(D_PROBE, "Sensor mt9v111"); - return SENSOR_MT9V111; + sd->sensor = SENSOR_MT9V111; + sd->i2c_base = 0x5c; + break; case 0x8243: PDEBUG(D_PROBE, "Sensor mi0360"); - return SENSOR_MI0360; + break; + default: + PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val); + break; } - PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val); - return SENSOR_MI0360; } static int configure_gpio(struct gspca_dev *gspca_dev, @@ -1327,21 +1331,15 @@ static int sd_init(struct gspca_dev *gspca_dev) case BRIDGE_SN9C105: if (regF1 != 0x11) return -ENODEV; - if (sd->sensor == SENSOR_MI0360) { - sd->sensor = mi0360_probe(gspca_dev); - if (sd->sensor == SENSOR_MT9V111) - sd->i2c_base = 0x5c; - } + if (sd->sensor == SENSOR_MI0360) + mi0360_probe(gspca_dev); reg_w(gspca_dev, 0x01, regGpio, 2); break; case BRIDGE_SN9C120: if (regF1 != 0x12) return -ENODEV; - if (sd->sensor == SENSOR_MI0360) { - sd->sensor = mi0360_probe(gspca_dev); - if (sd->sensor == SENSOR_MT9V111) - sd->i2c_base = 0x5c; - } + if (sd->sensor == SENSOR_MI0360) + mi0360_probe(gspca_dev); regGpio[1] = 0x70; reg_w(gspca_dev, 0x01, regGpio, 2); break; -- cgit v1.2.3 From 8e4ca258fea621ae40f8e7b33299147fda22c2c9 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 1 Feb 2009 18:48:55 +0100 Subject: gspca - sonixj: Adjust some exchanges with the sensor mt9v111. From: Jean-Francois Moine This patch also enables the autogain for the mt9v111. Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/sonixj.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c index 1d33e80a1..0aa4649bd 100644 --- a/linux/drivers/media/video/gspca/sonixj.c +++ b/linux/drivers/media/video/gspca/sonixj.c @@ -234,7 +234,11 @@ static __u32 ctrl_dis[] = { /* SENSOR_MI0360 1 */ (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_MO4000 2 */ +#if 1 + 0, +#else (1 << AUTOGAIN_IDX), +#endif /* SENSOR_MT9V111 3 */ (1 << INFRARED_IDX) | (1 << VFLIP_IDX), /* SENSOR_OM6802 4 */ @@ -517,8 +521,18 @@ static const u8 mt9v111_sensor_init[][8] = { {0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */ {0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */ {0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */ + {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x03, 0x01, 0xe1, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x04, 0x02, 0x81, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x05, 0x00, 0x04, 0x00, 0x00, 0x10}, {0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */ + {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x03, 0x01, 0xe6, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x04, 0x02, 0x86, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x05, 0x00, 0x04, 0x00, 0x00, 0x10}, + {0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */ + {0xb1, 0x5c, 0x0e, 0x00, 0x08, 0x00, 0x00, 0x10}, {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */ {0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */ {0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */ @@ -532,7 +546,11 @@ static const u8 mt9v111_sensor_init[][8] = { /*******/ {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, +#if 1 + {0xb1, 0x5c, 0x09, 0x01, 0x2c, 0x00, 0x00, 0x10}, +#else {0xb1, 0x5c, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10}, /* shutter width */ +#endif {0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10}, /* green1 gain */ {0xd1, 0x5c, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10}, /* red gain */ /*******/ @@ -1714,7 +1732,7 @@ static int sd_start(struct gspca_dev *gspca_dev) reg1 = 0x04; /* 320 clk 48Mhz */ } else { /* reg1 = 0x06; * 640 clk 24Mz (done) */ - reg17 = 0xe2; + reg17 = 0xc2; } break; case SENSOR_OM6802: -- cgit v1.2.3 From 0b54c23674aba500f0f7dcb646b2db160813d2dc Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 1 Feb 2009 20:15:01 +0100 Subject: gspca - vc032x: Bad revision for the webcam 041e:405b. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 45ece4a45..4842664a2 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -2553,7 +2553,7 @@ static const struct sd_desc sd_desc = { /* -- module initialisation -- */ static const __devinitdata struct usb_device_id device_table[] = { - {USB_DEVICE(0x041e, 0x405b), .driver_info = BRIDGE_VC0321}, + {USB_DEVICE(0x041e, 0x405b), .driver_info = BRIDGE_VC0323}, {USB_DEVICE(0x046d, 0x0892), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x046d, 0x0896), .driver_info = BRIDGE_VC0321}, {USB_DEVICE(0x046d, 0x0897), .driver_info = BRIDGE_VC0321}, -- cgit v1.2.3 From d7d02b86ebba841e90992de5bddb169575e682f5 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 1 Feb 2009 14:53:20 -0500 Subject: cx18: Fix coding style of a switch statement per checkpatch.pl From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-core.c | 50 +++++++++++++-------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index 50979d333..e6391bc5a 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -683,31 +683,31 @@ static int set_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt) static int valid_av_cmd(unsigned int cmd) { switch (cmd) { - /* All commands supported by cx18_av_cmd() */ - case VIDIOC_INT_DECODE_VBI_LINE: - case VIDIOC_INT_AUDIO_CLOCK_FREQ: - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - case VIDIOC_LOG_STATUS: - case VIDIOC_G_CTRL: - case VIDIOC_S_CTRL: - case VIDIOC_QUERYCTRL: - case VIDIOC_G_STD: - case VIDIOC_S_STD: - case AUDC_SET_RADIO: - case VIDIOC_INT_G_VIDEO_ROUTING: - case VIDIOC_INT_S_VIDEO_ROUTING: - case VIDIOC_INT_G_AUDIO_ROUTING: - case VIDIOC_INT_S_AUDIO_ROUTING: - case VIDIOC_S_FREQUENCY: - case VIDIOC_G_TUNER: - case VIDIOC_S_TUNER: - case VIDIOC_G_FMT: - case VIDIOC_S_FMT: - case VIDIOC_INT_RESET: - return 1; - default: - return 0; + /* All commands supported by cx18_av_cmd() */ + case VIDIOC_INT_DECODE_VBI_LINE: + case VIDIOC_INT_AUDIO_CLOCK_FREQ: + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: + case VIDIOC_LOG_STATUS: + case VIDIOC_G_CTRL: + case VIDIOC_S_CTRL: + case VIDIOC_QUERYCTRL: + case VIDIOC_G_STD: + case VIDIOC_S_STD: + case AUDC_SET_RADIO: + case VIDIOC_INT_G_VIDEO_ROUTING: + case VIDIOC_INT_S_VIDEO_ROUTING: + case VIDIOC_INT_G_AUDIO_ROUTING: + case VIDIOC_INT_S_AUDIO_ROUTING: + case VIDIOC_S_FREQUENCY: + case VIDIOC_G_TUNER: + case VIDIOC_S_TUNER: + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_INT_RESET: + return 1; + default: + return 0; } return 0; } -- cgit v1.2.3 From 343fbdd2e3f93d7a107012ecc1413cae5664e096 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 1 Feb 2009 19:42:12 -0500 Subject: cx18: Fix presentation timestamp (PTS) for VBI buffers From: Andy Walls The old code from ivtv used a CX23415/6 PTS, which was simply left at 0 in the cx18 driver. Since the CX23418 gives us what I think is a PTS (or some other 90 kHz clock count) with each VBI buffer, this change has the cx18 driver use that as a PTS. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.h | 1 - linux/drivers/media/video/cx18/cx18-fileops.c | 4 +--- linux/drivers/media/video/cx18/cx18-vbi.c | 18 ++++++++++-------- linux/drivers/media/video/cx18/cx18-vbi.h | 2 +- 4 files changed, 12 insertions(+), 13 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index d2829f576..0ef099186 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -293,7 +293,6 @@ struct cx18_stream { int dma; /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */ - u64 dma_pts; wait_queue_head_t waitq; /* Buffer Stats */ diff --git a/linux/drivers/media/video/cx18/cx18-fileops.c b/linux/drivers/media/video/cx18/cx18-fileops.c index 7d979ea28..c73fbe65b 100644 --- a/linux/drivers/media/video/cx18/cx18-fileops.c +++ b/linux/drivers/media/video/cx18/cx18-fileops.c @@ -224,7 +224,6 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) { /* byteswap and process VBI data */ cx18_process_vbi_data(cx, buf, - s_vbi->dma_pts, s_vbi->type); cx18_stream_put_buf_fw(s_vbi, buf); } @@ -245,8 +244,7 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, cx18_buf_swap(buf); else { /* byteswap and process VBI data */ - cx18_process_vbi_data(cx, buf, - s->dma_pts, s->type); + cx18_process_vbi_data(cx, buf, s->type); } return buf; } diff --git a/linux/drivers/media/video/cx18/cx18-vbi.c b/linux/drivers/media/video/cx18/cx18-vbi.c index 38d26c42e..d6e15e119 100644 --- a/linux/drivers/media/video/cx18/cx18-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-vbi.c @@ -168,27 +168,28 @@ static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf, } void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, - u64 pts_stamp, int streamtype) + int streamtype) { u8 *p = (u8 *) buf->buf; + u32 *q = (u32 *) buf->buf; u32 size = buf->bytesused; + u32 pts; int lines; if (streamtype != CX18_ENC_STREAM_TYPE_VBI) return; + cx18_buf_swap(buf); + /* - * Note the CX23418 provides a 12 byte header, in it's raw VBI - * buffers to us, that we currently throw away: - * 0x3fffffff [4 bytes of something] [4 byte timestamp] + * The CX23418 provides a 12 byte header in it's raw VBI buffers to us: + * 0x3fffffff [4 bytes of something] [4 byte presentation time stamp?] */ /* Raw VBI data */ if (cx18_raw_vbi(cx)) { u8 type; - cx18_buf_swap(buf); - /* Skip 12 bytes of header that gets stuffed in */ size -= 12; memcpy(p, &buf->buf[12], size); @@ -208,7 +209,8 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, } /* Sliced VBI data with data insertion */ - cx18_buf_swap(buf); + + pts = (q[0] == 0x3fffffff) ? q[2] : 0; /* first field */ /* compress_sliced_buf() will skip the 12 bytes of header */ @@ -230,6 +232,6 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, memcpy(p, &cx->vbi.sliced_data[0], size); if (cx->vbi.insert_mpeg) - copy_vbi_data(cx, lines, pts_stamp); + copy_vbi_data(cx, lines, pts); cx->vbi.frame++; } diff --git a/linux/drivers/media/video/cx18/cx18-vbi.h b/linux/drivers/media/video/cx18/cx18-vbi.h index c56ff7d28..e7e1ae427 100644 --- a/linux/drivers/media/video/cx18/cx18-vbi.h +++ b/linux/drivers/media/video/cx18/cx18-vbi.h @@ -22,5 +22,5 @@ */ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, - u64 pts_stamp, int streamtype); + int streamtype); int cx18_used_line(struct cx18 *cx, int line, int field); -- cgit v1.2.3 From 527d5f186187cc1a8c128b0aca06d047e7f753a4 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 1 Feb 2009 21:44:00 -0500 Subject: cx18: Remove an unused spinlock From: Andy Walls Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 2 -- linux/drivers/media/video/cx18/cx18-driver.h | 1 - 2 files changed, 3 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index f48d18f69..4699cecbe 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -563,8 +563,6 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) mutex_init(&cx->epu2apu_mb_lock); mutex_init(&cx->epu2cpu_mb_lock); - spin_lock_init(&cx->lock); - cx->work_queue = create_singlethread_workqueue(cx->name); if (cx->work_queue == NULL) { CX18_ERR("Unable to create work hander thread\n"); diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index 3a21013cd..d95c6ace2 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -429,7 +429,6 @@ struct cx18 { unsigned long i_flags; /* global cx18 flags */ atomic_t ana_capturing; /* count number of active analog capture streams */ atomic_t tot_capturing; /* total count number of active capture streams */ - spinlock_t lock; /* lock access to this struct */ int search_pack_header; int open_id; /* incremented each time an open occurs, used as -- cgit v1.2.3 From 3fd8c59cdeaedaa51a5db45b8dbf67dc6b907e19 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 2 Feb 2009 10:33:31 +0100 Subject: gspca - vc032x: Cleanup source, optimize and check i2c_write. From: Jean-Francois Moine Priority: normal Signed-off-by: Jean-Francois Moine --- linux/drivers/media/video/gspca/vc032x.c | 93 +++++++++++++------------------- 1 file changed, 37 insertions(+), 56 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c index 4842664a2..1832d241f 100644 --- a/linux/drivers/media/video/gspca/vc032x.c +++ b/linux/drivers/media/video/gspca/vc032x.c @@ -1953,44 +1953,40 @@ static void reg_w(struct usb_device *dev, 500); } -static void read_sensor_register(struct gspca_dev *gspca_dev, - __u16 address, __u16 *value) +static u16 read_sensor_register(struct gspca_dev *gspca_dev, + u16 address) { struct usb_device *dev = gspca_dev->dev; __u8 ldata, mdata, hdata; int retry = 50; - *value = 0; - reg_r(gspca_dev, 0xa1, 0xb33f, 1); - /*PDEBUG(D_PROBE, " I2c Bus Busy Wait 0x%02X ", tmpvalue); */ if (!(gspca_dev->usb_buf[0] & 0x02)) { - PDEBUG(D_ERR, "I2c Bus Busy Wait %d", - gspca_dev->usb_buf[0] & 0x02); - return; + PDEBUG(D_ERR, "I2c Bus Busy Wait %02x", + gspca_dev->usb_buf[0]); + return 0; } reg_w(dev, 0xa0, address, 0xb33a); reg_w(dev, 0xa0, 0x02, 0xb339); - reg_r(gspca_dev, 0xa1, 0xb33b, 1); - while (retry-- && gspca_dev->usb_buf[0]) { + do { + msleep(8); reg_r(gspca_dev, 0xa1, 0xb33b, 1); -/* PDEBUG(D_PROBE, "Read again 0xb33b %d", tmpvalue); */ - msleep(1); - } + } while (retry-- && gspca_dev->usb_buf[0]); + reg_r(gspca_dev, 0xa1, 0xb33e, 1); ldata = gspca_dev->usb_buf[0]; reg_r(gspca_dev, 0xa1, 0xb33d, 1); mdata = gspca_dev->usb_buf[0]; reg_r(gspca_dev, 0xa1, 0xb33c, 1); hdata = gspca_dev->usb_buf[0]; - PDEBUG(D_PROBE, "Read Sensor %02x%02x %02x", - hdata, mdata, ldata); + if (hdata != 0 && mdata != 0 && ldata != 0) + PDEBUG(D_PROBE, "Read Sensor %02x%02x %02x", + hdata, mdata, ldata); reg_r(gspca_dev, 0xa1, 0xb334, 1); if (gspca_dev->usb_buf[0] == 0x02) - *value = (hdata << 8) + mdata; - else - *value = hdata; + return (hdata << 8) + mdata; + return hdata; } static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) @@ -2011,7 +2007,7 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) reg_w(dev, 0xa0, 0x0c, 0xb309); reg_w(dev, 0xa0, ptsensor_info->I2cAdd, 0xb335); reg_w(dev, 0xa0, ptsensor_info->op, 0xb301); - read_sensor_register(gspca_dev, ptsensor_info->IdAdd, &value); + value = read_sensor_register(gspca_dev, ptsensor_info->IdAdd); if (value == ptsensor_info->VpId) return ptsensor_info->sensorId; @@ -2023,13 +2019,16 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) return -1; } -static __u8 i2c_write(struct gspca_dev *gspca_dev, +static void i2c_write(struct gspca_dev *gspca_dev, __u8 reg, const __u8 *val, __u8 size) { struct usb_device *dev = gspca_dev->dev; + int retry; +#ifdef GSPCA_DEBUG if (size > 3 || size < 1) - return -EINVAL; + return; +#endif reg_r(gspca_dev, 0xa1, 0xb33f, 1); reg_w(dev, 0xa0, size, 0xb334); reg_w(dev, 0xa0, reg, 0xb33a); @@ -2041,18 +2040,23 @@ static __u8 i2c_write(struct gspca_dev *gspca_dev, reg_w(dev, 0xa0, val[0], 0xb336); reg_w(dev, 0xa0, val[1], 0xb337); break; - case 3: + default: +/* case 3: */ reg_w(dev, 0xa0, val[0], 0xb336); reg_w(dev, 0xa0, val[1], 0xb337); reg_w(dev, 0xa0, val[2], 0xb338); break; - default: - reg_w(dev, 0xa0, 0x01, 0xb334); - return -EINVAL; } reg_w(dev, 0xa0, 0x01, 0xb339); - reg_r(gspca_dev, 0xa1, 0xb33b, 1); - return gspca_dev->usb_buf[0] == 0; + retry = 4; + do { + reg_r(gspca_dev, 0xa1, 0xb33b, 1); + if (gspca_dev->usb_buf[0] == 0) + break; + msleep(20); + } while (--retry > 0); + if (retry <= 0) + PDEBUG(D_ERR, "i2c_write failed"); } static void put_tab_to_reg(struct gspca_dev *gspca_dev, @@ -2077,7 +2081,7 @@ static void usb_exchange(struct gspca_dev *gspca_dev, return; case 0xcc: /* normal write */ reg_w(dev, 0xa0, data[i][2], - ((data[i][0])<<8) | data[i][1]); + (data[i][0]) << 8 | data[i][1]); break; case 0xaa: /* i2c op */ i2c_write(gspca_dev, data[i][1], &data[i][2], 1); @@ -2094,11 +2098,6 @@ static void usb_exchange(struct gspca_dev *gspca_dev, /*not reached*/ } -/* - "GammaT"=hex:04,17,31,4f,6a,83,99,ad,bf,ce,da,e5,ee,f5,fb,ff,ff - "MatrixT"=hex:60,f9,e5,e7,50,05,f3,e6,66 - */ - static void vc0321_reset(struct gspca_dev *gspca_dev) { reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb04d); @@ -2202,7 +2201,7 @@ static int sd_config(struct gspca_dev *gspca_dev, return 0; } -/* this function is called at probe and time */ +/* this function is called at probe and resume time */ static int sd_init(struct gspca_dev *gspca_dev) { return 0; @@ -2358,27 +2357,7 @@ static int sd_start(struct gspca_dev *gspca_dev) put_tab_to_reg(gspca_dev, GammaT, 17, 0xb85b); put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c); put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c); - /* Seem SHARPNESS */ - /* - reg_w(gspca_dev->dev, 0xa0, 0x80, 0xb80a); - reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb80b); - reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb80e); - */ - /* all 0x40 ??? do nothing - reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb822); - reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb823); - reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb824); - */ - /* Only works for HV7131R ?? - reg_r (gspca_dev, 0xa1, 0xb881, 1); - reg_w(gspca_dev->dev, 0xa0, 0xfe01, 0xb881); - reg_w(gspca_dev->dev, 0xa0, 0x79, 0xb801); - */ - /* only hv7131r et ov7660 - reg_w(gspca_dev->dev, 0xa0, 0x20, 0xb827); - reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb826); * ISP_GAIN 80 - reg_w(gspca_dev->dev, 0xa0, 0x23, 0xb800); * ISP CTRL_BAS - */ + /* set the led on 0x0892 0x0896 */ if (sd->sensor != SENSOR_PO1200) { reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); @@ -2528,7 +2507,8 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ strcpy((char *) menu->name, "50 Hz"); return 0; - case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ + default: +/* case 2: * V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ strcpy((char *) menu->name, "60 Hz"); return 0; } @@ -2591,6 +2571,7 @@ static struct usb_driver sd_driver = { static int __init sd_mod_init(void) { int ret; + ret = usb_register(&sd_driver); if (ret < 0) return ret; -- cgit v1.2.3 From 2dc910b4909cf078d58c86b8ba22aef60febc2ee Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 2 Feb 2009 19:50:09 +0200 Subject: Add Freescale MC44S803 tuner driver From: Jochen Friedrich Add Freescale MC44S803 tuner driver. Priority: normal Signed-off-by: Jochen Friedrich Signed-off-by: Antti Palosaari --- linux/drivers/media/common/tuners/Kconfig | 8 + linux/drivers/media/common/tuners/Makefile | 1 + linux/drivers/media/common/tuners/mc44s803.c | 371 ++++++++++++++++++++++ linux/drivers/media/common/tuners/mc44s803.h | 46 +++ linux/drivers/media/common/tuners/mc44s803_priv.h | 208 ++++++++++++ 5 files changed, 634 insertions(+) create mode 100644 linux/drivers/media/common/tuners/mc44s803.c create mode 100644 linux/drivers/media/common/tuners/mc44s803.h create mode 100644 linux/drivers/media/common/tuners/mc44s803_priv.h (limited to 'linux') diff --git a/linux/drivers/media/common/tuners/Kconfig b/linux/drivers/media/common/tuners/Kconfig index 6f92beaa5..7969b695c 100644 --- a/linux/drivers/media/common/tuners/Kconfig +++ b/linux/drivers/media/common/tuners/Kconfig @@ -29,6 +29,7 @@ config MEDIA_TUNER select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMIZE menuconfig MEDIA_TUNER_CUSTOMIZE bool "Customize analog and hybrid tuner modules to build" @@ -164,4 +165,11 @@ config MEDIA_TUNER_MXL5007T help A driver for the silicon tuner MxL5007T from MaxLinear. +config MEDIA_TUNER_MC44S803 + tristate "Freescale MC44S803 Low Power CMOS Broadband tuners" + depends on VIDEO_MEDIA && I2C + default m if DVB_FE_CUSTOMISE + help + Say Y here to support the Freescale MC44S803 based tuners + endif # MEDIA_TUNER_CUSTOMIZE diff --git a/linux/drivers/media/common/tuners/Makefile b/linux/drivers/media/common/tuners/Makefile index 4dfbe5b82..4132b2be7 100644 --- a/linux/drivers/media/common/tuners/Makefile +++ b/linux/drivers/media/common/tuners/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.o obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o +obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends diff --git a/linux/drivers/media/common/tuners/mc44s803.c b/linux/drivers/media/common/tuners/mc44s803.c new file mode 100644 index 000000000..20c4485ce --- /dev/null +++ b/linux/drivers/media/common/tuners/mc44s803.c @@ -0,0 +1,371 @@ +/* + * Driver for Freescale MC44S803 Low Power CMOS Broadband Tuner + * + * Copyright (c) 2009 Jochen Friedrich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= + */ + +#include +#include +#include +#include + +#include "dvb_frontend.h" + +#include "mc44s803.h" +#include "mc44s803_priv.h" + +#define mc_printk(level, format, arg...) \ + printk(level "mc44s803: " format , ## arg) + +/* Writes a single register */ +static int mc44s803_writereg(struct mc44s803_priv *priv, u32 val) +{ + u8 buf[3]; + struct i2c_msg msg = { + .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 3 + }; + + buf[0] = (val & 0xff0000) >> 16; + buf[1] = (val & 0xff00) >> 8; + buf[2] = (val & 0xff); + + if (i2c_transfer(priv->i2c, &msg, 1) != 1) { + mc_printk(KERN_WARNING, "I2C write failed\n"); + return -EREMOTEIO; + } + return 0; +} + +/* Reads a single register */ +static int mc44s803_readreg(struct mc44s803_priv *priv, u8 reg, u32 *val) +{ + u32 wval; + u8 buf[3]; + int ret; + struct i2c_msg msg[] = { + { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, + .buf = buf, .len = 3 }, + }; + + wval = MC44S803_REG_SM(MC44S803_REG_DATAREG, MC44S803_ADDR) | + MC44S803_REG_SM(reg, MC44S803_D); + + ret = mc44s803_writereg(priv, wval); + if (ret) + return ret; + + if (i2c_transfer(priv->i2c, msg, 1) != 1) { + mc_printk(KERN_WARNING, "I2C read failed\n"); + return -EREMOTEIO; + } + + *val = (buf[0] << 16) | (buf[1] << 8) | buf[2]; + + return 0; +} + +static int mc44s803_release(struct dvb_frontend *fe) +{ + struct mc44s803_priv *priv = fe->tuner_priv; + + fe->tuner_priv = NULL; + kfree(priv); + + return 0; +} + +static int mc44s803_init(struct dvb_frontend *fe) +{ + struct mc44s803_priv *priv = fe->tuner_priv; + u32 val; + int err; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + +/* Reset chip */ + val = MC44S803_REG_SM(MC44S803_REG_RESET, MC44S803_ADDR) | + MC44S803_REG_SM(1, MC44S803_RS); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + + val = MC44S803_REG_SM(MC44S803_REG_RESET, MC44S803_ADDR); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + +/* Power Up and Start Osc */ + + val = MC44S803_REG_SM(MC44S803_REG_REFOSC, MC44S803_ADDR) | + MC44S803_REG_SM(0xC0, MC44S803_REFOSC) | + MC44S803_REG_SM(1, MC44S803_OSCSEL); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + + val = MC44S803_REG_SM(MC44S803_REG_POWER, MC44S803_ADDR) | + MC44S803_REG_SM(0x200, MC44S803_POWER); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + + msleep(10); + + val = MC44S803_REG_SM(MC44S803_REG_REFOSC, MC44S803_ADDR) | + MC44S803_REG_SM(0x40, MC44S803_REFOSC) | + MC44S803_REG_SM(1, MC44S803_OSCSEL); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + + msleep(20); + +/* Setup Mixer */ + + val = MC44S803_REG_SM(MC44S803_REG_MIXER, MC44S803_ADDR) | + MC44S803_REG_SM(1, MC44S803_TRI_STATE) | + MC44S803_REG_SM(0x7F, MC44S803_MIXER_RES); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + +/* Setup Cirquit Adjust */ + + val = MC44S803_REG_SM(MC44S803_REG_CIRCADJ, MC44S803_ADDR) | + MC44S803_REG_SM(1, MC44S803_G1) | + MC44S803_REG_SM(1, MC44S803_G3) | + MC44S803_REG_SM(0x3, MC44S803_CIRCADJ_RES) | + MC44S803_REG_SM(1, MC44S803_G6) | + MC44S803_REG_SM(priv->cfg->dig_out, MC44S803_S1) | + MC44S803_REG_SM(0x3, MC44S803_LP) | + MC44S803_REG_SM(1, MC44S803_CLRF) | + MC44S803_REG_SM(1, MC44S803_CLIF); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + + val = MC44S803_REG_SM(MC44S803_REG_CIRCADJ, MC44S803_ADDR) | + MC44S803_REG_SM(1, MC44S803_G1) | + MC44S803_REG_SM(1, MC44S803_G3) | + MC44S803_REG_SM(0x3, MC44S803_CIRCADJ_RES) | + MC44S803_REG_SM(1, MC44S803_G6) | + MC44S803_REG_SM(priv->cfg->dig_out, MC44S803_S1) | + MC44S803_REG_SM(0x3, MC44S803_LP); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + +/* Setup Digtune */ + + val = MC44S803_REG_SM(MC44S803_REG_DIGTUNE, MC44S803_ADDR) | + MC44S803_REG_SM(3, MC44S803_XOD); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + +/* Setup AGC */ + + val = MC44S803_REG_SM(MC44S803_REG_LNAAGC, MC44S803_ADDR) | + MC44S803_REG_SM(1, MC44S803_AT1) | + MC44S803_REG_SM(1, MC44S803_AT2) | + MC44S803_REG_SM(1, MC44S803_AGC_AN_DIG) | + MC44S803_REG_SM(1, MC44S803_AGC_READ_EN) | + MC44S803_REG_SM(1, MC44S803_LNA0); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + return 0; + +exit: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + mc_printk(KERN_WARNING, "I/O Error\n"); + return err; +} + +static int mc44s803_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct mc44s803_priv *priv = fe->tuner_priv; + u32 r1, r2, n1, n2, lo1, lo2, freq, val; + int err; + + priv->frequency = params->frequency; + + r1 = MC44S803_OSC / 1000000; + r2 = MC44S803_OSC / 100000; + + n1 = (params->frequency + MC44S803_IF1 + 500000) / 1000000; + freq = MC44S803_OSC / r1 * n1; + lo1 = ((60 * n1) + (r1 / 2)) / r1; + freq = freq - params->frequency; + + n2 = (freq - MC44S803_IF2 + 50000) / 100000; + lo2 = ((60 * n2) + (r2 / 2)) / r2; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + val = MC44S803_REG_SM(MC44S803_REG_REFDIV, MC44S803_ADDR) | + MC44S803_REG_SM(r1-1, MC44S803_R1) | + MC44S803_REG_SM(r2-1, MC44S803_R2) | + MC44S803_REG_SM(1, MC44S803_REFBUF_EN); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + + val = MC44S803_REG_SM(MC44S803_REG_LO1, MC44S803_ADDR) | + MC44S803_REG_SM(n1-2, MC44S803_LO1); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + + val = MC44S803_REG_SM(MC44S803_REG_LO2, MC44S803_ADDR) | + MC44S803_REG_SM(n2-2, MC44S803_LO2); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + + val = MC44S803_REG_SM(MC44S803_REG_DIGTUNE, MC44S803_ADDR) | + MC44S803_REG_SM(1, MC44S803_DA) | + MC44S803_REG_SM(lo1, MC44S803_LO_REF) | + MC44S803_REG_SM(1, MC44S803_AT); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + + val = MC44S803_REG_SM(MC44S803_REG_DIGTUNE, MC44S803_ADDR) | + MC44S803_REG_SM(2, MC44S803_DA) | + MC44S803_REG_SM(lo2, MC44S803_LO_REF) | + MC44S803_REG_SM(1, MC44S803_AT); + + err = mc44s803_writereg(priv, val); + if (err) + goto exit; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return 0; + +exit: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + mc_printk(KERN_WARNING, "I/O Error\n"); + return err; +} + +static int mc44s803_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct mc44s803_priv *priv = fe->tuner_priv; + *frequency = priv->frequency; + return 0; +} + +static const struct dvb_tuner_ops mc44s803_tuner_ops = { + .info = { + .name = "Freescale MC44S803", + .frequency_min = 48000000, + .frequency_max = 1000000000, + .frequency_step = 100000, + }, + + .release = mc44s803_release, + .init = mc44s803_init, + .set_params = mc44s803_set_params, + .get_frequency = mc44s803_get_frequency +}; + +/* This functions tries to identify a MC44S803 tuner by reading the ID + register. This is hasty. */ +struct dvb_frontend *mc44s803_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, struct mc44s803_config *cfg) +{ + struct mc44s803_priv *priv; + u32 reg; + u8 id; + int ret; + + reg = 0; + + priv = kzalloc(sizeof(struct mc44s803_priv), GFP_KERNEL); + if (priv == NULL) + return NULL; + + priv->cfg = cfg; + priv->i2c = i2c; + priv->fe = fe; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */ + + ret = mc44s803_readreg(priv, MC44S803_REG_ID, ®); + if (ret) + goto error; + + id = MC44S803_REG_MS(reg, MC44S803_ID); + + if (id != 0x14) { + mc_printk(KERN_ERR, "unsupported ID " + "(%x should be 0x14)\n", id); + goto error; + } + + mc_printk(KERN_INFO, "successfully identified (ID = %x)\n", id); + memcpy(&fe->ops.tuner_ops, &mc44s803_tuner_ops, + sizeof(struct dvb_tuner_ops)); + + fe->tuner_priv = priv; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ + + return fe; + +error: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */ + + kfree(priv); + return NULL; +} +EXPORT_SYMBOL(mc44s803_attach); + +MODULE_AUTHOR("Jochen Friedrich"); +MODULE_DESCRIPTION("Freescale MC44S803 silicon tuner driver"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/common/tuners/mc44s803.h b/linux/drivers/media/common/tuners/mc44s803.h new file mode 100644 index 000000000..34f3892d3 --- /dev/null +++ b/linux/drivers/media/common/tuners/mc44s803.h @@ -0,0 +1,46 @@ +/* + * Driver for Freescale MC44S803 Low Power CMOS Broadband Tuner + * + * Copyright (c) 2009 Jochen Friedrich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= + */ + +#ifndef MC44S803_H +#define MC44S803_H + +struct dvb_frontend; +struct i2c_adapter; + +struct mc44s803_config { + u8 i2c_address; + u8 dig_out; +}; + +#if defined(CONFIG_MEDIA_TUNER_MC44S803) || \ + (defined(CONFIG_MEDIA_TUNER_MC44S803_MODULE) && defined(MODULE)) +extern struct dvb_frontend *mc44s803_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, struct mc44s803_config *cfg); +#else +static inline struct dvb_frontend *mc44s803_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, struct mc44s803_config *cfg) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_MEDIA_TUNER_MC44S803 */ + +#endif diff --git a/linux/drivers/media/common/tuners/mc44s803_priv.h b/linux/drivers/media/common/tuners/mc44s803_priv.h new file mode 100644 index 000000000..14a927809 --- /dev/null +++ b/linux/drivers/media/common/tuners/mc44s803_priv.h @@ -0,0 +1,208 @@ +/* + * Driver for Freescale MC44S803 Low Power CMOS Broadband Tuner + * + * Copyright (c) 2009 Jochen Friedrich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= + */ + +#ifndef MC44S803_PRIV_H +#define MC44S803_PRIV_H + +/* This driver is based on the information available in the datasheet + http://www.freescale.com/files/rf_if/doc/data_sheet/MC44S803.pdf + + SPI or I2C Address : 0xc0-0xc6 + + Reg.No | Function + ------------------------------------------- + 00 | Power Down + 01 | Reference Oszillator + 02 | Reference Dividers + 03 | Mixer and Reference Buffer + 04 | Reset/Serial Out + 05 | LO 1 + 06 | LO 2 + 07 | Circuit Adjust + 08 | Test + 09 | Digital Tune + 0A | LNA AGC + 0B | Data Register Address + 0C | Regulator Test + 0D | VCO Test + 0E | LNA Gain/Input Power + 0F | ID Bits + +*/ + +#define MC44S803_OSC 26000000 /* 26 MHz */ +#define MC44S803_IF1 1086000000 /* 1086 MHz */ +#define MC44S803_IF2 36125000 /* 36.125 MHz */ + +#define MC44S803_REG_POWER 0 +#define MC44S803_REG_REFOSC 1 +#define MC44S803_REG_REFDIV 2 +#define MC44S803_REG_MIXER 3 +#define MC44S803_REG_RESET 4 +#define MC44S803_REG_LO1 5 +#define MC44S803_REG_LO2 6 +#define MC44S803_REG_CIRCADJ 7 +#define MC44S803_REG_TEST 8 +#define MC44S803_REG_DIGTUNE 9 +#define MC44S803_REG_LNAAGC 0x0A +#define MC44S803_REG_DATAREG 0x0B +#define MC44S803_REG_REGTEST 0x0C +#define MC44S803_REG_VCOTEST 0x0D +#define MC44S803_REG_LNAGAIN 0x0E +#define MC44S803_REG_ID 0x0F + +/* Register definitions */ +#define MC44S803_ADDR 0x0F +#define MC44S803_ADDR_S 0 +/* REG_POWER */ +#define MC44S803_POWER 0xFFFFF0 +#define MC44S803_POWER_S 4 +/* REG_REFOSC */ +#define MC44S803_REFOSC 0x1FF0 +#define MC44S803_REFOSC_S 4 +#define MC44S803_OSCSEL 0x2000 +#define MC44S803_OSCSEL_S 13 +/* REG_REFDIV */ +#define MC44S803_R2 0x1FF0 +#define MC44S803_R2_S 4 +#define MC44S803_REFBUF_EN 0x2000 +#define MC44S803_REFBUF_EN_S 13 +#define MC44S803_R1 0x7C000 +#define MC44S803_R1_S 14 +/* REG_MIXER */ +#define MC44S803_R3 0x70 +#define MC44S803_R3_S 4 +#define MC44S803_MUX3 0x80 +#define MC44S803_MUX3_S 7 +#define MC44S803_MUX4 0x100 +#define MC44S803_MUX4_S 8 +#define MC44S803_OSC_SCR 0x200 +#define MC44S803_OSC_SCR_S 9 +#define MC44S803_TRI_STATE 0x400 +#define MC44S803_TRI_STATE_S 10 +#define MC44S803_BUF_GAIN 0x800 +#define MC44S803_BUF_GAIN_S 11 +#define MC44S803_BUF_IO 0x1000 +#define MC44S803_BUF_IO_S 12 +#define MC44S803_MIXER_RES 0xFE000 +#define MC44S803_MIXER_RES_S 13 +/* REG_RESET */ +#define MC44S803_RS 0x10 +#define MC44S803_RS_S 4 +#define MC44S803_SO 0x20 +#define MC44S803_SO_S 5 +/* REG_LO1 */ +#define MC44S803_LO1 0xFFF0 +#define MC44S803_LO1_S 4 +/* REG_LO2 */ +#define MC44S803_LO2 0x7FFF0 +#define MC44S803_LO2_S 4 +/* REG_CIRCADJ */ +#define MC44S803_G1 0x20 +#define MC44S803_G1_S 5 +#define MC44S803_G3 0x80 +#define MC44S803_G3_S 7 +#define MC44S803_CIRCADJ_RES 0x300 +#define MC44S803_CIRCADJ_RES_S 8 +#define MC44S803_G6 0x400 +#define MC44S803_G6_S 10 +#define MC44S803_G7 0x800 +#define MC44S803_G7_S 11 +#define MC44S803_S1 0x1000 +#define MC44S803_S1_S 12 +#define MC44S803_LP 0x7E000 +#define MC44S803_LP_S 13 +#define MC44S803_CLRF 0x80000 +#define MC44S803_CLRF_S 19 +#define MC44S803_CLIF 0x100000 +#define MC44S803_CLIF_S 20 +/* REG_TEST */ +/* REG_DIGTUNE */ +#define MC44S803_DA 0xF0 +#define MC44S803_DA_S 4 +#define MC44S803_XOD 0x300 +#define MC44S803_XOD_S 8 +#define MC44S803_RST 0x10000 +#define MC44S803_RST_S 16 +#define MC44S803_LO_REF 0x1FFF00 +#define MC44S803_LO_REF_S 8 +#define MC44S803_AT 0x200000 +#define MC44S803_AT_S 21 +#define MC44S803_MT 0x400000 +#define MC44S803_MT_S 22 +/* REG_LNAAGC */ +#define MC44S803_G 0x3F0 +#define MC44S803_G_S 4 +#define MC44S803_AT1 0x400 +#define MC44S803_AT1_S 10 +#define MC44S803_AT2 0x800 +#define MC44S803_AT2_S 11 +#define MC44S803_HL_GR_EN 0x8000 +#define MC44S803_HL_GR_EN_S 15 +#define MC44S803_AGC_AN_DIG 0x10000 +#define MC44S803_AGC_AN_DIG_S 16 +#define MC44S803_ATTEN_EN 0x20000 +#define MC44S803_ATTEN_EN_S 17 +#define MC44S803_AGC_READ_EN 0x40000 +#define MC44S803_AGC_READ_EN_S 18 +#define MC44S803_LNA0 0x80000 +#define MC44S803_LNA0_S 19 +#define MC44S803_AGC_SEL 0x100000 +#define MC44S803_AGC_SEL_S 20 +#define MC44S803_AT0 0x200000 +#define MC44S803_AT0_S 21 +#define MC44S803_B 0xC00000 +#define MC44S803_B_S 22 +/* REG_DATAREG */ +#define MC44S803_D 0xF0 +#define MC44S803_D_S 4 +/* REG_REGTEST */ +/* REG_VCOTEST */ +/* REG_LNAGAIN */ +#define MC44S803_IF_PWR 0x700 +#define MC44S803_IF_PWR_S 8 +#define MC44S803_RF_PWR 0x3800 +#define MC44S803_RF_PWR_S 11 +#define MC44S803_LNA_GAIN 0xFC000 +#define MC44S803_LNA_GAIN_S 14 +/* REG_ID */ +#define MC44S803_ID 0x3E00 +#define MC44S803_ID_S 9 + +/* Some macros to read/write fields */ + +/* First shift, then mask */ +#define MC44S803_REG_SM(_val, _reg) \ + (((_val) << _reg##_S) & (_reg)) + +/* First mask, then shift */ +#define MC44S803_REG_MS(_val, _reg) \ + (((_val) & (_reg)) >> _reg##_S) + +struct mc44s803_priv { + struct mc44s803_config *cfg; + struct i2c_adapter *i2c; + struct dvb_frontend *fe; + + u32 frequency; +}; + +#endif -- cgit v1.2.3 From f605aeb864167147d6fcf6841b3bb523276bb519 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 2 Feb 2009 19:59:50 +0200 Subject: af9015: add MC44S803 support From: Jochen Friedrich Add MC44S803 support to AF9015 driver. Priority: normal Signed-off-by: Jochen Friedrich Signed-off-by: Antti Palosaari --- linux/drivers/media/dvb/dvb-usb/Kconfig | 1 + linux/drivers/media/dvb/dvb-usb/af9015.c | 40 +++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 13 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 49f7b20c2..bbddc9fb6 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -297,5 +297,6 @@ config DVB_USB_AF9015 select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver diff --git a/linux/drivers/media/dvb/dvb-usb/af9015.c b/linux/drivers/media/dvb/dvb-usb/af9015.c index e518d47fe..88a365ad9 100644 --- a/linux/drivers/media/dvb/dvb-usb/af9015.c +++ b/linux/drivers/media/dvb/dvb-usb/af9015.c @@ -27,9 +27,7 @@ #include "qt1010.h" #include "tda18271.h" #include "mxl5005s.h" -#if 0 /* keep */ -#include "mc44s80x.h" -#endif +#include "mc44s803.h" static int dvb_usb_af9015_debug; module_param_named(debug, dvb_usb_af9015_debug, int, 0644); @@ -280,6 +278,21 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate. req.data = &msg[i+1].buf[0]; ret = af9015_ctrl_msg(d, &req); i += 2; + } else if (msg[i].flags & I2C_M_RD) { + ret = -EINVAL; + if (msg[i].addr == + af9015_af9013_config[0].demod_address) + goto error; + else + req.cmd = READ_I2C; + req.i2c_addr = msg[i].addr; + req.addr = addr; + req.mbox = mbox; + req.addr_len = addr_len; + req.data_len = msg[i].len; + req.data = &msg[i].buf[0]; + ret = af9015_ctrl_msg(d, &req); + i += 1; } else { if (msg[i].addr == af9015_af9013_config[0].demod_address) @@ -942,7 +955,6 @@ static int af9015_read_config(struct usb_device *udev) switch (val) { case AF9013_TUNER_ENV77H11D5: case AF9013_TUNER_MT2060: - case AF9013_TUNER_MC44S803: case AF9013_TUNER_QT1010: case AF9013_TUNER_UNKNOWN: case AF9013_TUNER_MT2060_2: @@ -955,6 +967,10 @@ static int af9015_read_config(struct usb_device *udev) case AF9013_TUNER_MXL5005R: af9015_af9013_config[i].rf_spec_inv = 0; break; + case AF9013_TUNER_MC44S803: + af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO; + af9015_af9013_config[i].rf_spec_inv = 1; + break; default: warn("tuner id:%d not supported, please report!", val); return -ENODEV; @@ -1142,6 +1158,11 @@ static struct mxl5005s_config af9015_mxl5005_config = { .AgcMasterByte = 0x00, }; +static struct mc44s803_config af9015_mc44s803_config = { + .i2c_address = 0xc0, + .dig_out = 1, +}; + static int af9015_tuner_attach(struct dvb_usb_adapter *adap) { struct af9015_state *state = adap->dev->priv; @@ -1186,15 +1207,8 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap) DVB_PLL_TDA665X) == NULL ? -ENODEV : 0; break; case AF9013_TUNER_MC44S803: -#if 0 /* keep */ - ret = dvb_attach(mc44s80x_attach, adap->fe, i2c_adap) - == NULL ? -ENODEV : 0; -#else - ret = -ENODEV; - info("Freescale MC44S803 tuner found but no driver for that" \ - "tuner. Look at the Linuxtv.org for tuner driver" \ - "status."); -#endif + ret = dvb_attach(mc44s803_attach, adap->fe, i2c_adap, + &af9015_mc44s803_config) == NULL ? -ENODEV : 0; break; case AF9013_TUNER_UNKNOWN: default: -- cgit v1.2.3 From 17f2b6ad963ce70cc8f191dc9def4100e54811f8 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 5 Feb 2009 09:48:43 -0200 Subject: radio-mr800: codingstyle cleanups From: Alexey Klimov Cleanups of many if-check constructions. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/radio-mr800.c | 36 +++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index 4aa51a282..caa71501a 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -378,13 +378,15 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + int retval; /* safety check */ if (radio->removed) return -EIO; radio->curfreq = f->frequency; - if (amradio_setfreq(radio, radio->curfreq) < 0) + retval = amradio_setfreq(radio, radio->curfreq); + if (retval < 0) amradio_dev_warn(&radio->videodev->dev, "set frequency failed\n"); return 0; @@ -443,6 +445,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + int retval; /* safety check */ if (radio->removed) @@ -451,13 +454,15 @@ static int vidioc_s_ctrl(struct file *file, void *priv, switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) { - if (amradio_stop(radio) < 0) { + retval = amradio_stop(radio); + if (retval < 0) { amradio_dev_warn(&radio->videodev->dev, "amradio_stop failed\n"); return -1; } } else { - if (amradio_start(radio) < 0) { + retval = amradio_start(radio); + if (retval < 0) { amradio_dev_warn(&radio->videodev->dev, "amradio_start failed\n"); return -1; @@ -508,20 +513,24 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) static int usb_amradio_open(struct file *file) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + int retval; lock_kernel(); radio->users = 1; radio->muted = 1; - if (amradio_start(radio) < 0) { + retval = amradio_start(radio); + if (retval < 0) { amradio_dev_warn(&radio->videodev->dev, "radio did not start up properly\n"); radio->users = 0; unlock_kernel(); return -EIO; } - if (amradio_setfreq(radio, radio->curfreq) < 0) + + retval = amradio_setfreq(radio, radio->curfreq); + if (retval < 0) amradio_dev_warn(&radio->videodev->dev, "set frequency failed\n"); @@ -554,8 +563,10 @@ static int usb_amradio_close(struct file *file) static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) { struct amradio_device *radio = usb_get_intfdata(intf); + int retval; - if (amradio_stop(radio) < 0) + retval = amradio_stop(radio); + if (retval < 0) dev_warn(&intf->dev, "amradio_stop failed\n"); dev_info(&intf->dev, "going into suspend..\n"); @@ -567,8 +578,10 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) static int usb_amradio_resume(struct usb_interface *intf) { struct amradio_device *radio = usb_get_intfdata(intf); + int retval; - if (amradio_start(radio) < 0) + retval = amradio_start(radio); + if (retval < 0) dev_warn(&intf->dev, "amradio_start failed\n"); dev_info(&intf->dev, "coming out of suspend..\n"); @@ -619,16 +632,16 @@ static struct video_device amradio_videodev_template = { .release = usb_amradio_device_release, }; -/* check if the device is present and register with v4l and -usb if it is */ +/* check if the device is present and register with v4l and usb if it is */ static int usb_amradio_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct amradio_device *radio; + int retval; radio = kmalloc(sizeof(struct amradio_device), GFP_KERNEL); - if (!(radio)) + if (!radio) return -ENOMEM; radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL); @@ -657,7 +670,8 @@ static int usb_amradio_probe(struct usb_interface *intf, mutex_init(&radio->lock); video_set_drvdata(radio->videodev, radio); - if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) { + retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); + if (retval < 0) { dev_warn(&intf->dev, "could not register video device\n"); video_device_release(radio->videodev); kfree(radio->buffer); -- cgit v1.2.3 From d29804beec15d8395aa769769f49c47b3804773a Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 5 Feb 2009 09:49:58 -0200 Subject: radio-mr800: place dev_err instead of dev_warn From: Alexey Klimov There should be dev_err message if video_register_device() fails. Correct this situation. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/radio-mr800.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index caa71501a..cf26043af 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -672,7 +672,7 @@ static int usb_amradio_probe(struct usb_interface *intf, video_set_drvdata(radio->videodev, radio); retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); if (retval < 0) { - dev_warn(&intf->dev, "could not register video device\n"); + dev_err(&intf->dev, "could not register video device\n"); video_device_release(radio->videodev); kfree(radio->buffer); kfree(radio); -- cgit v1.2.3 From 97f4aaf0e577018bba36f877b081e05c6be0567b Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 5 Feb 2009 09:51:51 -0200 Subject: radio-mr800: add more dev_err messages in probe From: Alexey Klimov Patch adds 3 dev_err messages in usb_amradio_probe() function. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/radio-mr800.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index cf26043af..83f4f2b67 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -641,19 +641,23 @@ static int usb_amradio_probe(struct usb_interface *intf, radio = kmalloc(sizeof(struct amradio_device), GFP_KERNEL); - if (!radio) + if (!radio) { + dev_err(&intf->dev, "kmalloc for amradio_device failed\n"); return -ENOMEM; + } radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL); - if (!(radio->buffer)) { + if (!radio->buffer) { + dev_err(&intf->dev, "kmalloc for radio->buffer failed\n"); kfree(radio); return -ENOMEM; } radio->videodev = video_device_alloc(); - if (!(radio->videodev)) { + if (!radio->videodev) { + dev_err(&intf->dev, "video_device_alloc failed\n"); kfree(radio->buffer); kfree(radio); return -ENOMEM; -- cgit v1.2.3 From b01c0f56c2b1a2db922b500adf902bbcde73e021 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 5 Feb 2009 09:53:02 -0200 Subject: radio-mr800: move radio start and stop in one function From: Alexey Klimov Patch introduces new amradio_set_mute function. Amradio_start and amradio_stop removed. This makes driver more flexible and it's useful for next changes. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/radio-mr800.c | 64 +++++++++++---------------------- 1 file changed, 21 insertions(+), 43 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index 83f4f2b67..5e5aafec1 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -88,6 +88,16 @@ devices, that would be 76 and 91. */ #define FREQ_MAX 108.0 #define FREQ_MUL 16000 +/* + * Commands that device should understand + * List isnt full and will be updated with implementation of new functions + */ +#define AMRADIO_SET_MUTE 0xab + +/* Comfortable defines for amradio_set_mute */ +#define AMRADIO_START 0x00 +#define AMRADIO_STOP 0x01 + /* module parameter */ static int radio_nr = -1; module_param(radio_nr, int, 0); @@ -172,40 +182,8 @@ static struct usb_driver usb_amradio_driver = { .supports_autosuspend = 0, }; -/* switch on radio. Send 8 bytes to device. */ -static int amradio_start(struct amradio_device *radio) -{ - int retval; - int size; - - mutex_lock(&radio->lock); - - radio->buffer[0] = 0x00; - radio->buffer[1] = 0x55; - radio->buffer[2] = 0xaa; - radio->buffer[3] = 0x00; - radio->buffer[4] = 0xab; - radio->buffer[5] = 0x00; - radio->buffer[6] = 0x00; - radio->buffer[7] = 0x00; - - retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), - (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - - if (retval) { - mutex_unlock(&radio->lock); - return retval; - } - - radio->muted = 0; - - mutex_unlock(&radio->lock); - - return retval; -} - -/* switch off radio */ -static int amradio_stop(struct amradio_device *radio) +/* switch on/off the radio. Send 8 bytes to device */ +static int amradio_set_mute(struct amradio_device *radio, char argument) { int retval; int size; @@ -220,8 +198,8 @@ static int amradio_stop(struct amradio_device *radio) radio->buffer[1] = 0x55; radio->buffer[2] = 0xaa; radio->buffer[3] = 0x00; - radio->buffer[4] = 0xab; - radio->buffer[5] = 0x01; + radio->buffer[4] = AMRADIO_SET_MUTE; + radio->buffer[5] = argument; radio->buffer[6] = 0x00; radio->buffer[7] = 0x00; @@ -233,7 +211,7 @@ static int amradio_stop(struct amradio_device *radio) return retval; } - radio->muted = 1; + radio->muted = argument; mutex_unlock(&radio->lock); @@ -454,14 +432,14 @@ static int vidioc_s_ctrl(struct file *file, void *priv, switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) { - retval = amradio_stop(radio); + retval = amradio_set_mute(radio, AMRADIO_STOP); if (retval < 0) { amradio_dev_warn(&radio->videodev->dev, "amradio_stop failed\n"); return -1; } } else { - retval = amradio_start(radio); + retval = amradio_set_mute(radio, AMRADIO_START); if (retval < 0) { amradio_dev_warn(&radio->videodev->dev, "amradio_start failed\n"); @@ -520,7 +498,7 @@ static int usb_amradio_open(struct file *file) radio->users = 1; radio->muted = 1; - retval = amradio_start(radio); + retval = amradio_set_mute(radio, AMRADIO_START); if (retval < 0) { amradio_dev_warn(&radio->videodev->dev, "radio did not start up properly\n"); @@ -550,7 +528,7 @@ static int usb_amradio_close(struct file *file) radio->users = 0; if (!radio->removed) { - retval = amradio_stop(radio); + retval = amradio_set_mute(radio, AMRADIO_STOP); if (retval < 0) amradio_dev_warn(&radio->videodev->dev, "amradio_stop failed\n"); @@ -565,7 +543,7 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message) struct amradio_device *radio = usb_get_intfdata(intf); int retval; - retval = amradio_stop(radio); + retval = amradio_set_mute(radio, AMRADIO_STOP); if (retval < 0) dev_warn(&intf->dev, "amradio_stop failed\n"); @@ -580,7 +558,7 @@ static int usb_amradio_resume(struct usb_interface *intf) struct amradio_device *radio = usb_get_intfdata(intf); int retval; - retval = amradio_start(radio); + retval = amradio_set_mute(radio, AMRADIO_START); if (retval < 0) dev_warn(&intf->dev, "amradio_start failed\n"); -- cgit v1.2.3 From ef963eaf3f1b40899c38f9926a867743dbaf11bb Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 5 Feb 2009 09:54:17 -0200 Subject: radio-mr800: fix amradio_set_freq From: Alexey Klimov Fixing frequency adjustment to provide better diapason(band?) fit. Also, add AMRADIO_SET_FREQ to the list of commands. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/radio-mr800.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index 5e5aafec1..f0f0182d4 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -92,6 +92,7 @@ devices, that would be 76 and 91. */ * Commands that device should understand * List isnt full and will be updated with implementation of new functions */ +#define AMRADIO_SET_FREQ 0xa4 #define AMRADIO_SET_MUTE 0xab /* Comfortable defines for amradio_set_mute */ @@ -223,7 +224,7 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) { int retval; int size; - unsigned short freq_send = 0x13 + (freq >> 3) / 25; + unsigned short freq_send = 0x10 + (freq >> 3) / 25; /* safety check */ if (radio->removed) @@ -235,7 +236,7 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) radio->buffer[1] = 0x55; radio->buffer[2] = 0xaa; radio->buffer[3] = 0x03; - radio->buffer[4] = 0xa4; + radio->buffer[4] = AMRADIO_SET_FREQ; radio->buffer[5] = 0x00; radio->buffer[6] = 0x00; radio->buffer[7] = 0x08; -- cgit v1.2.3 From 38f50860e8ac9f600fd8240f54f2fdb753f7bb9f Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 5 Feb 2009 09:56:07 -0200 Subject: radio-mr800: add stereo support From: Alexey Klimov Patch introduces new amradio_set_stereo function. Driver calls this func to make stereo radio reception. Corrects checking of returned value after usb_bulk_msg. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/radio-mr800.c | 81 ++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index f0f0182d4..b6ac1d48d 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -94,11 +94,16 @@ devices, that would be 76 and 91. */ */ #define AMRADIO_SET_FREQ 0xa4 #define AMRADIO_SET_MUTE 0xab +#define AMRADIO_SET_MONO 0xae /* Comfortable defines for amradio_set_mute */ #define AMRADIO_START 0x00 #define AMRADIO_STOP 0x01 +/* Comfortable defines for amradio_set_stereo */ +#define WANT_STEREO 0x00 +#define WANT_MONO 0x01 + /* module parameter */ static int radio_nr = -1; module_param(radio_nr, int, 0); @@ -266,13 +271,49 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) return retval; } - radio->stereo = 0; + mutex_unlock(&radio->lock); + + return retval; +} + +static int amradio_set_stereo(struct amradio_device *radio, char argument) +{ + int retval; + int size; + + /* safety check */ + if (radio->removed) + return -EIO; + + mutex_lock(&radio->lock); + + radio->buffer[0] = 0x00; + radio->buffer[1] = 0x55; + radio->buffer[2] = 0xaa; + radio->buffer[3] = 0x00; + radio->buffer[4] = AMRADIO_SET_MONO; + radio->buffer[5] = argument; + radio->buffer[6] = 0x00; + radio->buffer[7] = 0x00; + + retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), + (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); + + if (retval < 0 || size != BUFFER_LENGTH) { + radio->stereo = -1; + mutex_unlock(&radio->lock); + return retval; + } + + radio->stereo = 1; mutex_unlock(&radio->lock); return retval; } + + /* USB subsystem interface begins here */ /* handle unplugging of the device, release data structures @@ -310,6 +351,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + int retval; /* safety check */ if (radio->removed) @@ -321,7 +363,16 @@ static int vidioc_g_tuner(struct file *file, void *priv, /* TODO: Add function which look is signal stereo or not * amradio_getstat(radio); */ - radio->stereo = -1; + +/* we call amradio_set_stereo to set radio->stereo + * Honestly, amradio_getstat should cover this in future and + * amradio_set_stereo shouldn't be here + */ + retval = amradio_set_stereo(radio, WANT_STEREO); + if (retval < 0) + amradio_dev_warn(&radio->videodev->dev, + "set stereo failed\n"); + strcpy(v->name, "FM"); v->type = V4L2_TUNER_RADIO; v->rangelow = FREQ_MIN * FREQ_MUL; @@ -342,6 +393,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + int retval; /* safety check */ if (radio->removed) @@ -349,6 +401,25 @@ static int vidioc_s_tuner(struct file *file, void *priv, if (v->index > 0) return -EINVAL; + + /* mono/stereo selector */ + switch (v->audmode) { + case V4L2_TUNER_MODE_MONO: + retval = amradio_set_stereo(radio, WANT_MONO); + if (retval < 0) + amradio_dev_warn(&radio->videodev->dev, + "set mono failed\n"); + break; + case V4L2_TUNER_MODE_STEREO: + retval = amradio_set_stereo(radio, WANT_STEREO); + if (retval < 0) + amradio_dev_warn(&radio->videodev->dev, + "set stereo failed\n"); + break; + default: + return -EINVAL; + } + return 0; } @@ -508,6 +579,11 @@ static int usb_amradio_open(struct file *file) return -EIO; } + retval = amradio_set_stereo(radio, WANT_STEREO); + if (retval < 0) + amradio_dev_warn(&radio->videodev->dev, + "set stereo failed\n"); + retval = amradio_setfreq(radio, radio->curfreq); if (retval < 0) amradio_dev_warn(&radio->videodev->dev, @@ -649,6 +725,7 @@ static int usb_amradio_probe(struct usb_interface *intf, radio->users = 0; radio->usbdev = interface_to_usbdev(intf); radio->curfreq = 95.16 * FREQ_MUL; + radio->stereo = -1; mutex_init(&radio->lock); -- cgit v1.2.3 From 08e10a545481449933bbb9a40be2dbb4e3a7a40c Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 5 Feb 2009 09:57:19 -0200 Subject: radio-mr800: add few lost mutex locks From: Alexey Klimov Patch adds two lost mutex locks. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/radio-mr800.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index b6ac1d48d..e1c63d76e 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -434,7 +434,10 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (radio->removed) return -EIO; + mutex_lock(&radio->lock); radio->curfreq = f->frequency; + mutex_unlock(&radio->lock); + retval = amradio_setfreq(radio, radio->curfreq); if (retval < 0) amradio_dev_warn(&radio->videodev->dev, @@ -602,7 +605,9 @@ static int usb_amradio_close(struct file *file) if (!radio) return -ENODEV; + mutex_lock(&radio->lock); radio->users = 0; + mutex_unlock(&radio->lock); if (!radio->removed) { retval = amradio_set_mute(radio, AMRADIO_STOP); -- cgit v1.2.3 From bf126270efecf5e5531fa1972fc1e9b4b297f835 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 5 Feb 2009 09:58:31 -0200 Subject: radio-mr800: increase version and add comments From: Alexey Klimov Increase driver version to 0.10, remove old and add new useful comments. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/radio-mr800.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index e1c63d76e..60c8c19fc 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -22,7 +22,7 @@ */ /* - * Big thanks to authors of dsbr100.c and radio-si470x.c + * Big thanks to authors and contributors of dsbr100.c and radio-si470x.c * * When work was looked pretty good, i discover this: * http://av-usbradio.sourceforge.net/index.php @@ -30,18 +30,23 @@ * Latest release of theirs project was in 2005. * Probably, this driver could be improved trough using their * achievements (specifications given). - * So, we have smth to begin with. + * Also, Faidon Liambotis wrote nice driver for this radio + * in 2007. He allowed to use his driver to improve current mr800 radio driver. + * http://kerneltrap.org/mailarchive/linux-usb-devel/2007/10/11/342492 * - * History: * Version 0.01: First working version. * It's required to blacklist AverMedia USB Radio * in usbhid/hid-quirks.c + * Version 0.10: A lot of cleanups and fixes: unpluging the device, + * few mutex locks were added, codinstyle issues, etc. + * Added stereo support. Thanks to + * Douglas Schilling Landgraf and + * David Ellingsworth + * for discussion, help and support. * * Many things to do: * - Correct power managment of device (suspend & resume) - * - Make x86 independance (little-endian and big-endian stuff) * - Add code for scanning and smooth tuning - * - Checked and add stereo&mono stuff * - Add code for sensitivity value * - Correct mistakes * - In Japan another FREQ_MIN and FREQ_MAX @@ -63,8 +68,8 @@ /* driver and module definitions */ #define DRIVER_AUTHOR "Alexey Klimov " #define DRIVER_DESC "AverMedia MR 800 USB FM radio driver" -#define DRIVER_VERSION "0.01" -#define RADIO_VERSION KERNEL_VERSION(0, 0, 1) +#define DRIVER_VERSION "0.10" +#define RADIO_VERSION KERNEL_VERSION(0, 1, 0) MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); @@ -312,14 +317,11 @@ static int amradio_set_stereo(struct amradio_device *radio, char argument) return retval; } - - -/* USB subsystem interface begins here */ - -/* handle unplugging of the device, release data structures -if nothing keeps us from doing it. If something is still -keeping us busy, the release callback of v4l will take care -of releasing it. */ +/* Handle unplugging the device. + * We call video_unregister_device in any case. + * The last function called in this procedure is + * usb_amradio_device_release. + */ static void usb_amradio_disconnect(struct usb_interface *intf) { struct amradio_device *radio = usb_get_intfdata(intf); -- cgit v1.2.3 From 2b47bb2b85cbd75eff389304c2b55bebecfb4755 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 5 Feb 2009 10:00:03 -0200 Subject: radio-mr800: fix checking of retval after usb_bulk_msg From: Alexey Klimov Patch corrects checking of returned value after usb_bulk_msg. Now we also check if number of transferred bytes equals to BUFFER_LENGTH. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/radio-mr800.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-mr800.c b/linux/drivers/media/radio/radio-mr800.c index 60c8c19fc..c04c8887e 100644 --- a/linux/drivers/media/radio/radio-mr800.c +++ b/linux/drivers/media/radio/radio-mr800.c @@ -217,7 +217,7 @@ static int amradio_set_mute(struct amradio_device *radio, char argument) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval) { + if (retval < 0 || size != BUFFER_LENGTH) { mutex_unlock(&radio->lock); return retval; } @@ -254,7 +254,7 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval) { + if (retval < 0 || size != BUFFER_LENGTH) { mutex_unlock(&radio->lock); return retval; } @@ -271,7 +271,7 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2), (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT); - if (retval) { + if (retval < 0 || size != BUFFER_LENGTH) { mutex_unlock(&radio->lock); return retval; } -- cgit v1.2.3 From 1bef7beb0e6804e68c391f35f95c364e9c25bb53 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Thu, 5 Feb 2009 20:37:49 -0500 Subject: cx18: Fix VBI ioctl() handling and Raw/Sliced VBI state management From: Andy Walls More sliced VBI fixes to bring the cx18 driver closer to full V4L2 spec compliance for VBI and to get sliced VBI working better. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-vbi.c | 14 ++-- linux/drivers/media/video/cx18/cx18-ioctl.c | 109 +++++++++++++++++++++------ 2 files changed, 94 insertions(+), 29 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-av-vbi.c b/linux/drivers/media/video/cx18/cx18-av-vbi.c index 72325d774..b5763372a 100644 --- a/linux/drivers/media/video/cx18/cx18-av-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-av-vbi.c @@ -25,8 +25,8 @@ #include "cx18-driver.h" /* - * For sliced VBI output, we set up to use VIP-1.1, 10-bit mode, - * NN counts 4 bytes Dwords, an IDID of 0x00 0x80 or one with the VBI line #. + * For sliced VBI output, we set up to use VIP-1.1, 8-bit mode, + * NN counts 1 byte Dwords, an IDID with the VBI line # in it. * Thus, according to the VIP-2 Spec, our VBI ancillary data lines * (should!) look like: * 4 byte EAV code: 0xff 0x00 0x00 0xRP @@ -35,8 +35,8 @@ * 1 byte data identifier: ne010iii (parity bits, 010, DID bits) * 1 byte secondary data id: nessssss (parity bits, SDID bits) * 1 byte data word count: necccccc (parity bits, NN Dword count) - * 2 byte Internal DID: 0x00 0x80 (programmed value) - * 4*NN data bytes + * 2 byte Internal DID: VBI-line-# 0x80 + * NN data bytes * 1 byte checksum * Fill bytes needed to fil out to 4*NN bytes of payload * @@ -65,7 +65,7 @@ struct vbi_anc_data { u8 sdid; u8 data_count; u8 idid[2]; - u8 payload[1]; /* 4*data_count of payload */ + u8 payload[1]; /* data_count of payload */ /* u8 checksum; */ /* u8 fill[]; Variable number of fill bytes */ }; @@ -215,6 +215,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) cx18_av_write(cx, 0x406, 0x13); cx18_av_write(cx, 0x47f, vbi_offset); + /* Force impossible lines to 0 */ if (is_pal) { for (i = 0; i <= 6; i++) svbi->service_lines[0][i] = @@ -229,6 +230,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) svbi->service_lines[1][i] = 0; } + /* Build register values for requested service lines */ for (i = 7; i <= 23; i++) { for (x = 0; x <= 1; x++) { switch (svbi->service_lines[1-x][i]) { @@ -242,7 +244,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) lcr[i] |= 6 << (4 * x); break; case V4L2_SLICED_VPS: - lcr[i] |= 9 << (4 * x); + lcr[i] |= 7 << (4 * x); /*'840 differs*/ break; } } diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index 645c41937..c73c0e6b5 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -42,6 +42,13 @@ #include #include +static int cx18_vbi_streaming(struct cx18 *cx) +{ + struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; + return (s_vbi->handle != CX18_INVALID_TASK_HANDLE) && + test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); +} + u16 cx18_service2vbi(int type) { switch (type) { @@ -58,12 +65,21 @@ u16 cx18_service2vbi(int type) } } +/* Check if VBI services are allowed on the (field, line) for the video std */ static int valid_service_line(int field, int line, int is_pal) { - return (is_pal && line >= 6 && (line != 23 || field == 0)) || + return (is_pal && line >= 6 && + ((field == 0 && line <= 23) || (field == 1 && line <= 22))) || (!is_pal && line >= 10 && line < 22); } +/* + * For a (field, line, std) and inbound potential set of services for that line, + * return the first valid service of those passed in the incoming set for that + * line in priority order: + * CC, VPS, or WSS over TELETEXT for well known lines + * TELETEXT, before VPS, before CC, before WSS, for other lines + */ static u16 select_service_from_set(int field, int line, u16 set, int is_pal) { u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525); @@ -90,6 +106,10 @@ static u16 select_service_from_set(int field, int line, u16 set, int is_pal) return 0; } +/* + * Expand the service_set of *fmt into valid service_lines for the std, + * and clear the passed in fmt->service_set + */ void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) { u16 set = fmt->service_set; @@ -102,6 +122,10 @@ void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) } } +/* + * Sanitize the service_lines in *fmt per the video std, and return 1 + * if any service_line is left as valid after santization + */ static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) { int f, l; @@ -116,6 +140,7 @@ static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) return set != 0; } +/* Compute the service_set from the assumed valid service_lines of *fmt */ u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt) { int f, l; @@ -162,7 +187,7 @@ static int cx18_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi; vbifmt->sampling_rate = 27000000; - vbifmt->offset = 248; + vbifmt->offset = 248; /* FIXME - slightly wrong for both 50 & 60 Hz */ vbifmt->samples_per_line = vbi_active_samples - 4; vbifmt->sample_format = V4L2_PIX_FMT_GREY; vbifmt->start[0] = cx->vbi.start[0]; @@ -180,12 +205,25 @@ static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; + /* sane, V4L2 spec compliant, defaults */ vbifmt->reserved[0] = 0; vbifmt->reserved[1] = 0; vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines)); + vbifmt->service_set = 0; + + /* + * Fetch the configured service_lines and total service_set from the + * digitizer/slicer. Note, cx18_av_vbi() wipes the passed in + * fmt->fmt.sliced under valid calling conditions + */ + if (cx18_av_cmd(cx, VIDIOC_G_FMT, fmt)) + return -EINVAL; - cx18_av_cmd(cx, VIDIOC_G_FMT, fmt); + /* Ensure V4L2 spec compliant output */ + vbifmt->reserved[0] = 0; + vbifmt->reserved[1] = 0; + vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; vbifmt->service_set = cx18_get_service_set(vbifmt); return 0; } @@ -224,10 +262,12 @@ static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh, vbifmt->reserved[0] = 0; vbifmt->reserved[1] = 0; + /* If given a service set, expand it validly & clear passed in set */ if (vbifmt->service_set) cx18_expand_service_set(vbifmt, cx->is_50hz); - check_service_set(vbifmt, cx->is_50hz); - vbifmt->service_set = cx18_get_service_set(vbifmt); + /* Sanitize the service_lines, and compute the new set if any valid */ + if (check_service_set(vbifmt, cx->is_50hz)) + vbifmt->service_set = cx18_get_service_set(vbifmt); return 0; } @@ -272,12 +312,22 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, if (ret) return ret; - if (!cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0) + if (!cx18_raw_vbi(cx) && cx18_vbi_streaming(cx)) return -EBUSY; + /* + * Set the digitizer registers for raw active VBI. + * Note cx18_av_vbi_wipes out alot of the passed in fmt under valid + * calling conditions + */ + ret = cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); + if (ret) + return ret; + + /* Store our new v4l2 (non-)sliced VBI state */ cx->vbi.sliced_in->service_set = 0; cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; - cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); + return cx18_g_fmt_vbi_cap(file, fh, fmt); } @@ -293,17 +343,20 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, if (ret) return ret; - ret = cx18_try_fmt_sliced_vbi_cap(file, fh, fmt); - if (ret) - return ret; - - if (check_service_set(vbifmt, cx->is_50hz) == 0) - return -EINVAL; + cx18_try_fmt_sliced_vbi_cap(file, fh, fmt); - if (cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0) + if (cx18_raw_vbi(cx) && cx18_vbi_streaming(cx)) return -EBUSY; + /* + * Set the service_lines requested in the digitizer/slicer registers. + * Note, cx18_av_vbi() wipes some "impossible" service lines in the + * passed in fmt->fmt.sliced under valid calling conditions + */ + ret = cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); + if (ret) + return ret; + /* Store our current v4l2 sliced VBI settings */ cx->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in)); return 0; } @@ -657,16 +710,26 @@ static int cx18_g_sliced_vbi_cap(struct file *file, void *fh, int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; int f, l; - if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { - for (f = 0; f < 2; f++) { - for (l = 0; l < 24; l++) { - if (valid_service_line(f, l, cx->is_50hz)) - cap->service_lines[f][l] = set; - } + if (cap->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) + return -EINVAL; + + cap->service_set = 0; + for (f = 0; f < 2; f++) { + for (l = 0; l < 24; l++) { + if (valid_service_line(f, l, cx->is_50hz)) { + /* + * We can find all v4l2 supported vbi services + * for the standard, on a valid line for the std + */ + cap->service_lines[f][l] = set; + cap->service_set |= set; + } else + cap->service_lines[f][l] = 0; } - return 0; } - return -EINVAL; + for (f = 0; f < 3; f++) + cap->reserved[f] = 0; + return 0; } static int cx18_g_enc_index(struct file *file, void *fh, -- cgit v1.2.3 From c25f9358cc7b4f70622195b02aa6b33fb522bce8 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 5 Feb 2009 23:52:29 -0200 Subject: radio-si470x: use usb_make_path in usb-radio drivers From: Alexey Klimov Place usb_make_path in radio-si470x.c that used when reporting bus_info information in vidioc_querycap. Priority: normal Acked-by: Tobias Lorenz Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/radio-si470x.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index f3cdf3af4..f77a65d2a 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -1202,9 +1202,11 @@ static struct v4l2_queryctrl si470x_v4l2_queryctrl[] = { static int si470x_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *capability) { + struct si470x_device *radio = video_drvdata(file); + strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); - sprintf(capability->bus_info, "USB"); + usb_make_path(radio->usbdev, capability->bus_info, sizeof(capability->bus_info)); capability->version = DRIVER_KERNEL_VERSION; capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER | V4L2_CAP_RADIO; -- cgit v1.2.3 From 66588fb3c835b7f534deb67c863970dcfbccea30 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 6 Feb 2009 16:33:43 -0500 Subject: cx18: Fixes for enforcing when Encoder Raw VBI params can be set From: Andy Walls The Encoder will only allow the Raw VBI parameters, along with a number of other API parameters, to take effect when no analog captures are in progress. These parameters must be set before the first analog capture starts, be it MPEG, VBI, YUV, etc., and cannot be changed until the last one stops. It is not obvious to me what capture channel API parameters are shared and which ones must be set per capture channel, so set them all for every analog capture channel start up. This fixes the driver so that VBI capture can be started up after the MPEG capture is going. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-ioctl.c | 20 ++++--- linux/drivers/media/video/cx18/cx18-streams.c | 79 ++++++++++++++++++++------- 2 files changed, 71 insertions(+), 28 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index c73c0e6b5..c023c79cf 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -42,13 +42,6 @@ #include #include -static int cx18_vbi_streaming(struct cx18 *cx) -{ - struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; - return (s_vbi->handle != CX18_INVALID_TASK_HANDLE) && - test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); -} - u16 cx18_service2vbi(int type) { switch (type) { @@ -312,7 +305,11 @@ static int cx18_s_fmt_vbi_cap(struct file *file, void *fh, if (ret) return ret; - if (!cx18_raw_vbi(cx) && cx18_vbi_streaming(cx)) + /* + * Changing the Encoder's Raw VBI parameters won't have any effect + * if any analog capture is ongoing + */ + if (!cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0) return -EBUSY; /* @@ -345,8 +342,13 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, cx18_try_fmt_sliced_vbi_cap(file, fh, fmt); - if (cx18_raw_vbi(cx) && cx18_vbi_streaming(cx)) + /* + * Changing the Encoder's Raw VBI parameters won't have any effect + * if any analog capture is ongoing + */ + if (cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0) return -EBUSY; + /* * Set the service_lines requested in the digitizer/slicer registers. * Note, cx18_av_vbi() wipes some "impossible" service lines in the diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index bcd786988..f2b6a1410 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -349,6 +349,14 @@ static void cx18_vbi_setup(struct cx18_stream *s) /* setup VBI registers */ cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in); + /* + * Send the CX18_CPU_SET_RAW_VBI_PARAM API command to setup Encoder Raw + * VBI when the first analog capture channel starts, as once it starts + * (e.g. MPEG), we can't effect any change in the Encoder Raw VBI setup + * (i.e. for the VBI capture channels). We also send it for each + * analog capture channel anyway just to make sure we get the proper + * behavior + */ if (raw) { lines = cx->vbi.count * 2; } else { @@ -410,8 +418,7 @@ static void cx18_vbi_setup(struct cx18_stream *s) CX18_DEBUG_INFO("Setup VBI h: %d lines %x bpl %d fr %d %x %x\n", data[0], data[1], data[2], data[3], data[4], data[5]); - if (s->type == CX18_ENC_STREAM_TYPE_VBI) - cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); + cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); } struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, @@ -460,8 +467,8 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) u32 data[MAX_MB_ARGUMENTS]; struct cx18 *cx = s->cx; struct cx18_buffer *buf; - int ts = 0; int captype = 0; + struct cx18_api_func_private priv; if (s->video_dev == NULL && s->dvb.enabled == 0) return -EINVAL; @@ -479,7 +486,6 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) case CX18_ENC_STREAM_TYPE_TS: captype = CAPTURE_CHANNEL_TYPE_TS; - ts = 1; break; case CX18_ENC_STREAM_TYPE_YUV: captype = CAPTURE_CHANNEL_TYPE_YUV; @@ -488,8 +494,16 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) captype = CAPTURE_CHANNEL_TYPE_PCM; break; case CX18_ENC_STREAM_TYPE_VBI: +#ifdef CX18_ENCODER_PARSES_SLICED captype = cx18_raw_vbi(cx) ? CAPTURE_CHANNEL_TYPE_VBI : CAPTURE_CHANNEL_TYPE_SLICED_VBI; +#else + /* + * Currently we set things up so that Sliced VBI from the + * digitizer is handled as Raw VBI by the encoder + */ + captype = CAPTURE_CHANNEL_TYPE_VBI; +#endif cx->vbi.frame = 0; cx->vbi.inserted_frame = 0; memset(cx->vbi.sliced_mpeg_size, @@ -499,10 +513,6 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) return -EINVAL; } - /* mute/unmute video */ - cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, - s->handle, !!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)); - /* Clear Streamoff flags in case left from last capture */ clear_bit(CX18_F_S_STREAMOFF, &s->s_flags); @@ -510,31 +520,62 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) s->handle = data[0]; cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype); - if (atomic_read(&cx->ana_capturing) == 0 && !ts) { - struct cx18_api_func_private priv; - - /* Stuff from Windows, we don't know what it is */ + /* + * For everything but CAPTURE_CHANNEL_TYPE_TS, play it safe and + * set up all the parameters, as it is not obvious which parameters the + * firmware shares across capture channel types and which it does not. + * + * Some of the cx18_vapi() calls below apply to only certain capture + * channel types. We're hoping there's no harm in calling most of them + * anyway, as long as the values are all consistent. Setting some + * shared parameters will have no effect once an analog capture channel + * has started streaming. + */ + if (captype != CAPTURE_CHANNEL_TYPE_TS) { cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0); cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1); cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 8, 0); cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 4, 1); - cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, s->handle, 12); + /* + * Audio related reset according to + * Documentation/video4linux/cx2341x/fw-encoder-api.txt + */ + if (atomic_read(&cx->ana_capturing) == 0) + cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, + s->handle, 12); + + /* + * Number of lines for Field 1 & Field 2 according to + * Documentation/video4linux/cx2341x/fw-encoder-api.txt + * FIXME - currently we set this to 0 & 0 but things seem OK + */ cx18_vapi(cx, CX18_CPU_SET_CAPTURE_LINE_NO, 3, - s->handle, cx->digitizer, cx->digitizer); + s->handle, cx->digitizer, cx->digitizer); - /* Setup VBI */ if (cx->v4l2_cap & V4L2_CAP_VBI_CAPTURE) cx18_vbi_setup(s); - /* assign program index info. - Mask 7: select I/P/B, Num_req: 400 max */ + /* + * assign program index info. + * Mask 7: select I/P/B, Num_req: 400 max + * FIXME - currently we have this hardcoded as disabled + */ cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 1, 0); - /* Setup API for Stream */ + /* Call out to the common CX2341x API setup for user controls */ priv.cx = cx; priv.s = s; cx2341x_update(&priv, cx18_api_func, NULL, &cx->params); + + /* + * When starting a capture and we're set for radio, + * ensure the video is muted, despite the user control. + */ + if (!cx->params.video_mute && + test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) + cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle, + (cx->params.video_mute_yuv << 8) | 1); } if (atomic_read(&cx->tot_capturing) == 0) { @@ -578,7 +619,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) } /* you're live! sit back and await interrupts :) */ - if (!ts) + if (captype != CAPTURE_CHANNEL_TYPE_TS) atomic_inc(&cx->ana_capturing); atomic_inc(&cx->tot_capturing); return 0; -- cgit v1.2.3 From 7784b73d36b6f96ba397937b9246610fea511e09 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 6 Feb 2009 23:15:44 -0500 Subject: cx18: Use correct line counts per field in firmware API call From: Andy Walls The driver was incorrectly setting 0 line counts in a firmware API call to set the maximum amount of lines per field. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.h | 3 --- linux/drivers/media/video/cx18/cx18-streams.c | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-driver.h b/linux/drivers/media/video/cx18/cx18-driver.h index 0ef099186..20189283a 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.h +++ b/linux/drivers/media/video/cx18/cx18-driver.h @@ -479,9 +479,6 @@ struct cx18 { unsigned long dualwatch_jiffies; u32 dualwatch_stereo_mode; - /* Digitizer type */ - int digitizer; /* 0x00EF = saa7114 0x00FO = saa7115 0x0106 = mic */ - struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ struct cx18_options options; /* User options */ int stream_buffers[CX18_MAX_STREAMS]; /* # of buffers for each stream */ diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index f2b6a1410..cec4794bf 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -548,10 +548,11 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) /* * Number of lines for Field 1 & Field 2 according to * Documentation/video4linux/cx2341x/fw-encoder-api.txt - * FIXME - currently we set this to 0 & 0 but things seem OK + * Field 1 is 312 for 625 line systems in BT.656 + * Field 2 is 313 for 625 line systems in BT.656 */ cx18_vapi(cx, CX18_CPU_SET_CAPTURE_LINE_NO, 3, - s->handle, cx->digitizer, cx->digitizer); + s->handle, 312, 313); if (cx->v4l2_cap & V4L2_CAP_VBI_CAPTURE) cx18_vbi_setup(s); -- cgit v1.2.3 From 044e05207bc29e80220289d29bcae6780ec904ac Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 6 Feb 2009 23:31:22 -0500 Subject: cx18: Fix sliced VBI PTS and fix artifacts in last raw line of field From: Andy Walls Fixed an endianess problem with the collection of the PTS from the VBI buffer given to us by the encoder. Also extrapolated the last 12 bytes of the last line of each field, to remove artifacts created by removing the first 12 bytes of each field for raw VBI. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-vbi.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-vbi.c b/linux/drivers/media/video/cx18/cx18-vbi.c index d6e15e119..d8e7d371c 100644 --- a/linux/drivers/media/video/cx18/cx18-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-vbi.c @@ -179,6 +179,10 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, if (streamtype != CX18_ENC_STREAM_TYPE_VBI) return; + /* + * The CX23418 sends us data that is 32 bit LE swapped, but we want + * the raw VBI bytes in the order they were in the raster line + */ cx18_buf_swap(buf); /* @@ -190,17 +194,27 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, if (cx18_raw_vbi(cx)) { u8 type; - /* Skip 12 bytes of header that gets stuffed in */ + /* + * We've set up to get a field's worth of VBI data at a time. + * Skip 12 bytes of header prefixing the first field or the + * last 12 bytes in the last VBI line from the first field that + * prefixes the second field. + */ size -= 12; memcpy(p, &buf->buf[12], size); type = p[3]; + /* Extrapolate the last 12 bytes of the field's last line */ + memset(&p[size], (int) p[size - 1], 12); + size = buf->bytesused = compress_raw_buf(cx, p, size); - /* second field of the frame? */ if (type == raw_vbi_sav_rp[1]) { - /* Dirty hack needed for backwards - compatibility of old VBI software. */ + /* + * Hack needed for compatibility with old VBI software. + * Write the frame # at the end of the last line of the + * second field + */ p += size - 4; memcpy(p, &cx->vbi.frame, 4); cx->vbi.frame++; @@ -210,7 +224,7 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, /* Sliced VBI data with data insertion */ - pts = (q[0] == 0x3fffffff) ? q[2] : 0; + pts = (be32_to_cpu(q[0] == 0x3fffffff)) ? be32_to_cpu(q[2]) : 0; /* first field */ /* compress_sliced_buf() will skip the 12 bytes of header */ -- cgit v1.2.3 From 40b47e5cc5ca4d00352b85e68426a50b7edae2aa Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 7 Feb 2009 13:47:28 -0500 Subject: cx18: Process Raw VBI on a whole frame basis; fix VBI buffer size From: Andy Walls The cx23418 appears to send Raw VBI buffers with a PTS on a per frame basis, not per field, so process Raw VBI on a whole frame basis and reduce some complexity. Fix VBI buffer size computation to handle a whole frame of Raw VBI for a 625 line system, which is the worst case and will work for 525 lines systems as well. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-driver.c | 54 +++++++++++----------------- linux/drivers/media/video/cx18/cx18-vbi.c | 31 +++++++--------- 2 files changed, 33 insertions(+), 52 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index f3a50f673..7a256a4fd 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -448,34 +448,38 @@ static void cx18_process_options(struct cx18 *cx) cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufsize; cx->stream_buf_size[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufsize; cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufsize; - cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = 0; /* computed later */ + cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_active_samples * 36; cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufsize; cx->stream_buf_size[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control no data */ - /* Except for VBI ensure stream_buffers & stream_buf_size are valid */ + /* Ensure stream_buffers & stream_buf_size are valid */ for (i = 0; i < CX18_MAX_STREAMS; i++) { - /* User said to use 0 buffers */ - if (cx->stream_buffers[i] == 0) { - cx->options.megabytes[i] = 0; - cx->stream_buf_size[i] = 0; - continue; - } - /* User said to use 0 MB total */ - if (cx->options.megabytes[i] <= 0) { + if (cx->stream_buffers[i] == 0 || /* User said 0 buffers */ + cx->options.megabytes[i] <= 0 || /* User said 0 MB total */ + cx->stream_buf_size[i] <= 0) { /* User said buf size 0 */ cx->options.megabytes[i] = 0; cx->stream_buffers[i] = 0; cx->stream_buf_size[i] = 0; continue; } - /* VBI is computed later or user said buffer has size 0 */ - if (cx->stream_buf_size[i] <= 0) { - if (i != CX18_ENC_STREAM_TYPE_VBI) { - cx->options.megabytes[i] = 0; - cx->stream_buffers[i] = 0; - cx->stream_buf_size[i] = 0; + /* + * VBI is a special case where the stream_buf_size is fixed + * and already in bytes + */ + if (i == CX18_ENC_STREAM_TYPE_VBI) { + if (cx->stream_buffers[i] < 0) { + cx->stream_buffers[i] = + cx->options.megabytes[i] * 1024 * 1024 + / cx->stream_buf_size[i]; + } else { + /* N.B. This might round down to 0 */ + cx->options.megabytes[i] = + cx->stream_buffers[i] + * cx->stream_buf_size[i]/(1024 * 1024); } continue; } + /* All other streams have stream_buf_size in kB at this point */ if (cx->stream_buffers[i] < 0) { cx->stream_buffers[i] = cx->options.megabytes[i] * 1024 / cx->stream_buf_size[i]; @@ -739,7 +743,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, { int retval = 0; int i; - int vbi_buf_size; u32 devtype; struct cx18 *cx; @@ -895,23 +898,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, } cx->params.video_gop_size = cx->is_60hz ? 15 : 12; - /* - * FIXME: setting the buffer size based on the tuner standard is - * suboptimal, as the CVBS and SVideo inputs could use a different std - * and the buffer could end up being too small in that case. - */ - vbi_buf_size = vbi_active_samples * (cx->is_60hz ? 24 : 36) / 2; - cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size; - - if (cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] < 0) - cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] = - cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] * 1024 * 1024 - / vbi_buf_size; - else - cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = - cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] * vbi_buf_size - / (1024 * 1024); - if (cx->options.radio > 0) cx->v4l2_cap |= V4L2_CAP_RADIO; diff --git a/linux/drivers/media/video/cx18/cx18-vbi.c b/linux/drivers/media/video/cx18/cx18-vbi.c index d8e7d371c..52082d4a1 100644 --- a/linux/drivers/media/video/cx18/cx18-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-vbi.c @@ -103,12 +103,11 @@ static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp) } /* Compress raw VBI format, removes leading SAV codes and surplus space - after the field. - Returns new compressed size. */ + after the frame. Returns new compressed size. */ static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size) { u32 line_size = vbi_active_samples; - u32 lines = cx->vbi.count; + u32 lines = cx->vbi.count * 2; u8 sav1 = raw_vbi_sav_rp[0]; u8 sav2 = raw_vbi_sav_rp[1]; u8 *q = buf; @@ -195,30 +194,26 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, u8 type; /* - * We've set up to get a field's worth of VBI data at a time. - * Skip 12 bytes of header prefixing the first field or the - * last 12 bytes in the last VBI line from the first field that - * prefixes the second field. + * We've set up to get a frame's worth of VBI data at a time. + * Skip 12 bytes of header prefixing the first field. */ size -= 12; memcpy(p, &buf->buf[12], size); type = p[3]; - /* Extrapolate the last 12 bytes of the field's last line */ + /* Extrapolate the last 12 bytes of the frame's last line */ memset(&p[size], (int) p[size - 1], 12); + size += 12; size = buf->bytesused = compress_raw_buf(cx, p, size); - if (type == raw_vbi_sav_rp[1]) { - /* - * Hack needed for compatibility with old VBI software. - * Write the frame # at the end of the last line of the - * second field - */ - p += size - 4; - memcpy(p, &cx->vbi.frame, 4); - cx->vbi.frame++; - } + /* + * Hack needed for compatibility with old VBI software. + * Write the frame # at the last 4 bytes of the frame + */ + p += size - 4; + memcpy(p, &cx->vbi.frame, 4); + cx->vbi.frame++; return; } -- cgit v1.2.3 From 41579b5b51a952f7bfaf05f5147f83148a7a3a68 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 8 Feb 2009 03:00:14 -0200 Subject: dsbr100: Add few lost mutex locks. From: Alexey Klimov Patch adds two lost mutex locks. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/radio/dsbr100.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/radio/dsbr100.c b/linux/drivers/media/radio/dsbr100.c index 0516711f8..155a75341 100644 --- a/linux/drivers/media/radio/dsbr100.c +++ b/linux/drivers/media/radio/dsbr100.c @@ -455,7 +455,10 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (radio->removed) return -EIO; + mutex_lock(&radio->lock); radio->curfreq = f->frequency; + mutex_unlock(&radio->lock); + retval = dsbr100_setfreq(radio, radio->curfreq); if (retval < 0) dev_warn(&radio->usbdev->dev, "Set frequency failed\n"); @@ -606,7 +609,10 @@ static int usb_dsbr100_close(struct file *file) if (!radio) return -ENODEV; + mutex_lock(&radio->lock); radio->users = 0; + mutex_unlock(&radio->lock); + if (!radio->removed) { retval = dsbr100_stop(radio); if (retval < 0) { -- cgit v1.2.3 From f9263f9b94e9a6f28065616efc07eb78d000a662 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sun, 8 Feb 2009 20:40:04 -0500 Subject: cx18: Finally get sliced VBI working - for 525 line 60 Hz systems at least From: Andy Walls Sliced VBI, in the manner that ivtv implements it as a separate data stream, now works for 525 line 60 Hz systems like NTSC-M. It may work for 625 line 50 Hz systems, but I have more engineering work to do, to verify it is operating properly. Sliced data insertion into the MPEG PS should be working, but is untested. Priority: normal Signed-off-by: Andy Walls --- linux/drivers/media/video/cx18/cx18-av-core.c | 44 ++++++++++++++++++++------- linux/drivers/media/video/cx18/cx18-av-core.h | 19 +++++++++++- linux/drivers/media/video/cx18/cx18-av-vbi.c | 10 +++--- linux/drivers/media/video/cx18/cx18-driver.c | 4 ++- linux/drivers/media/video/cx18/cx18-streams.c | 19 +++++++++--- linux/drivers/media/video/cx18/cx18-vbi.c | 19 +++++++++--- 6 files changed, 88 insertions(+), 27 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-av-core.c b/linux/drivers/media/video/cx18/cx18-av-core.c index 5279b8e45..343ddfd1b 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.c +++ b/linux/drivers/media/video/cx18/cx18-av-core.c @@ -172,11 +172,11 @@ static void cx18_av_initialize(struct cx18 *cx) /* * Initial VBI setup * VIP-1.1, 10 bit mode, enable Raw, disable sliced, - * don't clamp raw samples when codes are in use, 4 byte user D-words, - * programmed IDID, RP code V bit transition on VBLANK, data during + * don't clamp raw samples when codes are in use, 1 byte user D-words, + * IDID0 has line #, RP code V bit transition on VBLANK, data during * blanking intervals */ - cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010252e); + cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4013252e); /* Set the video input. The setting in MODE_CTRL gets lost when we do the above setup */ @@ -218,6 +218,7 @@ void cx18_av_std_setup(struct cx18 *cx) cx18_av_write(cx, 0x49f, 0x14); if (std & V4L2_STD_625_50) { + /* FIXME - revisit these for Sliced VBI */ hblank = 132; hactive = 720; burst = 93; @@ -241,13 +242,34 @@ void cx18_av_std_setup(struct cx18 *cx) sc = 672351; } } else { + /* + * The following relationships of half line counts should hold: + * 525 = vsync + vactive + vblank656 + * 12 = vblank656 - vblank + * + * vsync: always 6 half-lines of vsync pulses + * vactive: half lines of active video + * vblank656: half lines, after line 3, of blanked video + * vblank: half lines, after line 9, of blanked video + * + * vblank656 starts counting from the falling edge of the first + * vsync pulse (start of line 4) + * vblank starts counting from the after the 6 vsync pulses and + * 6 equalization pulses (start of line 10) + * + * For 525 line systems the driver will extract VBI information + * from lines 10 through 21. To avoid the EAV RP code from + * toggling at the start of hblank at line 22, where sliced VBI + * data from line 21 is stuffed, also treat line 22 as blanked. + */ + vblank656 = 38; /* lines 4 through 22 */ + vblank = 26; /* lines 10 through 22 */ + vactive = 481; /* lines 23 through 262.5 */ + hactive = 720; hblank = 122; - vactive = 487; luma_lpf = 1; uv_lpf = 1; - vblank = 26; - vblank656 = 26; src_decimation = 0x21f; if (std == V4L2_STD_PAL_60) { @@ -330,14 +352,14 @@ void cx18_av_std_setup(struct cx18 *cx) cx18_av_write(cx, 0x47d, 0xff & sc >> 8); cx18_av_write(cx, 0x47e, 0xff & sc >> 16); - /* Sets VBI parameters */ if (std & V4L2_STD_625_50) { - cx18_av_write(cx, 0x47f, 0x01); - state->vbi_line_offset = 5; + state->slicer_line_delay = 1; + state->slicer_line_offset = (6 + state->slicer_line_delay - 2); } else { - cx18_av_write(cx, 0x47f, 0x00); - state->vbi_line_offset = 8; + state->slicer_line_delay = 0; + state->slicer_line_offset = (10 + state->slicer_line_delay - 2); } + cx18_av_write(cx, 0x47f, state->slicer_line_delay); } /* ----------------------------------------------------------------------- */ diff --git a/linux/drivers/media/video/cx18/cx18-av-core.h b/linux/drivers/media/video/cx18/cx18-av-core.h index cf68a6039..d83760cae 100644 --- a/linux/drivers/media/video/cx18/cx18-av-core.h +++ b/linux/drivers/media/video/cx18/cx18-av-core.h @@ -79,11 +79,28 @@ struct cx18_av_state { enum cx18_av_audio_input aud_input; u32 audclk_freq; int audmode; - int vbi_line_offset; int default_volume; u32 id; u32 rev; int is_initialized; + + /* + * The VBI slicer starts operating and counting lines, begining at + * slicer line count of 1, at D lines after the deassertion of VRESET + * This staring field line, S, is 6 or 10 for 625 or 525 line systems. + * Sliced ancillary data captured on VBI slicer line M is sent at the + * beginning of the next VBI slicer line, VBI slicer line count N = M+1. + * Thus when the VBI slicer reports a VBI slicer line number with + * ancillary data, the IDID0 byte indicates VBI slicer line N. + * The actual field line that the captured data comes from is + * L = M+(S+D-1) = N-1+(S+D-1) = N + (S+D-2). + * + * D is the slicer_line_delay value programmed into register 0x47f. + * (S+D-2) is the slicer_line_offset used to convert slicer reported + * line counts to actual field lines. + */ + int slicer_line_delay; + int slicer_line_offset; }; diff --git a/linux/drivers/media/video/cx18/cx18-av-vbi.c b/linux/drivers/media/video/cx18/cx18-av-vbi.c index b5763372a..43267d1af 100644 --- a/linux/drivers/media/video/cx18/cx18-av-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-av-vbi.c @@ -182,7 +182,6 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) case VIDIOC_S_FMT: { int is_pal = !(state->std & V4L2_STD_525_60); - int vbi_offset = is_pal ? 1 : 0; int i, x; u8 lcr[24]; @@ -199,7 +198,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) cx18_av_std_setup(cx); /* VBI Offset */ - cx18_av_write(cx, 0x47f, vbi_offset); + cx18_av_write(cx, 0x47f, state->slicer_line_delay); cx18_av_write(cx, 0x404, 0x2e); break; } @@ -213,7 +212,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) /* Sliced VBI */ cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */ cx18_av_write(cx, 0x406, 0x13); - cx18_av_write(cx, 0x47f, vbi_offset); + cx18_av_write(cx, 0x47f, state->slicer_line_delay); /* Force impossible lines to 0 */ if (is_pal) { @@ -261,7 +260,8 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) } cx18_av_write(cx, 0x43c, 0x16); - cx18_av_write(cx, 0x474, is_pal ? 0x2a : 0x22); + /* FIXME - should match vblank set in cx18_av_std_setup() */ + cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26); break; } @@ -286,7 +286,7 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) did = anc->did; sdid = anc->sdid & 0xf; l = anc->idid[0] & 0x3f; - l += state->vbi_line_offset; + l += state->slicer_line_offset; p = anc->payload; /* Decode the SDID set by the slicer */ diff --git a/linux/drivers/media/video/cx18/cx18-driver.c b/linux/drivers/media/video/cx18/cx18-driver.c index 7a256a4fd..a95ac7795 100644 --- a/linux/drivers/media/video/cx18/cx18-driver.c +++ b/linux/drivers/media/video/cx18/cx18-driver.c @@ -640,7 +640,9 @@ static void __devinit cx18_init_struct2(struct cx18 *cx) cx->av_state.aud_input = CX18_AV_AUDIO8; cx->av_state.audclk_freq = 48000; cx->av_state.audmode = V4L2_TUNER_MODE_LANG1; - cx->av_state.vbi_line_offset = 8; + cx->av_state.slicer_line_delay = 0; + cx->av_state.slicer_line_offset = + (10 + cx->av_state.slicer_line_delay - 2); } static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev, diff --git a/linux/drivers/media/video/cx18/cx18-streams.c b/linux/drivers/media/video/cx18/cx18-streams.c index cec4794bf..e4a70cefc 100644 --- a/linux/drivers/media/video/cx18/cx18-streams.c +++ b/linux/drivers/media/video/cx18/cx18-streams.c @@ -360,9 +360,16 @@ static void cx18_vbi_setup(struct cx18_stream *s) if (raw) { lines = cx->vbi.count * 2; } else { - lines = cx->is_60hz ? 24 : 38; - if (cx->is_60hz) - lines += 2; + /* + * For 525/60 systems, according to the VIP 2 & BT.656 std: + * The EAV RP code's Field bit toggles on line 4, a few lines + * after the Vertcal Blank bit has already toggled. + * Tell the encoder to capture 21-4+1=18 lines per field, + * since we want lines 10 through 21. + * + * FIXME - revisit for 625/50 systems + */ + lines = cx->is_60hz ? (21 - 4 + 1) * 2 : 38; } data[0] = s->handle; @@ -402,9 +409,13 @@ static void cx18_vbi_setup(struct cx18_stream *s) * * Since the V bit is only allowed to toggle in the EAV RP code, * just before the first active region line, these two - * are problematic and we have to ignore them: + * are problematic: * 0x90 (Task HorizontalBlank) * 0xd0 (Task EvenField HorizontalBlank) + * + * We have set the digitzer to consider the first active line + * as part of VerticalBlank as well so we don't have to look for + * these problem codes nor lose the last line of sliced data. */ data[4] = 0xB0F0B0F0; /* diff --git a/linux/drivers/media/video/cx18/cx18-vbi.c b/linux/drivers/media/video/cx18/cx18-vbi.c index 52082d4a1..8e6f4d4af 100644 --- a/linux/drivers/media/video/cx18/cx18-vbi.c +++ b/linux/drivers/media/video/cx18/cx18-vbi.c @@ -221,13 +221,22 @@ void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf, pts = (be32_to_cpu(q[0] == 0x3fffffff)) ? be32_to_cpu(q[2]) : 0; + /* + * For calls to compress_sliced_buf(), ensure there are an integral + * number of lines by shifting the real data up over the 12 bytes header + * that got stuffed in. + * FIXME - there's a smarter way to do this with pointers, but for some + * reason I can't get it to work correctly right now. + */ + memcpy(p, &buf->buf[12], size-12); + /* first field */ - /* compress_sliced_buf() will skip the 12 bytes of header */ lines = compress_sliced_buf(cx, 0, p, size / 2, sliced_vbi_eav_rp[0]); - /* second field */ - /* experimentation shows that the second half does not always - begin at the exact address. So start a bit earlier - (hence 32). */ + /* + * second field + * In case the second half does not always begin at the exact address, + * start a bit earlier (hence 32). + */ lines = compress_sliced_buf(cx, lines, p + size / 2 - 32, size / 2 + 32, sliced_vbi_eav_rp[1]); /* always return at least one empty line */ -- cgit v1.2.3 From 6eaf346bd10a29047d3a0012f73d377e9ff2df67 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Feb 2009 19:26:02 +0100 Subject: dvb: fix 2.6.16 compile warning From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-core/dvbdev.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.c b/linux/drivers/media/dvb/dvb-core/dvbdev.c index 4609e3ebd..f6084e19d 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.c +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c @@ -83,7 +83,11 @@ static int dvb_device_open(struct inode *inode, struct file *file) file->private_data = dvbdev; old_fops = file->f_op; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17) file->f_op = fops_get(dvbdev->fops); +#else + file->f_op = (struct file_operations *)fops_get(dvbdev->fops); +#endif if (file->f_op == NULL) { file->f_op = old_fops; goto fail; -- cgit v1.2.3 From 2190a34473772cfc12d3d8cbdd441bbff2a84c25 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Feb 2009 19:31:59 +0100 Subject: ivtv/cx18: fix g_fmt and try_fmt for raw video From: Hans Verkuil The raw video device didn't report the image size correctly. When setting a new image the image height has to be a multiple of 32 lines. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/cx18/cx18-ioctl.c | 17 +++++++++++------ linux/drivers/media/video/ivtv/ivtv-ioctl.c | 14 +++++++++----- 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-ioctl.c b/linux/drivers/media/video/cx18/cx18-ioctl.c index c023c79cf..995e19c23 100644 --- a/linux/drivers/media/video/cx18/cx18-ioctl.c +++ b/linux/drivers/media/video/cx18/cx18-ioctl.c @@ -160,10 +160,8 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh, pixfmt->priv = 0; if (id->type == CX18_ENC_STREAM_TYPE_YUV) { pixfmt->pixelformat = V4L2_PIX_FMT_HM12; - /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ - pixfmt->sizeimage = - pixfmt->height * pixfmt->width + - pixfmt->height * (pixfmt->width / 2); + /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */ + pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; pixfmt->bytesperline = 720; } else { pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; @@ -228,11 +226,18 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh, struct cx18 *cx = id->cx; int w = fmt->fmt.pix.width; int h = fmt->fmt.pix.height; + int min_h = 2; w = min(w, 720); - w = max(w, 1); + w = max(w, 2); + if (id->type == CX18_ENC_STREAM_TYPE_YUV) { + /* YUV height must be a multiple of 32 */ + h &= ~0x1f; + min_h = 32; + } h = min(h, cx->is_50hz ? 576 : 480); - h = max(h, 2); + h = max(h, min_h); + cx18_g_fmt_vid_cap(file, fh, fmt); fmt->fmt.pix.width = w; fmt->fmt.pix.height = h; diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index f6b3ef6e6..779d4110f 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -345,10 +345,8 @@ static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f pixfmt->priv = 0; if (id->type == IVTV_ENC_STREAM_TYPE_YUV) { pixfmt->pixelformat = V4L2_PIX_FMT_HM12; - /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ - pixfmt->sizeimage = - pixfmt->height * pixfmt->width + - pixfmt->height * (pixfmt->width / 2); + /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */ + pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; pixfmt->bytesperline = 720; } else { pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; @@ -469,11 +467,17 @@ static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format struct ivtv *itv = id->itv; int w = fmt->fmt.pix.width; int h = fmt->fmt.pix.height; + int min_h = 2; w = min(w, 720); w = max(w, 2); + if (id->type == IVTV_ENC_STREAM_TYPE_YUV) { + /* YUV height must be a multiple of 32 */ + h &= ~0x1f; + min_h = 32; + } h = min(h, itv->is_50hz ? 576 : 480); - h = max(h, 2); + h = max(h, min_h); ivtv_g_fmt_vid_cap(file, fh, fmt); fmt->fmt.pix.width = w; fmt->fmt.pix.height = h; -- cgit v1.2.3 From c56f7694e4d231f52e5dd570abf003863813a3c6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 6 Feb 2009 19:35:22 +0100 Subject: doc: update hm12 documentation. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/cx2341x/README.hm12 | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linux') diff --git a/linux/Documentation/video4linux/cx2341x/README.hm12 b/linux/Documentation/video4linux/cx2341x/README.hm12 index 0e213ed09..b36148ea0 100644 --- a/linux/Documentation/video4linux/cx2341x/README.hm12 +++ b/linux/Documentation/video4linux/cx2341x/README.hm12 @@ -32,6 +32,10 @@ Y, U and V planes. This code assumes frames of 720x576 (PAL) pixels. The width of a frame is always 720 pixels, regardless of the actual specified width. +If the height is not a multiple of 32 lines, then the captured video is +missing macroblocks at the end and is unusable. So the height must be a +multiple of 32. + -------------------------------------------------------------------------- #include -- cgit v1.2.3 From 721dc4a20bd1636daf1304885f235c8844e2cdda Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 7 Feb 2009 11:02:27 +0100 Subject: ivtv: cleanup naming conventions From: Hans Verkuil Use consistent naming for pci_dev, v4l2_device and video_device. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/ivtv/ivtv-driver.c | 93 +++++++++++++------------- linux/drivers/media/video/ivtv/ivtv-driver.h | 24 +++---- linux/drivers/media/video/ivtv/ivtv-fileops.c | 2 +- linux/drivers/media/video/ivtv/ivtv-firmware.c | 2 +- linux/drivers/media/video/ivtv/ivtv-gpio.c | 4 +- linux/drivers/media/video/ivtv/ivtv-i2c.c | 14 ++-- linux/drivers/media/video/ivtv/ivtv-ioctl.c | 6 +- linux/drivers/media/video/ivtv/ivtv-irq.c | 4 +- linux/drivers/media/video/ivtv/ivtv-queue.c | 8 +-- linux/drivers/media/video/ivtv/ivtv-queue.h | 8 +-- linux/drivers/media/video/ivtv/ivtv-streams.c | 68 +++++++++---------- linux/drivers/media/video/ivtv/ivtv-udma.c | 10 +-- linux/drivers/media/video/ivtv/ivtv-udma.h | 4 +- linux/drivers/media/video/ivtv/ivtv-yuv.c | 6 +- linux/drivers/media/video/ivtv/ivtvfb.c | 6 +- 15 files changed, 129 insertions(+), 130 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.c b/linux/drivers/media/video/ivtv/ivtv-driver.c index 05bba3928..5e90897a2 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.c +++ b/linux/drivers/media/video/ivtv/ivtv-driver.c @@ -357,7 +357,7 @@ void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv) static void ivtv_process_eeprom(struct ivtv *itv) { struct tveeprom tv; - int pci_slot = PCI_SLOT(itv->dev->devfn); + int pci_slot = PCI_SLOT(itv->pdev->devfn); ivtv_read_eeprom(itv, &tv); @@ -604,7 +604,7 @@ static void ivtv_process_options(struct ivtv *itv) itv->std = ivtv_parse_std(itv); if (itv->std == 0 && tunertype >= 0) itv->std = tunertype ? V4L2_STD_MN : (V4L2_STD_ALL & ~V4L2_STD_MN); - itv->has_cx23415 = (itv->dev->device == PCI_DEVICE_ID_IVTV15); + itv->has_cx23415 = (itv->pdev->device == PCI_DEVICE_ID_IVTV15); chipname = itv->has_cx23415 ? "cx23415" : "cx23416"; if (itv->options.cardtype == -1) { IVTV_INFO("Ignore card (detected %s based chip)\n", chipname); @@ -617,9 +617,9 @@ static void ivtv_process_options(struct ivtv *itv) IVTV_ERR("Unknown user specified type, trying to autodetect card\n"); } if (itv->card == NULL) { - if (itv->dev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE || - itv->dev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT1 || - itv->dev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT2) { + if (itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE || + itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT1 || + itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT2) { itv->card = ivtv_get_card(itv->has_cx23415 ? IVTV_CARD_PVR_350 : IVTV_CARD_PVR_150); IVTV_INFO("Autodetected Hauppauge card (%s based)\n", chipname); @@ -630,13 +630,13 @@ static void ivtv_process_options(struct ivtv *itv) if (itv->card->pci_list == NULL) continue; for (j = 0; itv->card->pci_list[j].device; j++) { - if (itv->dev->device != + if (itv->pdev->device != itv->card->pci_list[j].device) continue; - if (itv->dev->subsystem_vendor != + if (itv->pdev->subsystem_vendor != itv->card->pci_list[j].subsystem_vendor) continue; - if (itv->dev->subsystem_device != + if (itv->pdev->subsystem_device != itv->card->pci_list[j].subsystem_device) continue; IVTV_INFO("Autodetected %s card (%s based)\n", @@ -650,9 +650,9 @@ done: if (itv->card == NULL) { itv->card = ivtv_get_card(IVTV_CARD_PVR_150); IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n", - itv->dev->vendor, itv->dev->device); + itv->pdev->vendor, itv->pdev->device); IVTV_ERR(" subsystem vendor/device: [%04x:%04x]\n", - itv->dev->subsystem_vendor, itv->dev->subsystem_device); + itv->pdev->subsystem_vendor, itv->pdev->subsystem_device); IVTV_ERR(" %s based\n", chipname); IVTV_ERR("Defaulting to %s card\n", itv->card->name); IVTV_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); @@ -671,7 +671,7 @@ done: */ static int __devinit ivtv_init_struct1(struct ivtv *itv) { - itv->base_addr = pci_resource_start(itv->dev, 0); + itv->base_addr = pci_resource_start(itv->pdev, 0); itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */ itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */ @@ -682,7 +682,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) spin_lock_init(&itv->lock); spin_lock_init(&itv->dma_reg_lock); - itv->irq_work_queues = create_singlethread_workqueue(itv->device.name); + itv->irq_work_queues = create_singlethread_workqueue(itv->v4l2_dev.name); if (itv->irq_work_queues == NULL) { IVTV_ERR("Could not create ivtv workqueue\n"); return -1; @@ -770,7 +770,7 @@ static void __devinit ivtv_init_struct2(struct ivtv *itv) itv->audio_input = itv->card->video_inputs[i].audio_index; } -static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, +static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, const struct pci_device_id *pci_id) { u16 cmd; @@ -779,11 +779,11 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, IVTV_DEBUG_INFO("Enabling pci device\n"); - if (pci_enable_device(dev)) { + if (pci_enable_device(pdev)) { IVTV_ERR("Can't enable device!\n"); return -EIO; } - if (pci_set_dma_mask(dev, 0xffffffff)) { + if (pci_set_dma_mask(pdev, 0xffffffff)) { IVTV_ERR("No suitable DMA available.\n"); return -EIO; } @@ -809,11 +809,11 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, } /* Check for bus mastering */ - pci_read_config_word(dev, PCI_COMMAND, &cmd); + pci_read_config_word(pdev, PCI_COMMAND, &cmd); if (!(cmd & PCI_COMMAND_MASTER)) { IVTV_DEBUG_INFO("Attempting to enable Bus Mastering\n"); - pci_set_master(dev); - pci_read_config_word(dev, PCI_COMMAND, &cmd); + pci_set_master(pdev); + pci_read_config_word(pdev, PCI_COMMAND, &cmd); if (!(cmd & PCI_COMMAND_MASTER)) { IVTV_ERR("Bus Mastering is not enabled\n"); return -ENXIO; @@ -821,26 +821,26 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, } IVTV_DEBUG_INFO("Bus Mastering Enabled.\n"); - pci_read_config_byte(dev, PCI_CLASS_REVISION, &card_rev); - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &card_rev); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < 64 && ivtv_pci_latency) { IVTV_INFO("Unreasonably low latency timer, " "setting to 64 (was %d)\n", pci_latency); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); } /* This config space value relates to DMA latencies. The default value 0x8080 is too low however and will lead to DMA errors. 0xffff is the max value which solves these problems. */ - pci_write_config_dword(dev, 0x40, 0xffff); + pci_write_config_dword(pdev, 0x40, 0xffff); IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, " "irq: %d, latency: %d, memory: 0x%lx\n", - itv->dev->device, card_rev, dev->bus->number, - PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), - itv->dev->irq, pci_latency, (unsigned long)itv->base_addr); + pdev->device, card_rev, pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + pdev->irq, pci_latency, (unsigned long)itv->base_addr); return 0; } @@ -939,7 +939,7 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) } } -static int __devinit ivtv_probe(struct pci_dev *dev, +static int __devinit ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) { int retval = 0; @@ -949,17 +949,17 @@ static int __devinit ivtv_probe(struct pci_dev *dev, itv = kzalloc(sizeof(struct ivtv), GFP_ATOMIC); if (itv == NULL) return -ENOMEM; - itv->dev = dev; + itv->pdev = pdev; itv->instance = atomic_inc_return(&ivtv_instance) - 1; - retval = v4l2_device_register(&dev->dev, &itv->device); + retval = v4l2_device_register(&pdev->dev, &itv->v4l2_dev); if (retval) { kfree(itv); return retval; } /* "ivtv + PCI ID" is a bit of a mouthful, so use "ivtv + instance" instead. */ - snprintf(itv->device.name, sizeof(itv->device.name), + snprintf(itv->v4l2_dev.name, sizeof(itv->v4l2_dev.name), "ivtv%d", itv->instance); IVTV_INFO("Initializing card %d\n", itv->instance); @@ -976,12 +976,11 @@ static int __devinit ivtv_probe(struct pci_dev *dev, IVTV_DEBUG_INFO("base addr: 0x%08x\n", itv->base_addr); /* PCI Device Setup */ - if ((retval = ivtv_setup_pci(itv, dev, pci_id)) != 0) { - if (retval == -EIO) - goto free_workqueue; - else if (retval == -ENXIO) - goto free_mem; - } + retval = ivtv_setup_pci(itv, pdev, pci_id); + if (retval == -EIO) + goto free_workqueue; + if (retval == -ENXIO) + goto free_mem; /* map io memory */ IVTV_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n", @@ -1158,8 +1157,8 @@ static int __devinit ivtv_probe(struct pci_dev *dev, ivtv_set_irq_mask(itv, 0xffffffff); /* Register IRQ */ - retval = request_irq(itv->dev->irq, ivtv_irq_handler, - IRQF_SHARED | IRQF_DISABLED, itv->device.name, (void *)itv); + retval = request_irq(itv->pdev->irq, ivtv_irq_handler, + IRQF_SHARED | IRQF_DISABLED, itv->v4l2_dev.name, (void *)itv); if (retval) { IVTV_ERR("Failed to register irq %d\n", retval); goto free_i2c; @@ -1181,7 +1180,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, free_streams: ivtv_streams_cleanup(itv, 1); free_irq: - free_irq(itv->dev->irq, (void *)itv); + free_irq(itv->pdev->irq, (void *)itv); free_i2c: exit_ivtv_i2c(itv); free_io: @@ -1198,7 +1197,7 @@ err: retval = -ENODEV; IVTV_ERR("Error %d on initialization\n", retval); - v4l2_device_unregister(&itv->device); + v4l2_device_unregister(&itv->v4l2_dev); kfree(itv); return retval; } @@ -1296,10 +1295,10 @@ int ivtv_init_on_first_open(struct ivtv *itv) return 0; } -static void ivtv_remove(struct pci_dev *pci_dev) +static void ivtv_remove(struct pci_dev *pdev) { - struct v4l2_device *dev = dev_get_drvdata(&pci_dev->dev); - struct ivtv *itv = to_ivtv(dev); + struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); + struct ivtv *itv = to_ivtv(v4l2_dev); int i; IVTV_DEBUG_INFO("Removing card\n"); @@ -1340,11 +1339,9 @@ static void ivtv_remove(struct pci_dev *pci_dev) ivtv_streams_cleanup(itv, 1); ivtv_udma_free(itv); - v4l2_device_unregister(&itv->device); - exit_ivtv_i2c(itv); - free_irq(itv->dev->irq, (void *)itv); + free_irq(itv->pdev->irq, (void *)itv); ivtv_iounmap(itv); release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); @@ -1352,11 +1349,13 @@ static void ivtv_remove(struct pci_dev *pci_dev) if (itv->has_cx23415) release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); - pci_disable_device(itv->dev); + pci_disable_device(itv->pdev); for (i = 0; i < IVTV_VBI_FRAMES; i++) kfree(itv->vbi.sliced_mpeg_data[i]); printk(KERN_INFO "ivtv: Removed %s\n", itv->card_name); + + v4l2_device_unregister(&itv->v4l2_dev); kfree(itv); } diff --git a/linux/drivers/media/video/ivtv/ivtv-driver.h b/linux/drivers/media/video/ivtv/ivtv-driver.h index 03df1cb7d..15779519a 100644 --- a/linux/drivers/media/video/ivtv/ivtv-driver.h +++ b/linux/drivers/media/video/ivtv/ivtv-driver.h @@ -134,7 +134,7 @@ extern int ivtv_debug; #define IVTV_DEBUG(x, type, fmt, args...) \ do { \ if ((x) & ivtv_debug) \ - v4l2_info(&itv->device, " " type ": " fmt , ##args); \ + v4l2_info(&itv->v4l2_dev, " " type ": " fmt , ##args); \ } while (0) #define IVTV_DEBUG_WARN(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_WARN, "warn", fmt , ## args) #define IVTV_DEBUG_INFO(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_INFO, "info", fmt , ## args) @@ -150,7 +150,7 @@ extern int ivtv_debug; #define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \ do { \ if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL)) \ - v4l2_info(&itv->device, " " type ": " fmt , ##args); \ + v4l2_info(&itv->v4l2_dev, " " type ": " fmt , ##args); \ } while (0) #define IVTV_DEBUG_HI_WARN(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_WARN, "warn", fmt , ## args) #define IVTV_DEBUG_HI_INFO(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_INFO, "info", fmt , ## args) @@ -164,9 +164,9 @@ extern int ivtv_debug; #define IVTV_DEBUG_HI_YUV(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) /* Standard kernel messages */ -#define IVTV_ERR(fmt, args...) v4l2_err(&itv->device, fmt , ## args) -#define IVTV_WARN(fmt, args...) v4l2_warn(&itv->device, fmt , ## args) -#define IVTV_INFO(fmt, args...) v4l2_info(&itv->device, fmt , ## args) +#define IVTV_ERR(fmt, args...) v4l2_err(&itv->v4l2_dev, fmt , ## args) +#define IVTV_WARN(fmt, args...) v4l2_warn(&itv->v4l2_dev, fmt , ## args) +#define IVTV_INFO(fmt, args...) v4l2_info(&itv->v4l2_dev, fmt , ## args) /* output modes (cx23415 only) */ #define OUT_NONE 0 @@ -316,7 +316,7 @@ struct ivtv; /* forward reference */ struct ivtv_stream { /* These first four fields are always set, even if the stream is not actually created. */ - struct video_device *v4l2dev; /* NULL when stream not created */ + struct video_device *vdev; /* NULL when stream not created */ struct ivtv *itv; /* for ease of use */ const char *name; /* name of the stream */ int type; /* stream type */ @@ -593,7 +593,7 @@ struct ivtv_card; /* Struct to hold info about ivtv cards */ struct ivtv { /* General fixed card data */ - struct pci_dev *dev; /* PCI device */ + struct pci_dev *pdev; /* PCI device */ const struct ivtv_card *card; /* card information */ const char *card_name; /* full name of the card */ const struct ivtv_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */ @@ -613,7 +613,7 @@ struct ivtv { volatile void __iomem *reg_mem; /* pointer to mapped registers */ struct ivtv_options options; /* user options */ - struct v4l2_device device; + struct v4l2_device v4l2_dev; struct v4l2_subdev sd_gpio; /* GPIO sub-device */ u16 instance; @@ -720,9 +720,9 @@ struct ivtv { struct osd_info *osd_info; /* ivtvfb private OSD info */ }; -static inline struct ivtv *to_ivtv(struct v4l2_device *dev) +static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev) { - return container_of(dev, struct ivtv, device); + return container_of(v4l2_dev, struct ivtv, v4l2_dev); } /* Globals */ @@ -789,7 +789,7 @@ static inline int ivtv_raw_vbi(const struct ivtv *itv) /* Call the specified callback for all subdevs matching hw (if 0, then match them all). Ignore any errors. */ #define ivtv_call_hw(itv, hw, o, f, args...) \ - __v4l2_device_call_subdevs(&(itv)->device, !(hw) || (sd->grp_id & (hw)), o, f , ##args) + __v4l2_device_call_subdevs(&(itv)->v4l2_dev, !(hw) || (sd->grp_id & (hw)), o, f , ##args) #define ivtv_call_all(itv, o, f, args...) ivtv_call_hw(itv, 0, o, f , ##args) @@ -797,7 +797,7 @@ static inline int ivtv_raw_vbi(const struct ivtv *itv) match them all). If the callback returns an error other than 0 or -ENOIOCTLCMD, then return with that error code. */ #define ivtv_call_hw_err(itv, hw, o, f, args...) \ - __v4l2_device_call_subdevs_until_err(&(itv)->device, !(hw) || (sd->grp_id & (hw)), o, f , ##args) + __v4l2_device_call_subdevs_until_err(&(itv)->v4l2_dev, !(hw) || (sd->grp_id & (hw)), o, f , ##args) #define ivtv_call_all_err(itv, o, f, args...) ivtv_call_hw_err(itv, 0, o, f , ##args) diff --git a/linux/drivers/media/video/ivtv/ivtv-fileops.c b/linux/drivers/media/video/ivtv/ivtv-fileops.c index 617667d1c..cfaacf609 100644 --- a/linux/drivers/media/video/ivtv/ivtv-fileops.c +++ b/linux/drivers/media/video/ivtv/ivtv-fileops.c @@ -991,7 +991,7 @@ int ivtv_v4l2_open(struct file *filp) mutex_lock(&itv->serialize_lock); if (ivtv_init_on_first_open(itv)) { IVTV_ERR("Failed to initialize on minor %d\n", - s->v4l2dev->minor); + vdev->minor); mutex_unlock(&itv->serialize_lock); return -ENXIO; } diff --git a/linux/drivers/media/video/ivtv/ivtv-firmware.c b/linux/drivers/media/video/ivtv/ivtv-firmware.c index 6dba55b7e..c1b7ec475 100644 --- a/linux/drivers/media/video/ivtv/ivtv-firmware.c +++ b/linux/drivers/media/video/ivtv/ivtv-firmware.c @@ -52,7 +52,7 @@ static int load_fw_direct(const char *fn, volatile u8 __iomem *mem, struct ivtv int retries = 3; retry: - if (retries && request_firmware(&fw, fn, &itv->dev->dev) == 0) { + if (retries && request_firmware(&fw, fn, &itv->pdev->dev) == 0) { int i; volatile u32 __iomem *dst = (volatile u32 __iomem *)mem; const u32 *src = (const u32 *)fw->data; diff --git a/linux/drivers/media/video/ivtv/ivtv-gpio.c b/linux/drivers/media/video/ivtv/ivtv-gpio.c index dc2850e87..3321983d8 100644 --- a/linux/drivers/media/video/ivtv/ivtv-gpio.c +++ b/linux/drivers/media/video/ivtv/ivtv-gpio.c @@ -384,7 +384,7 @@ int ivtv_gpio_init(struct ivtv *itv) write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT); write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR); v4l2_subdev_init(&itv->sd_gpio, &subdev_ops); - snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->device.name); + snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->v4l2_dev.name); itv->sd_gpio.grp_id = IVTV_HW_GPIO; - return v4l2_device_register_subdev(&itv->device, &itv->sd_gpio); + return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio); } diff --git a/linux/drivers/media/video/ivtv/ivtv-i2c.c b/linux/drivers/media/video/ivtv/ivtv-i2c.c index 41452e111..682377c1a 100644 --- a/linux/drivers/media/video/ivtv/ivtv-i2c.c +++ b/linux/drivers/media/video/ivtv/ivtv-i2c.c @@ -198,14 +198,14 @@ struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw) struct v4l2_subdev *result = NULL; struct v4l2_subdev *sd; - spin_lock(&itv->device.lock); - v4l2_device_for_each_subdev(sd, &itv->device) { + spin_lock(&itv->v4l2_dev.lock); + v4l2_device_for_each_subdev(sd, &itv->v4l2_dev) { if (sd->grp_id == hw) { result = sd; break; } } - spin_unlock(&itv->device.lock); + spin_unlock(&itv->v4l2_dev.lock); return result; } @@ -476,8 +476,8 @@ static int ivtv_read(struct ivtv *itv, unsigned char addr, unsigned char *data, intervening stop condition */ static int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) { - struct v4l2_device *drv = i2c_get_adapdata(i2c_adap); - struct ivtv *itv = to_ivtv(drv); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap); + struct ivtv *itv = to_ivtv(v4l2_dev); int retval; int i; @@ -617,13 +617,13 @@ int init_ivtv_i2c(struct ivtv *itv) sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d", itv->instance); - i2c_set_adapdata(&itv->i2c_adap, &itv->device); + i2c_set_adapdata(&itv->i2c_adap, &itv->v4l2_dev); memcpy(&itv->i2c_client, &ivtv_i2c_client_template, sizeof(struct i2c_client)); itv->i2c_client.adapter = &itv->i2c_adap; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) - itv->i2c_adap.dev.parent = &itv->dev->dev; + itv->i2c_adap.dev.parent = &itv->pdev->dev; #endif IVTV_DEBUG_I2C("setting scl and sda to 1\n"); diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c index 779d4110f..aa55a3cc4 100644 --- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c @@ -770,7 +770,7 @@ static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vc strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); - snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->dev)); + snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev)); vcap->version = IVTV_DRIVER_VERSION; /* version */ vcap->capabilities = itv->v4l2_cap; /* capabilities */ return 0; @@ -1517,12 +1517,12 @@ static int ivtv_log_status(struct file *file, void *fh) } IVTV_INFO("Tuner: %s\n", test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); - cx2341x_log_status(&itv->params, itv->device.name); + cx2341x_log_status(&itv->params, itv->v4l2_dev.name); IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); for (i = 0; i < IVTV_MAX_STREAMS; i++) { struct ivtv_stream *s = &itv->streams[i]; - if (s->v4l2dev == NULL || s->buffers == 0) + if (s->vdev == NULL || s->buffers == 0) continue; IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags, (s->buffers - s->q_free.buffers) * 100 / s->buffers, diff --git a/linux/drivers/media/video/ivtv/ivtv-irq.c b/linux/drivers/media/video/ivtv/ivtv-irq.c index 20e758d29..6dda1dd03 100644 --- a/linux/drivers/media/video/ivtv/ivtv-irq.c +++ b/linux/drivers/media/video/ivtv/ivtv-irq.c @@ -46,7 +46,7 @@ static void ivtv_pio_work_handler(struct ivtv *itv) IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n"); if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS || - s->v4l2dev == NULL || !ivtv_use_pio(s)) { + s->vdev == NULL || !ivtv_use_pio(s)) { itv->cur_pio_stream = -1; /* trigger PIO complete user interrupt */ write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); @@ -115,7 +115,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA int rc; /* sanity checks */ - if (s->v4l2dev == NULL) { + if (s->vdev == NULL) { IVTV_DEBUG_WARN("Stream %s not started\n", s->name); return -1; } diff --git a/linux/drivers/media/video/ivtv/ivtv-queue.c b/linux/drivers/media/video/ivtv/ivtv-queue.c index 71bd13e22..ff7b7dede 100644 --- a/linux/drivers/media/video/ivtv/ivtv-queue.c +++ b/linux/drivers/media/video/ivtv/ivtv-queue.c @@ -230,7 +230,7 @@ int ivtv_stream_alloc(struct ivtv_stream *s) return -ENOMEM; } if (ivtv_might_use_dma(s)) { - s->sg_handle = pci_map_single(itv->dev, s->sg_dma, sizeof(struct ivtv_sg_element), s->dma); + s->sg_handle = pci_map_single(itv->pdev, s->sg_dma, sizeof(struct ivtv_sg_element), s->dma); ivtv_stream_sync_for_cpu(s); } @@ -248,7 +248,7 @@ int ivtv_stream_alloc(struct ivtv_stream *s) } INIT_LIST_HEAD(&buf->list); if (ivtv_might_use_dma(s)) { - buf->dma_handle = pci_map_single(s->itv->dev, + buf->dma_handle = pci_map_single(s->itv->pdev, buf->buf, s->buf_size + 256, s->dma); ivtv_buf_sync_for_cpu(s, buf); } @@ -271,7 +271,7 @@ void ivtv_stream_free(struct ivtv_stream *s) /* empty q_free */ while ((buf = ivtv_dequeue(s, &s->q_free))) { if (ivtv_might_use_dma(s)) - pci_unmap_single(s->itv->dev, buf->dma_handle, + pci_unmap_single(s->itv->pdev, buf->dma_handle, s->buf_size + 256, s->dma); kfree(buf->buf); kfree(buf); @@ -280,7 +280,7 @@ void ivtv_stream_free(struct ivtv_stream *s) /* Free SG Array/Lists */ if (s->sg_dma != NULL) { if (s->sg_handle != IVTV_DMA_UNMAPPED) { - pci_unmap_single(s->itv->dev, s->sg_handle, + pci_unmap_single(s->itv->pdev, s->sg_handle, sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); s->sg_handle = IVTV_DMA_UNMAPPED; } diff --git a/linux/drivers/media/video/ivtv/ivtv-queue.h b/linux/drivers/media/video/ivtv/ivtv-queue.h index 476556afd..91233839a 100644 --- a/linux/drivers/media/video/ivtv/ivtv-queue.h +++ b/linux/drivers/media/video/ivtv/ivtv-queue.h @@ -53,14 +53,14 @@ static inline int ivtv_use_dma(struct ivtv_stream *s) static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf) { if (ivtv_use_dma(s)) - pci_dma_sync_single_for_cpu(s->itv->dev, buf->dma_handle, + pci_dma_sync_single_for_cpu(s->itv->pdev, buf->dma_handle, s->buf_size + 256, s->dma); } static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf) { if (ivtv_use_dma(s)) - pci_dma_sync_single_for_device(s->itv->dev, buf->dma_handle, + pci_dma_sync_single_for_device(s->itv->pdev, buf->dma_handle, s->buf_size + 256, s->dma); } @@ -82,14 +82,14 @@ void ivtv_stream_free(struct ivtv_stream *s); static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s) { if (ivtv_use_dma(s)) - pci_dma_sync_single_for_cpu(s->itv->dev, s->sg_handle, + pci_dma_sync_single_for_cpu(s->itv->pdev, s->sg_handle, sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); } static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s) { if (ivtv_use_dma(s)) - pci_dma_sync_single_for_device(s->itv->dev, s->sg_handle, + pci_dma_sync_single_for_device(s->itv->pdev, s->sg_handle, sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); } diff --git a/linux/drivers/media/video/ivtv/ivtv-streams.c b/linux/drivers/media/video/ivtv/ivtv-streams.c index 854a950af..15da01710 100644 --- a/linux/drivers/media/video/ivtv/ivtv-streams.c +++ b/linux/drivers/media/video/ivtv/ivtv-streams.c @@ -137,11 +137,11 @@ static struct { static void ivtv_stream_init(struct ivtv *itv, int type) { struct ivtv_stream *s = &itv->streams[type]; - struct video_device *dev = s->v4l2dev; + struct video_device *vdev = s->vdev; - /* we need to keep v4l2dev, so restore it afterwards */ + /* we need to keep vdev, so restore it afterwards */ memset(s, 0, sizeof(*s)); - s->v4l2dev = dev; + s->vdev = vdev; /* initialize ivtv_stream fields */ s->itv = itv; @@ -172,10 +172,10 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) int num_offset = ivtv_stream_info[type].num_offset; int num = itv->instance + ivtv_first_minor + num_offset; - /* These four fields are always initialized. If v4l2dev == NULL, then + /* These four fields are always initialized. If vdev == NULL, then this stream is not in use. In that case no other fields but these four can be used. */ - s->v4l2dev = NULL; + s->vdev = NULL; s->itv = itv; s->type = type; s->name = ivtv_stream_info[type].name; @@ -197,21 +197,21 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) ivtv_stream_init(itv, type); /* allocate and initialize the v4l2 video device structure */ - s->v4l2dev = video_device_alloc(); - if (s->v4l2dev == NULL) { + s->vdev = video_device_alloc(); + if (s->vdev == NULL) { IVTV_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name); return -ENOMEM; } - snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "%s %s", - itv->device.name, s->name); + snprintf(s->vdev->name, sizeof(s->vdev->name), "%s %s", + itv->v4l2_dev.name, s->name); - s->v4l2dev->num = num; - s->v4l2dev->v4l2_dev = &itv->device; - s->v4l2dev->fops = ivtv_stream_info[type].fops; - s->v4l2dev->release = video_device_release; - s->v4l2dev->tvnorms = V4L2_STD_ALL; - ivtv_set_funcs(s->v4l2dev); + s->vdev->num = num; + s->vdev->v4l2_dev = &itv->v4l2_dev; + s->vdev->fops = ivtv_stream_info[type].fops; + s->vdev->release = video_device_release; + s->vdev->tvnorms = V4L2_STD_ALL; + ivtv_set_funcs(s->vdev); return 0; } @@ -226,7 +226,7 @@ int ivtv_streams_setup(struct ivtv *itv) if (ivtv_prep_dev(itv, type)) break; - if (itv->streams[type].v4l2dev == NULL) + if (itv->streams[type].vdev == NULL) continue; /* Allocate Stream */ @@ -247,28 +247,28 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) int vfl_type = ivtv_stream_info[type].vfl_type; int num; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) return 0; - num = s->v4l2dev->num; + num = s->vdev->num; /* card number + user defined offset + device offset */ if (type != IVTV_ENC_STREAM_TYPE_MPG) { struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG]; - if (s_mpg->v4l2dev) - num = s_mpg->v4l2dev->num + ivtv_stream_info[type].num_offset; + if (s_mpg->vdev) + num = s_mpg->vdev->num + ivtv_stream_info[type].num_offset; } - video_set_drvdata(s->v4l2dev, s); + video_set_drvdata(s->vdev, s); /* Register device. First try the desired minor, then any free one. */ - if (video_register_device(s->v4l2dev, vfl_type, num)) { + if (video_register_device(s->vdev, vfl_type, num)) { IVTV_ERR("Couldn't register v4l2 device for %s kernel number %d\n", s->name, num); - video_device_release(s->v4l2dev); - s->v4l2dev = NULL; + video_device_release(s->vdev); + s->vdev = NULL; return -ENOMEM; } - num = s->v4l2dev->num; + num = s->vdev->num; switch (vfl_type) { case VFL_TYPE_GRABBER: @@ -316,9 +316,9 @@ void ivtv_streams_cleanup(struct ivtv *itv, int unregister) /* Teardown all streams */ for (type = 0; type < IVTV_MAX_STREAMS; type++) { - struct video_device *vdev = itv->streams[type].v4l2dev; + struct video_device *vdev = itv->streams[type].vdev; - itv->streams[type].v4l2dev = NULL; + itv->streams[type].vdev = NULL; if (vdev == NULL) continue; @@ -449,7 +449,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) int captype = 0, subtype = 0; int enable_passthrough = 0; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) return -EINVAL; IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name); @@ -611,7 +611,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) struct cx2341x_mpeg_params *p = &itv->params; int datatype; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) return -EINVAL; IVTV_DEBUG_INFO("Setting some initial decoder settings\n"); @@ -657,7 +657,7 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset) { struct ivtv *itv = s->itv; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) return -EINVAL; if (test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) @@ -705,7 +705,7 @@ void ivtv_stop_all_captures(struct ivtv *itv) for (i = IVTV_MAX_STREAMS - 1; i >= 0; i--) { struct ivtv_stream *s = &itv->streams[i]; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) continue; if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { ivtv_stop_v4l2_encode_stream(s, 0); @@ -720,7 +720,7 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) int cap_type; int stopmode; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) return -EINVAL; /* This function assumes that you are allowed to stop the capture @@ -834,7 +834,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) { struct ivtv *itv = s->itv; - if (s->v4l2dev == NULL) + if (s->vdev == NULL) return -EINVAL; if (s->type != IVTV_DEC_STREAM_TYPE_YUV && s->type != IVTV_DEC_STREAM_TYPE_MPG) @@ -895,7 +895,7 @@ int ivtv_passthrough_mode(struct ivtv *itv, int enable) struct ivtv_stream *yuv_stream = &itv->streams[IVTV_ENC_STREAM_TYPE_YUV]; struct ivtv_stream *dec_stream = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; - if (yuv_stream->v4l2dev == NULL || dec_stream->v4l2dev == NULL) + if (yuv_stream->vdev == NULL || dec_stream->vdev == NULL) return -EINVAL; IVTV_DEBUG_INFO("ivtv ioctl: Select passthrough mode\n"); diff --git a/linux/drivers/media/video/ivtv/ivtv-udma.c b/linux/drivers/media/video/ivtv/ivtv-udma.c index 5d4964b24..c3f8a5eac 100644 --- a/linux/drivers/media/video/ivtv/ivtv-udma.c +++ b/linux/drivers/media/video/ivtv/ivtv-udma.c @@ -94,7 +94,7 @@ void ivtv_udma_alloc(struct ivtv *itv) { if (itv->udma.SG_handle == 0) { /* Map DMA Page Array Buffer */ - itv->udma.SG_handle = pci_map_single(itv->dev, itv->udma.SGarray, + itv->udma.SG_handle = pci_map_single(itv->pdev, itv->udma.SGarray, sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); ivtv_udma_sync_for_cpu(itv); } @@ -148,7 +148,7 @@ int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, } /* Map SG List */ - dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); + dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); /* Fill SG Array with new values */ ivtv_udma_fill_sg_array (dma, ivtv_dest_addr, 0, -1); @@ -173,7 +173,7 @@ void ivtv_udma_unmap(struct ivtv *itv) /* Unmap Scatterlist */ if (dma->SG_length) { - pci_unmap_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); + pci_unmap_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); dma->SG_length = 0; } /* sync DMA */ @@ -192,13 +192,13 @@ void ivtv_udma_free(struct ivtv *itv) /* Unmap SG Array */ if (itv->udma.SG_handle) { - pci_unmap_single(itv->dev, itv->udma.SG_handle, + pci_unmap_single(itv->pdev, itv->udma.SG_handle, sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); } /* Unmap Scatterlist */ if (itv->udma.SG_length) { - pci_unmap_sg(itv->dev, itv->udma.SGlist, itv->udma.page_count, PCI_DMA_TODEVICE); + pci_unmap_sg(itv->pdev, itv->udma.SGlist, itv->udma.page_count, PCI_DMA_TODEVICE); } for (i = 0; i < IVTV_DMA_SG_OSD_ENT; i++) { diff --git a/linux/drivers/media/video/ivtv/ivtv-udma.h b/linux/drivers/media/video/ivtv/ivtv-udma.h index df727e23b..ee3c9efb5 100644 --- a/linux/drivers/media/video/ivtv/ivtv-udma.h +++ b/linux/drivers/media/video/ivtv/ivtv-udma.h @@ -35,13 +35,13 @@ void ivtv_udma_start(struct ivtv *itv); static inline void ivtv_udma_sync_for_device(struct ivtv *itv) { - pci_dma_sync_single_for_device((struct pci_dev *)itv->dev, itv->udma.SG_handle, + pci_dma_sync_single_for_device(itv->pdev, itv->udma.SG_handle, sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); } static inline void ivtv_udma_sync_for_cpu(struct ivtv *itv) { - pci_dma_sync_single_for_cpu((struct pci_dev *)itv->dev, itv->udma.SG_handle, + pci_dma_sync_single_for_cpu(itv->pdev, itv->udma.SG_handle, sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); } diff --git a/linux/drivers/media/video/ivtv/ivtv-yuv.c b/linux/drivers/media/video/ivtv/ivtv-yuv.c index ee9110737..7912ed6b7 100644 --- a/linux/drivers/media/video/ivtv/ivtv-yuv.c +++ b/linux/drivers/media/video/ivtv/ivtv-yuv.c @@ -103,7 +103,7 @@ static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, dma->page_count = 0; return -ENOMEM; } - dma->SG_length = pci_map_sg(itv->dev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); + dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); /* Fill SG Array with new values */ ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size); @@ -910,7 +910,7 @@ static void ivtv_yuv_init(struct ivtv *itv) /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN); if (yi->blanking_ptr) { - yi->blanking_dmaptr = pci_map_single(itv->dev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE); + yi->blanking_dmaptr = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE); } else { yi->blanking_dmaptr = 0; IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n"); @@ -1237,7 +1237,7 @@ void ivtv_yuv_close(struct ivtv *itv) if (yi->blanking_ptr) { kfree(yi->blanking_ptr); yi->blanking_ptr = NULL; - pci_unmap_single(itv->dev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE); + pci_unmap_single(itv->pdev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE); } /* Invalidate the old dimension information */ diff --git a/linux/drivers/media/video/ivtv/ivtvfb.c b/linux/drivers/media/video/ivtv/ivtvfb.c index 26b91d2c8..a48fe216b 100644 --- a/linux/drivers/media/video/ivtv/ivtvfb.c +++ b/linux/drivers/media/video/ivtv/ivtvfb.c @@ -1201,12 +1201,12 @@ static int ivtvfb_init_card(struct ivtv *itv) static int __init ivtvfb_callback_init(struct device *dev, void *p) { struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); - struct ivtv *itv = container_of(v4l2_dev, struct ivtv, device); + struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev); if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { if (ivtvfb_init_card(itv) == 0) { IVTVFB_INFO("Framebuffer registered on %s\n", - itv->device.name); + itv->v4l2_dev.name); (*(int *)p)++; } } @@ -1216,7 +1216,7 @@ static int __init ivtvfb_callback_init(struct device *dev, void *p) static int ivtvfb_callback_cleanup(struct device *dev, void *p) { struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); - struct ivtv *itv = container_of(v4l2_dev, struct ivtv, device); + struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev); if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { -- cgit v1.2.3 From b8e52030ce27c936c72151dfca30fd90e857ebab Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 7 Feb 2009 11:07:04 +0100 Subject: doc: use consistent naming conventions for vdev and v4l2_dev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/v4l2-framework.txt | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'linux') diff --git a/linux/Documentation/video4linux/v4l2-framework.txt b/linux/Documentation/video4linux/v4l2-framework.txt index cc3506242..73f9b6423 100644 --- a/linux/Documentation/video4linux/v4l2-framework.txt +++ b/linux/Documentation/video4linux/v4l2-framework.txt @@ -134,7 +134,7 @@ The recommended approach is as follows: static atomic_t drv_instance = ATOMIC_INIT(0); -static int __devinit drv_probe(struct pci_dev *dev, +static int __devinit drv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) { ... @@ -218,7 +218,7 @@ to add new ops and categories. A sub-device driver initializes the v4l2_subdev struct using: - v4l2_subdev_init(subdev, &ops); + v4l2_subdev_init(sd, &ops); Afterwards you need to initialize subdev->name with a unique name and set the module owner. This is done for you if you use the i2c helper functions. @@ -226,7 +226,7 @@ module owner. This is done for you if you use the i2c helper functions. A device (bridge) driver needs to register the v4l2_subdev with the v4l2_device: - int err = v4l2_device_register_subdev(device, subdev); + int err = v4l2_device_register_subdev(v4l2_dev, sd); This can fail if the subdev module disappeared before it could be registered. After this function was called successfully the subdev->dev field points to @@ -234,17 +234,17 @@ the v4l2_device. You can unregister a sub-device using: - v4l2_device_unregister_subdev(subdev); + v4l2_device_unregister_subdev(sd); -Afterwards the subdev module can be unloaded and subdev->dev == NULL. +Afterwards the subdev module can be unloaded and sd->dev == NULL. You can call an ops function either directly: - err = subdev->ops->core->g_chip_ident(subdev, &chip); + err = sd->ops->core->g_chip_ident(sd, &chip); but it is better and easier to use this macro: - err = v4l2_subdev_call(subdev, core, g_chip_ident, &chip); + err = v4l2_subdev_call(sd, core, g_chip_ident, &chip); The macro will to the right NULL pointer checks and returns -ENODEV if subdev is NULL, -ENOIOCTLCMD if either subdev->core or subdev->core->g_chip_ident is @@ -252,12 +252,12 @@ NULL, or the actual result of the subdev->ops->core->g_chip_ident ops. It is also possible to call all or a subset of the sub-devices: - v4l2_device_call_all(dev, 0, core, g_chip_ident, &chip); + v4l2_device_call_all(v4l2_dev, 0, core, g_chip_ident, &chip); Any subdev that does not support this ops is skipped and error results are ignored. If you want to check for errors use this: - err = v4l2_device_call_until_err(dev, 0, core, g_chip_ident, &chip); + err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_chip_ident, &chip); Any error except -ENOIOCTLCMD will exit the loop with that error. If no errors (except -ENOIOCTLCMD) occured, then 0 is returned. @@ -505,8 +505,8 @@ There are a few useful helper functions: You can set/get driver private data in the video_device struct using: -void *video_get_drvdata(struct video_device *dev); -void video_set_drvdata(struct video_device *dev, void *data); +void *video_get_drvdata(struct video_device *vdev); +void video_set_drvdata(struct video_device *vdev, void *data); Note that you can safely call video_set_drvdata() before calling video_register_device(). -- cgit v1.2.3 From 03ba675c15fe86ace9d44dc86d769b6695621e69 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 7 Feb 2009 11:23:40 +0100 Subject: saa7146: implement v4l2_device support. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/common/saa7146_core.c | 17 ++++++++++------- linux/include/media/saa7146.h | 3 +++ 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/common/saa7146_core.c b/linux/drivers/media/common/saa7146_core.c index 9bce837f3..ef11ab98c 100644 --- a/linux/drivers/media/common/saa7146_core.c +++ b/linux/drivers/media/common/saa7146_core.c @@ -367,13 +367,16 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent ERR(("out of memory.\n")); goto out; } + err = v4l2_device_register(&pci->dev, &dev->v4l2_dev); + if (err) + goto err_free; DEB_EE(("pci:%p\n",pci)); err = pci_enable_device(pci); if (err < 0) { ERR(("pci_enable_device() failed.\n")); - goto err_free; + goto err_unreg; } /* enable bus-mastering */ @@ -456,8 +459,6 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device)); dev->ext = ext; - pci_set_drvdata(pci, dev); - mutex_init(&dev->lock); spin_lock_init(&dev->int_slock); spin_lock_init(&dev->slock); @@ -481,7 +482,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent if (ext->attach(dev, pci_ext)) { DEB_D(("ext->attach() failed for %p. skipping device.\n",dev)); - goto err_unprobe; + goto err_free_i2c; } INIT_LIST_HEAD(&dev->item); @@ -492,8 +493,6 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent out: return err; -err_unprobe: - pci_set_drvdata(pci, NULL); err_free_i2c: pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle); @@ -511,6 +510,8 @@ err_release: pci_release_region(pci, 0); err_disable: pci_disable_device(pci); +err_unreg: + v4l2_device_unregister(&dev->v4l2_dev); err_free: kfree(dev); goto out; @@ -518,7 +519,8 @@ err_free: static void saa7146_remove_one(struct pci_dev *pdev) { - struct saa7146_dev* dev = pci_get_drvdata(pdev); + struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev); + struct saa7146_dev *dev = container_of(v4l2_dev, struct saa7146_dev, v4l2_dev); struct { void *addr; dma_addr_t dma; @@ -532,6 +534,7 @@ static void saa7146_remove_one(struct pci_dev *pdev) DEB_EE(("dev:%p\n",dev)); dev->ext->detach(dev); + v4l2_device_unregister(&dev->v4l2_dev); /* shut down all video dma transfers */ saa7146_write(dev, MC1, 0x00ff0000); diff --git a/linux/include/media/saa7146.h b/linux/include/media/saa7146.h index 8034124f1..689bc8ebd 100644 --- a/linux/include/media/saa7146.h +++ b/linux/include/media/saa7146.h @@ -14,6 +14,7 @@ #include "compat.h" #include #include +#include #include /* for vmalloc() */ #include /* for vmalloc_to_page() */ @@ -111,6 +112,8 @@ struct saa7146_dev struct list_head item; + struct v4l2_device v4l2_dev; + /* different device locks */ spinlock_t slock; struct mutex lock; -- cgit v1.2.3 From 730fafde64c1efd147ec7f58edf1bc0cc24ef24b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 7 Feb 2009 11:38:12 +0100 Subject: saa7146: i2c adapdata now points to v4l2_device. From: Hans Verkuil Prepare for converting to v4l2_subdev. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/common/saa7146_core.c | 2 +- linux/drivers/media/common/saa7146_i2c.c | 5 +++-- linux/include/media/saa7146.h | 5 +++++ 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/common/saa7146_core.c b/linux/drivers/media/common/saa7146_core.c index ef11ab98c..067a1f282 100644 --- a/linux/drivers/media/common/saa7146_core.c +++ b/linux/drivers/media/common/saa7146_core.c @@ -520,7 +520,7 @@ err_free: static void saa7146_remove_one(struct pci_dev *pdev) { struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev); - struct saa7146_dev *dev = container_of(v4l2_dev, struct saa7146_dev, v4l2_dev); + struct saa7146_dev *dev = to_saa7146_dev(v4l2_dev); struct { void *addr; dma_addr_t dma; diff --git a/linux/drivers/media/common/saa7146_i2c.c b/linux/drivers/media/common/saa7146_i2c.c index 255b14551..f275846da 100644 --- a/linux/drivers/media/common/saa7146_i2c.c +++ b/linux/drivers/media/common/saa7146_i2c.c @@ -391,7 +391,8 @@ out: /* utility functions */ static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num) { - struct saa7146_dev* dev = i2c_get_adapdata(adapter); + struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter); + struct saa7146_dev *dev = to_saa7146_dev(v4l2_dev); /* use helper function to transfer data */ return saa7146_i2c_transfer(dev, msg, num, adapter->retries); @@ -423,7 +424,7 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c if( NULL != i2c_adapter ) { BUG_ON(!i2c_adapter->class); - i2c_set_adapdata(i2c_adapter,dev); + i2c_set_adapdata(i2c_adapter, &dev->v4l2_dev); i2c_adapter->dev.parent = &dev->pci->dev; i2c_adapter->algo = &saa7146_algo; i2c_adapter->algo_data = NULL; diff --git a/linux/include/media/saa7146.h b/linux/include/media/saa7146.h index 689bc8ebd..8cb90d36e 100644 --- a/linux/include/media/saa7146.h +++ b/linux/include/media/saa7146.h @@ -149,6 +149,11 @@ struct saa7146_dev struct saa7146_dma d_rps1; }; +static inline struct saa7146_dev *to_saa7146_dev(struct v4l2_device *v4l2_dev) +{ + return container_of(v4l2_dev, struct saa7146_dev, v4l2_dev); +} + /* from saa7146_i2c.c */ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate); -- cgit v1.2.3 From 735182acc722237aca3cd7c6e5fde27c965d8334 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 7 Feb 2009 11:45:08 +0100 Subject: saa7146: the adapter class will be NULL when v4l2_subdev is used. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/common/saa7146_i2c.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/common/saa7146_i2c.c b/linux/drivers/media/common/saa7146_i2c.c index f275846da..68674799b 100644 --- a/linux/drivers/media/common/saa7146_i2c.c +++ b/linux/drivers/media/common/saa7146_i2c.c @@ -422,8 +422,12 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c dev->i2c_bitrate = bitrate; saa7146_i2c_reset(dev); - if( NULL != i2c_adapter ) { + if (i2c_adapter) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) + /* For kernels > 2.6.22 it can actually be NULL + when v4l2_subdev is used. */ BUG_ON(!i2c_adapter->class); +#endif i2c_set_adapdata(i2c_adapter, &dev->v4l2_dev); i2c_adapter->dev.parent = &dev->pci->dev; i2c_adapter->algo = &saa7146_algo; -- cgit v1.2.3 From 24aa05d2510d2f036343fc58aa76658a4a6f66ac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 7 Feb 2009 15:00:02 +0100 Subject: v4l2: prefill ident and revision from v4l2_dbg_chip_ident. From: Hans Verkuil Drivers that implement this always have to set the ident and revision to V4L2_IDENT_NONE and 0. Do this in the v4l2 core so drivers don't have to do this. Priority: normal Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/v4l2-ioctl.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/video/v4l2-ioctl.c b/linux/drivers/media/video/v4l2-ioctl.c index 165bc9005..ec139df5c 100644 --- a/linux/drivers/media/video/v4l2-ioctl.c +++ b/linux/drivers/media/video/v4l2-ioctl.c @@ -24,6 +24,7 @@ #endif #include #include +#include #include #include "compat.h" @@ -1746,6 +1747,8 @@ static long __video_do_ioctl(struct file *file, if (!ops->vidioc_g_chip_ident) break; + p->ident = V4L2_IDENT_NONE; + p->revision = 0; ret = ops->vidioc_g_chip_ident(file, fh, p); if (!ret) dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision); -- cgit v1.2.3 From 2f363ae420765f2ca6c9a3263649936f10f25138 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 7 Feb 2009 15:18:05 +0100 Subject: saa7146: convert saa7146 and mxb in particular to v4l2_subdev. From: Hans Verkuil Modified mxb to load the i2c modules through v4l2_subdev. So no more probing. Modified tea6415c and tea6420 to use the standard routing ops to do the routing, rather than using private commands. Dropped the private commands from tda9840 (they were never used except during initialization of the module). Added saa7146 support for VIDIOC_DBG_G_CHIP_IDENT. Converted saa5246a and saa5249 to v4l2_subdev. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/common/saa7146_video.c | 25 ++- linux/drivers/media/video/mxb.c | 277 ++++++++++++----------------- linux/drivers/media/video/saa5246a.c | 74 +++++--- linux/drivers/media/video/saa5249.c | 75 +++++--- linux/drivers/media/video/tda9840.c | 79 ++------ linux/drivers/media/video/tda9840.h | 14 -- linux/drivers/media/video/tea6415c.c | 50 +++--- linux/drivers/media/video/tea6415c.h | 12 -- linux/drivers/media/video/tea6420.c | 66 ++++--- linux/drivers/media/video/tea6420.h | 27 +-- linux/include/media/v4l2-chip-ident.h | 18 ++ 11 files changed, 349 insertions(+), 368 deletions(-) delete mode 100644 linux/drivers/media/video/tda9840.h (limited to 'linux') diff --git a/linux/drivers/media/common/saa7146_video.c b/linux/drivers/media/common/saa7146_video.c index a0cf6dacf..6536853c1 100644 --- a/linux/drivers/media/common/saa7146_video.c +++ b/linux/drivers/media/common/saa7146_video.c @@ -1,4 +1,5 @@ #include +#include #include "compat.h" static int max_memory = 32; @@ -210,6 +211,7 @@ static struct v4l2_queryctrl controls[] = { .step = 1, .default_value = 128, .type = V4L2_CTRL_TYPE_INTEGER, + .flags = V4L2_CTRL_FLAG_SLIDER, },{ .id = V4L2_CID_CONTRAST, .name = "Contrast", @@ -218,6 +220,7 @@ static struct v4l2_queryctrl controls[] = { .step = 1, .default_value = 64, .type = V4L2_CTRL_TYPE_INTEGER, + .flags = V4L2_CTRL_FLAG_SLIDER, },{ .id = V4L2_CID_SATURATION, .name = "Saturation", @@ -226,15 +229,16 @@ static struct v4l2_queryctrl controls[] = { .step = 1, .default_value = 64, .type = V4L2_CTRL_TYPE_INTEGER, + .flags = V4L2_CTRL_FLAG_SLIDER, },{ .id = V4L2_CID_VFLIP, - .name = "Vertical flip", + .name = "Vertical Flip", .minimum = 0, .maximum = 1, .type = V4L2_CTRL_TYPE_BOOLEAN, },{ .id = V4L2_CID_HFLIP, - .name = "Horizontal flip", + .name = "Horizontal Flip", .minimum = 0, .maximum = 1, .type = V4L2_CTRL_TYPE_BOOLEAN, @@ -1113,6 +1117,22 @@ static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type ty return err; } +static int vidioc_g_chip_ident(struct file *file, void *__fh, + struct v4l2_dbg_chip_ident *chip) +{ + struct saa7146_fh *fh = __fh; + struct saa7146_dev *dev = fh->dev; + + chip->ident = V4L2_IDENT_NONE; + chip->revision = 0; + if (v4l2_chip_match_host(&chip->match)) { + chip->ident = V4L2_IDENT_SAA7146; + return 0; + } + return v4l2_device_call_until_err(&dev->v4l2_dev, 0, + core, g_chip_ident, chip); +} + #ifdef CONFIG_VIDEO_V4L1_COMPAT static int vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *mbuf) { @@ -1153,6 +1173,7 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, + .vidioc_g_chip_ident = vidioc_g_chip_ident, .vidioc_overlay = vidioc_overlay, .vidioc_g_fbuf = vidioc_g_fbuf, diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index e7b94e6b1..fda3b7581 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -33,9 +33,14 @@ #include "mxb.h" #include "tea6415c.h" #include "tea6420.h" -#include "tda9840.h" -#define I2C_SAA7111 0x24 +#define I2C_SAA5246A 0x11 +#define I2C_SAA7111A 0x24 +#define I2C_TDA9840 0x42 +#define I2C_TEA6415C 0x43 +#define I2C_TEA6420_1 0x4c +#define I2C_TEA6420_2 0x4d +#define I2C_TUNER 0x60 #define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) @@ -80,31 +85,29 @@ static struct { static int video_audio_connect[MXB_INPUTS] = { 0, 1, 3, 3 }; -/* these are the necessary input-output-pins for bringing one audio source -(see above) to the CD-output */ -static struct tea6420_multiplex TEA6420_cd[MXB_AUDIOS+1][2] = - { - {{1,1,0},{1,1,0}}, /* Tuner */ - {{5,1,0},{6,1,0}}, /* AUX 1 */ - {{4,1,0},{6,1,0}}, /* AUX 2 */ - {{3,1,0},{6,1,0}}, /* AUX 3 */ - {{1,1,0},{3,1,0}}, /* Radio */ - {{1,1,0},{2,1,0}}, /* CD-Rom */ - {{6,1,0},{6,1,0}} /* Mute */ - }; - -/* these are the necessary input-output-pins for bringing one audio source -(see above) to the line-output */ -static struct tea6420_multiplex TEA6420_line[MXB_AUDIOS+1][2] = - { - {{2,3,0},{1,2,0}}, - {{5,3,0},{6,2,0}}, - {{4,3,0},{6,2,0}}, - {{3,3,0},{6,2,0}}, - {{2,3,0},{3,2,0}}, - {{2,3,0},{2,2,0}}, - {{6,3,0},{6,2,0}} /* Mute */ - }; +/* These are the necessary input-output-pins for bringing one audio source + (see above) to the CD-output. Note that gain is set to 0 in this table. */ +static struct v4l2_routing TEA6420_cd[MXB_AUDIOS + 1][2] = { + { { 1, 1 }, { 1, 1 } }, /* Tuner */ + { { 5, 1 }, { 6, 1 } }, /* AUX 1 */ + { { 4, 1 }, { 6, 1 } }, /* AUX 2 */ + { { 3, 1 }, { 6, 1 } }, /* AUX 3 */ + { { 1, 1 }, { 3, 1 } }, /* Radio */ + { { 1, 1 }, { 2, 1 } }, /* CD-Rom */ + { { 6, 1 }, { 6, 1 } } /* Mute */ +}; + +/* These are the necessary input-output-pins for bringing one audio source + (see above) to the line-output. Note that gain is set to 0 in this table. */ +static struct v4l2_routing TEA6420_line[MXB_AUDIOS + 1][2] = { + { { 2, 3 }, { 1, 2 } }, + { { 5, 3 }, { 6, 2 } }, + { { 4, 3 }, { 6, 2 } }, + { { 3, 3 }, { 6, 2 } }, + { { 2, 3 }, { 3, 2 } }, + { { 2, 3 }, { 2, 2 } }, + { { 6, 3 }, { 6, 2 } } /* Mute */ +}; #define MAXCONTROLS 1 static struct v4l2_queryctrl mxb_controls[] = { @@ -118,12 +121,12 @@ struct mxb struct i2c_adapter i2c_adapter; - struct i2c_client *saa7111a; - struct i2c_client *tda9840; - struct i2c_client *tea6415c; - struct i2c_client *tuner; - struct i2c_client *tea6420_1; - struct i2c_client *tea6420_2; + struct v4l2_subdev *saa7111a; + struct v4l2_subdev *tda9840; + struct v4l2_subdev *tea6415c; + struct v4l2_subdev *tuner; + struct v4l2_subdev *tea6420_1; + struct v4l2_subdev *tea6420_2; int cur_mode; /* current audio mode (mono, stereo, ...) */ int cur_input; /* current input */ @@ -131,84 +134,54 @@ struct mxb struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */ }; -static struct saa7146_extension extension; - -static int mxb_check_clients(struct device *dev, void *data) -{ - struct mxb *mxb = data; - struct i2c_client *client = i2c_verify_client(dev); - - if (!client) - return 0; - - if (I2C_ADDR_TEA6420_1 == client->addr) - mxb->tea6420_1 = client; - if (I2C_ADDR_TEA6420_2 == client->addr) - mxb->tea6420_2 = client; - if (I2C_TEA6415C_2 == client->addr) - mxb->tea6415c = client; - if (I2C_ADDR_TDA9840 == client->addr) - mxb->tda9840 = client; - if (I2C_SAA7111 == client->addr) - mxb->saa7111a = client; - if (0x60 == client->addr) - mxb->tuner = client; +#define saa7111a_call(mxb, o, f, args...) \ + v4l2_subdev_call(mxb->saa7111a, o, f, ##args) +#define tea6420_1_call(mxb, o, f, args...) \ + v4l2_subdev_call(mxb->tea6420_1, o, f, ##args) +#define tea6420_2_call(mxb, o, f, args...) \ + v4l2_subdev_call(mxb->tea6420_2, o, f, ##args) +#define tda9840_call(mxb, o, f, args...) \ + v4l2_subdev_call(mxb->tda9840, o, f, ##args) +#define tea6415c_call(mxb, o, f, args...) \ + v4l2_subdev_call(mxb->tea6415c, o, f, ##args) +#define tuner_call(mxb, o, f, args...) \ + v4l2_subdev_call(mxb->tuner, o, f, ##args) +#define call_all(dev, o, f, args...) \ + v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args) - return 0; -} +static struct saa7146_extension extension; -static int mxb_probe(struct saa7146_dev* dev) +static int mxb_probe(struct saa7146_dev *dev) { - struct mxb* mxb = NULL; - int result; - - result = request_module("saa7115"); - if (result < 0) { - printk("mxb: saa7111 i2c module not available.\n"); - return -ENODEV; - } - result = request_module("tea6420"); - if (result < 0) { - printk("mxb: tea6420 i2c module not available.\n"); - return -ENODEV; - } - result = request_module("tea6415c"); - if (result < 0) { - printk("mxb: tea6415c i2c module not available.\n"); - return -ENODEV; - } - result = request_module("tda9840"); - if (result < 0) { - printk("mxb: tda9840 i2c module not available.\n"); - return -ENODEV; - } - result = request_module("tuner"); - if (result < 0) { - printk("mxb: tuner i2c module not available.\n"); - return -ENODEV; - } + struct mxb *mxb = NULL; mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); - if( NULL == mxb ) { + if (mxb == NULL) { DEB_D(("not enough kernel memory.\n")); return -ENOMEM; } - mxb->i2c_adapter = (struct i2c_adapter) { - .class = I2C_CLASS_TV_ANALOG, - }; - +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) + mxb->i2c_adapter.class = I2C_CLASS_TV_ANALOG; +#endif snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num); saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); - if(i2c_add_adapter(&mxb->i2c_adapter) < 0) { + if (i2c_add_adapter(&mxb->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); kfree(mxb); return -EFAULT; } - /* loop through all i2c-devices on the bus and look who is there */ - device_for_each_child(&mxb->i2c_adapter.dev, mxb, mxb_check_clients); + mxb->saa7111a = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "saa7115", "saa7111", I2C_SAA7111A); + mxb->tea6420_1 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6420", "tea6420", I2C_TEA6420_1); + mxb->tea6420_2 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6420", "tea6420", I2C_TEA6420_2); + mxb->tea6415c = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6415c", "tea6415c", I2C_TEA6415C); + mxb->tda9840 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tda9840", "tda9840", I2C_TDA9840); + mxb->tuner = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tuner", "tuner", I2C_TUNER); + if (v4l2_i2c_new_subdev(&mxb->i2c_adapter, "saa5246a", "saa5246a", I2C_SAA5246A)) { + printk(KERN_INFO "mxb: found teletext decoder\n"); + } /* check if all devices are present */ if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c || @@ -296,47 +269,45 @@ static int mxb_init_done(struct saa7146_dev* dev) struct v4l2_routing route; int i = 0, err = 0; - struct tea6415c_multiplex vm; /* select video mode in saa7111a */ - mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_S_STD, &std); + saa7111a_call(mxb, tuner, s_std, std); /* select tuner-output on saa7111a */ i = 0; route.input = SAA7115_COMPOSITE0; route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS; - mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route); + saa7111a_call(mxb, video, s_routing, &route); /* select a tuner type */ tun_setup.mode_mask = T_ANALOG_TV; tun_setup.addr = ADDR_UNSET; tun_setup.type = TUNER_PHILIPS_PAL; - mxb->tuner->driver->command(mxb->tuner, TUNER_SET_TYPE_ADDR, &tun_setup); + tuner_call(mxb, tuner, s_type_addr, &tun_setup); /* tune in some frequency on tuner */ mxb->cur_freq.tuner = 0; mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV; mxb->cur_freq.frequency = freq; - mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, - &mxb->cur_freq); + tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq); /* set a default video standard */ - mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); + tuner_call(mxb, tuner, s_std, std); /* mute audio on tea6420s */ - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[6][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[6][1]); - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[6][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[6][1]); + tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]); + tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]); + tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]); + tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]); - /* switch to tuner-channel on tea6415c*/ - vm.out = 17; - vm.in = 3; - mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm); + /* switch to tuner-channel on tea6415c */ + route.input = 3; + route.output = 17; + tea6415c_call(mxb, video, s_routing, &route); - /* select tuner-output on multicable on tea6415c*/ - vm.in = 3; - vm.out = 13; - mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm); + /* select tuner-output on multicable on tea6415c */ + route.input = 3; + route.output = 13; + tea6415c_call(mxb, video, s_routing, &route); /* the rest for mxb */ mxb->cur_input = 0; @@ -462,14 +433,14 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc) mxb->cur_mute = vc->value; if (!vc->value) { /* switch the audio-source */ - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, + tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[video_audio_connect[mxb->cur_input]][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, + tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[video_audio_connect[mxb->cur_input]][1]); } else { - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, + tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, + tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]); } DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value)); @@ -500,7 +471,6 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct mxb *mxb = (struct mxb *)dev->ext_priv; - struct tea6415c_multiplex vm; struct v4l2_routing route; int i = 0; @@ -519,16 +489,16 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) switch (input) { case TUNER: i = SAA7115_COMPOSITE0; - vm.in = 3; - vm.out = 17; + route.input = 3; + route.output = 17; - if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { + if (tea6415c_call(mxb, video, s_routing, &route)) { printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n"); return -EFAULT; } /* connect tuner-output always to multicable */ - vm.in = 3; - vm.out = 13; + route.input = 3; + route.output = 13; break; case AUX3_YC: /* nothing to be done here. aux3_yc is @@ -542,8 +512,8 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) break; case AUX1: i = SAA7115_COMPOSITE0; - vm.in = 1; - vm.out = 17; + route.input = 1; + route.output = 17; break; } @@ -551,7 +521,7 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) switch (input) { case TUNER: case AUX1: - if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) { + if (tea6415c_call(mxb, video, s_routing, &route)) { printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n"); return -EFAULT; } @@ -563,14 +533,14 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) /* switch video in saa7111a */ route.input = i; route.output = 0; - if (mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route)) + if (saa7111a_call(mxb, video, s_routing, &route)) printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a #1.\n"); /* switch the audio-source only if necessary */ if (0 == mxb->cur_mute) { - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, + tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[video_audio_connect[input]][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, + tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[video_audio_connect[input]][1]); } @@ -590,14 +560,12 @@ static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t) DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); memset(t, 0, sizeof(*t)); - i2c_clients_command(&mxb->i2c_adapter, VIDIOC_G_TUNER, t); - strlcpy(t->name, "TV Tuner", sizeof(t->name)); t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; t->audmode = mxb->cur_mode; - return 0; + return call_all(dev, tuner, g_tuner, t); } static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t) @@ -611,8 +579,7 @@ static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t) } mxb->cur_mode = t->audmode; - i2c_clients_command(&mxb->i2c_adapter, VIDIOC_S_TUNER, t); - return 0; + return call_all(dev, tuner, s_tuner, t); } static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f) @@ -653,7 +620,7 @@ static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency)); /* tune in desired frequency */ - mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, &mxb->cur_freq); + tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq); /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */ spin_lock(&dev->slock); @@ -688,19 +655,15 @@ static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; - struct mxb *mxb = (struct mxb *)dev->ext_priv; - i2c_clients_command(&mxb->i2c_adapter, VIDIOC_DBG_G_REGISTER, reg); - return 0; + return call_all(dev, core, g_register, reg); } static int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; - struct mxb *mxb = (struct mxb *)dev->ext_priv; - i2c_clients_command(&mxb->i2c_adapter, VIDIOC_DBG_S_REGISTER, reg); - return 0; + return call_all(dev, core, s_register, reg); } #endif @@ -721,8 +684,8 @@ static long vidioc_default(struct file *file, void *fh, int cmd, void *arg) DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n", i)); - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[i][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[i][1]); + tea6420_1_call(mxb, audio, s_routing, &TEA6420_cd[i][0]); + tea6420_2_call(mxb, audio, s_routing, &TEA6420_cd[i][1]); return 0; } @@ -736,8 +699,8 @@ static long vidioc_default(struct file *file, void *fh, int cmd, void *arg) } DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n", i)); - mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[i][0]); - mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[i][1]); + tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[i][0]); + tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[i][1]); return 0; } @@ -792,13 +755,6 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data } } - i2c_use_client(mxb->tea6420_1); - i2c_use_client(mxb->tea6420_2); - i2c_use_client(mxb->tea6415c); - i2c_use_client(mxb->tda9840); - i2c_use_client(mxb->saa7111a); - i2c_use_client(mxb->tuner); - printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num); mxb_num++; @@ -812,13 +768,6 @@ static int mxb_detach(struct saa7146_dev *dev) DEB_EE(("dev:%p\n", dev)); - i2c_release_client(mxb->tea6420_1); - i2c_release_client(mxb->tea6420_2); - i2c_release_client(mxb->tea6415c); - i2c_release_client(mxb->tda9840); - i2c_release_client(mxb->saa7111a); - i2c_release_client(mxb->tuner); - saa7146_unregister_device(&mxb->video_dev,dev); if (MXB_BOARD_CAN_DO_VBI(dev)) saa7146_unregister_device(&mxb->vbi_dev, dev); @@ -835,8 +784,6 @@ static int mxb_detach(struct saa7146_dev *dev) static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard) { struct mxb *mxb = (struct mxb *)dev->ext_priv; - int zero = 0; - int one = 1; if (V4L2_STD_PAL_I == standard->id) { v4l2_std_id std = V4L2_STD_PAL_I; @@ -845,8 +792,8 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* unset the 7111 gpio register -- I don't know what this does exactly */ - mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &zero); - mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); + saa7111a_call(mxb, core, s_gpio, 0); + tuner_call(mxb, tuner, s_std, std); } else { v4l2_std_id std = V4L2_STD_PAL_BG; @@ -854,8 +801,8 @@ static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standa /* set the 7146 gpio register -- I don't know what this does exactly */ saa7146_write(dev, GPIO_CTRL, 0x00404050); /* set the 7111 gpio register -- I don't know what this does exactly */ - mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &one); - mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std); + saa7111a_call(mxb, core, s_gpio, 1); + tuner_call(mxb, tuner, s_std, std); } return 0; } diff --git a/linux/drivers/media/video/saa5246a.c b/linux/drivers/media/video/saa5246a.c index be23b5bd5..d7faf20bc 100644 --- a/linux/drivers/media/video/saa5246a.c +++ b/linux/drivers/media/video/saa5246a.c @@ -46,10 +46,11 @@ #include #include #include -#include -#include +#include +#include +#include #include -#include +#include #include "compat.h" MODULE_AUTHOR("Michael Geng "); @@ -386,16 +387,27 @@ MODULE_LICENSE("GPL"); #define MINUTE_MAX 0x59 #define PAGE_MAX 0x8FF +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +static unsigned short normal_i2c[] = { 0x11, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; +#endif struct saa5246a_device { + struct v4l2_subdev sd; + struct video_device *vdev; u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; int is_searching[NUM_DAUS]; - struct i2c_client *client; unsigned long in_use; struct mutex lock; }; +static inline struct saa5246a_device *to_dev(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa5246a_device, sd); +} + static struct video_device saa_template; /* Declared near bottom */ /* @@ -404,12 +416,13 @@ static struct video_device saa_template; /* Declared near bottom */ static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data) { + struct i2c_client *client = v4l2_get_subdevdata(&t->sd); char buf[64]; buf[0] = reg; memcpy(buf+1, data, count); - if(i2c_master_send(t->client, buf, count+1)==count+1) + if (i2c_master_send(client, buf, count + 1) == count + 1) return 0; return -1; } @@ -437,7 +450,9 @@ static int i2c_senddata(struct saa5246a_device *t, ...) */ static int i2c_getdata(struct saa5246a_device *t, int count, u8 *buf) { - if(i2c_master_recv(t->client, buf, count)!=count) + struct i2c_client *client = v4l2_get_subdevdata(&t->sd); + + if (i2c_master_recv(client, buf, count) != count) return -1; return 0; } @@ -962,9 +977,6 @@ static int saa5246a_open(struct file *file) { struct saa5246a_device *t = video_drvdata(file); - if (t->client == NULL) - return -ENODEV; - if (test_and_set_bit(0, &t->in_use)) return -EBUSY; @@ -1034,18 +1046,29 @@ static struct video_device saa_template = .minor = -1, }; -/* Addresses to scan */ -static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; +static int saa5246a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA5246A, 0); +} + +static const struct v4l2_subdev_core_ops saa5246a_core_ops = { + .g_chip_ident = saa5246a_g_chip_ident, +}; + +static const struct v4l2_subdev_ops saa5246a_ops = { + .core = &saa5246a_core_ops, +}; -I2C_CLIENT_INSMOD; static int saa5246a_probe(struct i2c_client *client, const struct i2c_device_id *id) { int pgbuf; int err; - struct video_device *vd; struct saa5246a_device *t; + struct v4l2_subdev *sd; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); @@ -1054,40 +1077,43 @@ static int saa5246a_probe(struct i2c_client *client, t = kzalloc(sizeof(*t), GFP_KERNEL); if (t == NULL) return -ENOMEM; + sd = &t->sd; + v4l2_i2c_subdev_init(sd, client, &saa5246a_ops); mutex_init(&t->lock); /* Now create a video4linux device */ - vd = video_device_alloc(); - if (vd == NULL) { + t->vdev = video_device_alloc(); + if (t->vdev == NULL) { kfree(t); return -ENOMEM; } - i2c_set_clientdata(client, vd); - memcpy(vd, &saa_template, sizeof(*vd)); + memcpy(t->vdev, &saa_template, sizeof(*t->vdev)); for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); t->is_searching[pgbuf] = false; } - video_set_drvdata(vd, t); + video_set_drvdata(t->vdev, t); /* Register it */ - err = video_register_device(vd, VFL_TYPE_VTX, -1); + err = video_register_device(t->vdev, VFL_TYPE_VTX, -1); if (err < 0) { kfree(t); - video_device_release(vd); + video_device_release(t->vdev); + t->vdev = NULL; return err; } - t->client = client; return 0; } static int saa5246a_remove(struct i2c_client *client) { - struct video_device *vd = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct saa5246a_device *t = to_dev(sd); - video_unregister_device(vd); - kfree(video_get_drvdata(vd)); + video_unregister_device(t->vdev); + v4l2_device_unregister_subdev(sd); + kfree(t); return 0; } diff --git a/linux/drivers/media/video/saa5249.c b/linux/drivers/media/video/saa5249.c index eeb0edea4..12f48ebd3 100644 --- a/linux/drivers/media/video/saa5249.c +++ b/linux/drivers/media/video/saa5249.c @@ -50,16 +50,23 @@ #include #include #include -#include -#include +#include +#include +#include #include -#include +#include #include "compat.h" MODULE_AUTHOR("Michael Geng "); MODULE_DESCRIPTION("Philips SAA5249 Teletext decoder driver"); MODULE_LICENSE("GPL"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +static unsigned short normal_i2c[] = { 0x11, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; +#endif + #define VTX_VER_MAJ 1 #define VTX_VER_MIN 8 @@ -96,17 +103,23 @@ typedef struct { struct saa5249_device { + struct v4l2_subdev sd; + struct video_device *vdev; vdau_t vdau[NUM_DAUS]; /* Data for virtual DAUs (the 5249 only has one */ /* real DAU, so we have to simulate some more) */ int vtx_use_count; int is_searching[NUM_DAUS]; int disp_mode; int virtual_mode; - struct i2c_client *client; unsigned long in_use; struct mutex lock; }; +static inline struct saa5249_device *to_dev(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa5249_device, sd); +} + #define CCTWR 34 /* I²C write/read-address of vtx-chip */ #define CCTRD 35 @@ -148,12 +161,13 @@ static void jdelay(unsigned long delay) static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data) { + struct i2c_client *client = v4l2_get_subdevdata(&t->sd); char buf[64]; buf[0] = reg; memcpy(buf+1, data, count); - if (i2c_master_send(t->client, buf, count + 1) == count + 1) + if (i2c_master_send(client, buf, count + 1) == count + 1) return 0; return -1; } @@ -181,7 +195,9 @@ static int i2c_senddata(struct saa5249_device *t, ...) static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf) { - if(i2c_master_recv(t->client, buf, count)!=count) + struct i2c_client *client = v4l2_get_subdevdata(&t->sd); + + if (i2c_master_recv(client, buf, count) != count) return -1; return 0; } @@ -498,9 +514,6 @@ static int saa5249_open(struct file *file) struct saa5249_device *t = video_drvdata(file); int pgbuf; - if (t->client == NULL) - return -ENODEV; - if (test_and_set_bit(0, &t->in_use)) return -EBUSY; @@ -554,18 +567,28 @@ static struct video_device saa_template = .release = video_device_release, }; -/* Addresses to scan */ -static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; +static int saa5249_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); -I2C_CLIENT_INSMOD; + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA5249, 0); +} + +static const struct v4l2_subdev_core_ops saa5249_core_ops = { + .g_chip_ident = saa5249_g_chip_ident, +}; + +static const struct v4l2_subdev_ops saa5249_ops = { + .core = &saa5249_core_ops, +}; static int saa5249_probe(struct i2c_client *client, const struct i2c_device_id *id) { int pgbuf; int err; - struct video_device *vd; struct saa5249_device *t; + struct v4l2_subdev *sd; v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); @@ -574,16 +597,17 @@ static int saa5249_probe(struct i2c_client *client, t = kzalloc(sizeof(*t), GFP_KERNEL); if (t == NULL) return -ENOMEM; + sd = &t->sd; + v4l2_i2c_subdev_init(sd, client, &saa5249_ops); mutex_init(&t->lock); /* Now create a video4linux device */ - vd = kmalloc(sizeof(struct video_device), GFP_KERNEL); - if (vd == NULL) { + t->vdev = video_device_alloc(); + if (t->vdev == NULL) { kfree(client); return -ENOMEM; } - i2c_set_clientdata(client, vd); - memcpy(vd, &saa_template, sizeof(*vd)); + memcpy(t->vdev, &saa_template, sizeof(*t->vdev)); for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) { memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf)); @@ -594,26 +618,27 @@ static int saa5249_probe(struct i2c_client *client, t->vdau[pgbuf].stopped = true; t->is_searching[pgbuf] = false; } - video_set_drvdata(vd, t); + video_set_drvdata(t->vdev, t); /* Register it */ - err = video_register_device(vd, VFL_TYPE_VTX, -1); + err = video_register_device(t->vdev, VFL_TYPE_VTX, -1); if (err < 0) { kfree(t); - kfree(vd); + video_device_release(t->vdev); + t->vdev = NULL; return err; } - t->client = client; return 0; } static int saa5249_remove(struct i2c_client *client) { - struct video_device *vd = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct saa5249_device *t = to_dev(sd); - video_unregister_device(vd); - kfree(video_get_drvdata(vd)); - kfree(vd); + video_unregister_device(t->vdev); + v4l2_device_unregister_subdev(sd); + kfree(t); return 0; } diff --git a/linux/drivers/media/video/tda9840.c b/linux/drivers/media/video/tda9840.c index d2178ad78..f6d27d581 100644 --- a/linux/drivers/media/video/tda9840.c +++ b/linux/drivers/media/video/tda9840.c @@ -30,8 +30,8 @@ #include #include #include -#include -#include "tda9840.h" +#include +#include #include "compat.h" MODULE_AUTHOR("Michael Hunold "); @@ -57,11 +57,11 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define TDA9840_SET_BOTH_R 0x16 #define TDA9840_SET_EXTERNAL 0x7a -/* addresses to scan, found only at 0x42 (7-Bit) */ -static unsigned short normal_i2c[] = { I2C_ADDR_TDA9840, I2C_CLIENT_END }; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +static unsigned short normal_i2c[] = { 0x42, I2C_CLIENT_END }; -/* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; +#endif static void tda9840_write(struct v4l2_subdev *sd, u8 reg, u8 val) { @@ -138,60 +138,17 @@ static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t) return 0; } -static long tda9840_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) +static int tda9840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { - int byte; - - switch (cmd) { - case TDA9840_LEVEL_ADJUST: - byte = *(int *)arg; - v4l2_dbg(1, debug, sd, "TDA9840_LEVEL_ADJUST: %d\n", byte); - - /* check for correct range */ - if (byte > 25 || byte < -20) - return -EINVAL; - - /* calculate actual value to set, see specs, page 18 */ - byte /= 5; - if (0 < byte) - byte += 0x8; - else - byte = -byte; - tda9840_write(sd, LEVEL_ADJUST, byte); - break; - - case TDA9840_STEREO_ADJUST: - byte = *(int *)arg; - v4l2_dbg(1, debug, sd, "TDA9840_STEREO_ADJUST: %d\n", byte); - - /* check for correct range */ - if (byte > 25 || byte < -24) - return -EINVAL; - - /* calculate actual value to set */ - byte /= 5; - if (0 < byte) - byte += 0x20; - else - byte = -byte; - - tda9840_write(sd, STEREO_ADJUST, byte); - break; - default: - return -ENOIOCTLCMD; - } - return 0; -} + struct i2c_client *client = v4l2_get_subdevdata(sd); -static int tda9840_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TDA9840, 0); } /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tda9840_core_ops = { - .ioctl = tda9840_ioctl, + .g_chip_ident = tda9840_g_chip_ident, }; static const struct v4l2_subdev_tuner_ops tda9840_tuner_ops = { @@ -210,8 +167,6 @@ static int tda9840_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct v4l2_subdev *sd; - int result; - int byte; /* let's see whether this adapter can support what we need */ if (!i2c_check_functionality(client->adapter, @@ -228,15 +183,9 @@ static int tda9840_probe(struct i2c_client *client, v4l2_i2c_subdev_init(sd, client, &tda9840_ops); /* set initial values for level & stereo - adjustment, mode */ - byte = 0; - result = tda9840_ioctl(sd, TDA9840_LEVEL_ADJUST, &byte); - result |= tda9840_ioctl(sd, TDA9840_STEREO_ADJUST, &byte); + tda9840_write(sd, LEVEL_ADJUST, 0); + tda9840_write(sd, STEREO_ADJUST, 0); tda9840_write(sd, SWITCH, TDA9840_SET_STEREO); - if (result) { - v4l2_dbg(1, debug, sd, "could not initialize tda9840\n"); - kfree(sd); - return -ENODEV; - } return 0; } @@ -249,12 +198,15 @@ static int tda9840_remove(struct i2c_client *client) return 0; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static int tda9840_legacy_probe(struct i2c_adapter *adapter) { /* Let's see whether this is a known adapter we can attach to. Prevents conflicts with tvaudio.c. */ return adapter->id == I2C_HW_SAA7146; } +#endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static const struct i2c_device_id tda9840_id[] = { { "tda9840", 0 }, @@ -265,10 +217,11 @@ MODULE_DEVICE_TABLE(i2c, tda9840_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tda9840", - .command = tda9840_command, .probe = tda9840_probe, .remove = tda9840_remove, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) .legacy_probe = tda9840_legacy_probe, +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = tda9840_id, #endif diff --git a/linux/drivers/media/video/tda9840.h b/linux/drivers/media/video/tda9840.h deleted file mode 100644 index dc12ae7ca..000000000 --- a/linux/drivers/media/video/tda9840.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __INCLUDED_TDA9840__ -#define __INCLUDED_TDA9840__ - -#define I2C_ADDR_TDA9840 0x42 - -/* values may range between +2.5 and -2.0; - the value has to be multiplied with 10 */ -#define TDA9840_LEVEL_ADJUST _IOW('v',3,int) - -/* values may range between +2.5 and -2.4; - the value has to be multiplied with 10 */ -#define TDA9840_STEREO_ADJUST _IOW('v',4,int) - -#endif diff --git a/linux/drivers/media/video/tea6415c.c b/linux/drivers/media/video/tea6415c.c index 2e57dd281..eaf29bd90 100644 --- a/linux/drivers/media/video/tea6415c.c +++ b/linux/drivers/media/video/tea6415c.c @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include #include "tea6415c.h" #include "compat.h" @@ -45,25 +46,27 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -/* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */ -static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END }; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +static unsigned short normal_i2c[] = { 0x03, 0x43, I2C_CLIENT_END }; -/* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; +#endif -/* makes a connection between the input-pin 'i' and the output-pin 'o' - for the tea6415c-client 'client' */ -static int switch_matrix(struct i2c_client *client, int i, int o) +/* makes a connection between the input-pin 'i' and the output-pin 'o' */ +static int tea6415c_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { + struct i2c_client *client = v4l2_get_subdevdata(sd); u8 byte = 0; + u32 i = route->input; + u32 o = route->output; int ret; - v4l_dbg(1, debug, client, "i=%d, o=%d\n", i, o); + v4l2_dbg(1, debug, sd, "i=%d, o=%d\n", i, o); /* check if the pins are valid */ if (0 == ((1 == i || 3 == i || 5 == i || 6 == i || 8 == i || 10 == i || 20 == i || 11 == i) && (18 == o || 17 == o || 16 == o || 15 == o || 14 == o || 13 == o))) - return -1; + return -EINVAL; /* to understand this, have a look at the tea6415c-specs (p.5) */ switch (o) { @@ -116,37 +119,33 @@ static int switch_matrix(struct i2c_client *client, int i, int o) ret = i2c_smbus_write_byte(client, byte); if (ret) { - v4l_dbg(1, debug, client, + v4l2_dbg(1, debug, sd, "i2c_smbus_write_byte() failed, ret:%d\n", ret); return -EIO; } return ret; } -static long tea6415c_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) +static int tea6415c_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { - if (cmd == TEA6415C_SWITCH) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct tea6415c_multiplex *v = (struct tea6415c_multiplex *)arg; + struct i2c_client *client = v4l2_get_subdevdata(sd); - return switch_matrix(client, v->in, v->out); - } - return -ENOIOCTLCMD; -} - -static int tea6415c_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEA6415C, 0); } /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tea6415c_core_ops = { - .ioctl = tea6415c_ioctl, + .g_chip_ident = tea6415c_g_chip_ident, +}; + +static const struct v4l2_subdev_video_ops tea6415c_video_ops = { + .s_routing = tea6415c_s_routing, }; static const struct v4l2_subdev_ops tea6415c_ops = { .core = &tea6415c_core_ops, + .video = &tea6415c_video_ops, }; /* this function is called by i2c_probe */ @@ -177,12 +176,14 @@ static int tea6415c_remove(struct i2c_client *client) return 0; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static int tea6415c_legacy_probe(struct i2c_adapter *adapter) { /* Let's see whether this is a known adapter we can attach to. Prevents conflicts with tvaudio.c. */ return adapter->id == I2C_HW_SAA7146; } +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static const struct i2c_device_id tea6415c_id[] = { @@ -194,10 +195,11 @@ MODULE_DEVICE_TABLE(i2c, tea6415c_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tea6415c", - .command = tea6415c_command, .probe = tea6415c_probe, .remove = tea6415c_remove, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) .legacy_probe = tea6415c_legacy_probe, +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = tea6415c_id, #endif diff --git a/linux/drivers/media/video/tea6415c.h b/linux/drivers/media/video/tea6415c.h index f84ed8005..3a47d6975 100644 --- a/linux/drivers/media/video/tea6415c.h +++ b/linux/drivers/media/video/tea6415c.h @@ -1,10 +1,6 @@ #ifndef __INCLUDED_TEA6415C__ #define __INCLUDED_TEA6415C__ -/* possible i2c-addresses */ -#define I2C_TEA6415C_1 0x03 -#define I2C_TEA6415C_2 0x43 - /* the tea6415c's design is quite brain-dead. although there are 8 inputs and 6 outputs, these aren't enumerated in any way. because I don't want to say "connect input pin 20 to output pin 17", I define @@ -28,12 +24,4 @@ #define TEA6415C_INPUT7 1 #define TEA6415C_INPUT8 11 -struct tea6415c_multiplex -{ - int in; /* input-pin */ - int out; /* output-pin */ -}; - -#define TEA6415C_SWITCH _IOW('v',1,struct tea6415c_multiplex) - #endif diff --git a/linux/drivers/media/video/tea6420.c b/linux/drivers/media/video/tea6420.c index 023952ae7..8bddef6d9 100644 --- a/linux/drivers/media/video/tea6420.c +++ b/linux/drivers/media/video/tea6420.c @@ -32,7 +32,8 @@ #include #include #include -#include +#include +#include #include "tea6420.h" #include "compat.h" @@ -45,24 +46,28 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); -/* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */ -static unsigned short normal_i2c[] = { I2C_ADDR_TEA6420_1, I2C_ADDR_TEA6420_2, I2C_CLIENT_END }; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) +static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END }; -/* magic definition of all other variables and things */ I2C_CLIENT_INSMOD; +#endif /* make a connection between the input 'i' and the output 'o' - with gain 'g' for the tea6420-client 'client' (note: i = 6 means 'mute') */ -static int tea6420_switch(struct i2c_client *client, int i, int o, int g) + with gain 'g' (note: i = 6 means 'mute') */ +static int tea6420_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + int i = route->input; + int o = route->output & 0xf; + int g = (route->output >> 4) & 0xf; u8 byte; int ret; - v4l_dbg(1, debug, client, "i=%d, o=%d, g=%d\n", i, o, g); + v4l2_dbg(1, debug, sd, "i=%d, o=%d, g=%d\n", i, o, g); /* check if the parameters are valid */ if (i < 1 || i > 6 || o < 1 || o > 4 || g < 0 || g > 6 || g % 2 != 0) - return -1; + return -EINVAL; byte = ((o - 1) << 5); byte |= (i - 1); @@ -84,37 +89,33 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g) ret = i2c_smbus_write_byte(client, byte); if (ret) { - v4l_dbg(1, debug, client, + v4l2_dbg(1, debug, sd, "i2c_smbus_write_byte() failed, ret:%d\n", ret); return -EIO; } return 0; } -static long tea6420_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg) +static int tea6420_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { - if (cmd == TEA6420_SWITCH) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct tea6420_multiplex *a = (struct tea6420_multiplex *)arg; + struct i2c_client *client = v4l2_get_subdevdata(sd); - return tea6420_switch(client, a->in, a->out, a->gain); - } - return -ENOIOCTLCMD; -} - -static int tea6420_command(struct i2c_client *client, unsigned cmd, void *arg) -{ - return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEA6420, 0); } /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops tea6420_core_ops = { - .ioctl = tea6420_ioctl, + .g_chip_ident = tea6420_g_chip_ident, +}; + +static const struct v4l2_subdev_audio_ops tea6420_audio_ops = { + .s_routing = tea6420_s_routing, }; static const struct v4l2_subdev_ops tea6420_ops = { .core = &tea6420_core_ops, + .audio = &tea6420_audio_ops, }; /* this function is called by i2c_probe */ @@ -131,20 +132,24 @@ static int tea6420_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); + sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + if (sd == NULL) + return -ENOMEM; + v4l2_i2c_subdev_init(sd, client, &tea6420_ops); + /* set initial values: set "mute"-input to all outputs at gain 0 */ err = 0; for (i = 1; i < 5; i++) { - err += tea6420_switch(client, 6, i, 0); + struct v4l2_routing route; + + route.input = 6; + route.output = i; + err += tea6420_s_routing(sd, &route); } if (err) { v4l_dbg(1, debug, client, "could not initialize tea6420\n"); return -ENODEV; } - - sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); - if (sd == NULL) - return -ENOMEM; - v4l2_i2c_subdev_init(sd, client, &tea6420_ops); return 0; } @@ -157,12 +162,14 @@ static int tea6420_remove(struct i2c_client *client) return 0; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) static int tea6420_legacy_probe(struct i2c_adapter *adapter) { /* Let's see whether this is a known adapter we can attach to. Prevents conflicts with tvaudio.c. */ return adapter->id == I2C_HW_SAA7146; } +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) static const struct i2c_device_id tea6420_id[] = { @@ -174,10 +181,11 @@ MODULE_DEVICE_TABLE(i2c, tea6420_id); static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "tea6420", - .command = tea6420_command, .probe = tea6420_probe, .remove = tea6420_remove, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) .legacy_probe = tea6420_legacy_probe, +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = tea6420_id, #endif diff --git a/linux/drivers/media/video/tea6420.h b/linux/drivers/media/video/tea6420.h index 5ef7c18e0..4aa3edb3e 100644 --- a/linux/drivers/media/video/tea6420.h +++ b/linux/drivers/media/video/tea6420.h @@ -1,17 +1,24 @@ #ifndef __INCLUDED_TEA6420__ #define __INCLUDED_TEA6420__ -/* possible addresses */ -#define I2C_ADDR_TEA6420_1 0x4c -#define I2C_ADDR_TEA6420_2 0x4d +/* input pins */ +#define TEA6420_OUTPUT1 1 +#define TEA6420_OUTPUT2 2 +#define TEA6420_OUTPUT3 3 +#define TEA6420_OUTPUT4 4 -struct tea6420_multiplex -{ - int in; /* input of audio switch */ - int out; /* output of audio switch */ - int gain; /* gain of connection */ -}; +/* output pins */ +#define TEA6420_INPUT1 1 +#define TEA6420_INPUT2 2 +#define TEA6420_INPUT3 3 +#define TEA6420_INPUT4 4 +#define TEA6420_INPUT5 5 +#define TEA6420_INPUT6 6 -#define TEA6420_SWITCH _IOW('v',1,struct tea6420_multiplex) +/* gain on the output pins, ORed with the output pin */ +#define TEA6420_GAIN0 0x00 +#define TEA6420_GAIN2 0x20 +#define TEA6420_GAIN4 0x40 +#define TEA6420_GAIN6 0x60 #endif diff --git a/linux/include/media/v4l2-chip-ident.h b/linux/include/media/v4l2-chip-ident.h index 9aaf652b2..4e2182e52 100644 --- a/linux/include/media/v4l2-chip-ident.h +++ b/linux/include/media/v4l2-chip-ident.h @@ -63,6 +63,9 @@ enum { V4L2_IDENT_OV7720 = 251, V4L2_IDENT_OV7725 = 252, + /* module saa7146: reserved range 300-309 */ + V4L2_IDENT_SAA7146 = 300, + /* Conexant MPEG encoder/decoders: reserved range 410-420 */ V4L2_IDENT_CX23415 = 415, V4L2_IDENT_CX23416 = 416, @@ -74,9 +77,21 @@ enum { /* module tvp5150 */ V4L2_IDENT_TVP5150 = 5150, + /* module saa5246a: just ident 5246 */ + V4L2_IDENT_SAA5246A = 5246, + + /* module saa5249: just ident 5249 */ + V4L2_IDENT_SAA5249 = 5249, + /* module cs5345: just ident 5345 */ V4L2_IDENT_CS5345 = 5345, + /* module tea6415c: just ident 6415 */ + V4L2_IDENT_TEA6415C = 6415, + + /* module tea6420: just ident 6420 */ + V4L2_IDENT_TEA6420 = 6420, + /* module saa6752hs: reserved range 6750-6759 */ V4L2_IDENT_SAA6752HS = 6752, V4L2_IDENT_SAA6752HS_AC3 = 6753, @@ -87,6 +102,9 @@ enum { /* module wm8775: just ident 8775 */ V4L2_IDENT_WM8775 = 8775, + /* module tda9840: just ident 9840 */ + V4L2_IDENT_TDA9840 = 9840, + /* module tw9910: just ident 9910 */ V4L2_IDENT_TW9910 = 9910, -- cgit v1.2.3 From 7a1cf2bbfb14fef2c4debf9f474cd0ed65a7c65e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 7 Feb 2009 15:25:05 +0100 Subject: saa7146: setting control while capturing should return EBUSY, not EINVAL. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/common/saa7146_video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/common/saa7146_video.c b/linux/drivers/media/common/saa7146_video.c index 6536853c1..240757afb 100644 --- a/linux/drivers/media/common/saa7146_video.c +++ b/linux/drivers/media/common/saa7146_video.c @@ -698,7 +698,7 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D(("V4L2_CID_HFLIP while active capture.\n")); mutex_unlock(&dev->lock); - return -EINVAL; + return -EBUSY; } vv->hflip = c->value; break; @@ -706,7 +706,7 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) if (IS_CAPTURE_ACTIVE(fh) != 0) { DEB_D(("V4L2_CID_VFLIP while active capture.\n")); mutex_unlock(&dev->lock); - return -EINVAL; + return -EBUSY; } vv->vflip = c->value; break; -- cgit v1.2.3 From 7c101a67fb72f74c1a2af5e2ab8e206a5fd9f5ff Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 8 Feb 2009 00:15:22 +0100 Subject: saa7146: prevent unnecessary loading of v4l2-common. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/common/saa7146_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/common/saa7146_video.c b/linux/drivers/media/common/saa7146_video.c index 240757afb..b7d73b7fd 100644 --- a/linux/drivers/media/common/saa7146_video.c +++ b/linux/drivers/media/common/saa7146_video.c @@ -1125,7 +1125,7 @@ static int vidioc_g_chip_ident(struct file *file, void *__fh, chip->ident = V4L2_IDENT_NONE; chip->revision = 0; - if (v4l2_chip_match_host(&chip->match)) { + if (chip->match.type == V4L2_CHIP_MATCH_HOST && !chip->match.addr) { chip->ident = V4L2_IDENT_SAA7146; return 0; } -- cgit v1.2.3 From b857ad615158d8e49953055fb34cd55050d5ebf2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 8 Feb 2009 00:42:33 +0100 Subject: saa7146: move v4l2 device registration to saa7146_vv. From: Hans Verkuil Doing the v4l2_device registration in the saa7146 core will make it dependent on v4l2, even for DVB-only boards. This registration and unregistration belongs in saa7146_vv instead. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/common/saa7146_core.c | 14 +++++++------- linux/drivers/media/common/saa7146_fops.c | 11 +++++++++-- 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/common/saa7146_core.c b/linux/drivers/media/common/saa7146_core.c index 067a1f282..dfb4915a8 100644 --- a/linux/drivers/media/common/saa7146_core.c +++ b/linux/drivers/media/common/saa7146_core.c @@ -367,16 +367,13 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent ERR(("out of memory.\n")); goto out; } - err = v4l2_device_register(&pci->dev, &dev->v4l2_dev); - if (err) - goto err_free; DEB_EE(("pci:%p\n",pci)); err = pci_enable_device(pci); if (err < 0) { ERR(("pci_enable_device() failed.\n")); - goto err_unreg; + goto err_free; } /* enable bus-mastering */ @@ -484,6 +481,10 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent DEB_D(("ext->attach() failed for %p. skipping device.\n",dev)); goto err_free_i2c; } + /* V4L extensions will set the pci drvdata to the v4l2_device in the + attach() above. So for those cards that do not use V4L we have to + set it explicitly. */ + pci_set_drvdata(pci, &dev->v4l2_dev); INIT_LIST_HEAD(&dev->item); list_add_tail(&dev->item,&saa7146_devices); @@ -510,8 +511,6 @@ err_release: pci_release_region(pci, 0); err_disable: pci_disable_device(pci); -err_unreg: - v4l2_device_unregister(&dev->v4l2_dev); err_free: kfree(dev); goto out; @@ -534,7 +533,8 @@ static void saa7146_remove_one(struct pci_dev *pdev) DEB_EE(("dev:%p\n",dev)); dev->ext->detach(dev); - v4l2_device_unregister(&dev->v4l2_dev); + /* Zero the PCI drvdata after use. */ + pci_set_drvdata(pdev, NULL); /* shut down all video dma transfers */ saa7146_write(dev, MC1, 0x00ff0000); diff --git a/linux/drivers/media/common/saa7146_fops.c b/linux/drivers/media/common/saa7146_fops.c index c6cc8574a..90e1d1ebb 100644 --- a/linux/drivers/media/common/saa7146_fops.c +++ b/linux/drivers/media/common/saa7146_fops.c @@ -447,11 +447,17 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status) int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) { - struct saa7146_vv *vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL); + struct saa7146_vv *vv; + int err; + + err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev); + if (err) + return err; + vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL); if (vv == NULL) { ERR(("out of memory. aborting.\n")); - return -1; + return -ENOMEM; } ext_vv->ops = saa7146_video_ioctl_ops; ext_vv->core_ops = &saa7146_video_ioctl_ops; @@ -497,6 +503,7 @@ int saa7146_vv_release(struct saa7146_dev* dev) DEB_EE(("dev:%p\n",dev)); + v4l2_device_unregister(&dev->v4l2_dev); pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle); kfree(vv); dev->vv_data = NULL; -- cgit v1.2.3 From 2f8e6c790e74ada20db6965056476d944041fdfa Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 8 Feb 2009 11:45:34 -0200 Subject: em28xx: remove bad check (changeset a31c595188af) From: Douglas Schilling Landgraf Removed bad check. Thanks to Robert Krakora to report that. Priority: high Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-audio.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index fcf21a614..ebbc64b3a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -62,7 +62,7 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) int i; dprintk("Stopping isoc\n"); - for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { + for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { if (!irqs_disabled()) usb_kill_urb(dev->adev.urb[i]); else @@ -74,7 +74,6 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) dev->adev.transfer_buffer[i] = NULL; } - dev->isoc_ctl.num_bufs = 0; return 0; } @@ -179,8 +178,6 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) dprintk("Starting isoc transfers\n"); - dev->isoc_ctl.num_bufs = 0; - for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { struct urb *urb; int j, k; @@ -222,19 +219,10 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); if (errCode) { - if (dev->isoc_ctl.num_bufs == 0) { - usb_free_urb(dev->adev.urb[i]); - dev->adev.urb[i] = NULL; - kfree(dev->adev.transfer_buffer[i]); - dev->adev.transfer_buffer[i] = NULL; - } else - em28xx_isoc_audio_deinit(dev); + em28xx_isoc_audio_deinit(dev); return errCode; } - mutex_lock(&dev->lock); - dev->isoc_ctl.num_bufs++; - mutex_unlock(&dev->lock); } return 0; -- cgit v1.2.3 From 2bd11adc025f4c324d0eb2a9861bdf7589e3b74e Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 8 Feb 2009 14:09:11 -0200 Subject: em28xx: Fix for em28xx memory leak and function rename From: Robert Krakora Fix for em28xx memory leak and function rename Priority: high Signed-off-by: Robert Krakora Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-audio.c | 22 ++++++++++++++++++---- linux/drivers/media/video/em28xx/em28xx-core.c | 13 +++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index ebbc64b3a..8753398b0 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -57,7 +57,7 @@ MODULE_PARM_DESC(debug, "activates debug info"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static int em28xx_isoc_audio_deinit(struct em28xx *dev) +static int em28xx_deinit_isoc_audio(struct em28xx *dev) { int i; @@ -67,6 +67,7 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) usb_kill_urb(dev->adev.urb[i]); else usb_unlink_urb(dev->adev.urb[i]); + usb_free_urb(dev->adev.urb[i]); dev->adev.urb[i] = NULL; @@ -100,6 +101,20 @@ static void em28xx_audio_isocirq(struct urb *urb) struct snd_pcm_substream *substream; struct snd_pcm_runtime *runtime; #endif + + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* error */ + dprintk("urb completition error %d.\n", urb->status); + break; + } + if (dev->adev.capture_pcm_substream) { substream = dev->adev.capture_pcm_substream; runtime = substream->runtime; @@ -219,8 +234,7 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); if (errCode) { - em28xx_isoc_audio_deinit(dev); - + em28xx_deinit_isoc_audio(dev); return errCode; } } @@ -240,7 +254,7 @@ static int em28xx_cmd(struct em28xx *dev, int cmd, int arg) em28xx_init_audio_isoc(dev); } else if (dev->adev.capture_stream == STREAM_ON && arg == 0) { dev->adev.capture_stream = STREAM_OFF; - em28xx_isoc_audio_deinit(dev); + em28xx_deinit_isoc_audio(dev); } else { printk(KERN_ERR "An underrun very likely occurred. " "Ignoring it.\n"); diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 15d86bc97..743215ca9 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -836,6 +836,19 @@ static void em28xx_irq_callback(struct urb *urb) struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); int rc, i; + switch (urb->status) { + case 0: /* success */ + case -ETIMEDOUT: /* NAK */ + break; + case -ECONNRESET: /* kill */ + case -ENOENT: + case -ESHUTDOWN: + return; + default: /* error */ + em28xx_isocdbg("urb completition error %d.\n", urb->status); + break; + } + /* Copy data from URB */ spin_lock(&dev->slock); rc = dev->isoc_ctl.isoc_copy(dev, urb); -- cgit v1.2.3 From 96f4a3677c2e17fe91f9956779fad977ec6a8f8c Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 8 Feb 2009 14:10:39 -0200 Subject: em28xx: Fix for em28xx audio startup From: Robert Krakora Essentially if a snd_em28xx_capture_trigger() stop followed by a snd_em28xx_capture_trigger() start would not yield any data because there was some logic put in with an adev->shutdown variable which did not seem warranted in my humble opinion. It would cause snd_em28xx_capture_trigger start never to start up the audio stream until the device was closed and reopened again. Upon re-opening the device adev->shutdown is reset and audio data would again flow. Priority: high Signed-off-by: Robert Krakora Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-audio.c | 12 +----------- linux/drivers/media/video/em28xx/em28xx.h | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index 8753398b0..921ec190d 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -174,9 +174,6 @@ static void em28xx_audio_isocirq(struct urb *urb) } urb->status = 0; - if (dev->adev.shutdown) - return; - status = usb_submit_urb(urb, GFP_ATOMIC); if (status < 0) { em28xx_errdev("resubmit of audio urb failed (error=%i)\n", @@ -387,13 +384,6 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) em28xx_audio_analog_set(dev); mutex_unlock(&dev->lock); - if (dev->adev.users == 0 && dev->adev.shutdown == 1) { - dprintk("audio users: %d\n", dev->adev.users); - dprintk("disabling audio stream!\n"); - dev->adev.shutdown = 0; - dprintk("released lock\n"); - em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); - } return 0; } @@ -463,7 +453,7 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1); return 0; case SNDRV_PCM_TRIGGER_STOP: - dev->adev.shutdown = 1; + em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); return 0; default: return -EINVAL; diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 1e2ffea54..f3d0d3184 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -430,7 +430,7 @@ struct em28xx_audio { struct snd_card *sndcard; #endif - int users, shutdown; + int users; enum em28xx_stream_state capture_stream; spinlock_t slock; }; -- cgit v1.2.3 From c06f528a6de5324f104965c8a90907211963e29e Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 8 Feb 2009 15:17:15 -0200 Subject: em28xx-audio: Add spinlock for trigger From: Douglas Schilling Landgraf Added spinlock for trigger session Priority: high Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-audio.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index 921ec190d..a5a28eb19 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -445,19 +445,27 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, #endif { struct em28xx *dev = snd_pcm_substream_chip(substream); + int retval; dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START)? "start": "stop"); + + spin_lock(&dev->adev.slock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1); - return 0; + retval = 0; + break; case SNDRV_PCM_TRIGGER_STOP: em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); - return 0; + retval = 0; + break; default: - return -EINVAL; + retval = -EINVAL; } + + spin_unlock(&dev->adev.slock); + return retval; } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -- cgit v1.2.3 From 88f9e29eb77d77129e59b899af1ef9e462997409 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 8 Feb 2009 02:11:13 -0200 Subject: em28xx-audio: Add lock for users From: Douglas Schilling Landgraf Added lock for users count Priority: high Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-audio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index a5a28eb19..5102ff75f 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -356,7 +356,9 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) dprintk("changing alternate number to 7\n"); } + mutex_lock(&dev->lock); dev->adev.users++; + mutex_unlock(&dev->lock); snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); dev->adev.capture_pcm_substream = substream; @@ -375,12 +377,12 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) #endif { struct em28xx *dev = snd_pcm_substream_chip(substream); - dev->adev.users--; dprintk("closing device\n"); dev->mute = 1; mutex_lock(&dev->lock); + dev->adev.users--; em28xx_audio_analog_set(dev); mutex_unlock(&dev->lock); -- cgit v1.2.3 From a24b83e8ea0f14b0f879c03a8d9547b6cb06e7e4 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 8 Feb 2009 02:16:32 -0200 Subject: em28xx-audio: replace printk with em28xx_errdev From: Alexey Klimov Patch removes printk and place em28xx_errdev macros to provide information about driver name to dmesg. Priority: normal Signed-off-by: Alexey Klimov Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index 5102ff75f..1d665ba27 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -253,7 +253,7 @@ static int em28xx_cmd(struct em28xx *dev, int cmd, int arg) dev->adev.capture_stream = STREAM_OFF; em28xx_deinit_isoc_audio(dev); } else { - printk(KERN_ERR "An underrun very likely occurred. " + em28xx_errdev("An underrun very likely occurred. " "Ignoring it.\n"); } return 0; -- cgit v1.2.3 From 46b15827cbd9a9297b369049585c78e6e685aacd Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Sun, 8 Feb 2009 02:38:10 -0200 Subject: em28xx-audio: Add macros EM28XX_START_AUDIO / EM28XX_STOP_AUDIO From: Douglas Schilling Landgraf Added macros EM28XX_START_AUDIO and EM28XX_STOP_AUDIO for em28xx_cmd(). Priority: normal Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-audio.c | 10 +++++----- linux/drivers/media/video/em28xx/em28xx.h | 4 ++++ 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index 1d665ba27..e7dfebd7b 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -246,10 +246,10 @@ static int em28xx_cmd(struct em28xx *dev, int cmd, int arg) switch (cmd) { case EM28XX_CAPTURE_STREAM_EN: - if (dev->adev.capture_stream == STREAM_OFF && arg == 1) { + if (dev->adev.capture_stream == STREAM_OFF && arg == EM28XX_START_AUDIO) { dev->adev.capture_stream = STREAM_ON; em28xx_init_audio_isoc(dev); - } else if (dev->adev.capture_stream == STREAM_ON && arg == 0) { + } else if (dev->adev.capture_stream == STREAM_ON && arg == EM28XX_STOP_AUDIO) { dev->adev.capture_stream = STREAM_OFF; em28xx_deinit_isoc_audio(dev); } else { @@ -425,7 +425,7 @@ static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream) dprintk("Stop capture, if needed\n"); if (dev->adev.capture_stream == STREAM_ON) - em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); + em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, EM28XX_STOP_AUDIO); return 0; } @@ -455,11 +455,11 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, spin_lock(&dev->adev.slock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: - em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1); + em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, EM28XX_START_AUDIO); retval = 0; break; case SNDRV_PCM_TRIGGER_STOP: - em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0); + em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, EM28XX_STOP_AUDIO); retval = 0; break; default: diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index f3d0d3184..81e7292ae 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -112,6 +112,10 @@ #define EM28XX_BOARD_NOT_VALIDATED 1 #define EM28XX_BOARD_VALIDATED 0 +/* Params for em28xx_cmd() audio */ +#define EM28XX_START_AUDIO 1 +#define EM28XX_STOP_AUDIO 0 + /* maximum number of em28xx boards */ #define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */ -- cgit v1.2.3 From ca4755f6e3b59333a7d5df3b7808d785bfb006b1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 8 Feb 2009 09:34:43 -0200 Subject: tda827x: Be sure that gate will be open/closed at the proper time From: Mauro Carvalho Chehab The gate control logic is broken: several routines just keep it open; other rotines close it properly; there are even other routines that assumes that it is open without really checking or opening it. Instead of having to manually handle the gate control and having such troubles, let a sub-routine take care of the gate, opening it before i2c_transfer and closing it after that. This avoids leaving the gate into a random state. Priority: normal CC: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tda827x.c | 183 ++++++++++++++++------------ 1 file changed, 102 insertions(+), 81 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/common/tuners/tda827x.c b/linux/drivers/media/common/tuners/tda827x.c index a14fe817d..eb989c241 100644 --- a/linux/drivers/media/common/tuners/tda827x.c +++ b/linux/drivers/media/common/tuners/tda827x.c @@ -133,11 +133,31 @@ static const struct tda827x_data tda827x_table[] = { { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} }; +static int tuner_transfer(struct dvb_frontend *fe, + struct i2c_msg *msg, + const int size) +{ + int rc; + struct tda827x_priv *priv = fe->tuner_priv; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + rc = i2c_transfer(priv->i2c_adap, msg, size); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + if (rc >= 0 && rc != size) + return -EIO; + + return rc; +} + static int tda827xo_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct tda827x_priv *priv = fe->tuner_priv; u8 buf[14]; + int rc; struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, .buf = buf, .len = sizeof(buf) }; @@ -184,27 +204,29 @@ static int tda827xo_set_params(struct dvb_frontend *fe, buf[13] = 0x40; msg.len = 14; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { - printk("%s: could not write to tuner at addr: 0x%02x\n", - __func__, priv->i2c_addr << 1); - return -EIO; - } + rc = tuner_transfer(fe, &msg, 1); + if (rc < 0) + goto err; + msleep(500); /* correct CP value */ buf[0] = 0x30; buf[1] = 0x50 + tda827x_table[i].cp; msg.len = 2; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(priv->i2c_adap, &msg, 1); + rc = tuner_transfer(fe, &msg, 1); + if (rc < 0) + goto err; priv->frequency = params->frequency; priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; return 0; + +err: + printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n", + __func__, priv->i2c_addr << 1); + return rc; } static int tda827xo_sleep(struct dvb_frontend *fe) @@ -215,9 +237,7 @@ static int tda827xo_sleep(struct dvb_frontend *fe) .buf = buf, .len = sizeof(buf) }; dprintk("%s:\n", __func__); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); if (priv->cfg && priv->cfg->sleep) priv->cfg->sleep(fe); @@ -267,44 +287,44 @@ static int tda827xo_set_analog_params(struct dvb_frontend *fe, msg.buf = tuner_reg; msg.len = 8; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); msg.buf = reg2; msg.len = 2; reg2[0] = 0x80; reg2[1] = 0; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); reg2[0] = 0x60; reg2[1] = 0xbf; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); reg2[0] = 0x30; reg2[1] = tuner_reg[4] + 0x80; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); msleep(1); reg2[0] = 0x30; reg2[1] = tuner_reg[4] + 4; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); msleep(1); reg2[0] = 0x30; reg2[1] = tuner_reg[4]; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); msleep(550); reg2[0] = 0x30; reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); reg2[0] = 0x60; reg2[1] = 0x3f; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); reg2[0] = 0x80; reg2[1] = 0x08; /* Vsync en */ - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); priv->frequency = params->frequency; @@ -318,7 +338,7 @@ static void tda827xo_agcf(struct dvb_frontend *fe) struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, .buf = data, .len = 2}; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); } /* ------------------------------------------------------------------ */ @@ -399,13 +419,8 @@ static int tda827xa_sleep(struct dvb_frontend *fe) .buf = buf, .len = sizeof(buf) }; dprintk("%s:\n", __func__); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(priv->i2c_adap, &msg, 1); - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); + tuner_transfer(fe, &msg, 1); if (priv->cfg && priv->cfg->sleep) priv->cfg->sleep(fe); @@ -456,7 +471,7 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high, buf[1] = high ? 0 : 1; if (priv->cfg->config == 2) buf[1] = high ? 1 : 0; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); break; case 3: /* switch with GPIO of saa713x */ if (fe->callback) @@ -475,7 +490,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe, struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, .buf = buf, .len = sizeof(buf) }; - int i, tuner_freq, if_freq; + int i, tuner_freq, if_freq, rc; u32 N; dprintk("%s:\n", __func__); @@ -517,35 +532,32 @@ static int tda827xa_set_params(struct dvb_frontend *fe, buf[9] = 0x24; buf[10] = 0x00; msg.len = 11; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { - printk("%s: could not write to tuner at addr: 0x%02x\n", - __func__, priv->i2c_addr << 1); - return -EIO; - } + rc = tuner_transfer(fe, &msg, 1); + if (rc < 0) + goto err; + buf[0] = 0x90; buf[1] = 0xff; buf[2] = 0x60; buf[3] = 0x00; buf[4] = 0x59; // lpsel, for 6MHz + 2 msg.len = 5; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(priv->i2c_adap, &msg, 1); + rc = tuner_transfer(fe, &msg, 1); + if (rc < 0) + goto err; buf[0] = 0xa0; buf[1] = 0x40; msg.len = 2; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(priv->i2c_adap, &msg, 1); + rc = tuner_transfer(fe, &msg, 1); + if (rc < 0) + goto err; msleep(11); msg.flags = I2C_M_RD; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(priv->i2c_adap, &msg, 1); + rc = tuner_transfer(fe, &msg, 1); + if (rc < 0) + goto err; msg.flags = 0; buf[1] >>= 4; @@ -554,49 +566,55 @@ static int tda827xa_set_params(struct dvb_frontend *fe, tda827xa_lna_gain(fe, 0, NULL); buf[0] = 0x60; buf[1] = 0x0c; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(priv->i2c_adap, &msg, 1); + rc = tuner_transfer(fe, &msg, 1); + if (rc < 0) + goto err; } buf[0] = 0xc0; buf[1] = 0x99; // lpsel, for 6MHz + 2 - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(priv->i2c_adap, &msg, 1); + rc = tuner_transfer(fe, &msg, 1); + if (rc < 0) + goto err; buf[0] = 0x60; buf[1] = 0x3c; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(priv->i2c_adap, &msg, 1); + rc = tuner_transfer(fe, &msg, 1); + if (rc < 0) + goto err; /* correct CP value */ buf[0] = 0x30; buf[1] = 0x10 + tda827xa_dvbt[i].scr; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(priv->i2c_adap, &msg, 1); + rc = tuner_transfer(fe, &msg, 1); + if (rc < 0) + goto err; msleep(163); buf[0] = 0xc0; buf[1] = 0x39; // lpsel, for 6MHz + 2 - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(priv->i2c_adap, &msg, 1); + rc = tuner_transfer(fe, &msg, 1); + if (rc < 0) + goto err; msleep(3); /* freeze AGC1 */ buf[0] = 0x50; buf[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - i2c_transfer(priv->i2c_adap, &msg, 1); + rc = tuner_transfer(fe, &msg, 1); + if (rc < 0) + goto err; priv->frequency = params->frequency; priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; + return 0; + +err: + printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n", + __func__, priv->i2c_addr << 1); + return rc; } @@ -644,7 +662,7 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe, tuner_reg[9] = 0x20; tuner_reg[10] = 0x00; msg.len = 11; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); tuner_reg[0] = 0x90; tuner_reg[1] = 0xff; @@ -652,19 +670,19 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe, tuner_reg[3] = 0; tuner_reg[4] = 0x99 + (priv->lpsel << 1); msg.len = 5; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); tuner_reg[0] = 0xa0; tuner_reg[1] = 0xc0; msg.len = 2; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); tuner_reg[0] = 0x30; tuner_reg[1] = 0x10 + tda827xa_analog[i].scr; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); msg.flags = I2C_M_RD; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); msg.flags = 0; tuner_reg[1] >>= 4; dprintk("AGC2 gain is: %d\n", tuner_reg[1]); @@ -674,24 +692,24 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe, msleep(100); tuner_reg[0] = 0x60; tuner_reg[1] = 0x3c; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); msleep(163); tuner_reg[0] = 0x50; tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4); - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); tuner_reg[0] = 0x80; tuner_reg[1] = 0x28; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); tuner_reg[0] = 0xb0; tuner_reg[1] = 0x01; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); tuner_reg[0] = 0xc0; tuner_reg[1] = 0x19 + (priv->lpsel << 1); - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); priv->frequency = params->frequency; @@ -704,7 +722,7 @@ static void tda827xa_agcf(struct dvb_frontend *fe) unsigned char data[] = {0x80, 0x2c}; struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0, .buf = data, .len = 2}; - i2c_transfer(priv->i2c_adap, &msg, 1); + tuner_transfer(fe, &msg, 1); } /* ------------------------------------------------------------------ */ @@ -793,16 +811,19 @@ static struct dvb_tuner_ops tda827xa_tuner_ops = { }; static int tda827x_probe_version(struct dvb_frontend *fe) -{ u8 data; +{ + u8 data; + int rc; struct tda827x_priv *priv = fe->tuner_priv; struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD, .buf = &data, .len = 1 }; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { + + rc = tuner_transfer(fe, &msg, 1); + + if (rc < 0) { printk("%s: could not read from tuner at addr: 0x%02x\n", __func__, msg.addr << 1); - return -EIO; + return rc; } if ((data & 0x3c) == 0) { dprintk("tda827x tuner found\n"); -- cgit v1.2.3 From cde88dd58c4b1be925590b3b7f8d454cfd0d7441 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 8 Feb 2009 09:42:29 -0200 Subject: tda8290: Print an error if i2c_gate is not provided From: Mauro Carvalho Chehab While here, be sure that gate will be kept disabled if an error occurs. Priority: normal CC: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tda8290.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/common/tuners/tda8290.c b/linux/drivers/media/common/tuners/tda8290.c index 67c0fd5f7..54423df4c 100644 --- a/linux/drivers/media/common/tuners/tda8290.c +++ b/linux/drivers/media/common/tuners/tda8290.c @@ -589,8 +589,11 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) u8 data; struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 }; - if (NULL == analog_ops->i2c_gate_ctrl) + if (!analog_ops->i2c_gate_ctrl) { + printk(KERN_ERR "tda8290: no gate control were provided!\n"); + return -EINVAL; + } analog_ops->i2c_gate_ctrl(fe, 1); @@ -638,6 +641,7 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) if (ret != 1) { tuner_warn("tuner access failed!\n"); + analog_ops->i2c_gate_ctrl(fe, 0); return -EREMOTEIO; } -- cgit v1.2.3 From 8e932048c503b5597b2bde42ef5f781d6dc9ae16 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 8 Feb 2009 09:50:50 -0200 Subject: saa7134: move tuner init code to saa7134-cards From: Mauro Carvalho Chehab On certain devices, before opening a tuner, we need to open the tuner gate via i2c. This patch just moves the tuner probing code to the same place where such i2c commands are handled, to make easier to fix this trouble on later patches. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 24 +++++++++++++++++++++++ linux/drivers/media/video/saa7134/saa7134-core.c | 24 ----------------------- 2 files changed, 24 insertions(+), 24 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index 9ad47eba4..be614fa88 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -6300,6 +6300,30 @@ int saa7134_board_init2(struct saa7134_dev *dev) unsigned char buf; int board; + /* initialize hardware #2 */ + if (TUNER_ABSENT != dev->tuner_type) { + int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); + + /* Note: radio tuner address is always filled in, + so we do not need to probe for a radio tuner device. */ + if (dev->radio_type != UNSET) + v4l2_i2c_new_subdev(&dev->i2c_adap, + "tuner", "tuner", dev->radio_addr); + if (has_demod) + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + if (dev->tuner_addr == ADDR_UNSET) { + enum v4l2_i2c_tuner_type type = + has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; + + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(type)); + } else { + v4l2_i2c_new_subdev(&dev->i2c_adap, + "tuner", "tuner", dev->tuner_addr); + } + } + switch (dev->board) { case SAA7134_BOARD_BMK_MPEX_NOTUNER: case SAA7134_BOARD_BMK_MPEX_TUNER: diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index 6e98c992c..78b5c8f3c 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -1034,30 +1034,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* wait a bit, register i2c bus */ msleep(100); saa7134_i2c_register(dev); - - /* initialize hardware #2 */ - if (TUNER_ABSENT != dev->tuner_type) { - int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); - - /* Note: radio tuner address is always filled in, - so we do not need to probe for a radio tuner device. */ - if (dev->radio_type != UNSET) - v4l2_i2c_new_subdev(&dev->i2c_adap, - "tuner", "tuner", dev->radio_addr); - if (has_demod) - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); - if (dev->tuner_addr == ADDR_UNSET) { - enum v4l2_i2c_tuner_type type = - has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(type)); - } else { - v4l2_i2c_new_subdev(&dev->i2c_adap, - "tuner", "tuner", dev->tuner_addr); - } - } saa7134_board_init2(dev); saa7134_hwinit2(dev); -- cgit v1.2.3 From 695dfe0ccd35ae13a124ba61bcedc089f536510a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 8 Feb 2009 10:33:15 -0200 Subject: saa7134: Fix analog mode on devices that need to open an i2c gate From: Mauro Carvalho Chehab Some saa7134 devices require to open an i2c gate before tuning. This patch fix the initialization for those devices. The nxt200x_gate_ctrl() logic were returned back to the old place, since we don't know how to close the gate. A future pacth could revert that change and provide the proper close gate control, to avoid keeping it open forever. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-cards.c | 147 +++++++++++----------- 1 file changed, 77 insertions(+), 70 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c index be614fa88..01cc9543f 100644 --- a/linux/drivers/media/video/saa7134/saa7134-cards.c +++ b/linux/drivers/media/video/saa7134/saa7134-cards.c @@ -5995,32 +5995,6 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) /* ----------------------------------------------------------- */ -static void nxt200x_gate_ctrl(struct saa7134_dev *dev, int open) -{ - /* enable tuner */ - int i; - static const u8 buffer [][2] = { - { 0x10, 0x12 }, - { 0x13, 0x04 }, - { 0x16, 0x00 }, - { 0x14, 0x04 }, - { 0x17, 0x00 }, - }; - - dev->i2c_client.addr = 0x0a; - - /* FIXME: don't know how to close the i2c gate on NXT200x */ - if (!open) - return; - - for (i = 0; i < ARRAY_SIZE(buffer); i++) - if (2 != i2c_master_send(&dev->i2c_client, - &buffer[i][0], ARRAY_SIZE(buffer[0]))) - printk(KERN_WARNING - "%s: Unable to enable tuner(%i).\n", - dev->name, i); -} - int saa7134_board_init1(struct saa7134_dev *dev) { /* Always print gpio, often manufacturers encode tuner type and other info. */ @@ -6218,10 +6192,6 @@ int saa7134_board_init1(struct saa7134_dev *dev) "are supported for now.\n", dev->name, card(dev).name, dev->name); break; - case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: - case SAA7134_BOARD_KWORLD_ATSC110: - dev->gate_ctrl = nxt200x_gate_ctrl; - break; } return 0; } @@ -6300,33 +6270,20 @@ int saa7134_board_init2(struct saa7134_dev *dev) unsigned char buf; int board; - /* initialize hardware #2 */ - if (TUNER_ABSENT != dev->tuner_type) { - int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); - - /* Note: radio tuner address is always filled in, - so we do not need to probe for a radio tuner device. */ - if (dev->radio_type != UNSET) - v4l2_i2c_new_subdev(&dev->i2c_adap, - "tuner", "tuner", dev->radio_addr); - if (has_demod) - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); - if (dev->tuner_addr == ADDR_UNSET) { - enum v4l2_i2c_tuner_type type = - has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; - - v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", - "tuner", v4l2_i2c_tuner_addrs(type)); - } else { - v4l2_i2c_new_subdev(&dev->i2c_adap, - "tuner", "tuner", dev->tuner_addr); - } - } - + /* Put here the code that enables the chips that are needed + for analog mode and doesn't depend on the tuner attachment. + It is also a good idea to get tuner type from eeprom, etc before + initializing tuner, since we can avoid loading tuner driver + on devices that has TUNER_ABSENT + */ switch (dev->board) { case SAA7134_BOARD_BMK_MPEX_NOTUNER: case SAA7134_BOARD_BMK_MPEX_TUNER: + /* Checks if the device has a tuner at 0x60 addr + If the device doesn't have a tuner, TUNER_ABSENT + will be used at tuner_type, avoiding loading tuner + without needing it + */ dev->i2c_client.addr = 0x60; board = (i2c_master_recv(&dev->i2c_client, &buf, 0) < 0) ? SAA7134_BOARD_BMK_MPEX_NOTUNER @@ -6344,11 +6301,15 @@ int saa7134_board_init2(struct saa7134_dev *dev) u8 subaddr; u8 data[3]; int ret, tuner_t; - struct i2c_msg msg[] = {{.addr=0x50, .flags=0, .buf=&subaddr, .len = 1}, {.addr=0x50, .flags=I2C_M_RD, .buf=data, .len = 3}}; + subaddr= 0x14; tuner_t = 0; + + /* Retrieve device data from eeprom, checking for the + proper tuner_type. + */ ret = i2c_transfer(&dev->i2c_adap, msg, 2); if (ret != 2) { printk(KERN_ERR "EEPROM read failure\n"); @@ -6404,12 +6365,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->name, saa7134_boards[dev->board].name); break; } + /* break intentionally omitted */ case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: { - /* The Philips EUROPA based hybrid boards have the tuner connected through - * the channel decoder. We have to make it transparent to find it + /* The Philips EUROPA based hybrid boards have the tuner + connected through the channel decoder. We have to make it + transparent to find it */ u8 data[] = { 0x07, 0x02}; struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)}; @@ -6430,21 +6393,15 @@ int saa7134_board_init2(struct saa7134_dev *dev) if (dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) { dev->tuner_type = TUNER_PHILIPS_TDA8290; - saa7134_tuner_setup(dev); - data[2] = 0x68; i2c_transfer(&dev->i2c_adap, &msg, 1); - - /* Tuner setup is handled before I2C transfer. - Due to that, there's no need to do it later - */ - return 0; + break; } i2c_transfer(&dev->i2c_adap, &msg, 1); break; } - case SAA7134_BOARD_ASUSTeK_TVFM7135: - /* The card below is detected as card=53, but is different */ + case SAA7134_BOARD_ASUSTeK_TVFM7135: + /* The card below is detected as card=53, but is different */ if (dev->autodetected && (dev->eedata[0x27] == 0x03)) { dev->board = SAA7134_BOARD_ASUSTeK_P7131_ANALOG; printk(KERN_INFO "%s: P7131 analog only, using " @@ -6515,9 +6472,9 @@ int saa7134_board_init2(struct saa7134_dev *dev) /* Don't do this if the board was specifically selected with an * insmod option or if we have the default configuration T200*/ - if(!dev->autodetected || (dev->eedata[0x41] == 0xd0)) + if (!dev->autodetected || (dev->eedata[0x41] == 0xd0)) break; - if(dev->eedata[0x41] == 0x02) { + if (dev->eedata[0x41] == 0x02) { /* Reconfigure board as T200A */ dev->board = SAA7134_BOARD_VIDEOMATE_DVBT_200A; dev->tuner_type = saa7134_boards[dev->board].tuner_type; @@ -6530,6 +6487,58 @@ int saa7134_board_init2(struct saa7134_dev *dev) break; } break; + case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: + case SAA7134_BOARD_KWORLD_ATSC110: + { + struct i2c_msg msg = { .addr = 0x0a, .flags = 0 }; + int i; + static u8 buffer[][2] = { + { 0x10, 0x12 }, + { 0x13, 0x04 }, + { 0x16, 0x00 }, + { 0x14, 0x04 }, + { 0x17, 0x00 }, + }; + + for (i = 0; i < ARRAY_SIZE(buffer); i++) { + msg.buf = &buffer[i][0]; + msg.len = ARRAY_SIZE(buffer[0]); + if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) + printk(KERN_WARNING + "%s: Unable to enable tuner(%i).\n", + dev->name, i); + } + break; + } + } /* switch() */ + + /* initialize tuner */ + if (TUNER_ABSENT != dev->tuner_type) { + int has_demod = (dev->tda9887_conf & TDA9887_PRESENT); + + /* Note: radio tuner address is always filled in, + so we do not need to probe for a radio tuner device. */ + if (dev->radio_type != UNSET) + v4l2_i2c_new_subdev(&dev->i2c_adap, + "tuner", "tuner", dev->radio_addr); + if (has_demod) + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); + if (dev->tuner_addr == ADDR_UNSET) { + enum v4l2_i2c_tuner_type type = + has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV; + + v4l2_i2c_new_probed_subdev(&dev->i2c_adap, "tuner", + "tuner", v4l2_i2c_tuner_addrs(type)); + } else { + v4l2_i2c_new_subdev(&dev->i2c_adap, + "tuner", "tuner", dev->tuner_addr); + } + } + + saa7134_tuner_setup(dev); + + switch (dev->board) { case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: { struct v4l2_priv_tun_config tea5767_cfg; @@ -6546,7 +6555,5 @@ int saa7134_board_init2(struct saa7134_dev *dev) } } /* switch() */ - saa7134_tuner_setup(dev); - return 0; } -- cgit v1.2.3 From 179db25fdf42f7df16cc1f2045211dcac5b08c2d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 Feb 2009 06:29:54 -0200 Subject: saa7134: Cleanup: remove unused waitqueue from struct From: Mauro Carvalho Chehab The waitqueue is never used. So, let's just remove it. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134.h | 1 - 1 file changed, 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index 040f447c6..f681751ae 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -447,7 +447,6 @@ struct saa7134_dmasound { unsigned int bufsize; struct saa7134_pgtable pt; struct videobuf_dmabuf dma; - wait_queue_head_t wq; unsigned int dma_blk; unsigned int read_offset; unsigned int read_count; -- cgit v1.2.3 From 3b9a242cbd6a8f91f6a3f13baf4519353d48372a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 Feb 2009 06:33:54 -0200 Subject: saa7134-video: two int controls lack a step From: Mauro Carvalho Chehab Fix two broken controls where a step weren't specified. Without a step, userspace apps won't allow to adjust such controls. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-video.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index 2180527b3..f3c170d23 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -452,6 +452,7 @@ static const struct v4l2_queryctrl video_ctrls[] = { .name = "y offset odd field", .minimum = 0, .maximum = 128, + .step = 1, .default_value = 0, .type = V4L2_CTRL_TYPE_INTEGER, },{ @@ -459,6 +460,7 @@ static const struct v4l2_queryctrl video_ctrls[] = { .name = "y offset even field", .minimum = 0, .maximum = 128, + .step = 1, .default_value = 0, .type = V4L2_CTRL_TYPE_INTEGER, },{ -- cgit v1.2.3 From 971e043fbd20b5614646918ed64a80c1fb0667f4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 Feb 2009 13:27:03 -0200 Subject: saa7134: get rid of KBL From: Mauro Carvalho Chehab KBL is not needed on saa7134, so, let's remove it. However, we should take some care to avoid opening the module while initializing it. This issue exists with newer udev's that opens a device as soon as the driver is registered. So, a proper lock is needed on open. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/saa7134/saa7134-core.c | 44 +++++++++++------------ linux/drivers/media/video/saa7134/saa7134-video.c | 14 ++++---- linux/drivers/media/video/saa7134/saa7134.h | 1 + 3 files changed, 30 insertions(+), 29 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c index 78b5c8f3c..d499064ee 100644 --- a/linux/drivers/media/video/saa7134/saa7134-core.c +++ b/linux/drivers/media/video/saa7134/saa7134-core.c @@ -86,8 +86,10 @@ MODULE_PARM_DESC(radio_nr, "radio device number"); MODULE_PARM_DESC(tuner, "tuner type"); MODULE_PARM_DESC(card, "card type"); -static DEFINE_MUTEX(devlist_lock); +DEFINE_MUTEX(saa7134_devlist_lock); +EXPORT_SYMBOL(saa7134_devlist_lock); LIST_HEAD(saa7134_devlist); +EXPORT_SYMBOL(saa7134_devlist); static LIST_HEAD(mops_list); static unsigned int saa7134_devcount; @@ -1052,6 +1054,18 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, v4l2_prio_init(&dev->prio); + mutex_lock(&saa7134_devlist_lock); + list_for_each_entry(mops, &mops_list, next) + mpeg_ops_attach(mops, dev); + list_add_tail(&dev->devlist, &saa7134_devlist); + mutex_unlock(&saa7134_devlist_lock); + + /* check for signal */ + saa7134_irq_video_signalchange(dev); + + if (TUNER_ABSENT != dev->tuner_type) + saa_call_all(dev, core, s_standby, 0); + /* register v4l devices */ if (saa7134_no_overlay > 0) printk(KERN_INFO "%s: Overlay support disabled.\n", dev->name); @@ -1089,21 +1103,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* everything worked */ saa7134_devcount++; - mutex_lock(&devlist_lock); - list_for_each_entry(mops, &mops_list, next) - mpeg_ops_attach(mops, dev); - list_add_tail(&dev->devlist,&saa7134_devlist); - mutex_unlock(&devlist_lock); - - /* check for signal */ - saa7134_irq_video_signalchange(dev); - - if (saa7134_dmasound_init && !dev->dmasound.priv_data) { + if (saa7134_dmasound_init && !dev->dmasound.priv_data) saa7134_dmasound_init(dev); - } - - if (TUNER_ABSENT != dev->tuner_type) - saa_call_all(dev, core, s_standby, 0); return 0; @@ -1154,11 +1155,11 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) saa7134_hwfini(dev); /* unregister */ - mutex_lock(&devlist_lock); + mutex_lock(&saa7134_devlist_lock); list_del(&dev->devlist); list_for_each_entry(mops, &mops_list, next) mpeg_ops_detach(mops, dev); - mutex_unlock(&devlist_lock); + mutex_unlock(&saa7134_devlist_lock); saa7134_devcount--; saa7134_i2c_unregister(dev); @@ -1321,11 +1322,11 @@ int saa7134_ts_register(struct saa7134_mpeg_ops *ops) { struct saa7134_dev *dev; - mutex_lock(&devlist_lock); + mutex_lock(&saa7134_devlist_lock); list_for_each_entry(dev, &saa7134_devlist, devlist) mpeg_ops_attach(ops, dev); list_add_tail(&ops->next,&mops_list); - mutex_unlock(&devlist_lock); + mutex_unlock(&saa7134_devlist_lock); return 0; } @@ -1333,11 +1334,11 @@ void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops) { struct saa7134_dev *dev; - mutex_lock(&devlist_lock); + mutex_lock(&saa7134_devlist_lock); list_del(&ops->next); list_for_each_entry(dev, &saa7134_devlist, devlist) mpeg_ops_detach(ops, dev); - mutex_unlock(&devlist_lock); + mutex_unlock(&saa7134_devlist_lock); } EXPORT_SYMBOL(saa7134_ts_register); @@ -1381,7 +1382,6 @@ module_exit(saa7134_fini); /* ----------------------------------------------------------- */ EXPORT_SYMBOL(saa7134_set_gpio); -EXPORT_SYMBOL(saa7134_devlist); EXPORT_SYMBOL(saa7134_boards); /* ----------------- for the DMA sound modules --------------- */ diff --git a/linux/drivers/media/video/saa7134/saa7134-video.c b/linux/drivers/media/video/saa7134/saa7134-video.c index f3c170d23..be7f98bc0 100644 --- a/linux/drivers/media/video/saa7134/saa7134-video.c +++ b/linux/drivers/media/video/saa7134/saa7134-video.c @@ -1335,7 +1335,7 @@ static int video_open(struct file *file) enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; int radio = 0; - lock_kernel(); + mutex_lock(&saa7134_devlist_lock); list_for_each_entry(dev, &saa7134_devlist, devlist) { if (dev->video_dev && (dev->video_dev->minor == minor)) goto found; @@ -1348,19 +1348,20 @@ static int video_open(struct file *file) goto found; } } - unlock_kernel(); + mutex_unlock(&saa7134_devlist_lock); return -ENODEV; - found: + +found: + mutex_unlock(&saa7134_devlist_lock); dprintk("open minor=%d radio=%d type=%s\n",minor,radio, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh),GFP_KERNEL); - if (NULL == fh) { - unlock_kernel(); + if (NULL == fh) return -ENOMEM; - } + file->private_data = fh; fh->dev = dev; fh->radio = radio; @@ -1393,7 +1394,6 @@ static int video_open(struct file *file) /* switch to video/vbi mode */ video_mux(dev,dev->ctl_input); } - unlock_kernel(); return 0; } diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h index f681751ae..c9d4d4354 100644 --- a/linux/drivers/media/video/saa7134/saa7134.h +++ b/linux/drivers/media/video/saa7134/saa7134.h @@ -646,6 +646,7 @@ struct saa7134_dev { /* saa7134-core.c */ extern struct list_head saa7134_devlist; +extern struct mutex saa7134_devlist_lock; extern int saa7134_no_overlay; void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); -- cgit v1.2.3 From ac487327990e64111a50dee1162658ea7b949645 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 9 Feb 2009 14:12:41 -0200 Subject: tda1004x: Fix eeprom firmware load on boards with 16MHz Xtal From: Mauro Carvalho Chehab For i2c normal work, we need to slow down the bus speed. However, the slow down breaks the eeprom firmware load. So, use normal speed for eeprom booting and then restore the i2c speed after that. It should also be noticed that no other I2C transfer should be in course while booting from eeprom, otherwise, tda10046 goes into an instable state. So, proper locking are needed at the i2c bus master. Tested with saa7134 MSI TV @nyware A/D board, that comes with an eeprom with firmware version 29. Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/frontends/tda1004x.c | 30 ++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/dvb/frontends/tda1004x.c b/linux/drivers/media/dvb/frontends/tda1004x.c index 1465ff77b..4981cef8b 100644 --- a/linux/drivers/media/dvb/frontends/tda1004x.c +++ b/linux/drivers/media/dvb/frontends/tda1004x.c @@ -162,7 +162,7 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg) if (ret != 2) { dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret); - return -1; + return -EINVAL; } dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__, @@ -481,16 +481,18 @@ static void tda10046_init_plls(struct dvb_frontend* fe) static int tda10046_fwupload(struct dvb_frontend* fe) { struct tda1004x_state* state = fe->demodulator_priv; - int ret; + int ret, confc4; const struct firmware *fw; /* reset + wake up chip */ if (state->config->xtal_freq == TDA10046_XTAL_4M) { - tda1004x_write_byteI(state, TDA1004X_CONFC4, 0); + confc4 = 0; } else { dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __func__); - tda1004x_write_byteI(state, TDA1004X_CONFC4, 0x80); + confc4 = 0x80; } + tda1004x_write_byteI(state, TDA1004X_CONFC4, confc4); + tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0); /* set GPIO 1 and 3 */ if (state->config->gpio_config != TDA10046_GPTRI) { @@ -508,13 +510,29 @@ static int tda10046_fwupload(struct dvb_frontend* fe) if (tda1004x_check_upload_ok(state) == 0) return 0; + /* + For i2c normal work, we need to slow down the bus speed. + However, the slow down breaks the eeprom firmware load. + So, use normal speed for eeprom booting and then restore the + i2c speed after that. Tested with MSI TV @nyware A/D board, + that comes with firmware version 29 inside their eeprom. + + It should also be noticed that no other I2C transfer should + be in course while booting from eeprom, otherwise, tda10046 + goes into an instable state. So, proper locking are needed + at the i2c bus master. + */ printk(KERN_INFO "tda1004x: trying to boot from eeprom\n"); - tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4); + tda1004x_write_byteI(state, TDA1004X_CONFC4, 4); msleep(300); - /* don't re-upload unless necessary */ + tda1004x_write_byteI(state, TDA1004X_CONFC4, confc4); + + /* Checks if eeprom firmware went without troubles */ if (tda1004x_check_upload_ok(state) == 0) return 0; + /* eeprom firmware didn't work. Load one manually. */ + if (state->config->request_firmware != NULL) { /* request the firmware, this will block until someone uploads it */ printk(KERN_INFO "tda1004x: waiting for firmware upload...\n"); -- cgit v1.2.3 From 5ebad183669c1c51f03b1a7273135d4a6135ce6a Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Tue, 10 Feb 2009 23:00:06 -0200 Subject: em28xx: Add DVC 101 model to Pinnacle Dazzle description From: Douglas Schilling Landgraf Added DVC 101 model to Pinnacle Dazzle description Priority: normal Signed-off-by: Douglas Schilling Landgraf --- linux/Documentation/video4linux/CARDLIST.em28xx | 2 +- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index f7a7f48f4..e67df4917 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -7,7 +7,7 @@ 6 -> Terratec Cinergy 200 USB (em2800) 7 -> Leadtek Winfast USB II (em2800) [0413:6023] 8 -> Kworld USB2800 (em2800) - 9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a] + 9 -> Pinnacle Dazzle DVC 90/DVC 100/DVC 101 (em2820/em2840) [2304:0207,2304:021a] 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 12 -> Kworld PVR TV 2800 RF (em2820/em2840) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 608fa86e4..4db2ead66 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -957,7 +957,7 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_PINNACLE_DVC_90] = { - .name = "Pinnacle Dazzle DVC 90/DVC 100", + .name = "Pinnacle Dazzle DVC 90/DVC 100/DVC 101", .tuner_type = TUNER_ABSENT, /* capture only board */ .decoder = EM28XX_SAA711X, .input = { { -- cgit v1.2.3 From c6fd49ac8accb7a3252958a16ddf87fd216e694e Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Wed, 11 Feb 2009 00:28:24 -0200 Subject: em28xx: Coding style fixes and a typo correction From: Nicola Soranzo Lots of coding style fixes and a typo correction for em28xx. Priority: normal Signed-off-by: Nicola Soranzo [dougsland@redhat.com: fixed a reject due to a change on em28xx-audio.c] Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-audio.c | 8 ++--- linux/drivers/media/video/em28xx/em28xx-cards.c | 24 +++++++------- linux/drivers/media/video/em28xx/em28xx-core.c | 19 +++++------ linux/drivers/media/video/em28xx/em28xx-i2c.c | 6 ++-- linux/drivers/media/video/em28xx/em28xx-video.c | 43 ++++++++++++++----------- linux/drivers/media/video/em28xx/em28xx.h | 6 ++-- 6 files changed, 59 insertions(+), 47 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index e7dfebd7b..f37abcffa 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -263,8 +263,7 @@ static int em28xx_cmd(struct em28xx *dev, int cmd, int arg) } #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16) -static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, - size_t size) +static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size) #else static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size) @@ -276,7 +275,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, struct snd_pcm_runtime *runtime = subs->runtime; #endif - dprintk("Alocating vbuffer\n"); + dprintk("Allocating vbuffer\n"); if (runtime->dma_area) { if (runtime->dma_bytes > size) return 0; @@ -478,8 +477,7 @@ static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream *substream) #endif { - unsigned long flags; - + unsigned long flags; struct em28xx *dev; snd_pcm_uframes_t hwptr_done; diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 4db2ead66..543fbb8e3 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -257,7 +257,7 @@ struct em28xx_board em28xx_boards[] = { .name = "Hauppauge WinTV USB 2", .tuner_type = TUNER_PHILIPS_FM1236_MK3, .tda9887_conf = TDA9887_PRESENT | - TDA9887_PORT1_ACTIVE| + TDA9887_PORT1_ACTIVE | TDA9887_PORT2_ACTIVE, .decoder = EM28XX_TVP5150, .has_msp34xx = 1, @@ -534,7 +534,7 @@ struct em28xx_board em28xx_boards[] = { }, [EM2861_BOARD_YAKUMO_MOVIE_MIXER] = { .name = "Yakumo MovieMixer", - .tuner_type = TUNER_ABSENT, /* Capture only device */ + .tuner_type = TUNER_ABSENT, /* Capture only device */ .decoder = EM28XX_TVP5150, .input = { { .type = EM28XX_VMUX_TELEVISION, @@ -902,11 +902,11 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2800_BOARD_GRABBEEX_USB2800] = { - .name = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder", - .is_em2800 = 1, - .decoder = EM28XX_SAA711X, - .tuner_type = TUNER_ABSENT, /* capture only board */ - .input = { { + .name = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder", + .is_em2800 = 1, + .decoder = EM28XX_SAA711X, + .tuner_type = TUNER_ABSENT, /* capture only board */ + .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, @@ -1282,7 +1282,9 @@ struct em28xx_board em28xx_boards[] = { .has_dvb = 1, .dvb_gpio = kworld_330u_digital, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, - .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_EEPROM_ON_BOARD | EM28XX_I2C_EEPROM_KEY_VALID, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_EEPROM_ON_BOARD | + EM28XX_I2C_EEPROM_KEY_VALID, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, @@ -1321,7 +1323,7 @@ struct em28xx_board em28xx_boards[] = { const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); /* table of devices that work with this driver */ -struct usb_device_id em28xx_id_table [] = { +struct usb_device_id em28xx_id_table[] = { { USB_DEVICE(0xeb1a, 0x2750), .driver_info = EM2750_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2751), @@ -1425,7 +1427,7 @@ MODULE_DEVICE_TABLE(usb, em28xx_id_table); /* * EEPROM hash table for devices with generic USB IDs */ -static struct em28xx_hash_table em28xx_eeprom_hash [] = { +static struct em28xx_hash_table em28xx_eeprom_hash[] = { /* P/N: SA 60002070465 Tuner: TVF7533-MF */ {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF}, {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF}, @@ -1457,7 +1459,7 @@ int em28xx_tuner_callback(void *ptr, int component, int command, int arg) } EXPORT_SYMBOL_GPL(em28xx_tuner_callback); -static void inline em28xx_set_model(struct em28xx *dev) +static inline void em28xx_set_model(struct em28xx *dev) { memcpy(&dev->board, &em28xx_boards[dev->model], sizeof(dev->board)); diff --git a/linux/drivers/media/video/em28xx/em28xx-core.c b/linux/drivers/media/video/em28xx/em28xx-core.c index 743215ca9..f10abc5b4 100644 --- a/linux/drivers/media/video/em28xx/em28xx-core.c +++ b/linux/drivers/media/video/em28xx/em28xx-core.c @@ -33,8 +33,8 @@ /* #define ENABLE_DEBUG_ISOC_FRAMES */ static unsigned int core_debug; -module_param(core_debug,int,0644); -MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); +module_param(core_debug, int, 0644); +MODULE_PARM_DESC(core_debug, "enable debug messages [core]"); #define em28xx_coredbg(fmt, arg...) do {\ if (core_debug) \ @@ -42,8 +42,8 @@ MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); dev->name, __func__ , ##arg); } while (0) static unsigned int reg_debug; -module_param(reg_debug,int,0644); -MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); +module_param(reg_debug, int, 0644); +MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]"); #define em28xx_regdbg(fmt, arg...) do {\ if (reg_debug) \ @@ -77,7 +77,7 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, return -EINVAL; if (reg_debug) { - printk( KERN_DEBUG "(pipe 0x%08x): " + printk(KERN_DEBUG "(pipe 0x%08x): " "IN: %02x %02x %02x %02x %02x %02x %02x %02x ", pipe, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, @@ -154,7 +154,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, if (reg_debug) { int byte; - printk( KERN_DEBUG "(pipe 0x%08x): " + printk(KERN_DEBUG "(pipe 0x%08x): " "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>", pipe, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, @@ -462,7 +462,8 @@ int em28xx_audio_analog_set(struct em28xx *dev) if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) { int sel = ac97_return_record_select(dev->ctl_aoutput); - /* Use the same input for both left and right channels */ + /* Use the same input for both left and right + channels */ sel |= (sel << 8); em28xx_write_ac97(dev, AC97_RECORD_SELECT, sel); @@ -698,7 +699,7 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v) em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); /* it seems that both H and V scalers must be active to work correctly */ - mode = (h || v)? 0x30: 0x00; + mode = (h || v) ? 0x30 : 0x00; } return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30); } @@ -967,7 +968,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, em28xx_err("unable to allocate %i bytes for transfer" " buffer %i%s\n", sb_size, i, - in_interrupt()?" while in int":""); + in_interrupt() ? " while in int" : ""); em28xx_uninit_isoc(dev); return -ENOMEM; } diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c index 7084728eb..1bdcf2500 100644 --- a/linux/drivers/media/video/em28xx/em28xx-i2c.c +++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c @@ -402,10 +402,12 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) dev->name); break; case 2: - printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n", dev->name); + printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n", + dev->name); break; case 3: - printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n", dev->name); + printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n", + dev->name); break; } diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c index 50c3af538..448a02b04 100644 --- a/linux/drivers/media/video/em28xx/em28xx-video.c +++ b/linux/drivers/media/video/em28xx/em28xx-video.c @@ -186,7 +186,8 @@ static void em28xx_copy_video(struct em28xx *dev, em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n", ((char *)startwrite + lencopy) - ((char *)outp + buf->vb.size)); - lencopy = remain = (char *)outp + buf->vb.size - (char *)startwrite; + remain = (char *)outp + buf->vb.size - (char *)startwrite; + lencopy = remain; } if (lencopy <= 0) return; @@ -202,7 +203,8 @@ static void em28xx_copy_video(struct em28xx *dev, else lencopy = bytesperline; - if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) { + if ((char *)startwrite + lencopy > (char *)outp + + buf->vb.size) { em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n", ((char *)startwrite + lencopy) - ((char *)outp + buf->vb.size)); @@ -351,7 +353,7 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) } if (p[0] == 0x22 && p[1] == 0x5a) { em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], - len, (p[2] & 1)? "odd" : "even"); + len, (p[2] & 1) ? "odd" : "even"); if (!(p[2] & 1)) { if (buf != NULL) @@ -480,7 +482,9 @@ fail: static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); + struct em28xx_buffer *buf = container_of(vb, + struct em28xx_buffer, + vb); struct em28xx_fh *fh = vq->priv_data; struct em28xx *dev = fh->dev; struct em28xx_dmaqueue *vidq = &dev->vidq; @@ -493,7 +497,9 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); + struct em28xx_buffer *buf = container_of(vb, + struct em28xx_buffer, + vb); struct em28xx_fh *fh = vq->priv_data; struct em28xx *dev = (struct em28xx *)fh->dev; @@ -561,7 +567,7 @@ static int res_get(struct em28xx_fh *fh) static int res_check(struct em28xx_fh *fh) { - return (fh->stream_on); + return fh->stream_on; } static void res_free(struct em28xx_fh *fh) @@ -795,7 +801,7 @@ out: return rc; } -static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) +static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) { struct em28xx_fh *fh = priv; struct em28xx *dev = fh->dev; @@ -1483,7 +1489,7 @@ static int vidioc_reqbufs(struct file *file, void *priv, if (rc < 0) return rc; - return (videobuf_reqbufs(&fh->vb_vidq, rb)); + return videobuf_reqbufs(&fh->vb_vidq, rb); } static int vidioc_querybuf(struct file *file, void *priv, @@ -1497,7 +1503,7 @@ static int vidioc_querybuf(struct file *file, void *priv, if (rc < 0) return rc; - return (videobuf_querybuf(&fh->vb_vidq, b)); + return videobuf_querybuf(&fh->vb_vidq, b); } static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1510,7 +1516,7 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) if (rc < 0) return rc; - return (videobuf_qbuf(&fh->vb_vidq, b)); + return videobuf_qbuf(&fh->vb_vidq, b); } static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) @@ -1523,8 +1529,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) if (rc < 0) return rc; - return (videobuf_dqbuf(&fh->vb_vidq, b, - file->f_flags & O_NONBLOCK)); + return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); } #ifdef CONFIG_VIDEO_V4L1_COMPAT @@ -1848,7 +1853,7 @@ em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count, * em28xx_v4l2_poll() * will allocate buffers when called for the first time */ -static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) +static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait) { struct em28xx_fh *fh = filp->private_data; struct em28xx *dev = fh->dev; @@ -2006,8 +2011,8 @@ static struct video_device em28xx_radio_template = { static struct video_device *em28xx_vdev_init(struct em28xx *dev, - const struct video_device *template, - const char *type_name) + const struct video_device *template, + const char *type_name) { struct video_device *vfd; @@ -2057,8 +2062,9 @@ int em28xx_register_analog_devices(struct em28xx *dev) /* enable vbi capturing */ /* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ - val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK); - em28xx_write_reg(dev, EM28XX_R0F_XCLK, (EM28XX_XCLK_AUDIO_UNMUTE | val)); + val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK); + em28xx_write_reg(dev, EM28XX_R0F_XCLK, + (EM28XX_XCLK_AUDIO_UNMUTE | val)); em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51); #endif @@ -2094,7 +2100,8 @@ int em28xx_register_analog_devices(struct em28xx *dev) } if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { - dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio"); + dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, + "radio"); if (!dev->radio_dev) { em28xx_errdev("cannot allocate video_device.\n"); return -ENODEV; diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 81e7292ae..a83a36f49 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -160,7 +160,8 @@ */ /* time to wait when stopping the isoc transfer */ -#define EM28XX_URB_TIMEOUT msecs_to_jiffies(EM28XX_NUM_BUFS * EM28XX_NUM_PACKETS) +#define EM28XX_URB_TIMEOUT \ + msecs_to_jiffies(EM28XX_NUM_BUFS * EM28XX_NUM_PACKETS) /* time in msecs to wait for i2c writes to finish */ #define EM2800_I2C_WRITE_TIMEOUT 20 @@ -537,7 +538,8 @@ struct em28xx { int num_alt; /* Number of alternative settings */ unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ - char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ + char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc + transfer */ char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ /* helper funcs that call usb_control_msg */ -- cgit v1.2.3 From c192ce009da1f0d6917e4d183859cf21b9c15896 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Wed, 11 Feb 2009 12:13:05 -0200 Subject: em28xx: support added for IO-DATA GV/MVP SZ - EMPIA-2820 chipset From: Indika Katugampala Priority: normal Signed-off-by: Indika Katugampala [dougsland@redhat.com: Fixed CodingStyle] Signed-off-by: Douglas Schilling Landgraf --- linux/Documentation/video4linux/CARDLIST.em28xx | 1 + linux/drivers/media/video/em28xx/em28xx-cards.c | 32 +++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 34 insertions(+) (limited to 'linux') diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index 69601089f..f97c8533d 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -61,3 +61,4 @@ 62 -> Gadmei TVR200 (em2820/em2840) 63 -> Kaiomy TVnPC U2 (em2860) [eb1a:e303] 64 -> Easy Cap Capture DC-60 (em2860) + 65 -> IO-DATA GV-MVP/SZ (em2820/em2840) [04bb:0515] diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 8e285fc84..d69000674 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1362,6 +1362,26 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, + [EM2820_BOARD_IODATA_GVMVP_SZ] = { + .name = "IO-DATA GV-MVP/SZ", + .tuner_type = TUNER_PHILIPS_FM1236_MK3, + .tuner_gpio = default_tuner_gpio, + .tda9887_conf = TDA9887_PRESENT, + .decoder = EM28XX_TVP5150, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = TVP5150_COMPOSITE0, + .amux = EM28XX_AMUX_VIDEO, + }, { /* Composite has not been tested yet */ + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = EM28XX_AMUX_VIDEO, + }, { /* S-video has not been tested yet */ + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = EM28XX_AMUX_VIDEO, + } }, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1465,6 +1485,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII }, { USB_DEVICE(0x093b, 0xa005), .driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U }, + { USB_DEVICE(0x04bb, 0x0515), + .driver_info = EM2820_BOARD_IODATA_GVMVP_SZ }, { }, }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); @@ -1658,6 +1680,16 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_write_regs(dev, 0x08, "\xf8", 1); break; + case EM2820_BOARD_IODATA_GVMVP_SZ: + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); + msleep(70); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); + msleep(10); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + msleep(70); + em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); + msleep(70); + break; } em28xx_gpio_set(dev, dev->board.tuner_gpio); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index a0128819d..4aebda6c7 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -102,6 +102,7 @@ #define EM2820_BOARD_GADMEI_TVR200 62 #define EM2860_BOARD_KAIOMY_TVNPC_U2 63 #define EM2860_BOARD_EASYCAP 64 +#define EM2820_BOARD_IODATA_GVMVP_SZ 65 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From ca22e13799e2e82ead5bed32cb6bf61bfd0a262a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 11 Feb 2009 15:13:20 -0200 Subject: em28xx: Add support for Kaiomy TVnPC U2 stick From: Mauro Carvalho Chehab Thanks to Peter Senna Tschudin for borrow me one of those devices. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.em28xx | 1 + linux/drivers/media/video/em28xx/em28xx-cards.c | 43 +++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 45 insertions(+) (limited to 'linux') diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index f7a7f48f4..e914b1374 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -57,5 +57,6 @@ 57 -> Kworld PlusTV HD Hybrid 330 (em2883) [eb1a:a316] 58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041] 60 -> Hauppauge WinTV HVR 850 (em2883) [2040:651f] + 61 -> Kaiomy TVnPC U2 (em2860) [eb1a:e303] 61 -> Pixelview PlayTV Box 4 USB 2.0 (em2820/em2840) 62 -> Gadmei TVR200 (em2820/em2840) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 608fa86e4..12f52803a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1317,6 +1317,33 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, } }, }, + [EM2860_BOARD_KAIOMY_TVNPC_U2] = { + .name = "Kaiomy TVnPC U2", + .vchannels = 3, + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .mts_firmware = 1, + .decoder = EM28XX_TVP5150, + .tuner_gpio = default_tuner_gpio, + .input = { { + .type = EM28XX_VMUX_TELEVISION, + .vmux = TVP5150_COMPOSITE0, + .amux = EM28XX_AMUX_VIDEO, + + }, { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = TVP5150_COMPOSITE1, + .amux = EM28XX_AMUX_LINE_IN, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = TVP5150_SVIDEO, + .amux = EM28XX_AMUX_LINE_IN, + } }, + .radio = { + .type = EM28XX_RADIO, + .amux = EM28XX_AMUX_LINE_IN, + } + } }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1344,6 +1371,8 @@ struct usb_device_id em28xx_id_table [] = { .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0xe300), .driver_info = EM2861_BOARD_KWORLD_PVRTV_300U }, + { USB_DEVICE(0xeb1a, 0xe303), + .driver_info = EM2860_BOARD_KAIOMY_TVNPC_U2 }, { USB_DEVICE(0xeb1a, 0xe305), .driver_info = EM2880_BOARD_KWORLD_DVB_305U }, { USB_DEVICE(0xeb1a, 0xe310), @@ -1593,6 +1622,20 @@ void em28xx_pre_card_setup(struct em28xx *dev) /* enables audio for that devices */ em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); break; + + case EM2860_BOARD_KAIOMY_TVNPC_U2: + em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x07", 1); + em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1); + em28xx_write_regs(dev, 0x0d, "\x42", 1); + em28xx_write_regs(dev, 0x08, "\xfd", 1); + msleep(10); + em28xx_write_regs(dev, 0x08, "\xff", 1); + msleep(10); + em28xx_write_regs(dev, 0x08, "\x7f", 1); + msleep(10); + em28xx_write_regs(dev, 0x08, "\x6b", 1); + + break; } em28xx_gpio_set(dev, dev->board.tuner_gpio); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 1e2ffea54..3fb1c05fe 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -100,6 +100,7 @@ #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 #define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 #define EM2820_BOARD_GADMEI_TVR200 62 +#define EM2860_BOARD_KAIOMY_TVNPC_U2 61 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From b3ce86f6a8cf81930b025976cade18b7b93c626c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 11 Feb 2009 15:15:14 -0200 Subject: Adds IR table for the IR provided with this board and includes it at From: Mauro Carvalho Chehab Kaiomy entry. Thanks to Peter Senna Tschudin for borrow me one of those devices. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/ir-keymaps.c | 49 +++++++++++++++++++++++++ linux/drivers/media/video/em28xx/em28xx-cards.c | 1 + linux/include/media/ir-common.h | 1 + 3 files changed, 51 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c index ee9931f56..03fabc86c 100644 --- a/linux/drivers/media/common/ir-keymaps.c +++ b/linux/drivers/media/common/ir-keymaps.c @@ -2502,6 +2502,55 @@ IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE] = { }; EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog); +/* Kaiomy TVnPC U2 + Mauro Carvalho Chehab + */ +IR_KEYTAB_TYPE ir_codes_kaiomy[IR_KEYTAB_SIZE] = { + [0x43] = KEY_POWER2, + [0x01] = KEY_LIST, + [0x0b] = KEY_ZOOM, + [0x03] = KEY_POWER, + + [0x04] = KEY_1, + [0x08] = KEY_2, + [0x02] = KEY_3, + + [0x0f] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + + [0x0c] = KEY_7, + [0x0d] = KEY_8, + [0x0a] = KEY_9, + + [0x11] = KEY_0, + + [0x09] = KEY_CHANNELUP, + [0x07] = KEY_CHANNELDOWN, + + [0x0e] = KEY_VOLUMEUP, + [0x13] = KEY_VOLUMEDOWN, + + [0x10] = KEY_HOME, + [0x12] = KEY_ENTER, + + [0x14] = KEY_RECORD, + [0x15] = KEY_STOP, + [0x16] = KEY_PLAY, + [0x17] = KEY_MUTE, + + [0x18] = KEY_UP, + [0x19] = KEY_DOWN, + [0x1a] = KEY_LEFT, + [0x1b] = KEY_RIGHT, + + [0x1c] = KEY_RED, + [0x1d] = KEY_GREEN, + [0x1e] = KEY_YELLOW, + [0x1f] = KEY_BLUE, +}; +EXPORT_SYMBOL_GPL(ir_codes_kaiomy); + IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = { [0x20] = KEY_LIST, [0x00] = KEY_POWER, diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index 12f52803a..a772170f4 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1325,6 +1325,7 @@ struct em28xx_board em28xx_boards[] = { .mts_firmware = 1, .decoder = EM28XX_TVP5150, .tuner_gpio = default_tuner_gpio, + .ir_codes = ir_codes_kaiomy, .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = TVP5150_COMPOSITE0, diff --git a/linux/include/media/ir-common.h b/linux/include/media/ir-common.h index 5bf2ea006..31e62abb5 100644 --- a/linux/include/media/ir-common.h +++ b/linux/include/media/ir-common.h @@ -159,6 +159,7 @@ extern IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_ati_tv_wonder_hd_600[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_kaiomy[IR_KEYTAB_SIZE]; #endif /* -- cgit v1.2.3 From 6bb5aad0cf3ec4e211f6b3a3a09ece3488019548 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 11 Feb 2009 15:18:36 -0200 Subject: em28xx: Add support for Easy Cap Capture DC-60 From: Mauro Carvalho Chehab Thanks to Peter Senna Tschudin for borrow me one of those devices. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- linux/Documentation/video4linux/CARDLIST.em28xx | 3 ++- linux/drivers/media/video/em28xx/em28xx-cards.c | 21 ++++++++++++++++++++- linux/drivers/media/video/em28xx/em28xx.h | 3 ++- 3 files changed, 24 insertions(+), 3 deletions(-) (limited to 'linux') diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index e914b1374..b336dcab1 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -57,6 +57,7 @@ 57 -> Kworld PlusTV HD Hybrid 330 (em2883) [eb1a:a316] 58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041] 60 -> Hauppauge WinTV HVR 850 (em2883) [2040:651f] - 61 -> Kaiomy TVnPC U2 (em2860) [eb1a:e303] 61 -> Pixelview PlayTV Box 4 USB 2.0 (em2820/em2840) 62 -> Gadmei TVR200 (em2820/em2840) + 63 -> Kaiomy TVnPC U2 (em2860) [eb1a:e303] + 64 -> Easy Cap Capture DC-60 (em2860) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index a772170f4..96e3b4e80 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -1344,7 +1344,22 @@ struct em28xx_board em28xx_boards[] = { .type = EM28XX_RADIO, .amux = EM28XX_AMUX_LINE_IN, } - } + }, + [EM2860_BOARD_EASYCAP] = { + .name = "Easy Cap Capture DC-60", + .vchannels = 2, + .tuner_type = TUNER_ABSENT, + .decoder = EM28XX_SAA711X, + .input = { { + .type = EM28XX_VMUX_COMPOSITE1, + .vmux = SAA7115_COMPOSITE0, + .amux = EM28XX_AMUX_LINE_IN, + }, { + .type = EM28XX_VMUX_SVIDEO, + .vmux = SAA7115_SVIDEO3, + .amux = EM28XX_AMUX_LINE_IN, + } }, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -1637,6 +1652,10 @@ void em28xx_pre_card_setup(struct em28xx *dev) em28xx_write_regs(dev, 0x08, "\x6b", 1); break; + case EM2860_BOARD_EASYCAP: + em28xx_write_regs(dev, 0x08, "\xf8", 1); + break; + } em28xx_gpio_set(dev, dev->board.tuner_gpio); diff --git a/linux/drivers/media/video/em28xx/em28xx.h b/linux/drivers/media/video/em28xx/em28xx.h index 3fb1c05fe..46f738a8d 100644 --- a/linux/drivers/media/video/em28xx/em28xx.h +++ b/linux/drivers/media/video/em28xx/em28xx.h @@ -100,7 +100,8 @@ #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 #define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 #define EM2820_BOARD_GADMEI_TVR200 62 -#define EM2860_BOARD_KAIOMY_TVNPC_U2 61 +#define EM2860_BOARD_KAIOMY_TVNPC_U2 63 +#define EM2860_BOARD_EASYCAP 64 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- cgit v1.2.3 From efb7c378b6c916b25aaeaa1a38d6307eb8407282 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Feb 2009 23:14:09 +0100 Subject: saa6588: convert to v4l2-i2c-drv-legacy.h From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa6588.c | 86 +++++++++++++------------------------ 1 file changed, 31 insertions(+), 55 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/saa6588.c b/linux/drivers/media/video/saa6588.c index ab41d9526..57a40e62f 100644 --- a/linux/drivers/media/video/saa6588.c +++ b/linux/drivers/media/video/saa6588.c @@ -32,6 +32,8 @@ #include #include +#include +#include #include "compat.h" /* Addresses to scan */ @@ -73,7 +75,7 @@ MODULE_LICENSE("GPL"); #define dprintk if (debug) printk struct saa6588 { - struct i2c_client client; + struct i2c_client *client; struct work_struct work; struct timer_list timer; spinlock_t lock; @@ -87,9 +89,6 @@ struct saa6588 { int data_available_for_read; }; -static struct i2c_driver driver; -static struct i2c_client client_template; - /* ---------------------------------------------------------------------- */ /* @@ -266,7 +265,7 @@ static void saa6588_i2c_poll(struct saa6588 *s) /* Although we only need 3 bytes, we have to read at least 6. SAA6588 returns garbage otherwise */ - if (6 != i2c_master_recv(&s->client, &tmpbuf[0], 6)) { + if (6 != i2c_master_recv(s->client, &tmpbuf[0], 6)) { if (debug > 1) dprintk(PREFIX "read error!\n"); return; @@ -389,7 +388,8 @@ static int saa6588_configure(struct saa6588 *s) dprintk(PREFIX "writing: 0w=0x%02x 1w=0x%02x 2w=0x%02x\n", buf[0], buf[1], buf[2]); - if (3 != (rc = i2c_master_send(&s->client, buf, 3))) + rc = i2c_master_send(s->client, buf, 3); + if (rc != 3) printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc); return 0; @@ -397,33 +397,34 @@ static int saa6588_configure(struct saa6588 *s) /* ---------------------------------------------------------------------- */ -static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind) +static int saa6588_probe(struct i2c_client *client, + const struct i2c_device_id *id) { struct saa6588 *s; - client_template.adapter = adap; - client_template.addr = addr; - printk(PREFIX "chip found @ 0x%x\n", addr << 1); + v4l_info(client, "saa6588 found @ 0x%x (%s)\n", + client->addr << 1, client->adapter->name); - if (NULL == (s = kmalloc(sizeof(*s), GFP_KERNEL))) + s = kzalloc(sizeof(*s), GFP_KERNEL); + if (s == NULL) return -ENOMEM; + s->client = client; s->buf_size = bufblocks * 3; - if (NULL == (s->buffer = kmalloc(s->buf_size, GFP_KERNEL))) { + s->buffer = kmalloc(s->buf_size, GFP_KERNEL); + if (s->buffer == NULL) { kfree(s); return -ENOMEM; } spin_lock_init(&s->lock); - s->client = client_template; s->block_count = 0; s->wr_index = 0; s->rd_index = 0; s->last_blocknum = 0xff; init_waitqueue_head(&s->read_queue); s->data_available_for_read = 0; - i2c_set_clientdata(&s->client, s); - i2c_attach_client(&s->client); + i2c_set_clientdata(client, s); saa6588_configure(s); @@ -440,21 +441,13 @@ static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind) return 0; } -static int saa6588_probe(struct i2c_adapter *adap) -{ - if (adap->class & I2C_CLASS_TV_ANALOG) - return i2c_probe(adap, &addr_data, saa6588_attach); - return 0; -} - -static int saa6588_detach(struct i2c_client *client) +static int saa6588_remove(struct i2c_client *client) { struct saa6588 *s = i2c_get_clientdata(client); del_timer_sync(&s->timer); flush_scheduled_work(); - i2c_detach_client(client); kfree(s->buffer); kfree(s); return 0; @@ -499,38 +492,21 @@ static int saa6588_command(struct i2c_client *client, unsigned int cmd, /* ----------------------------------------------------------------------- */ -static struct i2c_driver driver = { - .driver = { - .name = "saa6588", - }, - .id = -1, /* FIXME */ - .attach_adapter = saa6588_probe, - .detach_client = saa6588_detach, - .command = saa6588_command, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) +static const struct i2c_device_id saa6588_id[] = { + { "saa6588", 0 }, + { } }; +MODULE_DEVICE_TABLE(i2c, saa6588_id); -static struct i2c_client client_template = { +#endif +static struct v4l2_i2c_driver_data v4l2_i2c_data = { .name = "saa6588", - .driver = &driver, + .command = saa6588_command, + .probe = saa6588_probe, + .remove = saa6588_remove, + .legacy_class = I2C_CLASS_TV_ANALOG, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + .id_table = saa6588_id, +#endif }; - -static int __init saa6588_init_module(void) -{ - return i2c_add_driver(&driver); -} - -static void __exit saa6588_cleanup_module(void) -{ - i2c_del_driver(&driver); -} - -module_init(saa6588_init_module); -module_exit(saa6588_cleanup_module); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ -- cgit v1.2.3 From ed3c315b6213d5787151999cac89a343634a4814 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Feb 2009 23:23:57 +0100 Subject: saa6588: convert to v4l2_subdev. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa6588.c | 117 ++++++++++++++++++++++-------------- 1 file changed, 72 insertions(+), 45 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/saa6588.c b/linux/drivers/media/video/saa6588.c index 57a40e62f..53c74f2ba 100644 --- a/linux/drivers/media/video/saa6588.c +++ b/linux/drivers/media/video/saa6588.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include "compat.h" @@ -75,7 +75,7 @@ MODULE_LICENSE("GPL"); #define dprintk if (debug) printk struct saa6588 { - struct i2c_client *client; + struct v4l2_subdev sd; struct work_struct work; struct timer_list timer; spinlock_t lock; @@ -89,6 +89,11 @@ struct saa6588 { int data_available_for_read; }; +static inline struct saa6588 *to_saa6588(struct v4l2_subdev *sd) +{ + return container_of(sd, struct saa6588, sd); +} + /* ---------------------------------------------------------------------- */ /* @@ -258,6 +263,7 @@ static void block_to_buf(struct saa6588 *s, unsigned char *blockbuf) static void saa6588_i2c_poll(struct saa6588 *s) { + struct i2c_client *client = v4l2_get_subdevdata(&s->sd); unsigned long flags; unsigned char tmpbuf[6]; unsigned char blocknum; @@ -265,7 +271,7 @@ static void saa6588_i2c_poll(struct saa6588 *s) /* Although we only need 3 bytes, we have to read at least 6. SAA6588 returns garbage otherwise */ - if (6 != i2c_master_recv(s->client, &tmpbuf[0], 6)) { + if (6 != i2c_master_recv(client, &tmpbuf[0], 6)) { if (debug > 1) dprintk(PREFIX "read error!\n"); return; @@ -341,6 +347,7 @@ static void saa6588_work(struct work_struct *work) static int saa6588_configure(struct saa6588 *s) { + struct i2c_client *client = v4l2_get_subdevdata(&s->sd); unsigned char buf[3]; int rc; @@ -388,7 +395,7 @@ static int saa6588_configure(struct saa6588 *s) dprintk(PREFIX "writing: 0w=0x%02x 1w=0x%02x 2w=0x%02x\n", buf[0], buf[1], buf[2]); - rc = i2c_master_send(s->client, buf, 3); + rc = i2c_master_send(client, buf, 3); if (rc != 3) printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc); @@ -397,10 +404,64 @@ static int saa6588_configure(struct saa6588 *s) /* ---------------------------------------------------------------------- */ +static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +{ + struct saa6588 *s = to_saa6588(sd); + struct rds_command *a = arg; + + switch (cmd) { + /* --- open() for /dev/radio --- */ + case RDS_CMD_OPEN: + a->result = 0; /* return error if chip doesn't work ??? */ + break; + /* --- close() for /dev/radio --- */ + case RDS_CMD_CLOSE: + s->data_available_for_read = 1; + wake_up_interruptible(&s->read_queue); + a->result = 0; + break; + /* --- read() for /dev/radio --- */ + case RDS_CMD_READ: + read_from_buf(s, a); + break; + /* --- poll() for /dev/radio --- */ + case RDS_CMD_POLL: + a->result = 0; + if (s->data_available_for_read) { + a->result |= POLLIN | POLLRDNORM; + } + poll_wait(a->instance, &s->read_queue, a->event_list); + break; + + default: + /* nothing */ + return -ENOIOCTLCMD; + } + return 0; +} + +static int saa6588_command(struct i2c_client *client, unsigned cmd, void *arg) +{ + return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); +} + +/* ----------------------------------------------------------------------- */ + +static const struct v4l2_subdev_core_ops saa6588_core_ops = { + .ioctl = saa6588_ioctl, +}; + +static const struct v4l2_subdev_ops saa6588_ops = { + .core = &saa6588_core_ops, +}; + +/* ---------------------------------------------------------------------- */ + static int saa6588_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct saa6588 *s; + struct v4l2_subdev *sd; v4l_info(client, "saa6588 found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); @@ -409,7 +470,6 @@ static int saa6588_probe(struct i2c_client *client, if (s == NULL) return -ENOMEM; - s->client = client; s->buf_size = bufblocks * 3; s->buffer = kmalloc(s->buf_size, GFP_KERNEL); @@ -417,6 +477,8 @@ static int saa6588_probe(struct i2c_client *client, kfree(s); return -ENOMEM; } + sd = &s->sd; + v4l2_i2c_subdev_init(sd, client, &saa6588_ops); spin_lock_init(&s->lock); s->block_count = 0; s->wr_index = 0; @@ -424,12 +486,11 @@ static int saa6588_probe(struct i2c_client *client, s->last_blocknum = 0xff; init_waitqueue_head(&s->read_queue); s->data_available_for_read = 0; - i2c_set_clientdata(client, s); saa6588_configure(s); /* start polling via eventd */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) INIT_WORK(&s->work, saa6588_work, s); #else INIT_WORK(&s->work, saa6588_work); @@ -443,7 +504,10 @@ static int saa6588_probe(struct i2c_client *client, static int saa6588_remove(struct i2c_client *client) { - struct saa6588 *s = i2c_get_clientdata(client); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct saa6588 *s = to_saa6588(sd); + + v4l2_device_unregister_subdev(sd); del_timer_sync(&s->timer); flush_scheduled_work(); @@ -453,43 +517,6 @@ static int saa6588_remove(struct i2c_client *client) return 0; } -static int saa6588_command(struct i2c_client *client, unsigned int cmd, - void *arg) -{ - struct saa6588 *s = i2c_get_clientdata(client); - struct rds_command *a = (struct rds_command *)arg; - - switch (cmd) { - /* --- open() for /dev/radio --- */ - case RDS_CMD_OPEN: - a->result = 0; /* return error if chip doesn't work ??? */ - break; - /* --- close() for /dev/radio --- */ - case RDS_CMD_CLOSE: - s->data_available_for_read = 1; - wake_up_interruptible(&s->read_queue); - a->result = 0; - break; - /* --- read() for /dev/radio --- */ - case RDS_CMD_READ: - read_from_buf(s, a); - break; - /* --- poll() for /dev/radio --- */ - case RDS_CMD_POLL: - a->result = 0; - if (s->data_available_for_read) { - a->result |= POLLIN | POLLRDNORM; - } - poll_wait(a->instance, &s->read_queue, a->event_list); - break; - - default: - /* nothing */ - break; - } - return 0; -} - /* ----------------------------------------------------------------------- */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -- cgit v1.2.3 From d096d77d6e81756f65115cc8c10a2df07c64d466 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 11 Feb 2009 23:28:30 +0100 Subject: saa6588: add g_chip_ident support. From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa6588.c | 9 +++++++++ linux/include/media/v4l2-chip-ident.h | 3 +++ 2 files changed, 12 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/video/saa6588.c b/linux/drivers/media/video/saa6588.c index 53c74f2ba..4f60df943 100644 --- a/linux/drivers/media/video/saa6588.c +++ b/linux/drivers/media/video/saa6588.c @@ -33,6 +33,7 @@ #include #include +#include #include #include "compat.h" @@ -440,6 +441,13 @@ static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) return 0; } +static int saa6588_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA6588, 0); +} + static int saa6588_command(struct i2c_client *client, unsigned cmd, void *arg) { return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); @@ -448,6 +456,7 @@ static int saa6588_command(struct i2c_client *client, unsigned cmd, void *arg) /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa6588_core_ops = { + .g_chip_ident = saa6588_g_chip_ident, .ioctl = saa6588_ioctl, }; diff --git a/linux/include/media/v4l2-chip-ident.h b/linux/include/media/v4l2-chip-ident.h index 4e2182e52..bbe2bb6a5 100644 --- a/linux/include/media/v4l2-chip-ident.h +++ b/linux/include/media/v4l2-chip-ident.h @@ -92,6 +92,9 @@ enum { /* module tea6420: just ident 6420 */ V4L2_IDENT_TEA6420 = 6420, + /* module saa6588: just ident 6588 */ + V4L2_IDENT_SAA6588 = 6588, + /* module saa6752hs: reserved range 6750-6759 */ V4L2_IDENT_SAA6752HS = 6752, V4L2_IDENT_SAA6752HS_AC3 = 6753, -- cgit v1.2.3 From 6cd9330d1dfb971343c26b47a5658bd108a38fe4 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 12 Feb 2009 15:21:52 -0200 Subject: em28xx: CodingStyle fixes From: Nicola Soranzo Coding style fixes for recent changesets in em28xx. Priority: normal Signed-off-by: Nicola Soranzo Signed-off-by: Douglas Schilling Landgraf --- linux/drivers/media/video/em28xx/em28xx-audio.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/em28xx/em28xx-audio.c b/linux/drivers/media/video/em28xx/em28xx-audio.c index f37abcffa..bfa3986f5 100644 --- a/linux/drivers/media/video/em28xx/em28xx-audio.c +++ b/linux/drivers/media/video/em28xx/em28xx-audio.c @@ -246,10 +246,12 @@ static int em28xx_cmd(struct em28xx *dev, int cmd, int arg) switch (cmd) { case EM28XX_CAPTURE_STREAM_EN: - if (dev->adev.capture_stream == STREAM_OFF && arg == EM28XX_START_AUDIO) { + if (dev->adev.capture_stream == STREAM_OFF && + arg == EM28XX_START_AUDIO) { dev->adev.capture_stream = STREAM_ON; em28xx_init_audio_isoc(dev); - } else if (dev->adev.capture_stream == STREAM_ON && arg == EM28XX_STOP_AUDIO) { + } else if (dev->adev.capture_stream == STREAM_ON && + arg == EM28XX_STOP_AUDIO) { dev->adev.capture_stream = STREAM_OFF; em28xx_deinit_isoc_audio(dev); } else { @@ -448,8 +450,8 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, struct em28xx *dev = snd_pcm_substream_chip(substream); int retval; - dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START)? - "start": "stop"); + dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START) ? + "start" : "stop"); spin_lock(&dev->adev.slock); switch (cmd) { -- cgit v1.2.3 From e5a5404bb87498cd9b8009d407e1de1b2bbea611 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Thu, 12 Feb 2009 15:22:42 -0200 Subject: em28xx-cards: Add Pinnacle Dazzle Video Creator Plus DVC107 description From: Douglas Schilling Landgraf Added board Pinnacle Dazzle Video Creator Plus DVC107 to name description field. Priority: normal Signed-off-by: Douglas Schilling Landgraf --- linux/Documentation/video4linux/CARDLIST.em28xx | 2 +- linux/drivers/media/video/em28xx/em28xx-cards.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'linux') diff --git a/linux/Documentation/video4linux/CARDLIST.em28xx b/linux/Documentation/video4linux/CARDLIST.em28xx index f97c8533d..77874bd20 100644 --- a/linux/Documentation/video4linux/CARDLIST.em28xx +++ b/linux/Documentation/video4linux/CARDLIST.em28xx @@ -7,7 +7,7 @@ 6 -> Terratec Cinergy 200 USB (em2800) 7 -> Leadtek Winfast USB II (em2800) [0413:6023] 8 -> Kworld USB2800 (em2800) - 9 -> Pinnacle Dazzle DVC 90/DVC 100/DVC 101 (em2820/em2840) [2304:0207,2304:021a] + 9 -> Pinnacle Dazzle DVC 90/DVC 100/DVC 101/DVC 107 (em2820/em2840) [2304:0207,2304:021a] 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 12 -> Kworld PVR TV 2800 RF (em2820/em2840) diff --git a/linux/drivers/media/video/em28xx/em28xx-cards.c b/linux/drivers/media/video/em28xx/em28xx-cards.c index d69000674..5af4c417a 100644 --- a/linux/drivers/media/video/em28xx/em28xx-cards.c +++ b/linux/drivers/media/video/em28xx/em28xx-cards.c @@ -957,7 +957,7 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2820_BOARD_PINNACLE_DVC_90] = { - .name = "Pinnacle Dazzle DVC 90/DVC 100/DVC 101", + .name = "Pinnacle Dazzle DVC 90/DVC 100/DVC 101/DVC 107", .tuner_type = TUNER_ABSENT, /* capture only board */ .decoder = EM28XX_SAA711X, .input = { { -- cgit v1.2.3 From ae85ab3edf003a61636030b72791577b41818bb0 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Thu, 12 Feb 2009 18:55:45 +0100 Subject: Documentation and code cleanups From: Tobias Lorenz - "DealExtreme" sells the "PCear" radio and that comes from "Sanei Electric". - MPlayer is also usable as radio application. - Consistent usage of tabulators and blanks in the code. Priority: normal Signed-off-by: Tobias Lorenz --- linux/Documentation/video4linux/si470x.txt | 11 ++++++++--- linux/drivers/media/radio/radio-si470x.c | 11 ++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'linux') diff --git a/linux/Documentation/video4linux/si470x.txt b/linux/Documentation/video4linux/si470x.txt index 49679e6aa..3a7823e01 100644 --- a/linux/Documentation/video4linux/si470x.txt +++ b/linux/Documentation/video4linux/si470x.txt @@ -1,6 +1,6 @@ Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers -Copyright (c) 2008 Tobias Lorenz +Copyright (c) 2009 Tobias Lorenz Information from Silicon Labs @@ -41,7 +41,7 @@ chips are known to work: - 10c4:818a: Silicon Labs USB FM Radio Reference Design - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF) - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700) -- 10c5:819a: DealExtreme USB Radio +- 10c5:819a: Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear) Software @@ -52,6 +52,7 @@ Testing is usually done with most application under Debian/testing: - gradio - GTK FM radio tuner - kradio - Comfortable Radio Application for KDE - radio - ncurses-based radio application +- mplayer - The Ultimate Movie Player For Linux There is also a library libv4l, which can be used. It's going to have a function for frequency seeking, either by using hardware functionality as in radio-si470x @@ -69,7 +70,7 @@ Audio Listing USB Audio is provided by the ALSA snd_usb_audio module. It is recommended to also select SND_USB_AUDIO, as this is required to get sound from the radio. For listing you have to redirect the sound, for example using one of the following -commands. +commands. Please adjust the audio devices to your needs (/dev/dsp* and hw:x,x). If you just want to test audio (very poor quality): cat /dev/dsp1 > /dev/dsp @@ -80,6 +81,10 @@ sox -2 --endian little -r 96000 -t oss /dev/dsp1 -t oss /dev/dsp If you use arts try: arecord -D hw:1,0 -r96000 -c2 -f S16_LE | artsdsp aplay -B - +If you use mplayer try: +mplayer -radio adevice=hw=1.0:arate=96000 \ + -rawaudio rate=96000 \ + radio:///capture Module Parameters ================= diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index f77a65d2a..718481313 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -5,8 +5,9 @@ * - Silicon Labs USB FM Radio Reference Design * - ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF) * - KWorld USB FM Radio SnapMusic Mobile 700 (FM700) + * - Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear) * - * Copyright (c) 2008 Tobias Lorenz + * Copyright (c) 2009 Tobias Lorenz * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,7 +30,7 @@ * 2008-01-12 Tobias Lorenz * Version 1.0.0 * - First working version - * 2008-01-13 Tobias Lorenz + * 2008-01-13 Tobias Lorenz * Version 1.0.1 * - Improved error handling, every function now returns errno * - Improved multi user access (start/mute/stop) @@ -141,7 +142,7 @@ static struct usb_device_id si470x_usb_driver_id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) }, /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */ { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) }, - /* DealExtreme USB Radio */ + /* Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear) */ { USB_DEVICE_AND_INTERFACE_INFO(0x10c5, 0x819a, USB_CLASS_HID, 0, 0) }, /* Terminating entry */ { } @@ -341,7 +342,7 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*"); /* Report 19: stream */ #define STREAM_REPORT_SIZE 3 -#define STREAM_REPORT 19 +#define STREAM_REPORT 19 /* Report 20: scratch */ #define SCRATCH_PAGE_SIZE 63 @@ -410,7 +411,7 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*"); /* bootloader commands */ #define GET_SW_VERSION_COMMAND 0x00 -#define SET_PAGE_COMMAND 0x01 +#define SET_PAGE_COMMAND 0x01 #define ERASE_PAGE_COMMAND 0x02 #define WRITE_PAGE_COMMAND 0x03 #define CRC_ON_PAGE_COMMAND 0x04 -- cgit v1.2.3 From d0578265f7ee9cfe91ebb445d025f67987b7aaed Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Thu, 12 Feb 2009 18:55:56 +0100 Subject: Code rearrangements in preparation for other report types From: Tobias Lorenz LED_REPORT and all flash REPORTs are on it's way. This code rearrangement cleans up the code for proper integration later on. Priority: normal Signed-off-by: Tobias Lorenz --- linux/drivers/media/radio/radio-si470x.c | 122 +++++++++++++++++-------------- 1 file changed, 67 insertions(+), 55 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index 718481313..49317f91f 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -481,7 +481,7 @@ struct si470x_device { /************************************************************************** - * General Driver Functions + * General Driver Functions - REGISTER_REPORTs **************************************************************************/ /* @@ -566,60 +566,6 @@ static int si470x_set_register(struct si470x_device *radio, int regnr) } -/* - * si470x_get_all_registers - read entire registers - */ -static int si470x_get_all_registers(struct si470x_device *radio) -{ - unsigned char buf[ENTIRE_REPORT_SIZE]; - int retval; - unsigned char regnr; - - buf[0] = ENTIRE_REPORT; - - retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); - - if (retval >= 0) - for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++) - radio->registers[regnr] = get_unaligned_be16( - &buf[regnr * RADIO_REGISTER_SIZE + 1]); - - return (retval < 0) ? -EINVAL : 0; -} - - -/* - * si470x_get_rds_registers - read rds registers - */ -static int si470x_get_rds_registers(struct si470x_device *radio) -{ - unsigned char buf[RDS_REPORT_SIZE]; - int retval; - int size; - unsigned char regnr; - - buf[0] = RDS_REPORT; - - retval = usb_interrupt_msg(radio->usbdev, - usb_rcvintpipe(radio->usbdev, 1), - (void *) &buf, sizeof(buf), &size, usb_timeout); - if (size != sizeof(buf)) - printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " - "return size differs: %d != %zu\n", size, sizeof(buf)); - if (retval < 0) - printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " - "usb_interrupt_msg returned %d\n", retval); - - if (retval >= 0) - for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) - radio->registers[STATUSRSSI + regnr] = - get_unaligned_be16( - &buf[regnr * RADIO_REGISTER_SIZE + 1]); - - return (retval < 0) ? -EINVAL : 0; -} - - /* * si470x_set_chan - set the channel */ @@ -887,6 +833,70 @@ static int si470x_rds_on(struct si470x_device *radio) +/************************************************************************** + * General Driver Functions - ENTIRE_REPORT + **************************************************************************/ + +/* + * si470x_get_all_registers - read entire registers + */ +static int si470x_get_all_registers(struct si470x_device *radio) +{ + unsigned char buf[ENTIRE_REPORT_SIZE]; + int retval; + unsigned char regnr; + + buf[0] = ENTIRE_REPORT; + + retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); + + if (retval >= 0) + for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++) + radio->registers[regnr] = get_unaligned_be16( + &buf[regnr * RADIO_REGISTER_SIZE + 1]); + + return (retval < 0) ? -EINVAL : 0; +} + + + +/************************************************************************** + * General Driver Functions - RDS_REPORT + **************************************************************************/ + +/* + * si470x_get_rds_registers - read rds registers + */ +static int si470x_get_rds_registers(struct si470x_device *radio) +{ + unsigned char buf[RDS_REPORT_SIZE]; + int retval; + int size; + unsigned char regnr; + + buf[0] = RDS_REPORT; + + retval = usb_interrupt_msg(radio->usbdev, + usb_rcvintpipe(radio->usbdev, 1), + (void *) &buf, sizeof(buf), &size, usb_timeout); + if (size != sizeof(buf)) + printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " + "return size differs: %d != %zu\n", size, sizeof(buf)); + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " + "usb_interrupt_msg returned %d\n", retval); + + if (retval >= 0) + for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) + radio->registers[STATUSRSSI + regnr] = + get_unaligned_be16( + &buf[regnr * RADIO_REGISTER_SIZE + 1]); + + return (retval < 0) ? -EINVAL : 0; +} + + + /************************************************************************** * RDS Driver Functions **************************************************************************/ @@ -1101,6 +1111,7 @@ static int si470x_fops_open(struct file *file) } if (radio->users == 1) { + /* start radio */ retval = si470x_start(radio); if (retval < 0) usb_autopm_put_interface(radio->intf); @@ -1142,6 +1153,7 @@ static int si470x_fops_release(struct file *file) /* cancel read processes */ wake_up_interruptible(&radio->read_queue); + /* stop radio */ retval = si470x_stop(radio); usb_autopm_put_interface(radio->intf); } -- cgit v1.2.3 From 30db0e876957f7d463bc717f76c73b9e34aa9e92 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Thu, 12 Feb 2009 18:56:10 +0100 Subject: Correction of Stereo detection/setting and signal strength indication From: Tobias Lorenz Thanks to Bob Ross - correction of stereo detection/setting - correction of signal strength indicator scaling Priority: normal Signed-off-by: Tobias Lorenz --- linux/drivers/media/radio/radio-si470x.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index 49317f91f..d211d5176 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -99,6 +99,9 @@ * - blacklisted KWorld radio in hid-core.c and hid-ids.h * 2008-12-03 Mark Lord * - add support for DealExtreme USB Radio + * 2009-01-31 Bob Ross + * - correction of stereo detection/setting + * - correction of signal strength indicator scaling * * ToDo: * - add firmware download/update support @@ -1405,20 +1408,22 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, }; /* stereo indicator == stereo (instead of mono) */ - if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 1) - tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; - else + if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0) tuner->rxsubchans = V4L2_TUNER_SUB_MONO; + else + tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; /* mono/stereo selector */ - if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 1) - tuner->audmode = V4L2_TUNER_MODE_MONO; - else + if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0) tuner->audmode = V4L2_TUNER_MODE_STEREO; + else + tuner->audmode = V4L2_TUNER_MODE_MONO; /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */ - tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI) - * 0x0101; + /* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */ + tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI); + /* the ideal factor is 0xffff/75 = 873,8 */ + tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10); /* automatic frequency control: -1: freq to low, 1 freq to high */ /* AFCRL does only indicate that freq. differs, not if too low/high */ -- cgit v1.2.3 From c29af88de22ef512cc331c823d9d334f1c4515fc Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Thu, 12 Feb 2009 18:56:19 +0100 Subject: LED status output From: Tobias Lorenz This patch closes one of my todos that was since long on my list. Some people reported clicks and glitches in the audio stream, correlated to the LED color changing cycle. Thanks to Rick Bronson . Priority: normal Signed-off-by: Tobias Lorenz --- linux/drivers/media/radio/radio-si470x.c | 34 +++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index d211d5176..71c3228d8 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -102,11 +102,13 @@ * 2009-01-31 Bob Ross * - correction of stereo detection/setting * - correction of signal strength indicator scaling + * 2009-01-31 Rick Bronson + * Tobias Lorenz + * - add LED status output * * ToDo: * - add firmware download/update support * - RDS support: interrupt mode, instead of polling - * - add LED status output (check if that's not already done in firmware) */ @@ -900,6 +902,30 @@ static int si470x_get_rds_registers(struct si470x_device *radio) +/************************************************************************** + * General Driver Functions - LED_REPORT + **************************************************************************/ + +/* + * si470x_set_led_state - sets the led state + */ +static int si470x_set_led_state(struct si470x_device *radio, + unsigned char led_state) +{ + unsigned char buf[LED_REPORT_SIZE]; + int retval; + + buf[0] = LED_REPORT; + buf[1] = LED_COMMAND; + buf[2] = led_state; + + retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); + + return (retval < 0) ? -EINVAL : 0; +} + + + /************************************************************************** * RDS Driver Functions **************************************************************************/ @@ -1657,6 +1683,9 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, /* set initial frequency */ si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ + /* set led to connect state */ + si470x_set_led_state(radio, BLINK_GREEN_LED); + /* rds buffer allocation */ radio->buf_size = rds_buf * 3; radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); @@ -1740,6 +1769,9 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf) cancel_delayed_work_sync(&radio->work); usb_set_intfdata(intf, NULL); if (radio->users == 0) { + /* set led to disconnect state */ + si470x_set_led_state(radio, BLINK_ORANGE_LED); + video_unregister_device(radio->videodev); kfree(radio->buffer); kfree(radio); -- cgit v1.2.3 From a7fd6975aa1ecb967ed5c0ed1186a4cb17b59a1a Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Thu, 12 Feb 2009 18:56:30 +0100 Subject: Output HW/SW version from scratchpad From: Tobias Lorenz This patch adds functions to access the scratchpad. For it is this good for? In the first two bytes, the developers stored the HW/PCB version and the software release of the firmware. This is now written to syslog, so debugging get's easier. Also knowing the versions is the key for flash upgrades later on. There are also some cleanups of the flash report sizes. Altogether this should justify the new version number 1.0.9. Thanks to Rick Bronson Priority: normal Signed-off-by: Tobias Lorenz --- linux/drivers/media/radio/radio-si470x.c | 61 ++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 10 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/radio/radio-si470x.c b/linux/drivers/media/radio/radio-si470x.c index 71c3228d8..b0a1e5832 100644 --- a/linux/drivers/media/radio/radio-si470x.c +++ b/linux/drivers/media/radio/radio-si470x.c @@ -105,6 +105,7 @@ * 2009-01-31 Rick Bronson * Tobias Lorenz * - add LED status output + * - get HW/SW version from scratchpad * * ToDo: * - add firmware download/update support @@ -115,10 +116,10 @@ /* driver definitions */ #define DRIVER_AUTHOR "Tobias Lorenz " #define DRIVER_NAME "radio-si470x" -#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 8) +#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 9) #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" -#define DRIVER_VERSION "1.0.8" +#define DRIVER_VERSION "1.0.9" /* kernel includes */ @@ -355,9 +356,13 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*"); #define SCRATCH_REPORT 20 /* Reports 19-22: flash upgrade of the C8051F321 */ +#define WRITE_REPORT_SIZE 4 #define WRITE_REPORT 19 +#define FLASH_REPORT_SIZE 64 #define FLASH_REPORT 20 +#define CRC_REPORT_SIZE 3 #define CRC_REPORT 21 +#define RESPONSE_REPORT_SIZE 2 #define RESPONSE_REPORT 22 /* Report 23: currently unused, but can accept 60 byte reports on the HID */ @@ -430,12 +435,6 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*"); #define COMMAND_FAILED 0x02 #define COMMAND_PENDING 0x03 -/* buffer sizes */ -#define COMMAND_BUFFER_SIZE 4 -#define RESPONSE_BUFFER_SIZE 2 -#define FLASH_BUFFER_SIZE 64 -#define CRC_BUFFER_SIZE 3 - /************************************************************************** @@ -471,6 +470,10 @@ struct si470x_device { unsigned int buf_size; unsigned int rd_index; unsigned int wr_index; + + /* scratch page */ + unsigned char software_version; + unsigned char hardware_version; }; @@ -926,6 +929,35 @@ static int si470x_set_led_state(struct si470x_device *radio, +/************************************************************************** + * General Driver Functions - SCRATCH_REPORT + **************************************************************************/ + +/* + * si470x_get_scratch_versions - gets the scratch page and version infos + */ +static int si470x_get_scratch_page_versions(struct si470x_device *radio) +{ + unsigned char buf[SCRATCH_REPORT_SIZE]; + int retval; + + buf[0] = SCRATCH_REPORT; + + retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); + + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME ": si470x_get_scratch: " + "si470x_get_report returned %d\n", retval); + else { + radio->software_version = buf[1]; + radio->hardware_version = buf[2]; + } + + return (retval < 0) ? -EINVAL : 0; +} + + + /************************************************************************** * RDS Driver Functions **************************************************************************/ @@ -1656,7 +1688,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, sizeof(si470x_viddev_template)); video_set_drvdata(radio->videodev, radio); - /* show some infos about the specific device */ + /* show some infos about the specific si470x device */ if (si470x_get_all_registers(radio) < 0) { retval = -EIO; goto err_all; @@ -1664,7 +1696,16 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", radio->registers[DEVICEID], radio->registers[CHIPID]); - /* check if firmware is current */ + /* get software and hardware versions */ + if (si470x_get_scratch_page_versions(radio) < 0) { + retval = -EIO; + goto err_all; + } + printk(KERN_INFO DRIVER_NAME + ": software version %d, hardware version %d\n", + radio->software_version, radio->hardware_version); + + /* check if device and firmware is current */ if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) < RADIO_SW_VERSION_CURRENT) { printk(KERN_WARNING DRIVER_NAME -- cgit v1.2.3 From 4162a001c7f1ef358a70ce97fa1867e3d102cb32 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 09:08:27 +0100 Subject: saa6588: remove legacy_class, not needed for saa6588 From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/saa6588.c | 1 - 1 file changed, 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/saa6588.c b/linux/drivers/media/video/saa6588.c index 4f60df943..77c3b59e8 100644 --- a/linux/drivers/media/video/saa6588.c +++ b/linux/drivers/media/video/saa6588.c @@ -541,7 +541,6 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .command = saa6588_command, .probe = saa6588_probe, .remove = saa6588_remove, - .legacy_class = I2C_CLASS_TV_ANALOG, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) .id_table = saa6588_id, #endif -- cgit v1.2.3 From 52a672f1e1c02901afbfcc810f5ab962759a05e0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 09:12:02 +0100 Subject: cx2341x: fixed bug causing several audio controls to be no longer listed From: Hans Verkuil The cx2341x_mpeg_ctrls array must be ordered by control ID. I know that this is bad design, but for now I will just fix this bug and revisit it when all drivers have moved to v4l2_device/v4l2_subdev, since that will allow me to do greatly improve control handling. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx2341x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx2341x.c b/linux/drivers/media/video/cx2341x.c index c92b98135..ebee97bc2 100644 --- a/linux/drivers/media/video/cx2341x.c +++ b/linux/drivers/media/video/cx2341x.c @@ -46,12 +46,12 @@ const u32 cx2341x_mpeg_ctrls[] = { V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, V4L2_CID_MPEG_AUDIO_ENCODING, V4L2_CID_MPEG_AUDIO_L2_BITRATE, - V4L2_CID_MPEG_AUDIO_AC3_BITRATE, V4L2_CID_MPEG_AUDIO_MODE, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, V4L2_CID_MPEG_AUDIO_EMPHASIS, V4L2_CID_MPEG_AUDIO_CRC, V4L2_CID_MPEG_AUDIO_MUTE, + V4L2_CID_MPEG_AUDIO_AC3_BITRATE, V4L2_CID_MPEG_VIDEO_ENCODING, V4L2_CID_MPEG_VIDEO_ASPECT, V4L2_CID_MPEG_VIDEO_B_FRAMES, -- cgit v1.2.3 From 6a1975515ebe6c5782f5f5ccf0bfdbbe6a27bd8c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 11:48:21 +0100 Subject: v4l2-subdev: add querystd and g_input_status From: Hans Verkuil In order to convert the v4l1 zoran and vino i2c drivers to v4l2 these extra ops are required. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/v4l2-subdev.c | 4 ++++ linux/include/media/v4l2-common.h | 3 +++ linux/include/media/v4l2-subdev.h | 2 ++ 3 files changed, 9 insertions(+) (limited to 'linux') diff --git a/linux/drivers/media/video/v4l2-subdev.c b/linux/drivers/media/video/v4l2-subdev.c index 158bc55de..923ec8d01 100644 --- a/linux/drivers/media/video/v4l2-subdev.c +++ b/linux/drivers/media/video/v4l2-subdev.c @@ -104,6 +104,10 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) return v4l2_subdev_call(sd, video, g_fmt, arg); case VIDIOC_INT_S_STD_OUTPUT: return v4l2_subdev_call(sd, video, s_std_output, *(v4l2_std_id *)arg); + case VIDIOC_QUERYSTD: + return v4l2_subdev_call(sd, video, querystd, arg); + case VIDIOC_INT_G_INPUT_STATUS: + return v4l2_subdev_call(sd, video, g_input_status, arg); case VIDIOC_STREAMON: return v4l2_subdev_call(sd, video, s_stream, 1); case VIDIOC_STREAMOFF: diff --git a/linux/include/media/v4l2-common.h b/linux/include/media/v4l2-common.h index 0f864f8da..1637cc302 100644 --- a/linux/include/media/v4l2-common.h +++ b/linux/include/media/v4l2-common.h @@ -297,4 +297,7 @@ struct v4l2_crystal_freq { a v4l2_gpio struct if a direction is also needed. */ #define VIDIOC_INT_S_GPIO _IOW('d', 117, u32) +/* Get input status. Same as the status field in the v4l2_input struct. */ +#define VIDIOC_INT_G_INPUT_STATUS _IOR('d', 118, u32) + #endif /* V4L2_COMMON_H_ */ diff --git a/linux/include/media/v4l2-subdev.h b/linux/include/media/v4l2-subdev.h index 9c1663d91..cd640c6f0 100644 --- a/linux/include/media/v4l2-subdev.h +++ b/linux/include/media/v4l2-subdev.h @@ -115,6 +115,8 @@ struct v4l2_subdev_video_ops { int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data); int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap); int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std); + int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std); + int (*g_input_status)(struct v4l2_subdev *sd, u32 *status); int (*s_stream)(struct v4l2_subdev *sd, int enable); int (*s_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt); int (*g_fmt)(struct v4l2_subdev *sd, struct v4l2_format *fmt); -- cgit v1.2.3 From 660dd279265a8004e38a9f2ec42c7b43d1fbf308 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 13 Feb 2009 09:24:34 -0200 Subject: tuner: fix TUV1236D analog/digital setup From: Mauro Carvalho Chehab As reported by David Engel , ATSC115 doesn't work fine with mythtv. This software opens both analog and dvb interfaces of saa7134. What happens is that some tuner commands are going to the wrong place, as shown at the logs: Feb 12 20:37:48 opus kernel: tuner-simple 1-0061: using tuner params #0 (ntsc) Feb 12 20:37:48 opus kernel: tuner-simple 1-0061: freq = 67.25 (1076), range = 0, config = 0xce, cb = 0x01 Feb 12 20:37:48 opus kernel: tuner-simple 1-0061: Freq= 67.25 MHz, V_IF=45.75 MHz, Offset=0.00 MHz, div=1808 Feb 12 20:37:48 opus kernel: tuner 1-0061: tv freq set to 67.25 Feb 12 20:37:48 opus kernel: tuner-simple 1-000a: using tuner params #0 (ntsc) Feb 12 20:37:48 opus kernel: tuner-simple 1-000a: freq = 67.25 (1076), range = 0, config = 0xce, cb = 0x01 Feb 12 20:37:48 opus kernel: tuner-simple 1-000a: Freq= 67.25 MHz, V_IF=45.75 MHz, Offset=0.00 MHz, div=1808 Feb 12 20:37:48 opus kernel: tuner-simple 1-000a: tv 0x07 0x10 0xce 0x01 Feb 12 20:37:48 opus kernel: tuner-simple 1-0061: tv 0x07 0x10 0xce 0x01 This happens due to a hack at TUV1236D analog setup, where it replaces tuner address, at 0x61 for 0x0a, in order to save a few memory bytes. The code assumes that nobody else would try to access the tuner during that setup, but the point is that there's no lock to protect such access. So, this opens the possibility of race conditions to happen. Instead of hacking tuner address, this patch uses a temporary var with the proper tuner value to be used during the setup. This should save the issue, although we should consider to write some analog/digital lock at saa7134 driver. Priority: high Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/common/tuners/tuner-simple.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/common/tuners/tuner-simple.c b/linux/drivers/media/common/tuners/tuner-simple.c index 36aaa7e75..233476df9 100644 --- a/linux/drivers/media/common/tuners/tuner-simple.c +++ b/linux/drivers/media/common/tuners/tuner-simple.c @@ -325,7 +325,6 @@ static int simple_std_setup(struct dvb_frontend *fe, u8 *config, u8 *cb) { struct tuner_simple_priv *priv = fe->tuner_priv; - u8 tuneraddr; int rc; /* tv norm specific stuff for multi-norm tuners */ @@ -394,6 +393,7 @@ static int simple_std_setup(struct dvb_frontend *fe, case TUNER_PHILIPS_TUV1236D: { + struct tuner_i2c_props i2c = priv->i2c_props; /* 0x40 -> ATSC antenna input 1 */ /* 0x48 -> ATSC antenna input 2 */ /* 0x00 -> NTSC antenna input 1 */ @@ -405,17 +405,15 @@ static int simple_std_setup(struct dvb_frontend *fe, buffer[1] = 0x04; } /* set to the correct mode (analog or digital) */ - tuneraddr = priv->i2c_props.addr; - priv->i2c_props.addr = 0x0a; - rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2); + i2c.addr = 0x0a; + rc = tuner_i2c_xfer_send(&i2c, &buffer[0], 2); if (2 != rc) tuner_warn("i2c i/o error: rc == %d " "(should be 2)\n", rc); - rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2); + rc = tuner_i2c_xfer_send(&i2c, &buffer[2], 2); if (2 != rc) tuner_warn("i2c i/o error: rc == %d " "(should be 2)\n", rc); - priv->i2c_props.addr = tuneraddr; break; } } -- cgit v1.2.3 From 12a53c2ca239e0fd7a2b858b577d624677982ab9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 14:57:48 +0100 Subject: v4l2-common: add comments warning that about the sort order From: Hans Verkuil Control arrays as are used with v4l2_ctrl_next must be sorted from low to high. Add a comment at the top of all such arrays to warn about this. Priority: normal Signed-off-by: Hans Verkuil --- linux/drivers/media/video/cx18/cx18-controls.c | 1 + linux/drivers/media/video/cx2341x.c | 1 + linux/drivers/media/video/cx23885/cx23885-video.c | 1 + linux/drivers/media/video/cx88/cx88-video.c | 1 + linux/drivers/media/video/ivtv/ivtv-controls.c | 1 + linux/drivers/media/video/saa7134/saa7134-empress.c | 2 ++ linux/drivers/media/video/v4l2-common.c | 2 +- linux/include/media/v4l2-common.h | 5 +++++ 8 files changed, 13 insertions(+), 1 deletion(-) (limited to 'linux') diff --git a/linux/drivers/media/video/cx18/cx18-controls.c b/linux/drivers/media/video/cx18/cx18-controls.c index 6af4d5c19..10a4e07b7 100644 --- a/linux/drivers/media/video/cx18/cx18-controls.c +++ b/linux/drivers/media/video/cx18/cx18-controls.c @@ -30,6 +30,7 @@ #include "cx18-mailbox.h" #include "cx18-controls.h" +/* Must be sorted from low to high control ID! */ static const u32 user_ctrls[] = { V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, diff --git a/linux/drivers/media/video/cx2341x.c b/linux/drivers/media/video/cx2341x.c index ebee97bc2..01c4d2d02 100644 --- a/linux/drivers/media/video/cx2341x.c +++ b/linux/drivers/media/video/cx2341x.c @@ -39,6 +39,7 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +/* Must be sorted from low to high control ID! */ const u32 cx2341x_mpeg_ctrls[] = { V4L2_CID_MPEG_CLASS, V4L2_CID_MPEG_STREAM_TYPE, diff --git a/linux/drivers/media/video/cx23885/cx23885-video.c b/linux/drivers/media/video/cx23885/cx23885-video.c index 09291888d..131fc740a 100644 --- a/linux/drivers/media/video/cx23885/cx23885-video.c +++ b/linux/drivers/media/video/cx23885/cx23885-video.c @@ -276,6 +276,7 @@ static struct cx23885_ctrl cx23885_ctls[] = { }; static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls); +/* Must be sorted from low to high control ID! */ static const u32 cx23885_user_ctrls[] = { V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c index a95bcb0ea..c8870cf06 100644 --- a/linux/drivers/media/video/cx88/cx88-video.c +++ b/linux/drivers/media/video/cx88/cx88-video.c @@ -299,6 +299,7 @@ static struct cx88_ctrl cx8800_ctls[] = { }; static const int CX8800_CTLS = ARRAY_SIZE(cx8800_ctls); +/* Must be sorted from low to high control ID! */ const u32 cx88_user_ctrls[] = { V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, diff --git a/linux/drivers/media/video/ivtv/ivtv-controls.c b/linux/drivers/media/video/ivtv/ivtv-controls.c index 62aa06f5d..84995bcf4 100644 --- a/linux/drivers/media/video/ivtv/ivtv-controls.c +++ b/linux/drivers/media/video/ivtv/ivtv-controls.c @@ -26,6 +26,7 @@ #include "ivtv-mailbox.h" #include "ivtv-controls.h" +/* Must be sorted from low to high control ID! */ static const u32 user_ctrls[] = { V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, diff --git a/linux/drivers/media/video/saa7134/saa7134-empress.c b/linux/drivers/media/video/saa7134/saa7134-empress.c index 3b0b42545..813f5f88d 100644 --- a/linux/drivers/media/video/saa7134/saa7134-empress.c +++ b/linux/drivers/media/video/saa7134/saa7134-empress.c @@ -352,6 +352,7 @@ static int empress_s_ctrl(struct file *file, void *priv, static int empress_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c) { + /* Must be sorted from low to high control ID! */ static const u32 user_ctrls[] = { V4L2_CID_USER_CLASS, V4L2_CID_BRIGHTNESS, @@ -364,6 +365,7 @@ static int empress_queryctrl(struct file *file, void *priv, 0 }; + /* Must be sorted from low to high control ID! */ static const u32 mpeg_ctrls[] = { V4L2_CID_MPEG_CLASS, V4L2_CID_MPEG_STREAM_TYPE, diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c index 6cc7d4058..8ae8dd366 100644 --- a/linux/drivers/media/video/v4l2-common.c +++ b/linux/drivers/media/video/v4l2-common.c @@ -750,7 +750,7 @@ EXPORT_SYMBOL(v4l2_ctrl_query_menu_valid_items); /* ctrl_classes points to an array of u32 pointers, the last element is a NULL pointer. Each u32 array is a 0-terminated array of control IDs. Each array must be sorted low to high and belong to the same control - class. The array of u32 pointer must also be sorted, from low class IDs + class. The array of u32 pointers must also be sorted, from low class IDs to high class IDs. This function returns the first ID that follows after the given ID. diff --git a/linux/include/media/v4l2-common.h b/linux/include/media/v4l2-common.h index 0f864f8da..4d82f1619 100644 --- a/linux/include/media/v4l2-common.h +++ b/linux/include/media/v4l2-common.h @@ -107,6 +107,11 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, const char **menu_items); #define V4L2_CTRL_MENU_IDS_END (0xffffffff) int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids); + +/* Note: ctrl_classes points to an array of u32 pointers. Each u32 array is a + 0-terminated array of control IDs. Each array must be sorted low to high + and belong to the same control class. The array of u32 pointers must also + be sorted, from low class IDs to high class IDs. */ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id); /* ------------------------------------------------------------------------- */ -- cgit v1.2.3