diff options
Diffstat (limited to 'drivers/media')
61 files changed, 1562 insertions, 833 deletions
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 3a80e0cc736..624b21cef5b 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -87,6 +87,14 @@ config VIDEO_TVEEPROM tristate depends on I2C +config DAB + boolean "DAB adapters" + default y + ---help--- + Allow selecting support for for Digital Audio Broadcasting (DAB) + Receiver adapters. + +if DAB config USB_DABUSB tristate "DABUSB driver" depends on USB @@ -100,5 +108,6 @@ config USB_DABUSB To compile this driver as a module, choose M here: the module will be called dabusb. +endif # DAB endmenu diff --git a/drivers/media/Makefile b/drivers/media/Makefile index c578a529e7a..8fa19939c2b 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -5,4 +5,4 @@ obj-y := common/ obj-$(CONFIG_VIDEO_DEV) += video/ obj-$(CONFIG_VIDEO_DEV) += radio/ -obj-$(CONFIG_DVB) += dvb/ +obj-$(CONFIG_DVB_CORE) += dvb/ diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 86cbdbcf9d7..ef3e54cd940 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -136,28 +136,45 @@ char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa char *mem = vmalloc_32(length); int slen = 0; - if (NULL == mem) { - return NULL; - } + if (NULL == mem) + goto err_null; - if (!(pt->slist = vmalloc_to_sg(mem, pages))) { - vfree(mem); - return NULL; - } + if (!(pt->slist = vmalloc_to_sg(mem, pages))) + goto err_free_mem; - if (saa7146_pgtable_alloc(pci, pt)) { - kfree(pt->slist); - pt->slist = NULL; - vfree(mem); - return NULL; - } + if (saa7146_pgtable_alloc(pci, pt)) + goto err_free_slist; - slen = pci_map_sg(pci,pt->slist,pages,PCI_DMA_FROMDEVICE); - if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) { - return NULL; - } + pt->nents = pages; + slen = pci_map_sg(pci,pt->slist,pt->nents,PCI_DMA_FROMDEVICE); + if (0 == slen) + goto err_free_pgtable; + + if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) + goto err_unmap_sg; return mem; + +err_unmap_sg: + pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE); +err_free_pgtable: + saa7146_pgtable_free(pci, pt); +err_free_slist: + kfree(pt->slist); + pt->slist = NULL; +err_free_mem: + vfree(mem); +err_null: + return NULL; +} + +void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, char *mem, struct saa7146_pgtable *pt) +{ + pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE); + saa7146_pgtable_free(pci, pt); + kfree(pt->slist); + pt->slist = NULL; + vfree(mem); } void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt) @@ -166,8 +183,6 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt) return; pci_free_consistent(pci, pt->size, pt->cpu, pt->dma); pt->cpu = NULL; - kfree(pt->slist); - pt->slist = NULL; } int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) @@ -528,6 +543,7 @@ EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc); EXPORT_SYMBOL_GPL(saa7146_pgtable_free); EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single); EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable); +EXPORT_SYMBOL_GPL(saa7146_vfree_destroy_pgtable); EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done); EXPORT_SYMBOL_GPL(saa7146_setgpio); diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index c18a5da6493..b4770aecc01 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -307,7 +307,6 @@ static int fops_release(struct inode *inode, struct file *file) return 0; } -int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg); static int fops_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { /* diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index a97c8f5e9a5..efd2b746815 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig @@ -2,24 +2,16 @@ # Multimedia device configuration # -menu "Digital Video Broadcasting Devices" +source "drivers/media/dvb/dvb-core/Kconfig" -config DVB - bool "DVB For Linux" - depends on NET && INET +menuconfig DVB_CAPTURE_DRIVERS + bool "DVB/ATSC adapters" + depends on DVB_CORE + default y ---help--- - Support Digital Video Broadcasting hardware. Enable this if you - own a DVB adapter and want to use it or if you compile Linux for - a digital SetTopBox. - - API specs and user tools are available from <http://www.linuxtv.org/>. + Say Y to select Digital TV adapters - Please report problems regarding this driver to the LinuxDVB - mailing list. - - If unsure say N. - -source "drivers/media/dvb/dvb-core/Kconfig" +if DVB_CAPTURE_DRIVERS comment "Supported SAA7146 based PCI Adapters" depends on DVB_CORE && PCI && I2C @@ -48,4 +40,4 @@ comment "Supported DVB Frontends" depends on DVB_CORE source "drivers/media/dvb/frontends/Kconfig" -endmenu +endif # DVB_CAPTURE_DRIVERS diff --git a/drivers/media/dvb/dvb-core/Kconfig b/drivers/media/dvb/dvb-core/Kconfig index 1990eda10c4..e3e6839f807 100644 --- a/drivers/media/dvb/dvb-core/Kconfig +++ b/drivers/media/dvb/dvb-core/Kconfig @@ -1,12 +1,22 @@ config DVB_CORE - tristate "DVB Core Support" - depends on DVB + tristate "DVB for Linux" + depends on NET && INET select CRC32 help + Support Digital Video Broadcasting hardware. Enable this if you + own a DVB adapter and want to use it or if you compile Linux for + a digital SetTopBox. + DVB core utility functions for device handling, software fallbacks etc. Say Y when you have a DVB card and want to use it. Say Y if your want to build your drivers outside the kernel, but need the DVB core. All in-kernel drivers will select this automatically if needed. + + API specs and user tools are available from <http://www.linuxtv.org/>. + + Please report problems regarding this driver to the LinuxDVB + mailing list. + If unsure say N. config DVB_CORE_ATTACH diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 97715f7514d..403081689de 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -19,6 +19,7 @@ #define USB_VID_COMPRO_UNK 0x145f #define USB_VID_CYPRESS 0x04b4 #define USB_VID_DIBCOM 0x10b8 +#define USB_VID_DPOSH 0x1498 #define USB_VID_DVICO 0x0fe9 #define USB_VID_EMPIA 0xeb1a #define USB_VID_GENPIX 0x09c0 @@ -61,6 +62,8 @@ #define USB_PID_DIBCOM_STK7700P 0x1e14 #define USB_PID_DIBCOM_STK7700P_PC 0x1e78 #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 +#define USB_PID_DPOSH_M9206_COLD 0x9206 +#define USB_PID_DPOSH_M9206_WARM 0xa090 #define USB_PID_UNIWILL_STK7700P 0x6003 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 @@ -145,6 +148,8 @@ #define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513 #define USB_PID_OPERA1_COLD 0x2830 #define USB_PID_OPERA1_WARM 0x3829 +#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514 +#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513 #endif diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 0d721731a52..6f824a569e1 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -119,7 +119,7 @@ struct usb_data_stream_properties { * @caps: capabilities of the DVB USB device. * @pid_filter_count: number of PID filter position in the optional hardware * PID-filter. - * @streaming_crtl: called to start and stop the MPEG2-TS streaming of the + * @streaming_ctrl: called to start and stop the MPEG2-TS streaming of the * device (not URB submitting/killing). * @pid_filter_ctrl: called to en/disable the PID filter, if any. * @pid_filter: called to set/unset a PID for filtering. diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c index 45d7bc214c1..c546ddeda5d 100644 --- a/drivers/media/dvb/dvb-usb/m920x.c +++ b/drivers/media/dvb/dvb-usb/m920x.c @@ -3,8 +3,8 @@ * Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.org) * * 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, version 2. + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, version 2. * * see Documentation/dvb/README.dvb-usb for more information */ @@ -22,26 +22,7 @@ static int dvb_usb_m920x_debug; module_param_named(debug,dvb_usb_m920x_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); -static struct dvb_usb_rc_key megasky_rc_keys [] = { - { 0x0, 0x12, KEY_POWER }, - { 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */ - { 0x0, 0x02, KEY_CHANNELUP }, - { 0x0, 0x05, KEY_CHANNELDOWN }, - { 0x0, 0x03, KEY_VOLUMEUP }, - { 0x0, 0x06, KEY_VOLUMEDOWN }, - { 0x0, 0x04, KEY_MUTE }, - { 0x0, 0x07, KEY_OK }, /* TS */ - { 0x0, 0x08, KEY_STOP }, - { 0x0, 0x09, KEY_MENU }, /* swap */ - { 0x0, 0x0a, KEY_REWIND }, - { 0x0, 0x1b, KEY_PAUSE }, - { 0x0, 0x1f, KEY_FASTFORWARD }, - { 0x0, 0x0c, KEY_RECORD }, - { 0x0, 0x0d, KEY_CAMERA }, /* screenshot */ - { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */ -}; - -static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\ +static inline int m920x_read(struct usb_device *udev, u8 request, u16 value, u16 index, void *data, int size) { int ret; @@ -55,14 +36,14 @@ static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\ } if (ret != size) { - deb_rc("m920x_read = no data\n"); + deb("m920x_read = no data\n"); return -EIO; } return 0; } -static inline int m9206_write(struct usb_device *udev, u8 request, +static inline int m920x_write(struct usb_device *udev, u8 request, u16 value, u16 index) { int ret; @@ -74,32 +55,40 @@ static inline int m9206_write(struct usb_device *udev, u8 request, return ret; } -static int m9206_init(struct dvb_usb_device *d) +static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq) { int ret = 0; /* Remote controller init. */ if (d->props.rc_query) { - if ((ret = m9206_write(d->udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0) - return ret; + deb("Initialising remote control\n"); + while (rc_seq->address) { + if ((ret = m920x_write(d->udev, M9206_CORE, + rc_seq->data, + rc_seq->address)) != 0) { + deb("Initialising remote control failed\n"); + return ret; + } - if ((ret = m9206_write(d->udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0) - return ret; + rc_seq++; + } + + deb("Initialising remote control success\n"); } return ret; } -static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { - struct m9206_state *m = d->priv; + struct m920x_state *m = d->priv; int i, ret = 0; u8 rc_state[2]; - if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) + if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0) goto unlock; - if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) + if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0) goto unlock; for (i = 0; i < d->props.rc_key_map_size; i++) @@ -111,6 +100,14 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) *state = REMOTE_NO_KEY_PRESSED; goto unlock; + case 0x88: /* framing error or "invalid code" */ + case 0x99: + case 0xc0: + case 0xd8: + *state = REMOTE_NO_KEY_PRESSED; + m->rep_count = 0; + goto unlock; + case 0x93: case 0x92: m->rep_count = 0; @@ -118,31 +115,32 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state) goto unlock; case 0x91: - /* For comfort. */ + /* prevent immediate auto-repeat */ if (++m->rep_count > 2) *state = REMOTE_KEY_REPEAT; + else + *state = REMOTE_NO_KEY_PRESSED; goto unlock; default: - deb_rc("Unexpected rc response %x\n", rc_state[0]); + deb("Unexpected rc state %02x\n", rc_state[0]); *state = REMOTE_NO_KEY_PRESSED; goto unlock; } } if (rc_state[1] != 0) - deb_rc("Unknown rc key %x\n", rc_state[1]); + deb("Unknown rc key %02x\n", rc_state[1]); *state = REMOTE_NO_KEY_PRESSED; - unlock: + unlock: return ret; } /* I2C */ -static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], - int num) +static int m920x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) { struct dvb_usb_device *d = i2c_get_adapdata(adap); int i, j; @@ -155,33 +153,40 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], return -EAGAIN; for (i = 0; i < num; i++) { - if (msg[i].flags & (I2C_M_NO_RD_ACK|I2C_M_IGNORE_NAK|I2C_M_TEN) || - msg[i].len == 0) { - /* For a 0 byte message, I think sending the address to index 0x80|0x40 - * would be the correct thing to do. However, zero byte messages are - * only used for probing, and since we don't know how to get the slave's - * ack, we can't probe. */ + if (msg[i].flags & (I2C_M_NO_RD_ACK | I2C_M_IGNORE_NAK | I2C_M_TEN) || msg[i].len == 0) { + /* For a 0 byte message, I think sending the address + * to index 0x80|0x40 would be the correct thing to + * do. However, zero byte messages are only used for + * probing, and since we don't know how to get the + * slave's ack, we can't probe. */ ret = -ENOTSUPP; goto unlock; } /* Send START & address/RW bit */ if (!(msg[i].flags & I2C_M_NOSTART)) { - if ((ret = m9206_write(d->udev, M9206_I2C, (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0), 0x80)) != 0) + if ((ret = m920x_write(d->udev, M9206_I2C, + (msg[i].addr << 1) | + (msg[i].flags & I2C_M_RD ? 0x01 : 0), 0x80)) != 0) goto unlock; /* Should check for ack here, if we knew how. */ } if (msg[i].flags & I2C_M_RD) { for (j = 0; j < msg[i].len; j++) { - /* Last byte of transaction? Send STOP, otherwise send ACK. */ - int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x01; - if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x20|stop, &msg[i].buf[j], 1)) != 0) + /* Last byte of transaction? + * Send STOP, otherwise send ACK. */ + int stop = (i+1 == num && j+1 == msg[i].len) ? 0x40 : 0x01; + + if ((ret = m920x_read(d->udev, M9206_I2C, 0x0, + 0x20 | stop, + &msg[i].buf[j], 1)) != 0) goto unlock; } } else { for (j = 0; j < msg[i].len; j++) { /* Last byte of transaction? Then send STOP. */ - int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x00; - if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0) + int stop = (i+1 == num && j+1 == msg[i].len) ? 0x40 : 0x00; + + if ((ret = m920x_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0) goto unlock; /* Should check for ack here too. */ } @@ -189,25 +194,25 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], } ret = num; -unlock: + unlock: mutex_unlock(&d->i2c_mutex); return ret; } -static u32 m9206_i2c_func(struct i2c_adapter *adapter) +static u32 m920x_i2c_func(struct i2c_adapter *adapter) { return I2C_FUNC_I2C; } -static struct i2c_algorithm m9206_i2c_algo = { - .master_xfer = m9206_i2c_xfer, - .functionality = m9206_i2c_func, +static struct i2c_algorithm m920x_i2c_algo = { + .master_xfer = m920x_i2c_xfer, + .functionality = m920x_i2c_func, }; - -static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx, - int pid) +/* pid filter */ +static int m920x_set_filter(struct dvb_usb_adapter *adap, + int type, int idx, int pid) { int ret = 0; @@ -216,18 +221,18 @@ static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx, pid |= 0x8000; - if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0) + if ((ret = m920x_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0) return ret; - if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0) + if ((ret = m920x_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0) return ret; return ret; } -static int m9206_update_filters(struct dvb_usb_adapter *adap) +static int m920x_update_filters(struct dvb_usb_adapter *adap) { - struct m9206_state *m = adap->dev->priv; + struct m920x_state *m = adap->dev->priv; int enabled = m->filtering_enabled; int i, ret = 0, filter = 0; @@ -236,14 +241,14 @@ static int m9206_update_filters(struct dvb_usb_adapter *adap) enabled = 0; /* Disable all filters */ - if ((ret = m9206_set_filter(adap, 0x81, 1, enabled)) != 0) + if ((ret = m920x_set_filter(adap, 0x81, 1, enabled)) != 0) return ret; for (i = 0; i < M9206_MAX_FILTERS; i++) - if ((ret = m9206_set_filter(adap, 0x81, i + 2, 0)) != 0) + if ((ret = m920x_set_filter(adap, 0x81, i + 2, 0)) != 0) return ret; - if ((ret = m9206_set_filter(adap, 0x82, 0, 0x0)) != 0) + if ((ret = m920x_set_filter(adap, 0x82, 0, 0x0)) != 0) return ret; /* Set */ @@ -252,40 +257,38 @@ static int m9206_update_filters(struct dvb_usb_adapter *adap) if (m->filters[i] == 0) continue; - if ((ret = m9206_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0) + if ((ret = m920x_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0) return ret; filter++; } } - if ((ret = m9206_set_filter(adap, 0x82, 0, 0x02f5)) != 0) + if ((ret = m920x_set_filter(adap, 0x82, 0, 0x02f5)) != 0) return ret; return ret; } -static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) +static int m920x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff) { - struct m9206_state *m = adap->dev->priv; + struct m920x_state *m = adap->dev->priv; m->filtering_enabled = onoff ? 1 : 0; - return m9206_update_filters(adap); + return m920x_update_filters(adap); } -static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, - int onoff) +static int m920x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) { - struct m9206_state *m = adap->dev->priv; + struct m920x_state *m = adap->dev->priv; m->filters[index] = onoff ? pid : 0; - return m9206_update_filters(adap); + return m920x_update_filters(adap); } -static int m9206_firmware_download(struct usb_device *udev, - const struct firmware *fw) +static int m920x_firmware_download(struct usb_device *udev, const struct firmware *fw) { u16 value, index, size; u8 read[4], *buff; @@ -293,13 +296,13 @@ static int m9206_firmware_download(struct usb_device *udev, buff = kmalloc(65536, GFP_KERNEL); - if ((ret = m9206_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) + if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0) goto done; - deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]); + deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]); - if ((ret = m9206_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0) + if ((ret = m920x_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0) goto done; - deb_rc("%x\n", read[0]); + deb("%x\n", read[0]); for (pass = 0; pass < 2; pass++) { for (i = 0; i + (sizeof(u16) * 3) < fw->size;) { @@ -317,11 +320,11 @@ static int m9206_firmware_download(struct usb_device *udev, memcpy(buff, fw->data + i, size); ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0), - M9206_FW, - USB_TYPE_VENDOR | USB_DIR_OUT, - value, index, buff, size, 20); + M9206_FW, + USB_TYPE_VENDOR | USB_DIR_OUT, + value, index, buff, size, 20); if (ret != size) { - deb_rc("error while uploading fw!\n"); + deb("error while uploading fw!\n"); ret = -EIO; goto done; } @@ -330,7 +333,7 @@ static int m9206_firmware_download(struct usb_device *udev, i += size; } if (i != fw->size) { - deb_rc("bad firmware file!\n"); + deb("bad firmware file!\n"); ret = -EINVAL; goto done; } @@ -338,11 +341,11 @@ static int m9206_firmware_download(struct usb_device *udev, msleep(36); - /* m9206 will disconnect itself from the bus after this. */ - (void) m9206_write(udev, M9206_CORE, 0x01, M9206_FW_GO); - deb_rc("firmware uploaded!\n"); + /* m920x will disconnect itself from the bus after this. */ + (void) m920x_write(udev, M9206_CORE, 0x01, M9206_FW_GO); + deb("firmware uploaded!\n"); - done: + done: kfree(buff); return ret; @@ -362,7 +365,8 @@ static int m920x_identify_state(struct usb_device *udev, return 0; } -static int megasky_mt352_demod_init(struct dvb_frontend *fe) +/* demod configurations */ +static int m920x_mt352_demod_init(struct dvb_frontend *fe) { u8 config[] = { CONFIG, 0x3d }; u8 clock[] = { CLOCK_CTL, 0x30 }; @@ -382,74 +386,174 @@ static int megasky_mt352_demod_init(struct dvb_frontend *fe) mt352_write(fe, unk1, ARRAY_SIZE(unk1)); mt352_write(fe, unk2, ARRAY_SIZE(unk2)); - deb_rc("Demod init!\n"); + deb("Demod init!\n"); return 0; } -static struct mt352_config megasky_mt352_config = { +static struct mt352_config m920x_mt352_config = { .demod_address = 0x0f, .no_tuner = 1, - .demod_init = megasky_mt352_demod_init, + .demod_init = m920x_mt352_demod_init, +}; + +static struct tda1004x_config m920x_tda10046_08_config = { + .demod_address = 0x08, + .invert = 0, + .invert_oclk = 0, + .ts_mode = TDA10046_TS_SERIAL, + .xtal_freq = TDA10046_XTAL_16M, + .if_freq = TDA10046_FREQ_045, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GPTRI, + .request_firmware = NULL, +}; + +static struct tda1004x_config m920x_tda10046_0b_config = { + .demod_address = 0x0b, + .invert = 0, + .invert_oclk = 0, + .ts_mode = TDA10046_TS_SERIAL, + .xtal_freq = TDA10046_XTAL_16M, + .if_freq = TDA10046_FREQ_045, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GPTRI, + .request_firmware = NULL, /* uses firmware EEPROM */ +}; + +/* tuner configurations */ +static struct qt1010_config m920x_qt1010_config = { + .i2c_address = 0x62 }; -static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap) +/* Callbacks for DVB USB */ +static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap) { - deb_rc("megasky_frontend_attach!\n"); + deb("%s\n",__FUNCTION__); - if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL) + if ((adap->fe = dvb_attach(mt352_attach, + &m920x_mt352_config, + &adap->dev->i2c_adap)) == NULL) return -EIO; return 0; } -static struct qt1010_config megasky_qt1010_config = { - .i2c_address = 0x62 -}; - -static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap) +static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap) { - if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, - &megasky_qt1010_config) == NULL) - return -ENODEV; + deb("%s\n",__FUNCTION__); + + if ((adap->fe = dvb_attach(tda10046_attach, + &m920x_tda10046_08_config, + &adap->dev->i2c_adap)) == NULL) + return -EIO; return 0; } -static struct tda1004x_config digivox_tda10046_config = { - .demod_address = 0x08, - .invert = 0, - .invert_oclk = 0, - .ts_mode = TDA10046_TS_SERIAL, - .xtal_freq = TDA10046_XTAL_16M, - .if_freq = TDA10046_FREQ_045, - .agc_config = TDA10046_AGC_TDA827X, - .gpio_config = TDA10046_GPTRI, - .request_firmware = NULL, -}; - -static int digivox_tda10046_frontend_attach(struct dvb_usb_adapter *adap) +static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap) { - deb_rc("digivox_tda10046_frontend_attach!\n"); + deb("%s\n",__FUNCTION__); - if ((adap->fe = dvb_attach(tda10046_attach, &digivox_tda10046_config, + if ((adap->fe = dvb_attach(tda10046_attach, + &m920x_tda10046_0b_config, &adap->dev->i2c_adap)) == NULL) return -EIO; return 0; } -static int digivox_tda8275_tuner_attach(struct dvb_usb_adapter *adap) +static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap) { - if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, - NULL) == NULL) + deb("%s\n",__FUNCTION__); + + if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL) return -ENODEV; + return 0; } +static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap) +{ + deb("%s\n",__FUNCTION__); + + if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL) + return -ENODEV; + + return 0; +} + +static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap) +{ + deb("%s\n",__FUNCTION__); + + if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) + return -ENODEV; + + return 0; +} + +/* device-specific initialization */ +static struct m920x_inits megasky_rc_init [] = { + { M9206_RC_INIT2, 0xa8 }, + { M9206_RC_INIT1, 0x51 }, + { } /* terminating entry */ +}; + +static struct m920x_inits tvwalkertwin_rc_init [] = { + { M9206_RC_INIT2, 0x00 }, + { M9206_RC_INIT1, 0xef }, + { 0xff28, 0x00 }, + { 0xff23, 0x00 }, + { 0xff21, 0x30 }, + { } /* terminating entry */ +}; + +/* ir keymaps */ +static struct dvb_usb_rc_key megasky_rc_keys [] = { + { 0x0, 0x12, KEY_POWER }, + { 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */ + { 0x0, 0x02, KEY_CHANNELUP }, + { 0x0, 0x05, KEY_CHANNELDOWN }, + { 0x0, 0x03, KEY_VOLUMEUP }, + { 0x0, 0x06, KEY_VOLUMEDOWN }, + { 0x0, 0x04, KEY_MUTE }, + { 0x0, 0x07, KEY_OK }, /* TS */ + { 0x0, 0x08, KEY_STOP }, + { 0x0, 0x09, KEY_MENU }, /* swap */ + { 0x0, 0x0a, KEY_REWIND }, + { 0x0, 0x1b, KEY_PAUSE }, + { 0x0, 0x1f, KEY_FASTFORWARD }, + { 0x0, 0x0c, KEY_RECORD }, + { 0x0, 0x0d, KEY_CAMERA }, /* screenshot */ + { 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */ +}; + +static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = { + { 0x0, 0x01, KEY_ZOOM }, /* Full Screen */ + { 0x0, 0x02, KEY_CAMERA }, /* snapshot */ + { 0x0, 0x03, KEY_MUTE }, + { 0x0, 0x04, KEY_REWIND }, + { 0x0, 0x05, KEY_PLAYPAUSE }, /* Play/Pause */ + { 0x0, 0x06, KEY_FASTFORWARD }, + { 0x0, 0x07, KEY_RECORD }, + { 0x0, 0x08, KEY_STOP }, + { 0x0, 0x09, KEY_TIME }, /* Timeshift */ + { 0x0, 0x0c, KEY_COFFEE }, /* Recall */ + { 0x0, 0x0e, KEY_CHANNELUP }, + { 0x0, 0x12, KEY_POWER }, + { 0x0, 0x15, KEY_MENU }, /* source */ + { 0x0, 0x18, KEY_CYCLEWINDOWS }, /* TWIN PIP */ + { 0x0, 0x1a, KEY_CHANNELDOWN }, + { 0x0, 0x1b, KEY_VOLUMEDOWN }, + { 0x0, 0x1e, KEY_VOLUMEUP }, +}; + /* DVB USB Driver stuff */ static struct dvb_usb_device_properties megasky_properties; static struct dvb_usb_device_properties digivox_mini_ii_properties; +static struct dvb_usb_device_properties tvwalkertwin_properties; +static struct dvb_usb_device_properties dposh_properties; static int m920x_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -457,19 +561,57 @@ static int m920x_probe(struct usb_interface *intf, struct dvb_usb_device *d; struct usb_host_interface *alt; int ret; + struct m920x_inits *rc_init_seq = NULL; + int bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber; - deb_rc("Probed!\n"); + deb("Probing for m920x device at interface %d\n", bInterfaceNumber); - if (((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) || - ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, THIS_MODULE, &d)) == 0)) - goto found; + if (bInterfaceNumber == 0) { + /* Single-tuner device, or first interface on + * multi-tuner device + */ - return ret; + if ((ret = dvb_usb_device_init(intf, &megasky_properties, + THIS_MODULE, &d)) == 0) { + rc_init_seq = megasky_rc_init; + goto found; + } + + if ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, + THIS_MODULE, &d)) == 0) { + /* No remote control, so no rc_init_seq */ + goto found; + } + + /* This configures both tuners on the TV Walker Twin */ + if ((ret = dvb_usb_device_init(intf, &tvwalkertwin_properties, + THIS_MODULE, &d)) == 0) { + rc_init_seq = tvwalkertwin_rc_init; + goto found; + } + + if ((ret = dvb_usb_device_init(intf, &dposh_properties, + THIS_MODULE, &d)) == 0) { + /* Remote controller not supported yet. */ + goto found; + } + + return ret; + } else { + /* Another interface on a multi-tuner device */ -found: + /* The LifeView TV Walker Twin gets here, but struct + * tvwalkertwin_properties already configured both + * tuners, so there is nothing for us to do here + */ + + return -ENODEV; + } + + found: alt = usb_altnum_to_altsetting(intf, 1); if (alt == NULL) { - deb_rc("No alt found!\n"); + deb("No alt found!\n"); return -ENODEV; } @@ -478,7 +620,7 @@ found: if (ret < 0) return ret; - if ((ret = m9206_init(d)) != 0) + if ((ret = m920x_init(d, rc_init_seq)) != 0) return ret; return ret; @@ -488,6 +630,12 @@ static struct usb_device_id m920x_table [] = { { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) }, { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, USB_PID_MSI_DIGI_VOX_MINI_II) }, + { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, + USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD) }, + { USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC, + USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM) }, + { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_COLD) }, + { USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_WARM) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, m920x_table); @@ -497,14 +645,14 @@ static struct dvb_usb_device_properties megasky_properties = { .usb_ctrl = DEVICE_SPECIFIC, .firmware = "dvb-usb-megasky-02.fw", - .download_firmware = m9206_firmware_download, + .download_firmware = m920x_firmware_download, .rc_interval = 100, .rc_key_map = megasky_rc_keys, .rc_key_map_size = ARRAY_SIZE(megasky_rc_keys), - .rc_query = m9206_rc_query, + .rc_query = m920x_rc_query, - .size_of_priv = sizeof(struct m9206_state), + .size_of_priv = sizeof(struct m920x_state), .identify_state = m920x_identify_state, .num_adapters = 1, @@ -513,11 +661,11 @@ static struct dvb_usb_device_properties megasky_properties = { DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 8, - .pid_filter = m9206_pid_filter, - .pid_filter_ctrl = m9206_pid_filter_ctrl, + .pid_filter = m920x_pid_filter, + .pid_filter_ctrl = m920x_pid_filter_ctrl, - .frontend_attach = megasky_mt352_frontend_attach, - .tuner_attach = megasky_qt1010_tuner_attach, + .frontend_attach = m920x_mt352_frontend_attach, + .tuner_attach = m920x_qt1010_tuner_attach, .stream = { .type = USB_BULK, @@ -530,7 +678,7 @@ static struct dvb_usb_device_properties megasky_properties = { } }, }}, - .i2c_algo = &m9206_i2c_algo, + .i2c_algo = &m920x_i2c_algo, .num_device_descs = 1, .devices = { @@ -546,22 +694,22 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = { .usb_ctrl = DEVICE_SPECIFIC, .firmware = "dvb-usb-digivox-02.fw", - .download_firmware = m9206_firmware_download, + .download_firmware = m920x_firmware_download, - .size_of_priv = sizeof(struct m9206_state), + .size_of_priv = sizeof(struct m920x_state), .identify_state = m920x_identify_state, .num_adapters = 1, .adapter = {{ .caps = DVB_USB_ADAP_HAS_PID_FILTER | - DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 8, - .pid_filter = m9206_pid_filter, - .pid_filter_ctrl = m9206_pid_filter_ctrl, + .pid_filter = m920x_pid_filter, + .pid_filter_ctrl = m920x_pid_filter_ctrl, - .frontend_attach = digivox_tda10046_frontend_attach, - .tuner_attach = digivox_tda8275_tuner_attach, + .frontend_attach = m920x_tda10046_08_frontend_attach, + .tuner_attach = m920x_tda8275_60_tuner_attach, .stream = { .type = USB_BULK, @@ -574,7 +722,7 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = { } }, }}, - .i2c_algo = &m9206_i2c_algo, + .i2c_algo = &m920x_i2c_algo, .num_device_descs = 1, .devices = { @@ -585,6 +733,122 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = { } }; +/* LifeView TV Walker Twin support by Nick Andrew <nick@nick-andrew.net> + * + * LifeView TV Walker Twin has 1 x M9206, 2 x TDA10046, 2 x TDA8275A + * TDA10046 #0 is located at i2c address 0x08 + * TDA10046 #1 is located at i2c address 0x0b (presently disabled - not yet working) + * TDA8275A #0 is located at i2c address 0x60 + * TDA8275A #1 is located at i2c address 0x61 (presently disabled - not yet working) + */ +static struct dvb_usb_device_properties tvwalkertwin_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .firmware = "dvb-usb-tvwalkert.fw", + .download_firmware = m920x_firmware_download, + + .rc_interval = 100, + .rc_key_map = tvwalkertwin_rc_keys, + .rc_key_map_size = ARRAY_SIZE(tvwalkertwin_rc_keys), + .rc_query = m920x_rc_query, + + .size_of_priv = sizeof(struct m920x_state), + + .identify_state = m920x_identify_state, + .num_adapters = 1, + .adapter = {{ + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + + .pid_filter_count = 8, + .pid_filter = m920x_pid_filter, + .pid_filter_ctrl = m920x_pid_filter_ctrl, + + .frontend_attach = m920x_tda10046_08_frontend_attach, + .tuner_attach = m920x_tda8275_60_tuner_attach, + + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x81, + .u = { + .bulk = { + .buffersize = 512, + } + } + }},{ + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + + .pid_filter_count = 8, + .pid_filter = m920x_pid_filter, + .pid_filter_ctrl = m920x_pid_filter_ctrl, + + .frontend_attach = m920x_tda10046_0b_frontend_attach, + .tuner_attach = m920x_tda8275_61_tuner_attach, + + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 512, + } + } + }, + }}, + .i2c_algo = &m920x_i2c_algo, + + .num_device_descs = 1, + .devices = { + { .name = "LifeView TV Walker Twin DVB-T USB2.0", + .cold_ids = { &m920x_table[2], NULL }, + .warm_ids = { &m920x_table[3], NULL }, + }, + } +}; + +static struct dvb_usb_device_properties dposh_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .firmware = "dvb-usb-dposh-01.fw", + .download_firmware = m920x_firmware_download, + + .size_of_priv = sizeof(struct m920x_state), + + .identify_state = m920x_identify_state, + .num_adapters = 1, + .adapter = {{ + /* Hardware pid filters don't work with this device/firmware */ + + .frontend_attach = m920x_mt352_frontend_attach, + .tuner_attach = m920x_qt1010_tuner_attach, + + .stream = { + .type = USB_BULK, + .count = 8, + .endpoint = 0x81, + .u = { + .bulk = { + .buffersize = 512, + } + } + }, + }}, + .i2c_algo = &m920x_i2c_algo, + + .num_device_descs = 1, + .devices = { + { .name = "Dposh DVB-T USB2.0", + .cold_ids = { &m920x_table[4], NULL }, + .warm_ids = { &m920x_table[5], NULL }, + }, + } +}; + static struct usb_driver m920x_driver = { .name = "dvb_usb_m920x", .probe = m920x_probe, @@ -615,6 +879,11 @@ module_init (m920x_module_init); module_exit (m920x_module_exit); MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>"); -MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x"); +MODULE_DESCRIPTION("DVB Driver for ULI M920x"); MODULE_VERSION("0.1"); MODULE_LICENSE("GPL"); + +/* + * Local variables: + * c-basic-offset: 8 + */ diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h index 7dd3db65c80..2c8942d0422 100644 --- a/drivers/media/dvb/dvb-usb/m920x.h +++ b/drivers/media/dvb/dvb-usb/m920x.h @@ -4,7 +4,7 @@ #define DVB_USB_LOG_PREFIX "m920x" #include "dvb-usb.h" -#define deb_rc(args...) dprintk(dvb_usb_m920x_debug,0x01,args) +#define deb(args...) dprintk(dvb_usb_m920x_debug,0x01,args) #define M9206_CORE 0x22 #define M9206_RC_STATE 0xff51 @@ -59,9 +59,18 @@ What any other bits might mean, or how to get the slave's ACK/NACK response to a write, is unknown. */ -struct m9206_state { +struct m920x_state { u16 filters[M9206_MAX_FILTERS]; int filtering_enabled; int rep_count; }; + +/* Initialisation data for the m920x + */ + +struct m920x_inits { + u16 address; + u8 data; +}; + #endif diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c index 3ecb2e0ce80..c3fdc7cd094 100644 --- a/drivers/media/dvb/dvb-usb/vp702x-fe.c +++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c @@ -204,8 +204,8 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe, static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *m) { - //struct vp702x_fe_state *st = fe->demodulator_priv; - u8 cmd[8];//,ibuf[10]; + struct vp702x_fe_state *st = fe->demodulator_priv; + u8 cmd[8],ibuf[10]; memset(cmd,0,8); deb_fe("%s\n",__FUNCTION__); @@ -218,12 +218,12 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe, memcpy(&cmd[3], m->msg, m->msg_len); cmd[7] = vp702x_chksum(cmd,0,7); -// vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100); + vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100); -// if (ibuf[2] == 0 && ibuf[3] == 0) -// deb_fe("diseqc cmd failed.\n"); -// else -// deb_fe("diseqc cmd succeeded.\n"); + if (ibuf[2] == 0 && ibuf[3] == 0) + deb_fe("diseqc cmd failed.\n"); + else + deb_fe("diseqc cmd succeeded.\n"); return 0; } diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c index 058df5c1003..08a2599ed74 100644 --- a/drivers/media/dvb/pluto2/pluto2.c +++ b/drivers/media/dvb/pluto2/pluto2.c @@ -293,12 +293,20 @@ static void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets) * but no packets have been transfered. * [2] Sometimes (actually very often) NBPACKETS stays at zero * although one packet has been transfered. + * [3] Sometimes (actually rarely), the card gets into an erroneous + * mode where it continuously generates interrupts, claiming it + * has recieved nbpackets>TS_DMA_PACKETS packets, but no packet + * has been transfered. Only a reset seems to solve this */ if ((nbpackets == 0) || (nbpackets > TS_DMA_PACKETS)) { unsigned int i = 0; while (pluto->dma_buf[i] == 0x47) i += 188; nbpackets = i / 188; + if (i == 0) { + pluto_reset_ts(pluto, 1); + dev_printk(KERN_DEBUG, &pluto->pdev->dev, "resetting TS because of invalid packet counter\n"); + } } dvb_dmx_swfilter_packets(&pluto->demux, pluto->dma_buf, nbpackets); diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index 67becdd4db6..ef1108c0bf1 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -1246,6 +1246,9 @@ static void vpeirq(unsigned long data) if (!budget->feeding1 || (newdma == olddma)) return; + /* Ensure streamed PCI data is synced to CPU */ + pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE); + #if 0 /* track rps1 activity */ printk("vpeirq: %02x Event Counter 1 0x%04x\n", @@ -2679,8 +2682,8 @@ err_iobuf_vfree_6: err_pci_free_5: pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus); err_saa71466_vfree_4: - if (!av7110->grabbing) - saa7146_pgtable_free(pdev, &av7110->pt); + if (av7110->grabbing) + saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt); err_i2c_del_3: i2c_del_adapter(&av7110->i2c_adap); err_dvb_unregister_adapter_2: @@ -2710,7 +2713,7 @@ static int __devexit av7110_detach(struct saa7146_dev* saa) SAA7146_ISR_CLEAR(saa, MASK_10); msleep(50); tasklet_kill(&av7110->vpe_tasklet); - saa7146_pgtable_free(saa->pci, &av7110->pt); + saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt); } av7110_exit_v4l(av7110); diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 4ed4599ce81..9d42f88ebb0 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -904,7 +904,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc band = 1; } else if (tuner_frequency < 200000000) { cp = 6; - band = 2; + band = 1; } else if (tuner_frequency < 290000000) { cp = 3; band = 2; diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c index 6b97dc1e6b6..2557ac9620d 100644 --- a/drivers/media/dvb/ttpci/budget-core.c +++ b/drivers/media/dvb/ttpci/budget-core.c @@ -195,6 +195,9 @@ static void vpeirq(unsigned long data) u32 newdma = saa7146_read(budget->dev, PCI_VDP3); u32 count; + /* Ensure streamed PCI data is synced to CPU */ + pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE); + /* nearest lower position divisible by 188 */ newdma -= newdma % 188; @@ -504,16 +507,16 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, strcpy(budget->i2c_adap.name, budget->card->name); if (i2c_add_adapter(&budget->i2c_adap) < 0) { - dvb_unregister_adapter(&budget->dvb_adapter); - return -ENOMEM; + ret = -ENOMEM; + goto err_dvb_unregister; } ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac); - if (NULL == - (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt))) { + budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt); + if (NULL == budget->grabbing) { ret = -ENOMEM; - goto err; + goto err_del_i2c; } saa7146_write(dev, PCI_BT_V1, 0x001c0000); @@ -526,14 +529,16 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, if (bi->type != BUDGET_FS_ACTIVY) saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); - if (budget_register(budget) == 0) { - return 0; - } -err: - i2c_del_adapter(&budget->i2c_adap); + if (budget_register(budget) == 0) + return 0; /* Everything OK */ + + /* An error occurred, cleanup resources */ + saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt); - vfree(budget->grabbing); +err_del_i2c: + i2c_del_adapter(&budget->i2c_adap); +err_dvb_unregister: dvb_unregister_adapter(&budget->dvb_adapter); return ret; @@ -555,15 +560,13 @@ int ttpci_budget_deinit(struct budget *budget) budget_unregister(budget); - i2c_del_adapter(&budget->i2c_adap); - - dvb_unregister_adapter(&budget->dvb_adapter); - tasklet_kill(&budget->vpe_tasklet); - saa7146_pgtable_free(dev->pci, &budget->pt); + saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt); - vfree(budget->grabbing); + i2c_del_adapter(&budget->i2c_adap); + + dvb_unregister_adapter(&budget->dvb_adapter); return 0; } diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index af66a5d5ecd..a6ac82a609d 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -2,8 +2,14 @@ # Multimedia Video device configuration # -menu "Radio Adapters" +menuconfig RADIO_ADAPTERS + bool "Radio Adapters" depends on VIDEO_DEV + default y + ---help--- + Say Y here to enable selecting AM/FM radio adapters. + +if RADIO_ADAPTERS config RADIO_CADET tristate "ADS Cadet AM/FM Tuner" @@ -328,4 +334,5 @@ config USB_DSBR To compile this driver as a module, choose M here: the module will be called dsbr100. -endmenu + +endif # RADIO_ADAPTERS diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c index 449df1bb00d..3bd07f7e377 100644 --- a/drivers/media/radio/dsbr100.c +++ b/drivers/media/radio/dsbr100.c @@ -33,6 +33,10 @@ History: + Version 0.42: + Converted dsbr100 to use video_ioctl2 + by Douglas Landgraf <dougsland@gmail.com> + Version 0.41-ac1: Alan Cox: Some cleanups and fixes @@ -121,8 +125,6 @@ devices, that would be 76 and 91. */ static int usb_dsbr100_probe(struct usb_interface *intf, const struct usb_device_id *id); static void usb_dsbr100_disconnect(struct usb_interface *intf); -static int usb_dsbr100_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); static int usb_dsbr100_open(struct inode *inode, struct file *file); static int usb_dsbr100_close(struct inode *inode, struct file *file); @@ -142,26 +144,6 @@ struct dsbr100_device { }; -/* File system interface */ -static const struct file_operations usb_dsbr100_fops = { - .owner = THIS_MODULE, - .open = usb_dsbr100_open, - .release = usb_dsbr100_close, - .ioctl = usb_dsbr100_ioctl, - .compat_ioctl = v4l_compat_ioctl32, - .llseek = no_llseek, -}; - -/* V4L interface */ -static struct video_device dsbr100_videodev_template= -{ - .owner = THIS_MODULE, - .name = "D-Link DSB-R 100", - .type = VID_TYPE_TUNER, - .fops = &usb_dsbr100_fops, - .release = video_device_release, -}; - static struct usb_device_id usb_dsbr100_device_table [] = { { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) }, { } /* Terminating entry */ @@ -252,37 +234,6 @@ static void dsbr100_getstat(struct dsbr100_device *radio) /* USB subsystem interface begins here */ -/* check if the device is present and register with v4l and -usb if it is */ -static int usb_dsbr100_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct dsbr100_device *radio; - - if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL))) - return -ENOMEM; - if (!(radio->videodev = video_device_alloc())) { - kfree(radio); - return -ENOMEM; - } - memcpy(radio->videodev, &dsbr100_videodev_template, - sizeof(dsbr100_videodev_template)); - radio->removed = 0; - radio->users = 0; - radio->usbdev = interface_to_usbdev(intf); - radio->curfreq = FREQ_MIN*FREQ_MUL; - video_set_drvdata(radio->videodev, radio); - if (video_register_device(radio->videodev, VFL_TYPE_RADIO, - radio_nr)) { - warn("Could not register video device"); - video_device_release(radio->videodev); - kfree(radio); - return -EIO; - } - usb_set_intfdata(intf, radio); - return 0; -} - /* 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 @@ -307,133 +258,147 @@ static void usb_dsbr100_disconnect(struct usb_interface *intf) } -/* Video for Linux interface */ +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *v) +{ + strlcpy(v->driver, "dsbr100", sizeof(v->driver)); + strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card)); + sprintf(v->bus_info, "ISA"); + v->version = RADIO_VERSION; + v->capabilities = V4L2_CAP_TUNER; + return 0; +} -static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) +static int vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) { - struct dsbr100_device *radio=video_get_drvdata(video_devdata(file)); + struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); + + if (v->index > 0) + return -EINVAL; + + dsbr100_getstat(radio); + strcpy(v->name, "FM"); + v->type = V4L2_TUNER_RADIO; + v->rangelow = FREQ_MIN*FREQ_MUL; + v->rangehigh = FREQ_MAX*FREQ_MUL; + v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; + v->capability = V4L2_TUNER_CAP_LOW; + if(radio->stereo) + v->audmode = V4L2_TUNER_MODE_STEREO; + else + v->audmode = V4L2_TUNER_MODE_MONO; + v->signal = 0xffff; /* We can't get the signal strength */ + return 0; +} - if (!radio) - return -EIO; +static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + if (v->index > 0) + return -EINVAL; - switch(cmd) { - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *v = arg; - memset(v,0,sizeof(*v)); - strlcpy(v->driver, "dsbr100", sizeof (v->driver)); - strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof (v->card)); - sprintf(v->bus_info,"ISA"); - v->version = RADIO_VERSION; - v->capabilities = V4L2_CAP_TUNER; + return 0; +} - return 0; - } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *v = arg; +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); - if (v->index > 0) - return -EINVAL; + radio->curfreq = f->frequency; + if (dsbr100_setfreq(radio, radio->curfreq)==-1) + warn("Set frequency failed"); + return 0; +} - dsbr100_getstat(radio); +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); - memset(v,0,sizeof(*v)); - strcpy(v->name, "FM"); - v->type = V4L2_TUNER_RADIO; + f->type = V4L2_TUNER_RADIO; + f->frequency = radio->curfreq; + return 0; +} - v->rangelow = FREQ_MIN*FREQ_MUL; - v->rangehigh = FREQ_MAX*FREQ_MUL; - v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; - v->capability=V4L2_TUNER_CAP_LOW; - if(radio->stereo) - v->audmode = V4L2_TUNER_MODE_STEREO; - else - v->audmode = V4L2_TUNER_MODE_MONO; - v->signal = 0xFFFF; /* We can't get the signal strength */ +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + int i; + for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { + if (qc->id && qc->id == radio_qctrl[i].id) { + memcpy(qc, &(radio_qctrl[i]), + sizeof(*qc)); return 0; } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *v = arg; - - if (v->index > 0) - return -EINVAL; + } + return -EINVAL; +} - return 0; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); - radio->curfreq = f->frequency; - if (dsbr100_setfreq(radio, radio->curfreq)==-1) - warn("Set frequency failed"); - return 0; - } - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + ctrl->value = radio->muted; + return 0; + } + return -EINVAL; +} - f->type = V4L2_TUNER_RADIO; - f->frequency = radio->curfreq; +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct dsbr100_device *radio = video_get_drvdata(video_devdata(file)); - return 0; - } - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *qc = arg; - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), - sizeof(*qc)); - return 0; - } - } - return -EINVAL; - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *ctrl= arg; - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - ctrl->value=radio->muted; - return 0; - } - return -EINVAL; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *ctrl= arg; - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) { - if (dsbr100_stop(radio)==-1) - warn("Radio did not respond properly"); - } else { - if (dsbr100_start(radio)==-1) - warn("Radio did not respond properly"); - } - return 0; - } - return -EINVAL; + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + if (ctrl->value) { + if (dsbr100_stop(radio)==-1) + warn("Radio did not respond properly"); + } else { + if (dsbr100_start(radio)==-1) + warn("Radio did not respond properly"); } - default: - return v4l_compat_translate_ioctl(inode,file,cmd,arg, - usb_dsbr100_do_ioctl); + return 0; } + return -EINVAL; } -static int usb_dsbr100_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) { - return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl); + if (a->index > 1) + return -EINVAL; + + strcpy(a->name, "Radio"); + a->capability = V4L2_AUDCAP_STEREO; + return 0; +} + +static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +{ + if (i != 0) + return -EINVAL; + return 0; +} + +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + if (a->index != 0) + return -EINVAL; + return 0; } static int usb_dsbr100_open(struct inode *inode, struct file *file) @@ -465,6 +430,68 @@ static int usb_dsbr100_close(struct inode *inode, struct file *file) return 0; } +/* File system interface */ +static const struct file_operations usb_dsbr100_fops = { + .owner = THIS_MODULE, + .open = usb_dsbr100_open, + .release = usb_dsbr100_close, + .ioctl = video_ioctl2, + .compat_ioctl = v4l_compat_ioctl32, + .llseek = no_llseek, +}; + +/* V4L2 interface */ +static struct video_device dsbr100_videodev_template = +{ + .owner = THIS_MODULE, + .name = "D-Link DSB-R 100", + .type = VID_TYPE_TUNER, + .fops = &usb_dsbr100_fops, + .release = video_device_release, + .vidioc_querycap = vidioc_querycap, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, +}; + +/* check if the device is present and register with v4l and +usb if it is */ +static int usb_dsbr100_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct dsbr100_device *radio; + + if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL))) + return -ENOMEM; + if (!(radio->videodev = video_device_alloc())) { + kfree(radio); + return -ENOMEM; + } + memcpy(radio->videodev, &dsbr100_videodev_template, + sizeof(dsbr100_videodev_template)); + radio->removed = 0; + radio->users = 0; + radio->usbdev = interface_to_usbdev(intf); + radio->curfreq = FREQ_MIN*FREQ_MUL; + video_set_drvdata(radio->videodev, radio); + if (video_register_device(radio->videodev, VFL_TYPE_RADIO,radio_nr)) { + warn("Could not register video device"); + video_device_release(radio->videodev); + kfree(radio); + return -EIO; + } + usb_set_intfdata(intf, radio); + return 0; +} + static int __init dsbr100_init(void) { int retval = usb_register(&usb_dsbr100_driver); diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 8fbf0d8bd27..8cf2e9df5c8 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -48,6 +48,25 @@ #define CADET_VERSION KERNEL_VERSION(0,3,3) +static struct v4l2_queryctrl radio_qctrl[] = { + { + .id = V4L2_CID_AUDIO_MUTE, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .default_value = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + },{ + .id = V4L2_CID_AUDIO_VOLUME, + .name = "Volume", + .minimum = 0, + .maximum = 0xff, + .step = 1, + .default_value = 0xff, + .type = V4L2_CTRL_TYPE_INTEGER, + } +}; + static int io=-1; /* default to isapnp activation */ static int radio_nr = -1; static int users=0; @@ -347,135 +366,165 @@ cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) } +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *v) +{ + v->capabilities = + V4L2_CAP_TUNER | + V4L2_CAP_READWRITE; + v->version = CADET_VERSION; + strcpy(v->driver, "ADS Cadet"); + strcpy(v->card, "ADS Cadet"); + return 0; +} -static int cadet_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) +static int vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) { - switch(cmd) - { - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = arg; - memset(cap,0,sizeof(*cap)); - cap->capabilities = - V4L2_CAP_TUNER | - V4L2_CAP_READWRITE; - cap->version = CADET_VERSION; - strcpy(cap->driver, "ADS Cadet"); - strcpy(cap->card, "ADS Cadet"); - return 0; + v->type = V4L2_TUNER_RADIO; + switch (v->index) { + case 0: + strcpy(v->name, "FM"); + v->capability = V4L2_TUNER_CAP_STEREO; + v->rangelow = 1400; /* 87.5 MHz */ + v->rangehigh = 1728; /* 108.0 MHz */ + v->rxsubchans=cadet_getstereo(); + switch (v->rxsubchans){ + case V4L2_TUNER_SUB_MONO: + v->audmode = V4L2_TUNER_MODE_MONO; + break; + case V4L2_TUNER_SUB_STEREO: + v->audmode = V4L2_TUNER_MODE_STEREO; + break; + default: ; } - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *t = arg; - memset(t,0,sizeof(*t)); - t->type = V4L2_TUNER_RADIO; - switch (t->index) - { - case 0: strcpy(t->name, "FM"); - t->capability = V4L2_TUNER_CAP_STEREO; - t->rangelow = 1400; /* 87.5 MHz */ - t->rangehigh = 1728; /* 108.0 MHz */ - t->rxsubchans=cadet_getstereo(); - switch (t->rxsubchans){ - case V4L2_TUNER_SUB_MONO: - t->audmode = V4L2_TUNER_MODE_MONO; - break; - case V4L2_TUNER_SUB_STEREO: - t->audmode = V4L2_TUNER_MODE_STEREO; - break; - default: ; - } - break; - case 1: strcpy(t->name, "AM"); - t->capability = V4L2_TUNER_CAP_LOW; - t->rangelow = 8320; /* 520 kHz */ - t->rangehigh = 26400; /* 1650 kHz */ - t->rxsubchans = V4L2_TUNER_SUB_MONO; - t->audmode = V4L2_TUNER_MODE_MONO; - break; - default: - return -EINVAL; - } + break; + case 1: + strcpy(v->name, "AM"); + v->capability = V4L2_TUNER_CAP_LOW; + v->rangelow = 8320; /* 520 kHz */ + v->rangehigh = 26400; /* 1650 kHz */ + v->rxsubchans = V4L2_TUNER_SUB_MONO; + v->audmode = V4L2_TUNER_MODE_MONO; + break; + default: + return -EINVAL; + } + v->signal = sigstrength; /* We might need to modify scaling of this */ + return 0; +} - t->signal = sigstrength; /* We might need to modify scaling of this */ - return 0; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *t = arg; - if((t->index != 0)&&(t->index != 1)) - return -EINVAL; +static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + if((v->index != 0)&&(v->index != 1)) + return -EINVAL; + curtuner = v->index; + return 0; +} - curtuner = t->index; - return 0; - } - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; - memset(f,0,sizeof(*f)); - f->tuner = curtuner; - f->type = V4L2_TUNER_RADIO; - f->frequency = cadet_getfreq(); - return 0; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; - if (f->type != V4L2_TUNER_RADIO){ - return -EINVAL; - } - if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728))) { - return -EINVAL; - } - if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400))) { - return -EINVAL; - } - cadet_setfreq(f->frequency); - return 0; - } - case VIDIOC_G_CTRL: - { - struct v4l2_control *c = arg; - switch (c->id){ - case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ - c->value = (cadet_getvol() == 0); - break; - case V4L2_CID_AUDIO_VOLUME: - c->value = cadet_getvol(); - break; - default: - return -EINVAL; - } - return 0; - } - case VIDIOC_S_CTRL: - { - struct v4l2_control *c = arg; - switch (c->id){ - case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ - if (c->value) cadet_setvol(0); - else cadet_setvol(0xffff); - break; - case V4L2_CID_AUDIO_VOLUME: - cadet_setvol(c->value); - break; - default: - return -EINVAL; - } +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + f->tuner = curtuner; + f->type = V4L2_TUNER_RADIO; + f->frequency = cadet_getfreq(); + return 0; +} + + +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + if (f->type != V4L2_TUNER_RADIO) + return -EINVAL; + if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728))) + return -EINVAL; + if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400))) + return -EINVAL; + cadet_setfreq(f->frequency); + return 0; +} + +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { + if (qc->id && qc->id == radio_qctrl[i].id) { + memcpy(qc, &(radio_qctrl[i]), + sizeof(*qc)); return 0; } + } + return -EINVAL; +} - default: - return -ENOIOCTLCMD; +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + switch (ctrl->id){ + case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ + ctrl->value = (cadet_getvol() == 0); + break; + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = cadet_getvol(); + break; + default: + return -EINVAL; } + return 0; } -static int -cadet_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) { - return video_usercopy(inode, file, cmd, arg, cadet_do_ioctl); + switch (ctrl->id){ + case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ + if (ctrl->value) + cadet_setvol(0); + else + cadet_setvol(0xffff); + break; + case V4L2_CID_AUDIO_VOLUME: + cadet_setvol(ctrl->value); + break; + default: + return -EINVAL; + } + return 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + if (a->index > 1) + return -EINVAL; + strcpy(a->name, "Radio"); + a->capability = V4L2_AUDCAP_STEREO; + return 0; +} + +static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +{ + if (i != 0) + return -EINVAL; + return 0; +} + +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + if (a->index != 0) + return -EINVAL; + return 0; } static int @@ -512,7 +561,7 @@ static const struct file_operations cadet_fops = { .open = cadet_open, .release = cadet_release, .read = cadet_read, - .ioctl = cadet_ioctl, + .ioctl = video_ioctl2, .poll = cadet_poll, .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, @@ -524,6 +573,18 @@ static struct video_device cadet_radio= .name = "Cadet radio", .type = VID_TYPE_TUNER, .fops = &cadet_fops, + .vidioc_querycap = vidioc_querycap, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, }; static struct pnp_device_id cadet_pnp_devices[] = { diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c index 11f80cacd6e..8e33a19a22a 100644 --- a/drivers/media/radio/radio-maestro.c +++ b/drivers/media/radio/radio-maestro.c @@ -24,7 +24,6 @@ #include <linux/delay.h> #include <asm/io.h> #include <asm/uaccess.h> -#include <linux/mutex.h> #include <linux/pci.h> #include <linux/videodev2.h> #include <media/v4l2-common.h> @@ -110,7 +109,6 @@ struct radio_device { muted, /* VIDEO_AUDIO_MUTE */ stereo, /* VIDEO_TUNER_STEREO_ON */ tuned; /* signal strength (0 or 0xffff) */ - struct mutex lock; }; static u32 radio_bits_get(struct radio_device *dev) @@ -394,7 +392,6 @@ static int __devinit maestro_probe(struct pci_dev *pdev, } radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA; - mutex_init(&radio_unit->lock); maestro_radio_inst = video_device_alloc(); if (maestro_radio_inst == NULL) { diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index a4715901512..203f4373eeb 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c @@ -410,7 +410,6 @@ static struct video_device zoltrix_radio = .owner = THIS_MODULE, .name = "Zoltrix Radio Plus", .type = VID_TYPE_TUNER, - .hardware = 0, .fops = &zoltrix_fops, .vidioc_querycap = vidioc_querycap, .vidioc_g_tuner = vidioc_g_tuner, diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index bc773781993..5cb3f54b548 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -2,14 +2,19 @@ # Multimedia Video device configuration # -menu "Video Capture Adapters" +menuconfig VIDEO_CAPTURE_DRIVERS + bool "Video capture adapters" depends on VIDEO_DEV + default y + ---help--- + Say Y here to enable selecting the video adapters for + webcams, analog TV, and hybrid analog/digital TV. + Some of those devices also supports FM radio. -comment "Video Capture Adapters" +if VIDEO_CAPTURE_DRIVERS config VIDEO_ADV_DEBUG bool "Enable advanced debug functionality" - depends on VIDEO_DEV default n ---help--- Say Y here to enable advanced debugging functionality on some @@ -34,7 +39,7 @@ config VIDEO_HELPER_CHIPS_AUTO # menu "Encoders/decoders and other helper chips" - depends on VIDEO_DEV && !VIDEO_HELPER_CHIPS_AUTO + depends on !VIDEO_HELPER_CHIPS_AUTO comment "Audio decoders" @@ -61,7 +66,7 @@ config VIDEO_TDA7432 config VIDEO_TDA9840 tristate "Philips TDA9840 audio processor" - depends on VIDEO_DEV && I2C + depends on I2C ---help--- Support for tda9840 audio decoder chip found on some Zoran boards. @@ -79,7 +84,7 @@ config VIDEO_TDA9875 config VIDEO_TEA6415C tristate "Philips TEA6415C audio processor" - depends on VIDEO_DEV && I2C + depends on I2C ---help--- Support for tea6415c audio decoder chip found on some bt8xx boards. @@ -88,7 +93,7 @@ config VIDEO_TEA6415C config VIDEO_TEA6420 tristate "Philips TEA6420 audio processor" - depends on VIDEO_DEV && I2C + depends on I2C ---help--- Support for tea6420 audio decoder chip found on some bt8xx boards. @@ -469,7 +474,7 @@ config VIDEO_SAA5246A config VIDEO_SAA5249 tristate "SAA5249 Teletext processor" - depends on VIDEO_DEV && I2C && VIDEO_V4L2 + depends on I2C && VIDEO_V4L2 help Support for I2C bus based teletext using the SAA5249 chip. At the moment this is only useful on some European WinTV cards. @@ -479,7 +484,7 @@ config VIDEO_SAA5249 config TUNER_3036 tristate "SAB3036 tuner" - depends on VIDEO_DEV && I2C && VIDEO_V4L1 + depends on I2C && VIDEO_V4L1 help Say Y here to include support for Philips SAB3036 compatible tuners. If in doubt, say N. @@ -681,8 +686,12 @@ config VIDEO_CAFE_CCIC # USB Multimedia device configuration # -menu "V4L USB devices" - depends on USB && VIDEO_DEV +menuconfig V4L_USB_DRIVERS + bool "V4L USB devices" + depends on USB + default y + +if V4L_USB_DRIVERS source "drivers/media/video/pvrusb2/Kconfig" @@ -707,7 +716,7 @@ config VIDEO_OVCAMCHIP config USB_W9968CF tristate "USB W996[87]CF JPEG Dual Mode Camera support" - depends on USB && VIDEO_V4L1 && I2C + depends on VIDEO_V4L1 && I2C select VIDEO_OVCAMCHIP ---help--- Say Y here if you want support for cameras based on OV681 or @@ -725,7 +734,7 @@ config USB_W9968CF config USB_OV511 tristate "USB OV511 Camera support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. See <file:Documentation/video4linux/ov511.txt> @@ -736,7 +745,7 @@ config USB_OV511 config USB_SE401 tristate "USB SE401 Camera support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. See <file:Documentation/video4linux/se401.txt> @@ -749,7 +758,7 @@ source "drivers/media/video/sn9c102/Kconfig" config USB_STV680 tristate "USB STV680 (Pencam) Camera support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. This includes the Pencam line of cameras. @@ -765,7 +774,7 @@ source "drivers/media/video/pwc/Kconfig" config USB_ZR364XX tristate "USB ZR364XX Camera support" - depends on USB && VIDEO_V4L2 + depends on VIDEO_V4L2 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. @@ -775,6 +784,6 @@ config USB_ZR364XX To compile this driver as a module, choose M here: the module will be called zr364xx. -endmenu # V4L USB devices +endif # V4L_USB_DRIVERS -endmenu +endif # VIDEO_CAPTURE_DRIVERS diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 1757a588970..67bda9f9a44 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -555,7 +555,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) { struct v4l2_pix_format *pix; int HSC, VSC, Vsrc, Hsrc, filter, Vlines; - int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); + int is_50Hz = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); switch (fmt->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: @@ -567,7 +567,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4; Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4; - Vlines = pix->height + (is_pal ? 4 : 7); + Vlines = pix->height + (is_50Hz ? 4 : 7); if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) || (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) { diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 2ebde2fdbcb..543b05ebc0e 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -28,6 +28,7 @@ #include <linux/device.h> #include <linux/dma-mapping.h> #include <linux/interrupt.h> +#include <linux/dma-mapping.h> #include <asm/delay.h> #include "cx88.h" @@ -612,7 +613,7 @@ struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board } /* Driver asked for hardware access. */ -int cx8802_request_acquire(struct cx8802_driver *drv) +static int cx8802_request_acquire(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; @@ -632,7 +633,7 @@ int cx8802_request_acquire(struct cx8802_driver *drv) } /* Driver asked to release hardware. */ -int cx8802_request_release(struct cx8802_driver *drv) +static int cx8802_request_release(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index b94ef8ab28c..98fa35421bd 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -36,6 +36,7 @@ #include <linux/dma-mapping.h> #include <linux/delay.h> #include <linux/kthread.h> +#include <linux/dma-mapping.h> #include <asm/div64.h> #include "cx88.h" diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c index 6068c9bf82c..82bc3a28aa2 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c @@ -111,10 +111,6 @@ static struct i2c_adapter vp3054_i2c_adap_template = { .id = I2C_HW_B_CX2388x, }; -static struct i2c_client vp3054_i2c_client_template = { - .name = "VP-3054", -}; - int vp3054_i2c_probe(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; @@ -133,8 +129,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) sizeof(vp3054_i2c->adap)); memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template, sizeof(vp3054_i2c->algo)); - memcpy(&vp3054_i2c->client, &vp3054_i2c_client_template, - sizeof(vp3054_i2c->client)); vp3054_i2c->adap.class |= I2C_CLASS_TV_DIGITAL; @@ -144,7 +138,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) vp3054_i2c->algo.data = dev; i2c_set_adapdata(&vp3054_i2c->adap, dev); vp3054_i2c->adap.algo_data = &vp3054_i2c->algo; - vp3054_i2c->client.adapter = &vp3054_i2c->adap; vp3054_bit_setscl(dev,1); vp3054_bit_setsda(dev,1); diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.h b/drivers/media/video/cx88/cx88-vp3054-i2c.h index b7a0a04d242..637a7d23223 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.h +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.h @@ -26,7 +26,6 @@ struct vp3054_i2c_state { struct i2c_adapter adap; struct i2c_algo_bit_data algo; - struct i2c_client client; u32 state; }; diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 9285a58e47a..3823b62da4a 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -1,6 +1,6 @@ config VIDEO_EM28XX tristate "Empia EM2800/2820/2840 USB video capture support" - depends on VIDEO_V4L1 && USB && I2C + depends on VIDEO_V4L1 && I2C select VIDEO_BUF select VIDEO_TUNER select VIDEO_TVEEPROM diff --git a/drivers/media/video/et61x251/Kconfig b/drivers/media/video/et61x251/Kconfig index c6bff705688..664676f4406 100644 --- a/drivers/media/video/et61x251/Kconfig +++ b/drivers/media/video/et61x251/Kconfig @@ -1,6 +1,6 @@ config USB_ET61X251 tristate "USB ET61X[12]51 PC Camera Controller support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y here if you want support for cameras based on Etoms ET61X151 or ET61X251 PC Camera Controllers. diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 45b9328a538..e29f949adf5 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -74,7 +74,7 @@ int ivtv_first_minor = 0; struct ivtv *ivtv_cards[IVTV_MAX_CARDS]; /* Protects ivtv_cards_active */ -spinlock_t ivtv_cards_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(ivtv_cards_lock); /* add your revision and whatnot here */ static struct pci_device_id ivtv_pci_tbl[] __devinitdata = { diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 1637097ddec..8976487a65f 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -804,7 +804,7 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) struct ivtv_open_id *item; struct ivtv *itv = NULL; struct ivtv_stream *s = NULL; - int minor = MINOR(inode->i_rdev); + int minor = iminor(inode); /* Find which card this open was on */ spin_lock(&ivtv_cards_lock); diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index 5645c931889..d0c2cd78543 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig @@ -1,6 +1,6 @@ config VIDEO_PVRUSB2 tristate "Hauppauge WinTV-PVR USB2 support" - depends on VIDEO_V4L2 && USB && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && I2C && EXPERIMENTAL select FW_LOADER select VIDEO_TUNER select VIDEO_TVEEPROM diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index 5669c8ca9ca..20b614436d2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -391,22 +391,29 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw) int pvr2_encoder_configure(struct pvr2_hdw *hdw) { int ret; + int val; pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure" " (cx2341x module)"); hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING; hdw->enc_ctl_state.width = hdw->res_hor_val; hdw->enc_ctl_state.height = hdw->res_ver_val; - hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & - (V4L2_STD_NTSC|V4L2_STD_PAL_M)) ? + hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & V4L2_STD_525_60) ? 0 : 1); ret = 0; ret |= pvr2_encoder_prep_config(hdw); + /* saa7115: 0xf0 */ + val = 0xf0; + if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { + /* ivtv cx25840: 0x140 */ + val = 0x140; + } + if (!ret) ret = pvr2_encoder_vcmd( hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, - 0xf0, 0xf0); + val, val); /* setup firmware to notify us about some events (don't know why...) */ if (!ret) ret = pvr2_encoder_vcmd( diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index acf651e01f9..1311891e7ee 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -83,7 +83,7 @@ static struct pvr2_string_table pvr2_client_lists[] = { }; static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL}; -static DECLARE_MUTEX(pvr2_unit_sem); +static DEFINE_MUTEX(pvr2_unit_mtx); static int ctlchg = 0; static int initusbreset = 1; @@ -2076,14 +2076,14 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL); if (!hdw->ctl_read_urb) goto fail; - down(&pvr2_unit_sem); do { + mutex_lock(&pvr2_unit_mtx); do { for (idx = 0; idx < PVR_NUM; idx++) { if (unit_pointers[idx]) continue; hdw->unit_number = idx; unit_pointers[idx] = hdw; break; } - } while (0); up(&pvr2_unit_sem); + } while (0); mutex_unlock(&pvr2_unit_mtx); cnt1 = 0; cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2"); @@ -2186,13 +2186,13 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) } pvr2_i2c_core_done(hdw); pvr2_hdw_remove_usb_stuff(hdw); - down(&pvr2_unit_sem); do { + mutex_lock(&pvr2_unit_mtx); do { if ((hdw->unit_number >= 0) && (hdw->unit_number < PVR_NUM) && (unit_pointers[hdw->unit_number] == hdw)) { unit_pointers[hdw->unit_number] = NULL; } - } while (0); up(&pvr2_unit_sem); + } while (0); mutex_unlock(&pvr2_unit_mtx); kfree(hdw->controls); kfree(hdw->mpeg_ctrl_info); kfree(hdw->std_defs); diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 58fc3c730fe..6786d3c0c98 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -23,6 +23,7 @@ #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" #include "pvrusb2-fx2-cmd.h" +#include "pvrusb2.h" #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) @@ -38,6 +39,10 @@ static unsigned int i2c_scan = 0; module_param(i2c_scan, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); +static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 }; +module_param_array(ir_mode, int, NULL, 0444); +MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR"); + static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, unsigned int detail, char *buf,unsigned int maxlen); @@ -273,6 +278,15 @@ static int i2c_hack_wm8775(struct pvr2_hdw *hdw, return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen); } +/* This is an entry point designed to always fail any attempt to perform a + transfer. We use this to cause certain I2C addresses to not be + probed. */ +static int i2c_black_hole(struct pvr2_hdw *hdw, + u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen) +{ + return -EIO; +} + /* This is a special entry point that is entered if an I2C operation is attempted to a cx25840 chip on model 24xxx hardware. This chip can sometimes wedge itself. Worse still, when this happens msp3400 can @@ -994,10 +1008,17 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) } /* However, deal with various special cases for 24xxx hardware. */ + if (ir_mode[hdw->unit_number] == 0) { + printk(KERN_INFO "%s: IR disabled\n",hdw->name); + hdw->i2c_func[0x18] = i2c_black_hole; + } else if (ir_mode[hdw->unit_number] == 1) { + if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { + hdw->i2c_func[0x18] = i2c_24xxx_ir; + } + } if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { hdw->i2c_func[0x1b] = i2c_hack_wm8775; hdw->i2c_func[0x44] = i2c_hack_cx25840; - hdw->i2c_func[0x18] = i2c_24xxx_ir; } // Configure the adapter and set up everything else related to it. diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index a741c556a39..7ab79baa1c8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -518,40 +518,32 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) } sfp->item_last = cip; - cip->attr_name.attr.owner = THIS_MODULE; cip->attr_name.attr.name = "name"; cip->attr_name.attr.mode = S_IRUGO; cip->attr_name.show = fp->show_name; - cip->attr_type.attr.owner = THIS_MODULE; cip->attr_type.attr.name = "type"; cip->attr_type.attr.mode = S_IRUGO; cip->attr_type.show = fp->show_type; - cip->attr_min.attr.owner = THIS_MODULE; cip->attr_min.attr.name = "min_val"; cip->attr_min.attr.mode = S_IRUGO; cip->attr_min.show = fp->show_min; - cip->attr_max.attr.owner = THIS_MODULE; cip->attr_max.attr.name = "max_val"; cip->attr_max.attr.mode = S_IRUGO; cip->attr_max.show = fp->show_max; - cip->attr_val.attr.owner = THIS_MODULE; cip->attr_val.attr.name = "cur_val"; cip->attr_val.attr.mode = S_IRUGO; - cip->attr_custom.attr.owner = THIS_MODULE; cip->attr_custom.attr.name = "custom_val"; cip->attr_custom.attr.mode = S_IRUGO; - cip->attr_enum.attr.owner = THIS_MODULE; cip->attr_enum.attr.name = "enum_val"; cip->attr_enum.attr.mode = S_IRUGO; cip->attr_enum.show = fp->show_enum; - cip->attr_bits.attr.owner = THIS_MODULE; cip->attr_bits.attr.name = "bit_val"; cip->attr_bits.attr.mode = S_IRUGO; cip->attr_bits.show = fp->show_bits; @@ -616,12 +608,10 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) dip = kzalloc(sizeof(*dip),GFP_KERNEL); if (!dip) return; - dip->attr_debugcmd.attr.owner = THIS_MODULE; dip->attr_debugcmd.attr.name = "debugcmd"; dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP; dip->attr_debugcmd.show = debugcmd_show; dip->attr_debugcmd.store = debugcmd_store; - dip->attr_debuginfo.attr.owner = THIS_MODULE; dip->attr_debuginfo.attr.name = "debuginfo"; dip->attr_debuginfo.attr.mode = S_IRUGO; dip->attr_debuginfo.show = debuginfo_show; @@ -811,7 +801,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp, return; } - sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE; sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number"; sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; sfp->attr_v4l_minor_number.show = v4l_minor_number_show; @@ -825,7 +814,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->v4l_minor_number_created_ok = !0; } - sfp->attr_v4l_radio_minor_number.attr.owner = THIS_MODULE; sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number"; sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO; sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show; @@ -839,7 +827,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->v4l_radio_minor_number_created_ok = !0; } - sfp->attr_unit_number.attr.owner = THIS_MODULE; sfp->attr_unit_number.attr.name = "unit_number"; sfp->attr_unit_number.attr.mode = S_IRUGO; sfp->attr_unit_number.show = unit_number_show; @@ -852,7 +839,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->unit_number_created_ok = !0; } - sfp->attr_bus_info.attr.owner = THIS_MODULE; sfp->attr_bus_info.attr.name = "bus_info_str"; sfp->attr_bus_info.attr.mode = S_IRUGO; sfp->attr_bus_info.show = bus_info_show; diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig index 8fdf7101d3b..7298cf2e165 100644 --- a/drivers/media/video/pwc/Kconfig +++ b/drivers/media/video/pwc/Kconfig @@ -1,6 +1,6 @@ config USB_PWC tristate "USB Philips Cameras" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y or M here if you want to use one of these Philips & OEM webcams: diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 4ea479baee7..50f15adfa7c 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -1170,6 +1170,42 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE2, }, }, + [SAA7134_BOARD_ECS_TVP3XP_4CB6] = { + /* Barry Scott <barry.scott@onelan.co.uk> */ + .name = "Elitegroup ECS TVP3XP FM1246 Tuner Card (PAL,FM)", + .audio_clock = 0x187de7, + .tuner_type = TUNER_PHILIPS_PAL_I, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_tv_mono, + .vmux = 1, + .amux = LINE2, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + },{ + .name = "CVid over SVid", + .vmux = 0, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + }, + }, [SAA7134_BOARD_AVACSSMARTTV] = { /* Roman Pszonczenko <romka@kolos.math.uni.lodz.pl> */ .name = "AVACS SmartTV", @@ -2754,6 +2790,35 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }, }, + [SAA7134_BOARD_KWORLD_DVBT_210] = { + .name = "KWorld DVB-T 210", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 1 << 21, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, + }, + }, [SAA7134_BOARD_KWORLD_ATSC110] = { .name = "Kworld ATSC110", .audio_clock = 0x00187de7, @@ -3407,6 +3472,36 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200000, }, }, + [SAA7134_BOARD_SABRENT_TV_PCB05] = { + .name = "Sabrent PCMCIA TV-PCB05", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + },{ + .name = name_comp2, + .vmux = 0, + .amux = LINE1, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + }}, + .mute = { + .name = name_mute, + .amux = TV, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -3515,7 +3610,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x5168, /* Animation Technologies (LifeView) */ - .subdevice = 0x0214, /* Standard PCI, LR214WF */ + .subdevice = 0x0214, /* Standard PCI, LR214 Rev E and earlier (SAA7135) */ + .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5168, /* Animation Technologies (LifeView) */ + .subdevice = 0x5214, /* Standard PCI, LR214 Rev F onwards (SAA7131) */ .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, },{ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -3689,6 +3790,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .driver_data = SAA7134_BOARD_ECS_TVP3XP_4CB5, },{ .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1019, + .subdevice = 0x4cb6, + .driver_data = SAA7134_BOARD_ECS_TVP3XP_4CB6, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x12ab, .subdevice = 0x0800, @@ -3915,6 +4022,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .driver_data = SAA7134_BOARD_TEVION_DVBT_220RF, },{ .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x17de, + .subdevice = 0x7250, + .driver_data = SAA7134_BOARD_KWORLD_DVBT_210, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ .subvendor = 0x17de, .subdevice = 0x7350, @@ -4100,6 +4213,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x4857, .driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x0919, /* SinoVideo PCI 2309 Proteus (7134) */ + .subdevice = 0x2003, /* OEM cardbus */ + .driver_data = SAA7134_BOARD_SABRENT_TV_PCB05, + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -4178,6 +4297,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_CINERGY600_MK3: case SAA7134_BOARD_ECS_TVP3XP: case SAA7134_BOARD_ECS_TVP3XP_4CB5: + case SAA7134_BOARD_ECS_TVP3XP_4CB6: case SAA7134_BOARD_MD2819: case SAA7134_BOARD_KWORLD_VSTREAM_XPERT: case SAA7134_BOARD_KWORLD_XPERT: @@ -4426,6 +4546,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; case SAA7134_BOARD_PINNACLE_PCTV_310i: + case SAA7134_BOARD_KWORLD_DVBT_210: case SAA7134_BOARD_TEVION_DVBT_220RF: case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 65aec881bbd..e0eec80088c 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -887,6 +887,20 @@ static struct tda1004x_config asus_p7131_hybrid_lna_config = { .antenna_switch= 2, .request_firmware = philips_tda1004x_request_firmware }; +static struct tda1004x_config kworld_dvb_t_210_config = { + .demod_address = 0x08, + .invert = 1, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_16M, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP11_I, + .if_freq = TDA10046_FREQ_045, + .i2c_gate = 0x4b, + .tuner_address = 0x61, + .tuner_config = 2, + .antenna_switch= 1, + .request_firmware = philips_tda1004x_request_firmware +}; /* ------------------------------------------------------------------ * special case: this card uses saa713x GPIO22 for the mode switch */ @@ -1039,6 +1053,9 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set; } break; + case SAA7134_BOARD_KWORLD_DVBT_210: + configure_tda827x_fe(dev, &kworld_dvb_t_210_config); + break; case SAA7134_BOARD_PHILIPS_TIGER: configure_tda827x_fe(dev, &philips_tiger_config); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 62224cc958f..15623b27ad2 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -235,6 +235,9 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_M102 110 #define SAA7134_BOARD_ASUS_P7131_4871 111 #define SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA 112 +#define SAA7134_BOARD_ECS_TVP3XP_4CB6 113 +#define SAA7134_BOARD_KWORLD_DVBT_210 114 +#define SAA7134_BOARD_SABRENT_TV_PCB05 115 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig index 19204f5686e..f71f272776d 100644 --- a/drivers/media/video/sn9c102/Kconfig +++ b/drivers/media/video/sn9c102/Kconfig @@ -1,6 +1,6 @@ config USB_SN9C102 tristate "USB SN9C1xx PC Camera Controller support" - depends on USB && VIDEO_V4L2 + depends on VIDEO_V4L2 ---help--- Say Y here if you want support for cameras based on SONiX SN9C101, SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers. diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h index 680e7463452..11fcb49f5b9 100644 --- a/drivers/media/video/sn9c102/sn9c102.h +++ b/drivers/media/video/sn9c102/sn9c102.h @@ -141,7 +141,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id) void sn9c102_attach_sensor(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) + const struct sn9c102_sensor* sensor) { memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor)); } diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 89f83354de3..74a204f8ebc 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -48,8 +48,8 @@ #define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia" #define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" #define SN9C102_MODULE_LICENSE "GPL" -#define SN9C102_MODULE_VERSION "1:1.39" -#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 39) +#define SN9C102_MODULE_VERSION "1:1.44" +#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 44) /*****************************************************************************/ @@ -209,38 +209,41 @@ static void sn9c102_queue_unusedframes(struct sn9c102_device* cam) } /*****************************************************************************/ + /* - * Write a sequence of count value/register pairs. Returns -1 after the - * first failed write, or 0 for no errors. - */ + Write a sequence of count value/register pairs. Returns -1 after the first + failed write, or 0 for no errors. +*/ int sn9c102_write_regs(struct sn9c102_device* cam, const u8 valreg[][2], int count) { struct usb_device* udev = cam->usbdev; - u8* value = cam->control_buffer; /* Needed for DMA'able memory */ + u8* buff = cam->control_buffer; int i, res; for (i = 0; i < count; i++) { u8 index = valreg[i][1]; /* - * index is a u8, so it must be <256 and can't be out of range. - * If we put in a check anyway, gcc annoys us with a warning - * that our check is useless. People get all uppity when they - * see warnings in the kernel compile. - */ - - *value = valreg[i][0]; - res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - 0x08, 0x41, index, 0, - value, 1, SN9C102_CTRL_TIMEOUT); + index is a u8, so it must be <256 and can't be out of range. + If we put in a check anyway, gcc annoys us with a warning + hat our check is useless. People get all uppity when they + see warnings in the kernel compile. + */ + + *buff = valreg[i][0]; + + res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, + 0x41, index, 0, buff, 1, + SN9C102_CTRL_TIMEOUT); + if (res < 0) { DBG(3, "Failed to write a register (value 0x%02X, " - "index 0x%02X, error %d)", *value, index, res); + "index 0x%02X, error %d)", *buff, index, res); return -1; } - cam->reg[index] = *value; + cam->reg[index] = *buff; } return 0; @@ -272,8 +275,8 @@ int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index) } -/* NOTE: reading some registers always returns 0 */ -static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index) +/* NOTE: with the SN9C10[123] reading some registers always returns 0 */ +int sn9c102_read_reg(struct sn9c102_device* cam, u16 index) { struct usb_device* udev = cam->usbdev; u8* buff = cam->control_buffer; @@ -299,7 +302,8 @@ int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index) static int -sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor) +sn9c102_i2c_wait(struct sn9c102_device* cam, + const struct sn9c102_sensor* sensor) { int i, r; @@ -320,7 +324,7 @@ sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor) static int sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) + const struct sn9c102_sensor* sensor) { int r , err = 0; @@ -342,7 +346,7 @@ sn9c102_i2c_detect_read_error(struct sn9c102_device* cam, static int sn9c102_i2c_detect_write_error(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor) + const struct sn9c102_sensor* sensor) { int r; r = sn9c102_read_reg(cam, 0x08); @@ -352,12 +356,12 @@ sn9c102_i2c_detect_write_error(struct sn9c102_device* cam, int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 data0, u8 data1, - u8 n, u8 buffer[]) + const struct sn9c102_sensor* sensor, u8 data0, + u8 data1, u8 n, u8 buffer[]) { struct usb_device* udev = cam->usbdev; u8* data = cam->control_buffer; - int err = 0, res; + int i = 0, err = 0, res; /* Write cycle */ data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) | @@ -402,7 +406,8 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, } if (buffer) - memcpy(buffer, data, sizeof(buffer)); + for (i = 0; i < n && i < 5; i++) + buffer[n-i-1] = data[4-i]; return (int)data[4]; } @@ -410,7 +415,7 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 n, u8 data0, + const struct sn9c102_sensor* sensor, u8 n, u8 data0, u8 data1, u8 data2, u8 data3, u8 data4, u8 data5) { struct usb_device* udev = cam->usbdev; @@ -449,7 +454,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, int sn9c102_i2c_try_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 address) + const struct sn9c102_sensor* sensor, u8 address) { return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id, address, 1, NULL); @@ -458,7 +463,7 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam, int sn9c102_i2c_try_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 address, u8 value) + const struct sn9c102_sensor* sensor, u8 address, u8 value) { return sn9c102_i2c_try_raw_write(cam, sensor, 3, sensor->i2c_slave_id, address, @@ -657,16 +662,6 @@ sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f) } -static void -sn9c102_write_eoimarker(struct sn9c102_device* cam, struct sn9c102_frame_t* f) -{ - static const u8 eoi_marker[2] = {0xff, 0xd9}; - - memcpy(f->bufmem + f->buf.bytesused, eoi_marker, sizeof(eoi_marker)); - f->buf.bytesused += sizeof(eoi_marker); -} - - static void sn9c102_urb_complete(struct urb *urb) { struct sn9c102_device* cam = urb->context; @@ -3181,14 +3176,14 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp, static const struct file_operations sn9c102_fops = { .owner = THIS_MODULE, - .open = sn9c102_open, + .open = sn9c102_open, .release = sn9c102_release, - .ioctl = sn9c102_ioctl, + .ioctl = sn9c102_ioctl, .compat_ioctl = v4l_compat_ioctl32, - .read = sn9c102_read, - .poll = sn9c102_poll, - .mmap = sn9c102_mmap, - .llseek = no_llseek, + .read = sn9c102_read, + .poll = sn9c102_poll, + .mmap = sn9c102_mmap, + .llseek = no_llseek, }; /*****************************************************************************/ @@ -3251,7 +3246,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) break; } - for (i = 0; sn9c102_sensor_table[i]; i++) { + for (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) { err = sn9c102_sensor_table[i](cam); if (!err) break; @@ -3262,7 +3257,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) DBG(3, "Support for %s maintained by %s", cam->sensor.name, cam->sensor.maintainer); } else { - DBG(1, "No supported image sensor detected"); + DBG(1, "No supported image sensor detected for this bridge"); err = -ENODEV; goto fail; } diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index f49bd8c5b86..916054faf9b 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h @@ -86,6 +86,8 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, /* SN9C105 */ + { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), }, + { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), }, @@ -100,6 +102,7 @@ static const struct usb_device_id sn9c102_id_table[] = { { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), }, { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), }, /* SN9C120 */ + { SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, @@ -148,7 +151,6 @@ static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */ &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ - NULL, }; #endif /* _SN9C102_DEVTABLE_H_ */ diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c index 28a861aed04..eaf9ad0dc8a 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131d.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131d.c @@ -144,7 +144,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor hv7131d = { +static const struct sn9c102_sensor hv7131d = { .name = "HV7131D", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, @@ -248,12 +248,10 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam) err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, {0x28, 0x17}); - if (err) - return -EIO; r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00); r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01); - if (r0 < 0 || r1 < 0) + if (err || r0 < 0 || r1 < 0) return -EIO; if (r0 != 0x00 || r1 != 0x04) diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131r.c b/drivers/media/video/sn9c102/sn9c102_hv7131r.c index 5a495baa5f9..0fc401223cf 100644 --- a/drivers/media/video/sn9c102/sn9c102_hv7131r.c +++ b/drivers/media/video/sn9c102/sn9c102_hv7131r.c @@ -44,7 +44,6 @@ static int hv7131r_init(struct sn9c102_device* cam) {0xb0, 0x2b}, {0xc0, 0x2c}, {0xd0, 0x2d}, {0xe0, 0x2e}, {0xf0, 0x2f}, {0xff, 0x30}); - break; case BRIDGE_SN9C105: case BRIDGE_SN9C120: @@ -254,7 +253,7 @@ static int hv7131r_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor hv7131r = { +static const struct sn9c102_sensor hv7131r = { .name = "HV7131R", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120, @@ -350,11 +349,8 @@ int sn9c102_probe_hv7131r(struct sn9c102_device* cam) {0x34, 0x01}, {0x20, 0x17}, {0x34, 0x01}, {0x46, 0x01}); - if (err) - return -EIO; - devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00); - if (devid < 0) + if (err || devid < 0) return -EIO; if (devid != 0x02) diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c index 9200845d011..00b134ca0a3 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0343.c +++ b/drivers/media/video/sn9c102/sn9c102_mi0343.c @@ -55,45 +55,45 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam, struct v4l2_control* ctrl) { struct sn9c102_sensor* s = sn9c102_get_sensor(cam); - u8 data[5+1]; + u8 data[2]; switch (ctrl->id) { case V4L2_CID_EXPOSURE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2, + data) < 0) return -EIO; - ctrl->value = data[2]; + ctrl->value = data[0]; return 0; case V4L2_CID_GAIN: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2, + data) < 0) return -EIO; break; case V4L2_CID_HFLIP: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, + data) < 0) return -EIO; - ctrl->value = data[3] & 0x20 ? 1 : 0; + ctrl->value = data[1] & 0x20 ? 1 : 0; return 0; case V4L2_CID_VFLIP: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, + data) < 0) return -EIO; - ctrl->value = data[3] & 0x80 ? 1 : 0; + ctrl->value = data[1] & 0x80 ? 1 : 0; return 0; case V4L2_CID_RED_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2, + data) < 0) return -EIO; break; case V4L2_CID_BLUE_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2, + data) < 0) return -EIO; break; case SN9C102_V4L2_CID_GREEN_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2, + data) < 0) return -EIO; break; default: @@ -105,7 +105,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam, case V4L2_CID_RED_BALANCE: case V4L2_CID_BLUE_BALANCE: case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = data[3] | (data[2] << 8); + ctrl->value = data[1] | (data[0] << 8); if (ctrl->value >= 0x10 && ctrl->value <= 0x3f) ctrl->value -= 0x10; else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f) @@ -223,7 +223,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor mi0343 = { +static const struct sn9c102_sensor mi0343 = { .name = "MI-0343", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, @@ -332,20 +332,17 @@ static struct sn9c102_sensor mi0343 = { int sn9c102_probe_mi0343(struct sn9c102_device* cam) { - u8 data[5+1]; - int err = 0; - - err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, - {0x28, 0x17}); + u8 data[2]; - if (err) + if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17})) return -EIO; if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00, 2, data) < 0) return -EIO; - if (data[4] != 0x32 || data[3] != 0xe3) + if (data[1] != 0x42 || data[0] != 0xe3) return -ENODEV; sn9c102_attach_sensor(cam, &mi0343); diff --git a/drivers/media/video/sn9c102/sn9c102_mi0360.c b/drivers/media/video/sn9c102/sn9c102_mi0360.c index 64698acb0b1..f8d81d82e8d 100644 --- a/drivers/media/video/sn9c102/sn9c102_mi0360.c +++ b/drivers/media/video/sn9c102/sn9c102_mi0360.c @@ -27,20 +27,105 @@ static int mi0360_init(struct sn9c102_device* cam) struct sn9c102_sensor* s = sn9c102_get_sensor(cam); int err = 0; - err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, - {0x0a, 0x14}, {0x40, 0x01}, - {0x20, 0x17}, {0x07, 0x18}, - {0xa0, 0x19}, {0x02, 0x1c}, - {0x03, 0x1d}, {0x0f, 0x1e}, - {0x0c, 0x1f}, {0x00, 0x20}, - {0x10, 0x21}, {0x20, 0x22}, - {0x30, 0x23}, {0x40, 0x24}, - {0x50, 0x25}, {0x60, 0x26}, - {0x70, 0x27}, {0x80, 0x28}, - {0x90, 0x29}, {0xa0, 0x2a}, - {0xb0, 0x2b}, {0xc0, 0x2c}, - {0xd0, 0x2d}, {0xe0, 0x2e}, - {0xf0, 0x2f}, {0xff, 0x30}); + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C103: + err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, + {0x0a, 0x14}, {0x40, 0x01}, + {0x20, 0x17}, {0x07, 0x18}, + {0xa0, 0x19}, {0x02, 0x1c}, + {0x03, 0x1d}, {0x0f, 0x1e}, + {0x0c, 0x1f}, {0x00, 0x20}, + {0x10, 0x21}, {0x20, 0x22}, + {0x30, 0x23}, {0x40, 0x24}, + {0x50, 0x25}, {0x60, 0x26}, + {0x70, 0x27}, {0x80, 0x28}, + {0x90, 0x29}, {0xa0, 0x2a}, + {0xb0, 0x2b}, {0xc0, 0x2c}, + {0xd0, 0x2d}, {0xe0, 0x2e}, + {0xf0, 0x2f}, {0xff, 0x30}); + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02}, + {0x00, 0x03}, {0x1a, 0x04}, + {0x50, 0x05}, {0x20, 0x06}, + {0x10, 0x07}, {0x03, 0x10}, + {0x08, 0x14}, {0xa2, 0x17}, + {0x47, 0x18}, {0x00, 0x19}, + {0x1d, 0x1a}, {0x10, 0x1b}, + {0x02, 0x1c}, {0x03, 0x1d}, + {0x0f, 0x1e}, {0x0c, 0x1f}, + {0x00, 0x20}, {0x29, 0x21}, + {0x40, 0x22}, {0x54, 0x23}, + {0x66, 0x24}, {0x76, 0x25}, + {0x85, 0x26}, {0x94, 0x27}, + {0xa1, 0x28}, {0xae, 0x29}, + {0xbb, 0x2a}, {0xc7, 0x2b}, + {0xd3, 0x2c}, {0xde, 0x2d}, + {0xea, 0x2e}, {0xf4, 0x2f}, + {0xff, 0x30}, {0x00, 0x3F}, + {0xC7, 0x40}, {0x01, 0x41}, + {0x44, 0x42}, {0x00, 0x43}, + {0x44, 0x44}, {0x00, 0x45}, + {0x44, 0x46}, {0x00, 0x47}, + {0xC7, 0x48}, {0x01, 0x49}, + {0xC7, 0x4A}, {0x01, 0x4B}, + {0xC7, 0x4C}, {0x01, 0x4D}, + {0x44, 0x4E}, {0x00, 0x4F}, + {0x44, 0x50}, {0x00, 0x51}, + {0x44, 0x52}, {0x00, 0x53}, + {0xC7, 0x54}, {0x01, 0x55}, + {0xC7, 0x56}, {0x01, 0x57}, + {0xC7, 0x58}, {0x01, 0x59}, + {0x44, 0x5A}, {0x00, 0x5B}, + {0x44, 0x5C}, {0x00, 0x5D}, + {0x44, 0x5E}, {0x00, 0x5F}, + {0xC7, 0x60}, {0x01, 0x61}, + {0xC7, 0x62}, {0x01, 0x63}, + {0xC7, 0x64}, {0x01, 0x65}, + {0x44, 0x66}, {0x00, 0x67}, + {0x44, 0x68}, {0x00, 0x69}, + {0x44, 0x6A}, {0x00, 0x6B}, + {0xC7, 0x6C}, {0x01, 0x6D}, + {0xC7, 0x6E}, {0x01, 0x6F}, + {0xC7, 0x70}, {0x01, 0x71}, + {0x44, 0x72}, {0x00, 0x73}, + {0x44, 0x74}, {0x00, 0x75}, + {0x44, 0x76}, {0x00, 0x77}, + {0xC7, 0x78}, {0x01, 0x79}, + {0xC7, 0x7A}, {0x01, 0x7B}, + {0xC7, 0x7C}, {0x01, 0x7D}, + {0x44, 0x7E}, {0x00, 0x7F}, + {0x14, 0x84}, {0x00, 0x85}, + {0x27, 0x86}, {0x00, 0x87}, + {0x07, 0x88}, {0x00, 0x89}, + {0xEC, 0x8A}, {0x0f, 0x8B}, + {0xD8, 0x8C}, {0x0f, 0x8D}, + {0x3D, 0x8E}, {0x00, 0x8F}, + {0x3D, 0x90}, {0x00, 0x91}, + {0xCD, 0x92}, {0x0f, 0x93}, + {0xf7, 0x94}, {0x0f, 0x95}, + {0x0C, 0x96}, {0x00, 0x97}, + {0x00, 0x98}, {0x66, 0x99}, + {0x05, 0x9A}, {0x00, 0x9B}, + {0x04, 0x9C}, {0x00, 0x9D}, + {0x08, 0x9E}, {0x00, 0x9F}, + {0x2D, 0xC0}, {0x2D, 0xC1}, + {0x3A, 0xC2}, {0x05, 0xC3}, + {0x04, 0xC4}, {0x3F, 0xC5}, + {0x00, 0xC6}, {0x00, 0xC7}, + {0x50, 0xC8}, {0x3C, 0xC9}, + {0x28, 0xCA}, {0xD8, 0xCB}, + {0x14, 0xCC}, {0xEC, 0xCD}, + {0x32, 0xCE}, {0xDD, 0xCF}, + {0x32, 0xD0}, {0xDD, 0xD1}, + {0x6A, 0xD2}, {0x50, 0xD3}, + {0x00, 0xD4}, {0x00, 0xD5}, + {0x00, 0xD6}); + break; + default: + break; + } err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d, 0x00, 0x01, 0, 0); @@ -65,50 +150,50 @@ static int mi0360_get_ctrl(struct sn9c102_device* cam, struct v4l2_control* ctrl) { struct sn9c102_sensor* s = sn9c102_get_sensor(cam); - u8 data[5+1]; + u8 data[2]; switch (ctrl->id) { case V4L2_CID_EXPOSURE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2, + data) < 0) return -EIO; - ctrl->value = data[2]; + ctrl->value = data[0]; return 0; case V4L2_CID_GAIN: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2, + data) < 0) return -EIO; - ctrl->value = data[3]; + ctrl->value = data[1]; return 0; case V4L2_CID_RED_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2, + data) < 0) return -EIO; - ctrl->value = data[3]; + ctrl->value = data[1]; return 0; case V4L2_CID_BLUE_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2, + data) < 0) return -EIO; - ctrl->value = data[3]; + ctrl->value = data[1]; return 0; case SN9C102_V4L2_CID_GREEN_BALANCE: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2, + data) < 0) return -EIO; - ctrl->value = data[3]; + ctrl->value = data[1]; return 0; case V4L2_CID_HFLIP: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, + data) < 0) return -EIO; - ctrl->value = data[3] & 0x20 ? 1 : 0; + ctrl->value = data[1] & 0x20 ? 1 : 0; return 0; case V4L2_CID_VFLIP: - if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, - 2+1, data) < 0) + if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2, + data) < 0) return -EIO; - ctrl->value = data[3] & 0x80 ? 1 : 0; + ctrl->value = data[1] & 0x80 ? 1 : 0; return 0; default: return -EINVAL; @@ -178,8 +263,19 @@ static int mi0360_set_crop(struct sn9c102_device* cam, { struct sn9c102_sensor* s = sn9c102_get_sensor(cam); int err = 0; - u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0, - v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; + u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1; + + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C103: + h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0; + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1; + break; + default: + break; + } err += sn9c102_write_reg(cam, h_start, 0x12); err += sn9c102_write_reg(cam, v_start, 0x13); @@ -194,24 +290,30 @@ static int mi0360_set_pix_format(struct sn9c102_device* cam, struct sn9c102_sensor* s = sn9c102_get_sensor(cam); int err = 0; - if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) { - err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, - 0x0a, 0x00, 0x02, 0, 0); - err += sn9c102_write_reg(cam, 0x20, 0x19); - } else { + if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) { err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0a, 0x00, 0x05, 0, 0); err += sn9c102_write_reg(cam, 0x60, 0x19); + if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 || + sn9c102_get_bridge(cam) == BRIDGE_SN9C120) + err += sn9c102_write_reg(cam, 0xa6, 0x17); + } else { + err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, + 0x0a, 0x00, 0x02, 0, 0); + err += sn9c102_write_reg(cam, 0x20, 0x19); + if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 || + sn9c102_get_bridge(cam) == BRIDGE_SN9C120) + err += sn9c102_write_reg(cam, 0xa2, 0x17); } return err; } -static struct sn9c102_sensor mi0360 = { +static const struct sn9c102_sensor mi0360 = { .name = "MI-0360", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", - .supported_bridge = BRIDGE_SN9C103, + .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120, .frequency = SN9C102_I2C_100KHZ, .interface = SN9C102_I2C_2WIRES, .i2c_slave_id = 0x5d, @@ -317,19 +419,31 @@ static struct sn9c102_sensor mi0360 = { int sn9c102_probe_mi0360(struct sn9c102_device* cam) { - u8 data[5+1]; - int err; - err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, - {0x28, 0x17}); - if (err) - return -EIO; + u8 data[2]; + + switch (sn9c102_get_bridge(cam)) { + case BRIDGE_SN9C103: + if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17})) + return -EIO; + break; + case BRIDGE_SN9C105: + case BRIDGE_SN9C120: + if (sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1}, + {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17})) + return -EIO; + break; + default: + break; + } if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00, - 2+1, data) < 0) + 2, data) < 0) return -EIO; - if (data[2] != 0x82 || data[3] != 0x43) + if (data[0] != 0x82 || data[1] != 0x43) return -ENODEV; sn9c102_attach_sensor(cam, &mi0360); diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c index 31b6080b061..e6832347894 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7630.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7630.c @@ -29,9 +29,8 @@ static int ov7630_init(struct sn9c102_device* cam) switch (sn9c102_get_bridge(cam)) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: - err = sn9c102_write_const_regs(cam, {0x00, 0x14}, - {0x60, 0x17}, {0x0f, 0x18}, - {0x50, 0x19}); + err = sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, + {0x0f, 0x18}, {0x50, 0x19}); err += sn9c102_i2c_write(cam, 0x12, 0x8d); err += sn9c102_i2c_write(cam, 0x12, 0x0d); @@ -61,7 +60,6 @@ static int ov7630_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x71, 0x00); err += sn9c102_i2c_write(cam, 0x74, 0x21); err += sn9c102_i2c_write(cam, 0x7d, 0xf7); - break; case BRIDGE_SN9C103: err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03}, @@ -253,7 +251,7 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor ov7630 = { +static const struct sn9c102_sensor ov7630 = { .name = "OV7630", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, @@ -408,19 +406,16 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam) switch (sn9c102_get_bridge(cam)) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: - err = sn9c102_write_const_regs(cam, {0x01, 0x01}, - {0x00, 0x01}, {0x28, 0x17}); - + err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01}, + {0x28, 0x17}); break; case BRIDGE_SN9C103: /* do _not_ change anything! */ - err = sn9c102_write_const_regs(cam, {0x09, 0x01}, - {0x42, 0x01}, {0x28, 0x17}, - {0x44, 0x02}); + err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x42, 0x01}, + {0x28, 0x17}, {0x44, 0x02}); pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a); - if (err || pid < 0) { /* try a different initialization */ - err = sn9c102_write_reg(cam, 0x01, 0x01); - err += sn9c102_write_reg(cam, 0x00, 0x01); - } + if (err || pid < 0) /* try a different initialization */ + err += sn9c102_write_const_regs(cam, {0x01, 0x01}, + {0x00, 0x01}); break; default: break; diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c index c898e948fe8..4b6474048a7 100644 --- a/drivers/media/video/sn9c102/sn9c102_ov7660.c +++ b/drivers/media/video/sn9c102/sn9c102_ov7660.c @@ -104,8 +104,8 @@ static int ov7660_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x12, 0x80); err += sn9c102_i2c_write(cam, 0x11, 0x09); err += sn9c102_i2c_write(cam, 0x00, 0x0A); - err += sn9c102_i2c_write(cam, 0x01, 0x78); - err += sn9c102_i2c_write(cam, 0x02, 0x90); + err += sn9c102_i2c_write(cam, 0x01, 0x80); + err += sn9c102_i2c_write(cam, 0x02, 0x80); err += sn9c102_i2c_write(cam, 0x03, 0x00); err += sn9c102_i2c_write(cam, 0x04, 0x00); err += sn9c102_i2c_write(cam, 0x05, 0x08); @@ -122,7 +122,7 @@ static int ov7660_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x10, 0x20); err += sn9c102_i2c_write(cam, 0x11, 0x03); err += sn9c102_i2c_write(cam, 0x12, 0x05); - err += sn9c102_i2c_write(cam, 0x13, 0xF8); + err += sn9c102_i2c_write(cam, 0x13, 0xC7); err += sn9c102_i2c_write(cam, 0x14, 0x2C); err += sn9c102_i2c_write(cam, 0x15, 0x00); err += sn9c102_i2c_write(cam, 0x16, 0x02); @@ -162,7 +162,7 @@ static int ov7660_init(struct sn9c102_device* cam) err += sn9c102_i2c_write(cam, 0x38, 0x02); err += sn9c102_i2c_write(cam, 0x39, 0x43); err += sn9c102_i2c_write(cam, 0x3A, 0x00); - err += sn9c102_i2c_write(cam, 0x3B, 0x02); + err += sn9c102_i2c_write(cam, 0x3B, 0x0A); err += sn9c102_i2c_write(cam, 0x3C, 0x6C); err += sn9c102_i2c_write(cam, 0x3D, 0x99); err += sn9c102_i2c_write(cam, 0x3E, 0x0E); @@ -281,25 +281,34 @@ static int ov7660_get_ctrl(struct sn9c102_device* cam, return -EIO; break; case V4L2_CID_DO_WHITE_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x02); + if ((ctrl->value = sn9c102_read_reg(cam, 0x02)) < 0) + return -EIO; ctrl->value = (ctrl->value & 0x04) ? 1 : 0; break; case V4L2_CID_RED_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x05); + if ((ctrl->value = sn9c102_read_reg(cam, 0x05)) < 0) + return -EIO; ctrl->value &= 0x7f; break; case V4L2_CID_BLUE_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x06); + if ((ctrl->value = sn9c102_read_reg(cam, 0x06)) < 0) + return -EIO; ctrl->value &= 0x7f; break; case SN9C102_V4L2_CID_GREEN_BALANCE: - ctrl->value = sn9c102_pread_reg(cam, 0x07); + if ((ctrl->value = sn9c102_read_reg(cam, 0x07)) < 0) + return -EIO; ctrl->value &= 0x7f; break; + case SN9C102_V4L2_CID_BAND_FILTER: + if ((ctrl->value = sn9c102_i2c_read(cam, 0x3b)) < 0) + return -EIO; + ctrl->value &= 0x08; + break; case V4L2_CID_GAIN: if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0) return -EIO; - ctrl->value &= 0x7f; + ctrl->value &= 0x1f; break; case V4L2_CID_AUTOGAIN: if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0) @@ -335,12 +344,15 @@ static int ov7660_set_ctrl(struct sn9c102_device* cam, case SN9C102_V4L2_CID_GREEN_BALANCE: err += sn9c102_write_reg(cam, ctrl->value, 0x07); break; + case SN9C102_V4L2_CID_BAND_FILTER: + err += sn9c102_i2c_write(cam, ctrl->value << 3, 0x3b); + break; case V4L2_CID_GAIN: - err += sn9c102_i2c_write(cam, 0x00, ctrl->value); + err += sn9c102_i2c_write(cam, 0x00, 0x60 + ctrl->value); break; case V4L2_CID_AUTOGAIN: - err += sn9c102_i2c_write(cam, 0x13, 0xf0 | ctrl->value | - (ctrl->value << 1)); + err += sn9c102_i2c_write(cam, 0x13, 0xc0 | + (ctrl->value * 0x07)); break; default: return -EINVAL; @@ -386,7 +398,7 @@ static int ov7660_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor ov7660 = { +static const struct sn9c102_sensor ov7660 = { .name = "OV7660", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120, @@ -401,9 +413,9 @@ static struct sn9c102_sensor ov7660 = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "global gain", .minimum = 0x00, - .maximum = 0x7f, + .maximum = 0x1f, .step = 0x01, - .default_value = 0x0a, + .default_value = 0x09, .flags = 0, }, { @@ -413,7 +425,7 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0xff, .step = 0x01, - .default_value = 0x50, + .default_value = 0x27, .flags = 0, }, { @@ -433,7 +445,7 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0x7f, .step = 0x01, - .default_value = 0x1f, + .default_value = 0x14, .flags = 0, }, { @@ -443,7 +455,7 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0x7f, .step = 0x01, - .default_value = 0x1e, + .default_value = 0x14, .flags = 0, }, { @@ -453,7 +465,7 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0x01, .step = 0x01, - .default_value = 0x00, + .default_value = 0x01, .flags = 0, }, { @@ -463,7 +475,17 @@ static struct sn9c102_sensor ov7660 = { .minimum = 0x00, .maximum = 0x7f, .step = 0x01, - .default_value = 0x20, + .default_value = 0x14, + .flags = 0, + }, + { + .id = SN9C102_V4L2_CID_BAND_FILTER, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "band filter", + .minimum = 0x00, + .maximum = 0x01, + .step = 0x01, + .default_value = 0x00, .flags = 0, }, }, @@ -508,6 +530,7 @@ int sn9c102_probe_ov7660(struct sn9c102_device* cam) return -EIO; if (pid != 0x76 || ver != 0x60) return -ENODEV; + sn9c102_attach_sensor(cam, &ov7660); return 0; diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c index 67151964801..360f2a848bc 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas106b.c +++ b/drivers/media/video/sn9c102/sn9c102_pas106b.c @@ -163,7 +163,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor pas106b = { +static const struct sn9c102_sensor pas106b = { .name = "PAS106B", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, @@ -273,23 +273,21 @@ static struct sn9c102_sensor pas106b = { int sn9c102_probe_pas106b(struct sn9c102_device* cam) { - int r0 = 0, r1 = 0, err; + int r0 = 0, r1 = 0; unsigned int pid = 0; /* Minimal initialization to enable the I2C communication NOTE: do NOT change the values! */ - err = sn9c102_write_const_regs(cam, - {0x01, 0x01}, /* sensor power down */ - {0x00, 0x01}, /* sensor power on */ - {0x28, 0x17});/* sensor clock 24 MHz */ - if (err) + if (sn9c102_write_const_regs(cam, + {0x01, 0x01}, /* sensor power down */ + {0x00, 0x01}, /* sensor power on */ + {0x28, 0x17})) /* sensor clock at 24 MHz */ return -EIO; r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00); r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01); - if (r0 < 0 || r1 < 0) return -EIO; diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c index c1b8d6b63b4..ca4a1506ed3 100644 --- a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c +++ b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c @@ -35,29 +35,28 @@ static int pas202bcb_init(struct sn9c102_device* cam) switch (sn9c102_get_bridge(cam)) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: - err = sn9c102_write_const_regs(cam, {0x00, 0x10}, - {0x00, 0x11}, {0x00, 0x14}, - {0x20, 0x17}, {0x30, 0x19}, - {0x09, 0x18}); + err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11}, + {0x00, 0x14}, {0x20, 0x17}, + {0x30, 0x19}, {0x09, 0x18}); break; case BRIDGE_SN9C103: - err = sn9c102_write_const_regs(cam, {0x00, 0x02}, - {0x00, 0x03}, {0x1a, 0x04}, - {0x20, 0x05}, {0x20, 0x06}, - {0x20, 0x07}, {0x00, 0x10}, - {0x00, 0x11}, {0x00, 0x14}, - {0x20, 0x17}, {0x30, 0x19}, - {0x09, 0x18}, {0x02, 0x1c}, - {0x03, 0x1d}, {0x0f, 0x1e}, - {0x0c, 0x1f}, {0x00, 0x20}, - {0x10, 0x21}, {0x20, 0x22}, - {0x30, 0x23}, {0x40, 0x24}, - {0x50, 0x25}, {0x60, 0x26}, - {0x70, 0x27}, {0x80, 0x28}, - {0x90, 0x29}, {0xa0, 0x2a}, - {0xb0, 0x2b}, {0xc0, 0x2c}, - {0xd0, 0x2d}, {0xe0, 0x2e}, - {0xf0, 0x2f}, {0xff, 0x30}); + err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03}, + {0x1a, 0x04}, {0x20, 0x05}, + {0x20, 0x06}, {0x20, 0x07}, + {0x00, 0x10}, {0x00, 0x11}, + {0x00, 0x14}, {0x20, 0x17}, + {0x30, 0x19}, {0x09, 0x18}, + {0x02, 0x1c}, {0x03, 0x1d}, + {0x0f, 0x1e}, {0x0c, 0x1f}, + {0x00, 0x20}, {0x10, 0x21}, + {0x20, 0x22}, {0x30, 0x23}, + {0x40, 0x24}, {0x50, 0x25}, + {0x60, 0x26}, {0x70, 0x27}, + {0x80, 0x28}, {0x90, 0x29}, + {0xa0, 0x2a}, {0xb0, 0x2b}, + {0xc0, 0x2c}, {0xd0, 0x2d}, + {0xe0, 0x2e}, {0xf0, 0x2f}, + {0xff, 0x30}); break; default: break; @@ -197,7 +196,7 @@ static int pas202bcb_set_crop(struct sn9c102_device* cam, } -static struct sn9c102_sensor pas202bcb = { +static const struct sn9c102_sensor pas202bcb = { .name = "PAS202BCB", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103, @@ -313,9 +312,8 @@ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam) {0x28, 0x17});/* clock 24 MHz */ break; case BRIDGE_SN9C103: /* do _not_ change anything! */ - err = sn9c102_write_const_regs(cam, {0x09, 0x01}, - {0x44, 0x01}, {0x44, 0x02}, - {0x29, 0x17}); + err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x01}, + {0x44, 0x02}, {0x29, 0x17}); break; default: break; diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h index 1bbf64c897a..2d7d786b843 100644 --- a/drivers/media/video/sn9c102/sn9c102_sensor.h +++ b/drivers/media/video/sn9c102/sn9c102_sensor.h @@ -22,7 +22,7 @@ #define _SN9C102_SENSOR_H_ #include <linux/usb.h> -#include <linux/videodev.h> +#include <linux/videodev2.h> #include <linux/device.h> #include <linux/stddef.h> #include <linux/errno.h> @@ -74,7 +74,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id); /* Attach a probed sensor to the camera. */ extern void sn9c102_attach_sensor(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor); + const struct sn9c102_sensor* sensor); /* Read/write routines: they always return -1 on error, 0 or the read value @@ -85,10 +85,11 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, */ /* The "try" I2C I/O versions are used when probing the sensor */ -extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*, - u8 address, u8 value); -extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*, - u8 address); +extern int sn9c102_i2c_try_write(struct sn9c102_device*, + const struct sn9c102_sensor*, u8 address, + u8 value); +extern int sn9c102_i2c_try_read(struct sn9c102_device*, + const struct sn9c102_sensor*, u8 address); /* These must be used if and only if the sensor doesn't implement the standard @@ -102,29 +103,31 @@ extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*, byte. */ extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 n, + const struct sn9c102_sensor* sensor, u8 n, u8 data0, u8 data1, u8 data2, u8 data3, u8 data4, u8 data5); extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam, - struct sn9c102_sensor* sensor, u8 data0, - u8 data1, u8 n, u8 buffer[]); + const struct sn9c102_sensor* sensor, + u8 data0, u8 data1, u8 n, u8 buffer[]); /* To be used after the sensor struct has been attached to the camera struct */ extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value); extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address); /* I/O on registers in the bridge. Could be used by the sensor methods too */ +extern int sn9c102_read_reg(struct sn9c102_device*, u16 index); extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index); extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2], int count); /* - * Write multiple registers with constant values. For example: - * sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18}); - */ -#define sn9c102_write_const_regs(device, data...) \ - ({ const static u8 _data[][2] = {data}; \ - sn9c102_write_regs(device, _data, ARRAY_SIZE(_data)); }) + Write multiple registers with constant values. For example: + sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18}); + Register adresses must be < 256. +*/ +#define sn9c102_write_const_regs(sn9c102_device, data...) \ + ({ const static u8 _valreg[][2] = {data}; \ + sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); }) /*****************************************************************************/ diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c index 0e7ec8662c7..e7d2de2bace 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c @@ -88,7 +88,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor tas5110c1b = { +static const struct sn9c102_sensor tas5110c1b = { .name = "TAS5110C1B", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/drivers/media/video/sn9c102/sn9c102_tas5110d.c index 83a39e8b5e7..d32fdbccdc5 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5110d.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5110d.c @@ -68,7 +68,7 @@ static int tas5110d_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor tas5110d = { +static const struct sn9c102_sensor tas5110d = { .name = "TAS5110D", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c index 50406503fc4..56fb1d575a8 100644 --- a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c +++ b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c @@ -89,7 +89,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam, } -static struct sn9c102_sensor tas5130d1b = { +static const struct sn9c102_sensor tas5130d1b = { .name = "TAS5130D1B", .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>", .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102, diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig index a0fd82b924f..e4cb99c1f94 100644 --- a/drivers/media/video/usbvideo/Kconfig +++ b/drivers/media/video/usbvideo/Kconfig @@ -3,7 +3,7 @@ config VIDEO_USBVIDEO config USB_VICAM tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)" - depends on USB && VIDEO_DEV && VIDEO_V4L1 && EXPERIMENTAL + depends on VIDEO_V4L1 && EXPERIMENTAL select VIDEO_USBVIDEO ---help--- Say Y here if you have 3com homeconnect camera (vicam). @@ -13,7 +13,7 @@ config USB_VICAM config USB_IBMCAM tristate "USB IBM (Xirlink) C-it Camera support" - depends on USB && VIDEO_DEV && VIDEO_V4L1 + depends on VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want to connect a IBM "C-It" camera, also known as @@ -28,7 +28,7 @@ config USB_IBMCAM config USB_KONICAWC tristate "USB Konica Webcam support" - depends on USB && VIDEO_DEV && VIDEO_V4L1 + depends on VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want support for webcams based on a Konica @@ -39,7 +39,7 @@ config USB_KONICAWC config USB_QUICKCAM_MESSENGER tristate "USB Logitech Quickcam Messenger" - depends on USB && VIDEO_DEV && VIDEO_V4L1 + depends on VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y or M here to enable support for the USB Logitech Quickcam diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig index c43a5d89909..fc24ef05b3f 100644 --- a/drivers/media/video/usbvision/Kconfig +++ b/drivers/media/video/usbvision/Kconfig @@ -1,6 +1,6 @@ config VIDEO_USBVISION tristate "USB video devices based on Nogatech NT1003/1004/1005" - depends on I2C && VIDEO_V4L2 && USB + depends on I2C && VIDEO_V4L2 select VIDEO_TUNER select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO ---help--- diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index a861e150865..ede8543818b 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -127,7 +127,7 @@ set_v4l_control(struct inode *inode, /* ----------------------------------------------------------------- */ -static int palette2pixelformat[] = { +const static unsigned int palette2pixelformat[] = { [VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY, [VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555, [VIDEO_PALETTE_RGB565] = V4L2_PIX_FMT_RGB565, @@ -145,7 +145,7 @@ static int palette2pixelformat[] = { [VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P, }; -static unsigned int +static unsigned int __attribute_pure__ palette_to_pixelformat(unsigned int palette) { if (palette < ARRAY_SIZE(palette2pixelformat)) @@ -154,8 +154,8 @@ palette_to_pixelformat(unsigned int palette) return 0; } -static unsigned int -pixelformat_to_palette(int pixelformat) +static unsigned int __attribute_const__ +pixelformat_to_palette(unsigned int pixelformat) { int palette = 0; switch (pixelformat) @@ -616,6 +616,8 @@ v4l_compat_translate_ioctl(struct inode *inode, case VIDIOCSPICT: /* set tone controls & partial capture format */ { struct video_picture *pict = arg; + int mem_err = 0, ovl_err = 0; + memset(&fbuf2, 0, sizeof(fbuf2)); set_v4l_control(inode, file, @@ -628,33 +630,59 @@ v4l_compat_translate_ioctl(struct inode *inode, V4L2_CID_SATURATION, pict->colour, drv); set_v4l_control(inode, file, V4L2_CID_WHITENESS, pict->whiteness, drv); + /* + * V4L1 uses this ioctl to set both memory capture and overlay + * pixel format, while V4L2 has two different ioctls for this. + * Some cards may not support one or the other, and may support + * different pixel formats for memory vs overlay. + */ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL); fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = drv(inode, file, VIDIOC_G_FMT, fmt2); - if (err < 0) + /* If VIDIOC_G_FMT failed, then the driver likely doesn't + support memory capture. Trying to set the memory capture + parameters would be pointless. */ + if (err < 0) { dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err); - if (fmt2->fmt.pix.pixelformat != - palette_to_pixelformat(pict->palette)) { + mem_err = -1000; /* didn't even try */ + } else if (fmt2->fmt.pix.pixelformat != + palette_to_pixelformat(pict->palette)) { fmt2->fmt.pix.pixelformat = palette_to_pixelformat( pict->palette); - err = drv(inode, file, VIDIOC_S_FMT, fmt2); - if (err < 0) - dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",err); + mem_err = drv(inode, file, VIDIOC_S_FMT, fmt2); + if (mem_err < 0) + dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n", + mem_err); } err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); - if (err < 0) + /* If VIDIOC_G_FBUF failed, then the driver likely doesn't + support overlay. Trying to set the overlay parameters + would be quite pointless. */ + if (err < 0) { dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err); - if (fbuf2.fmt.pixelformat != - palette_to_pixelformat(pict->palette)) { + ovl_err = -1000; /* didn't even try */ + } else if (fbuf2.fmt.pixelformat != + palette_to_pixelformat(pict->palette)) { fbuf2.fmt.pixelformat = palette_to_pixelformat( pict->palette); - err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2); - if (err < 0) - dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",err); - err = 0; /* likely fails for non-root */ + ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2); + if (ovl_err < 0) + dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n", + ovl_err); } + if (ovl_err < 0 && mem_err < 0) + /* ioctl failed, couldn't set either parameter */ + if (mem_err != -1000) { + err = mem_err; + } else if (ovl_err == -EPERM) { + err = 0; + } else { + err = ovl_err; + } + else + err = 0; break; } case VIDIOCGTUNER: /* get tuner information */ diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index 459786ff459..a32dfbe0585 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -702,9 +702,7 @@ videobuf_qbuf(struct videobuf_queue *q, dprintk(1,"qbuf: memory type is wrong.\n"); goto done; } - if (buf->state == STATE_QUEUED || - buf->state == STATE_PREPARED || - buf->state == STATE_ACTIVE) { + if (buf->state != STATE_NEEDS_INIT && buf->state != STATE_IDLE) { dprintk(1,"qbuf: buffer is already queued or active.\n"); goto done; } diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 5263b50463e..b876aca69c7 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -433,13 +433,43 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, int ret = -EINVAL; if ( (vfd->debug & V4L2_DEBUG_IOCTL) && - !(vfd->debug | V4L2_DEBUG_IOCTL_ARG)) { + !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { v4l_print_ioctl(vfd->name, cmd); } +#ifdef CONFIG_VIDEO_V4L1_COMPAT + /*********************************************************** + Handles calls to the obsoleted V4L1 API + Due to the nature of VIDIOCGMBUF, each driver that supports + V4L1 should implement its own handler for this ioctl. + ***********************************************************/ + + /* --- streaming capture ------------------------------------- */ + if (cmd == VIDIOCGMBUF) { + struct video_mbuf *p=arg; + + memset(p,0,sizeof(p)); + + if (!vfd->vidiocgmbuf) + return ret; + ret=vfd->vidiocgmbuf(file, fh, p); + if (!ret) + dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n", + p->size, p->frames, + (unsigned long)p->offsets); + return ret; + } + + /******************************************************** + All other V4L1 calls are handled by v4l1_compat module. + Those calls will be translated into V4L2 calls, and + __video_do_ioctl will be called again, with one or more + V4L2 ioctls. + ********************************************************/ if (_IOC_TYPE(cmd)=='v') return v4l_compat_translate_ioctl(inode,file,cmd,arg, __video_do_ioctl); +#endif switch(cmd) { /* --- capabilities ------------------------------------------ */ @@ -791,24 +821,6 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ret=vfd->vidioc_overlay(file, fh, *i); break; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT - /* --- streaming capture ------------------------------------- */ - case VIDIOCGMBUF: - { - struct video_mbuf *p=arg; - - memset(p,0,sizeof(p)); - - if (!vfd->vidiocgmbuf) - break; - ret=vfd->vidiocgmbuf(file, fh, p); - if (!ret) - dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n", - p->size, p->frames, - (unsigned long)p->offsets); - break; - } -#endif case VIDIOC_G_FBUF: { struct v4l2_framebuffer *p=arg; diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig index a859a692018..47cd93f9c7d 100644 --- a/drivers/media/video/zc0301/Kconfig +++ b/drivers/media/video/zc0301/Kconfig @@ -1,6 +1,6 @@ config USB_ZC0301 tristate "USB ZC0301[P] Image Processor and Control Chip support" - depends on USB && VIDEO_V4L1 + depends on VIDEO_V4L1 ---help--- Say Y here if you want support for cameras based on the ZC0301 or ZC0301P Image Processors and Control Chips. |