diff options
Diffstat (limited to 'drivers/media')
102 files changed, 1350 insertions, 820 deletions
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index 5b34c134aa25..127b0526a727 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c @@ -545,11 +545,11 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, if( VFL_TYPE_GRABBER == type ) { vv->video_minor = vfd->minor; INFO(("%s: registered device video%d [v4l2]\n", - dev->name, vfd->minor & 0x1f)); + dev->name, vfd->num)); } else { vv->vbi_minor = vfd->minor; INFO(("%s: registered device vbi%d [v4l2]\n", - dev->name, vfd->minor & 0x1f)); + dev->name, vfd->num)); } *vid = vfd; diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 99be9e5c85f7..fe0bd55977e3 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -834,7 +834,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file) * copying is done already, arg is a kernel pointer. */ -int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) +static int __saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; @@ -1215,12 +1215,18 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int } #endif default: - return v4l_compat_translate_ioctl(inode,file,cmd,arg, - saa7146_video_do_ioctl); + return v4l_compat_translate_ioctl(file, cmd, arg, + __saa7146_video_do_ioctl); } return 0; } +int saa7146_video_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + return __saa7146_video_do_ioctl(file, cmd, arg); +} + /*********************************************************************************/ /* buffer handling functions */ diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 14e627ef6465..c1d92f838ca8 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -376,7 +376,7 @@ static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb) pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr); } -static void __devinit dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb) +static void dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb) { outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK)); outb(1, dm_io_mem(DM1105_CR)); diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 5689d1f1d444..7a421e9dba5a 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -223,6 +223,8 @@ static void dvb_frontend_init(struct dvb_frontend *fe) if (fe->ops.init) fe->ops.init(fe); if (fe->ops.tuner_ops.init) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.tuner_ops.init(fe); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); @@ -583,6 +585,8 @@ restart: if (fe->ops.set_voltage) fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF); if (fe->ops.tuner_ops.sleep) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.tuner_ops.sleep(fe); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); @@ -932,7 +936,8 @@ void dtv_property_dump(struct dtv_property *tvp) int is_legacy_delivery_system(fe_delivery_system_t s) { if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) || - (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS)) + (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS) || + (s == SYS_ATSC)) return 1; return 0; diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 3c13bcfa6385..62b68c291d99 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -261,7 +261,7 @@ config DVB_USB_DW2102 Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers and the TeVii S650. -config DVB_USB_CINERGY_T2 +config DVB_USB_CINERGY_T2 tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" depends on DVB_USB help @@ -283,6 +283,7 @@ config DVB_USB_ANYSEE config DVB_USB_DTV5100 tristate "AME DTV-5100 USB2.0 DVB-T support" depends on DVB_USB + select DVB_ZL10353 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE help Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index cb0829c038ce..e9ab0249d133 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -31,13 +31,13 @@ #include "mc44s80x.h" #endif -int dvb_usb_af9015_debug; +static int dvb_usb_af9015_debug; module_param_named(debug, dvb_usb_af9015_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); -int dvb_usb_af9015_remote; +static int dvb_usb_af9015_remote; module_param_named(remote, dvb_usb_af9015_remote, int, 0644); MODULE_PARM_DESC(remote, "select remote"); -int dvb_usb_af9015_dual_mode; +static int dvb_usb_af9015_dual_mode; module_param_named(dual_mode, dvb_usb_af9015_dual_mode, int, 0644); MODULE_PARM_DESC(dual_mode, "enable dual mode"); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -46,7 +46,7 @@ static DEFINE_MUTEX(af9015_usb_mutex); static struct af9015_config af9015_config; static struct dvb_usb_device_properties af9015_properties[2]; -int af9015_properties_count = ARRAY_SIZE(af9015_properties); +static int af9015_properties_count = ARRAY_SIZE(af9015_properties); static struct af9013_config af9015_af9013_config[] = { { @@ -549,7 +549,7 @@ static int af9015_eeprom_dump(struct dvb_usb_device *d) return 0; } -int af9015_download_ir_table(struct dvb_usb_device *d) +static int af9015_download_ir_table(struct dvb_usb_device *d) { int i, packets = 0, ret; u16 addr = 0x9a56; /* ir-table start address */ @@ -681,12 +681,6 @@ static int af9015_download_firmware(struct usb_device *udev, goto error; } - /* firmware is running, reconnect device in the usb bus */ - req.cmd = RECONNECT_USB; - ret = af9015_rw_udev(udev, &req); - if (ret) - err("reconnect failed: %d", ret); - error: return ret; } @@ -999,7 +993,7 @@ static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state) } /* init 2nd I2C adapter */ -int af9015_i2c_init(struct dvb_usb_device *d) +static int af9015_i2c_init(struct dvb_usb_device *d) { int ret; struct af9015_state *state = d->priv; @@ -1208,6 +1202,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .usb_ctrl = DEVICE_SPECIFIC, .download_firmware = af9015_download_firmware, .firmware = "dvb-usb-af9015.fw", + .no_reconnect = 1, .size_of_priv = sizeof(struct af9015_state), \ @@ -1306,6 +1301,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .usb_ctrl = DEVICE_SPECIFIC, .download_firmware = af9015_download_firmware, .firmware = "dvb-usb-af9015.fw", + .no_reconnect = 1, .size_of_priv = sizeof(struct af9015_state), \ @@ -1419,7 +1415,7 @@ static int af9015_usb_probe(struct usb_interface *intf, return ret; } -void af9015_i2c_exit(struct dvb_usb_device *d) +static void af9015_i2c_exit(struct dvb_usb_device *d) { struct af9015_state *state = d->priv; deb_info("%s: \n", __func__); diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index 882e8a4b3681..6c3c97293316 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h @@ -27,7 +27,6 @@ #define DVB_USB_LOG_PREFIX "af9015" #include "dvb-usb.h" -extern int dvb_usb_af9015_debug; #define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args) #define deb_rc(args...) dprintk(dvb_usb_af9015_debug, 0x02, args) #define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args) diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index c786359fba03..cd2edbcaa097 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -46,7 +46,7 @@ module_param_named(delsys, dvb_usb_anysee_delsys, int, 0644); MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)"); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -static struct mutex anysee_usb_mutex; +static DEFINE_MUTEX(anysee_usb_mutex); static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, u8 *rbuf, u8 rlen) @@ -456,8 +456,6 @@ static int anysee_probe(struct usb_interface *intf, struct usb_host_interface *alt; int ret; - mutex_init(&anysee_usb_mutex); - /* There is one interface with two alternate settings. Alternate setting 0 is for bulk transfer. Alternate setting 1 is for isochronous transfer. diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index 739193943c17..8b544fe79b0d 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h @@ -22,7 +22,7 @@ extern int dvb_usb_dib0700_debug; #define REQUEST_I2C_READ 0x2 #define REQUEST_I2C_WRITE 0x3 -#define REQUEST_POLL_RC 0x4 +#define REQUEST_POLL_RC 0x4 /* deprecated in firmware v1.20 */ #define REQUEST_JUMPRAM 0x8 #define REQUEST_SET_CLOCK 0xB #define REQUEST_SET_GPIO 0xC @@ -40,11 +40,14 @@ struct dib0700_state { u16 mt2060_if1[2]; u8 rc_toggle; u8 rc_counter; + u8 rc_func_version; u8 is_dib7000pc; u8 fw_use_new_i2c_api; u8 disable_streaming_master_mode; }; +extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, + u32 *romversion, u32 *ramversion, u32 *fwtype); extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen); diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index dd53cee3896d..200b215f4d8b 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -19,6 +19,22 @@ MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (defau DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, + u32 *romversion, u32 *ramversion, u32 *fwtype) +{ + u8 b[16]; + int ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), + REQUEST_GET_VERSION, + USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, + b, sizeof(b), USB_CTRL_GET_TIMEOUT); + *hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; + *romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7]; + *ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11]; + *fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15]; + return ret; +} + /* expecting rx buffer: request data[0] data[1] ... data[2] */ static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen) { diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 0cfccc24b190..f28d3ae59e04 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -38,6 +38,7 @@ static struct mt2060_config bristol_mt2060_config[2] = { } }; + static struct dibx000_agc_config bristol_dib3000p_mt2060_agc_config = { .band_caps = BAND_VHF | BAND_UHF, .setup = (1 << 8) | (5 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (2 << 0), @@ -451,8 +452,13 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; /* Number of keypresses to ignore before start repeating */ #define RC_REPEAT_DELAY 2 +#define RC_REPEAT_DELAY_V1_20 5 -static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) + + +/* Used by firmware versions < 1.20 (deprecated) */ +static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event, + int *state) { u8 key[4]; int i; @@ -529,6 +535,137 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) return 0; } +/* This is the structure of the RC response packet starting in firmware 1.20 */ +struct dib0700_rc_response { + u8 report_id; + u8 data_state; + u8 system_msb; + u8 system_lsb; + u8 data; + u8 not_data; +}; + +/* This supports the new IR response format for firmware v1.20 */ +static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, + int *state) +{ + struct dvb_usb_rc_key *keymap = d->props.rc_key_map; + struct dib0700_state *st = d->priv; + struct dib0700_rc_response poll_reply; + u8 buf[6]; + int i; + int status; + int actlen; + int found = 0; + + /* Set initial results in case we exit the function early */ + *event = 0; + *state = REMOTE_NO_KEY_PRESSED; + + /* Firmware v1.20 provides RC data via bulk endpoint 1 */ + status = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 1), buf, + sizeof(buf), &actlen, 50); + if (status < 0) { + /* No data available (meaning no key press) */ + return 0; + } + + if (actlen != sizeof(buf)) { + /* We didn't get back the 6 byte message we expected */ + err("Unexpected RC response size [%d]", actlen); + return -1; + } + + poll_reply.report_id = buf[0]; + poll_reply.data_state = buf[1]; + poll_reply.system_msb = buf[2]; + poll_reply.system_lsb = buf[3]; + poll_reply.data = buf[4]; + poll_reply.not_data = buf[5]; + + /* + info("rid=%02x ds=%02x sm=%02x sl=%02x d=%02x nd=%02x\n", + poll_reply.report_id, poll_reply.data_state, + poll_reply.system_msb, poll_reply.system_lsb, + poll_reply.data, poll_reply.not_data); + */ + + if ((poll_reply.data + poll_reply.not_data) != 0xff) { + /* Key failed integrity check */ + err("key failed integrity check: %02x %02x %02x %02x", + poll_reply.system_msb, poll_reply.system_lsb, + poll_reply.data, poll_reply.not_data); + return -1; + } + + /* Find the key in the map */ + for (i = 0; i < d->props.rc_key_map_size; i++) { + if (keymap[i].custom == poll_reply.system_lsb && + keymap[i].data == poll_reply.data) { + *event = keymap[i].event; + found = 1; + break; + } + } + + if (found == 0) { + err("Unknown remote controller key: %02x %02x %02x %02x", + poll_reply.system_msb, poll_reply.system_lsb, + poll_reply.data, poll_reply.not_data); + d->last_event = 0; + return 0; + } + + if (poll_reply.data_state == 1) { + /* New key hit */ + st->rc_counter = 0; + *event = keymap[i].event; + *state = REMOTE_KEY_PRESSED; + d->last_event = keymap[i].event; + } else if (poll_reply.data_state == 2) { + /* Key repeated */ + st->rc_counter++; + + /* prevents unwanted double hits */ + if (st->rc_counter > RC_REPEAT_DELAY_V1_20) { + *event = d->last_event; + *state = REMOTE_KEY_PRESSED; + st->rc_counter = RC_REPEAT_DELAY_V1_20; + } + } else { + err("Unknown data state [%d]", poll_reply.data_state); + } + + return 0; +} + +static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +{ + struct dib0700_state *st = d->priv; + + /* Because some people may have improperly named firmware files, + let's figure out whether to use the new firmware call or the legacy + call based on the firmware version embedded in the file */ + if (st->rc_func_version == 0) { + u32 hwver, romver, ramver, fwtype; + int ret = dib0700_get_version(d, &hwver, &romver, &ramver, + &fwtype); + if (ret < 0) { + err("Could not determine version info"); + return -1; + } + if (ramver < 0x10200) + st->rc_func_version = 1; + else + st->rc_func_version = 2; + } + + if (st->rc_func_version == 2) + return dib0700_rc_query_v1_20(d, event, state); + else + return dib0700_rc_query_legacy(d, event, state); +} + static struct dvb_usb_rc_key dib0700_rc_keys[] = { /* Key codes for the tiny Pinnacle remote*/ { 0x07, 0x00, KEY_MUTE }, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c index 5cef12a07f72..6fe71c6745eb 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c @@ -13,14 +13,14 @@ int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, { int actlen,ret = -ENOMEM; + if (!d || wbuf == NULL || wlen == 0) + return -EINVAL; + if (d->props.generic_bulk_ctrl_endpoint == 0) { err("endpoint for generic control not specified."); return -EINVAL; } - if (wbuf == NULL || wlen == 0) - return -EINVAL; - if ((ret = mutex_lock_interruptible(&d->usb_mutex))) return ret; diff --git a/drivers/media/dvb/dvb-usb/usb-urb.c b/drivers/media/dvb/dvb-usb/usb-urb.c index 397f51a7b2ad..da93b9e982c0 100644 --- a/drivers/media/dvb/dvb-usb/usb-urb.c +++ b/drivers/media/dvb/dvb-usb/usb-urb.c @@ -135,7 +135,7 @@ stream->buf_list[stream->buf_num], (long long)stream->dma_addr[stream->buf_num]) static int usb_bulk_urb_init(struct usb_data_stream *stream) { - int i; + int i, j; if ((i = usb_allocate_stream_buffers(stream,stream->props.count, stream->props.u.bulk.buffersize)) < 0) @@ -143,9 +143,13 @@ static int usb_bulk_urb_init(struct usb_data_stream *stream) /* allocate the URBs */ for (i = 0; i < stream->props.count; i++) { - if ((stream->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC)) == NULL) + stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); + if (!stream->urb_list[i]) { + deb_mem("not enough memory for urb_alloc_urb!.\n"); + for (j = 0; j < i; j++) + usb_free_urb(stream->urb_list[i]); return -ENOMEM; - + } usb_fill_bulk_urb( stream->urb_list[i], stream->udev, usb_rcvbulkpipe(stream->udev,stream->props.endpoint), stream->buf_list[i], @@ -170,9 +174,14 @@ static int usb_isoc_urb_init(struct usb_data_stream *stream) for (i = 0; i < stream->props.count; i++) { struct urb *urb; int frame_offset = 0; - if ((stream->urb_list[i] = - usb_alloc_urb(stream->props.u.isoc.framesperurb,GFP_ATOMIC)) == NULL) + + stream->urb_list[i] = usb_alloc_urb(stream->props.u.isoc.framesperurb, GFP_ATOMIC); + if (!stream->urb_list[i]) { + deb_mem("not enough memory for urb_alloc_urb!\n"); + for (j = 0; j < i; j++) + usb_free_urb(stream->urb_list[i]); return -ENOMEM; + } urb = stream->urb_list[i]; diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c index 21c1060cf10e..692b68a9e73b 100644 --- a/drivers/media/dvb/frontends/af9013.c +++ b/drivers/media/dvb/frontends/af9013.c @@ -1187,7 +1187,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status) if (tmp) *status |= FE_HAS_SYNC | FE_HAS_LOCK; - if (!*status & FE_HAS_SIGNAL) { + if (!(*status & FE_HAS_SIGNAL)) { /* AGC lock */ ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp); if (ret) @@ -1196,7 +1196,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status) *status |= FE_HAS_SIGNAL; } - if (!*status & FE_HAS_CARRIER) { + if (!(*status & FE_HAS_CARRIER)) { /* CFO lock */ ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp); if (ret) @@ -1205,7 +1205,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status) *status |= FE_HAS_CARRIER; } - if (!*status & FE_HAS_CARRIER) { + if (!(*status & FE_HAS_CARRIER)) { /* SFOE lock */ ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp); if (ret) diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c index 2febfb5a846b..40644aacffcb 100644 --- a/drivers/media/dvb/frontends/s5h1411.c +++ b/drivers/media/dvb/frontends/s5h1411.c @@ -38,6 +38,7 @@ struct s5h1411_state { struct dvb_frontend frontend; fe_modulation_t current_modulation; + unsigned int first_tune:1; u32 current_frequency; int if_freq; @@ -62,7 +63,7 @@ static struct init_tab { { S5H1411_I2C_TOP_ADDR, 0x08, 0x0047, }, { S5H1411_I2C_TOP_ADDR, 0x1c, 0x0400, }, { S5H1411_I2C_TOP_ADDR, 0x1e, 0x0370, }, - { S5H1411_I2C_TOP_ADDR, 0x1f, 0x342a, }, + { S5H1411_I2C_TOP_ADDR, 0x1f, 0x342c, }, { S5H1411_I2C_TOP_ADDR, 0x24, 0x0231, }, { S5H1411_I2C_TOP_ADDR, 0x25, 0x1011, }, { S5H1411_I2C_TOP_ADDR, 0x26, 0x0f07, }, @@ -100,7 +101,6 @@ static struct init_tab { { S5H1411_I2C_TOP_ADDR, 0x78, 0x3141, }, { S5H1411_I2C_TOP_ADDR, 0x7a, 0x3141, }, { S5H1411_I2C_TOP_ADDR, 0xb3, 0x8003, }, - { S5H1411_I2C_TOP_ADDR, 0xb5, 0xafbb, }, { S5H1411_I2C_TOP_ADDR, 0xb5, 0xa6bb, }, { S5H1411_I2C_TOP_ADDR, 0xb6, 0x0609, }, { S5H1411_I2C_TOP_ADDR, 0xb7, 0x2f06, }, @@ -393,7 +393,7 @@ static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz) switch (KHz) { case 3250: - s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d9); + s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d5); s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x5342); s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x10d9); break; @@ -464,13 +464,25 @@ static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion) if (inversion == 1) val |= 0x1000; /* Inverted */ - else - val |= 0x0000; state->inversion = inversion; return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val); } +static int s5h1411_set_serialmode(struct dvb_frontend *fe, int serial) +{ + struct s5h1411_state *state = fe->demodulator_priv; + u16 val; + + dprintk("%s(%d)\n", __func__, serial); + val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbd) & ~0x100; + + if (serial == 1) + val |= 0x100; + + return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, val); +} + static int s5h1411_enable_modulation(struct dvb_frontend *fe, fe_modulation_t m) { @@ -478,6 +490,12 @@ static int s5h1411_enable_modulation(struct dvb_frontend *fe, dprintk("%s(0x%08x)\n", __func__, m); + if ((state->first_tune == 0) && (m == state->current_modulation)) { + dprintk("%s() Already at desired modulation. Skipping...\n", + __func__); + return 0; + } + switch (m) { case VSB_8: dprintk("%s() VSB_8\n", __func__); @@ -502,6 +520,7 @@ static int s5h1411_enable_modulation(struct dvb_frontend *fe, } state->current_modulation = m; + state->first_tune = 0; s5h1411_softreset(fe); return 0; @@ -535,7 +554,7 @@ static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable) return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val); } -static int s5h1411_sleep(struct dvb_frontend *fe, int enable) +static int s5h1411_set_powerstate(struct dvb_frontend *fe, int enable) { struct s5h1411_state *state = fe->demodulator_priv; @@ -551,6 +570,11 @@ static int s5h1411_sleep(struct dvb_frontend *fe, int enable) return 0; } +static int s5h1411_sleep(struct dvb_frontend *fe) +{ + return s5h1411_set_powerstate(fe, 1); +} + static int s5h1411_register_reset(struct dvb_frontend *fe) { struct s5h1411_state *state = fe->demodulator_priv; @@ -574,9 +598,6 @@ static int s5h1411_set_frontend(struct dvb_frontend *fe, s5h1411_enable_modulation(fe, p->u.vsb.modulation); - /* Allow the demod to settle */ - msleep(100); - if (fe->ops.tuner_ops.set_params) { if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -587,6 +608,10 @@ static int s5h1411_set_frontend(struct dvb_frontend *fe, fe->ops.i2c_gate_ctrl(fe, 0); } + /* Issue a reset to the demod so it knows to resync against the + newly tuned frequency */ + s5h1411_softreset(fe); + return 0; } @@ -599,7 +624,7 @@ static int s5h1411_init(struct dvb_frontend *fe) dprintk("%s()\n", __func__); - s5h1411_sleep(fe, 0); + s5h1411_set_powerstate(fe, 0); s5h1411_register_reset(fe); for (i = 0; i < ARRAY_SIZE(init_tab); i++) @@ -610,12 +635,17 @@ static int s5h1411_init(struct dvb_frontend *fe) /* The datasheet says that after initialisation, VSB is default */ state->current_modulation = VSB_8; + /* Although the datasheet says it's in VSB, empirical evidence + shows problems getting lock on the first tuning request. Make + sure we call enable_modulation the first time around */ + state->first_tune = 1; + if (state->config->output_mode == S5H1411_SERIAL_OUTPUT) /* Serial */ - s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1101); + s5h1411_set_serialmode(fe, 1); else /* Parallel */ - s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1001); + s5h1411_set_serialmode(fe, 0); s5h1411_set_spectralinversion(fe, state->config->inversion); s5h1411_set_if_freq(fe, state->config->vsb_if); @@ -637,28 +667,29 @@ static int s5h1411_read_status(struct dvb_frontend *fe, fe_status_t *status) *status = 0; - /* Get the demodulator status */ - reg = (s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2) >> 15) - & 0x0001; - if (reg) - *status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_SIGNAL; + /* Register F2 bit 15 = Master Lock, removed */ switch (state->current_modulation) { case QAM_64: case QAM_256: reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf0); - if (reg & 0x100) - *status |= FE_HAS_VITERBI; - if (reg & 0x10) - *status |= FE_HAS_SYNC; + if (reg & 0x10) /* QAM FEC Lock */ + *status |= FE_HAS_SYNC | FE_HAS_LOCK; + if (reg & 0x100) /* QAM EQ Lock */ + *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL; + break; case VSB_8: - reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x5e); - if (reg & 0x0001) - *status |= FE_HAS_SYNC; reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2); - if (reg & 0x1000) - *status |= FE_HAS_VITERBI; + if (reg & 0x1000) /* FEC Lock */ + *status |= FE_HAS_SYNC | FE_HAS_LOCK; + if (reg & 0x2000) /* EQ Lock */ + *status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL; + + reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x53); + if (reg & 0x1) /* AFC Lock */ + *status |= FE_HAS_SIGNAL; + break; default: return -EINVAL; @@ -863,6 +894,7 @@ static struct dvb_frontend_ops s5h1411_ops = { }, .init = s5h1411_init, + .sleep = s5h1411_sleep, .i2c_gate_ctrl = s5h1411_i2c_gate_ctrl, .set_frontend = s5h1411_set_frontend, .get_frontend = s5h1411_get_frontend, diff --git a/drivers/media/dvb/frontends/s5h1411.h b/drivers/media/dvb/frontends/s5h1411.h index 7d542bc00c48..45ec0f82989c 100644 --- a/drivers/media/dvb/frontends/s5h1411.h +++ b/drivers/media/dvb/frontends/s5h1411.h @@ -47,7 +47,7 @@ struct s5h1411_config { u16 mpeg_timing; /* IF Freq for QAM and VSB in KHz */ -#define S5H1411_IF_2500 2500 +#define S5H1411_IF_3250 3250 #define S5H1411_IF_3500 3500 #define S5H1411_IF_4000 4000 #define S5H1411_IF_5380 5380 diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c index 6f9b77360440..e98d6caf2c23 100644 --- a/drivers/media/dvb/siano/sms-cards.c +++ b/drivers/media/dvb/siano/sms-cards.c @@ -95,7 +95,7 @@ static struct sms_board sms_boards[] = { [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = { .name = "Hauppauge WinTV MiniStick", .type = SMS_NOVA_B0, - .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw", + .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", }, }; diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 66ab0c6e9783..4a3f2b8ea37d 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -808,6 +808,12 @@ static int ttusb_alloc_iso_urbs(struct ttusb *ttusb) ISO_BUF_COUNT, &ttusb->iso_dma_handle); + if (!ttusb->iso_buffer) { + dprintk("%s: pci_alloc_consistent - not enough memory\n", + __func__); + return -ENOMEM; + } + memset(ttusb->iso_buffer, 0, ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT); @@ -1659,7 +1665,14 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i ttusb_setup_interfaces(ttusb); - ttusb_alloc_iso_urbs(ttusb); + result = ttusb_alloc_iso_urbs(ttusb); + if (result < 0) { + dprintk("%s: ttusb_alloc_iso_urbs - failed\n", __func__); + mutex_unlock(&ttusb->semi2c); + kfree(ttusb); + return result; + } + if (ttusb_init_controller(ttusb)) printk("ttusb_init_controller: error\n"); diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index ab33fec8a19f..0aa96df80fc2 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -1157,6 +1157,12 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) ISO_BUF_COUNT), &dec->iso_dma_handle); + if (!dec->iso_buffer) { + dprintk("%s: pci_alloc_consistent - not enough memory\n", + __func__); + return -ENOMEM; + } + memset(dec->iso_buffer, 0, ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT)); @@ -1254,6 +1260,7 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec) dec->irq_buffer = usb_buffer_alloc(dec->udev,IRQ_PACKET_SIZE, GFP_ATOMIC, &dec->irq_dma_handle); if(!dec->irq_buffer) { + usb_free_urb(dec->irq_urb); return -ENOMEM; } usb_fill_int_urb(dec->irq_urb, dec->udev,dec->irq_pipe, diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 04cd7c04bdde..5189c4eb439f 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -355,6 +355,20 @@ config USB_SI470X tristate "Silicon Labs Si470x FM Radio Receiver support" depends on USB && VIDEO_V4L2 ---help--- + This is a driver for USB devices with the Silicon Labs SI470x + chip. Currently these devices are known to work: + - 10c4:818a: Silicon Labs USB FM Radio Reference Design + - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) + - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700) + + Sound is provided by the ALSA USB Audio/MIDI driver. Therefore + if you don't want to use the device solely for RDS receiving, + it is recommended to also select SND_USB_AUDIO. + + Please have a look at the documentation, especially on how + to redirect the audio stream from the radio to your sound device: + Documentation/video4linux/si470x.txt + Say Y here if you want to connect this type of radio to your computer's USB port. diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c index 78f56944e640..a5ca176a7b08 100644 --- a/drivers/media/radio/dsbr100.c +++ b/drivers/media/radio/dsbr100.c @@ -171,11 +171,11 @@ static int dsbr100_start(struct dsbr100_device *radio) if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 || + 0x00, 0xC7, radio->transfer_buffer, 8, 300) < 0 || usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), DSB100_ONOFF, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x01, 0x00, radio->transfer_buffer, 8, 300)<0) + 0x01, 0x00, radio->transfer_buffer, 8, 300) < 0) return -1; radio->muted=0; return (radio->transfer_buffer)[0]; @@ -188,11 +188,11 @@ static int dsbr100_stop(struct dsbr100_device *radio) if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 || + 0x16, 0x1C, radio->transfer_buffer, 8, 300) < 0 || usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), DSB100_ONOFF, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x00, 0x00, radio->transfer_buffer, 8, 300)<0) + 0x00, 0x00, radio->transfer_buffer, 8, 300) < 0) return -1; radio->muted=1; return (radio->transfer_buffer)[0]; @@ -201,24 +201,24 @@ static int dsbr100_stop(struct dsbr100_device *radio) /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ static int dsbr100_setfreq(struct dsbr100_device *radio, int freq) { - freq = (freq/16*80)/1000+856; + freq = (freq / 16 * 80) / 1000 + 856; if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), DSB100_TUNE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - (freq>>8)&0x00ff, freq&0xff, - radio->transfer_buffer, 8, 300)<0 || + (freq >> 8) & 0x00ff, freq & 0xff, + radio->transfer_buffer, 8, 300) < 0 || usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 || + 0x96, 0xB7, radio->transfer_buffer, 8, 300) < 0 || usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) { + 0x00, 0x24, radio->transfer_buffer, 8, 300) < 0) { radio->stereo = -1; return -1; } - radio->stereo = ! ((radio->transfer_buffer)[0]&0x01); + radio->stereo = !((radio->transfer_buffer)[0] & 0x01); return (radio->transfer_buffer)[0]; } @@ -229,10 +229,10 @@ static void dsbr100_getstat(struct dsbr100_device *radio) if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), USB_REQ_GET_STATUS, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0) + 0x00 , 0x24, radio->transfer_buffer, 8, 300) < 0) radio->stereo = -1; else - radio->stereo = ! (radio->transfer_buffer[0]&0x01); + radio->stereo = !(radio->transfer_buffer[0] & 0x01); } @@ -265,7 +265,7 @@ static int vidioc_querycap(struct file *file, void *priv, { 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"); + sprintf(v->bus_info, "USB"); v->version = RADIO_VERSION; v->capabilities = V4L2_CAP_TUNER; return 0; @@ -282,9 +282,9 @@ static int vidioc_g_tuner(struct file *file, void *priv, 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->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; @@ -309,7 +309,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct dsbr100_device *radio = video_drvdata(file); radio->curfreq = f->frequency; - if (dsbr100_setfreq(radio, radio->curfreq)==-1) + if (dsbr100_setfreq(radio, radio->curfreq) == -1) dev_warn(&radio->usbdev->dev, "Set frequency failed\n"); return 0; } @@ -331,8 +331,7 @@ static int vidioc_queryctrl(struct file *file, void *priv, 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)); + memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); return 0; } } @@ -412,19 +411,25 @@ static int vidioc_s_audio(struct file *file, void *priv, static int usb_dsbr100_open(struct inode *inode, struct file *file) { struct dsbr100_device *radio = video_drvdata(file); + int retval; lock_kernel(); radio->users = 1; radio->muted = 1; - if (dsbr100_start(radio)<0) { + if (dsbr100_start(radio) < 0) { dev_warn(&radio->usbdev->dev, "Radio did not start up properly\n"); radio->users = 0; unlock_kernel(); return -EIO; } - dsbr100_setfreq(radio, radio->curfreq); + + retval = dsbr100_setfreq(radio, radio->curfreq); + + if (retval == -1) + printk(KERN_WARNING KBUILD_MODNAME ": Set frequency failed\n"); + unlock_kernel(); return 0; } @@ -485,13 +490,20 @@ static int usb_dsbr100_probe(struct usb_interface *intf, { struct dsbr100_device *radio; - if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL))) + radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL); + + if (!radio) return -ENOMEM; - if (!(radio->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL))) { + + radio->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL); + + if (!(radio->transfer_buffer)) { kfree(radio); return -ENOMEM; } - if (!(radio->videodev = video_device_alloc())) { + radio->videodev = video_device_alloc(); + + if (!(radio->videodev)) { kfree(radio->transfer_buffer); kfree(radio); return -ENOMEM; @@ -501,7 +513,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf, radio->removed = 0; radio->users = 0; radio->usbdev = interface_to_usbdev(intf); - radio->curfreq = FREQ_MIN*FREQ_MUL; + radio->curfreq = FREQ_MIN * FREQ_MUL; video_set_drvdata(radio->videodev, radio); if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr) < 0) { dev_warn(&intf->dev, "Could not register video device\n"); diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index a33717c48003..256cbeffdcb6 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -469,16 +469,21 @@ static int usb_amradio_open(struct inode *inode, struct file *file) { struct amradio_device *radio = video_get_drvdata(video_devdata(file)); + lock_kernel(); + radio->users = 1; radio->muted = 1; if (amradio_start(radio) < 0) { warn("Radio did not start up properly"); radio->users = 0; + unlock_kernel(); return -EIO; } if (amradio_setfreq(radio, radio->curfreq) < 0) warn("Set frequency failed"); + + unlock_kernel(); return 0; } diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 5920cd306975..3e1830293de5 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c @@ -4,6 +4,7 @@ * Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers: * - Silicon Labs USB FM Radio Reference Design * - ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF) + * - KWorld USB FM Radio SnapMusic Mobile 700 (FM700) * * Copyright (c) 2008 Tobias Lorenz <tobias.lorenz@gmx.net> * @@ -24,19 +25,6 @@ /* - * User Notes: - * - USB Audio is provided by the alsa snd_usb_audio module. - * For listing you have to redirect the sound, for example using: - * arecord -D hw:1,0 -r96000 -c2 -f S16_LE | artsdsp aplay -B - - * - regarding module parameters in /sys/module/radio_si470x/parameters: - * the contents of read-only files (0444) are not updated, even if - * space, band and de are changed using private video controls - * - increase tune_timeout, if you often get -EIO errors - * - hw_freq_seek returns -EAGAIN, when timed out or band limit is reached - */ - - -/* * History: * 2008-01-12 Tobias Lorenz <tobias.lorenz@gmx.net> * Version 1.0.0 @@ -105,6 +93,9 @@ * - afc indication * - more safety checks, let si470x_get_freq return errno * - vidioc behavior corrected according to v4l2 spec + * 2008-10-20 Alexey Klimov <klimov.linux@gmail.com> + * - add support for KWorld USB FM Radio FM700 + * - blacklisted KWorld radio in hid-core.c and hid-ids.h * * ToDo: * - add firmware download/update support @@ -145,6 +136,8 @@ static struct usb_device_id si470x_usb_driver_id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) }, /* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */ { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) }, + /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) }, /* Terminating entry */ { } }; diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 218754b4906a..e09b00693230 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -866,7 +866,7 @@ static int __init ar_init(void) } printk("video%d: Found M64278 VGA (IRQ %d, Freq %dMHz).\n", - ar->vdev->minor, M32R_IRQ_INT3, freq); + ar->vdev->num, M32R_IRQ_INT3, freq); return 0; diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 5858bf5ff41c..9ec4cec2e52d 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -4246,7 +4246,7 @@ static int __devinit bttv_register_video(struct bttv *btv) video_nr[btv->c.nr]) < 0) goto err; printk(KERN_INFO "bttv%d: registered device video%d\n", - btv->c.nr,btv->video_dev->minor & 0x1f); + btv->c.nr, btv->video_dev->num); if (device_create_file(&btv->video_dev->dev, &dev_attr_card)<0) { printk(KERN_ERR "bttv%d: device_create_file 'card' " @@ -4263,7 +4263,7 @@ static int __devinit bttv_register_video(struct bttv *btv) vbi_nr[btv->c.nr]) < 0) goto err; printk(KERN_INFO "bttv%d: registered device vbi%d\n", - btv->c.nr,btv->vbi_dev->minor & 0x1f); + btv->c.nr, btv->vbi_dev->num); if (!btv->has_radio) return 0; @@ -4275,7 +4275,7 @@ static int __devinit bttv_register_video(struct bttv *btv) radio_nr[btv->c.nr]) < 0) goto err; printk(KERN_INFO "bttv%d: registered device radio%d\n", - btv->c.nr,btv->radio_dev->minor & 0x1f); + btv->c.nr, btv->radio_dev->num); /* all done */ return 0; diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c index 17aa0adb3467..0f930d351466 100644 --- a/drivers/media/video/c-qcam.c +++ b/drivers/media/video/c-qcam.c @@ -815,7 +815,7 @@ static int init_cqcam(struct parport *port) } printk(KERN_INFO "video%d: Colour QuickCam found on %s\n", - qcam->vdev.minor, qcam->pport->name); + qcam->vdev.num, qcam->pport->name); qcams[num_cams++] = qcam; diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index fc9497bdd322..1740b9ebdcef 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -1476,12 +1476,9 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp) { struct cafe_camera *cam; - lock_kernel(); cam = cafe_find_dev(iminor(inode)); - if (cam == NULL) { - unlock_kernel(); + if (cam == NULL) return -ENODEV; - } filp->private_data = cam; mutex_lock(&cam->s_mutex); @@ -1493,7 +1490,6 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp) } (cam->users)++; mutex_unlock(&cam->s_mutex); - unlock_kernel(); return 0; } @@ -2059,10 +2055,10 @@ static void cafe_dfs_cam_setup(struct cafe_camera *cam) if (!cafe_dfs_root) return; - sprintf(fname, "regs-%d", cam->v4ldev.minor); + sprintf(fname, "regs-%d", cam->v4ldev.num); cam->dfs_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, cam, &cafe_dfs_reg_ops); - sprintf(fname, "cam-%d", cam->v4ldev.minor); + sprintf(fname, "cam-%d", cam->v4ldev.num); cam->dfs_cam_regs = debugfs_create_file(fname, 0444, cafe_dfs_root, cam, &cafe_dfs_cam_ops); } diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c index bd5d9de5a008..e6ca4012b5f0 100644 --- a/drivers/media/video/compat_ioctl32.c +++ b/drivers/media/video/compat_ioctl32.c @@ -867,6 +867,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_STREAMON32: case VIDIOC_STREAMOFF32: case VIDIOC_G_PARM: + case VIDIOC_S_PARM: case VIDIOC_G_STD: case VIDIOC_S_STD: case VIDIOC_G_TUNER: @@ -885,6 +886,8 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_S_INPUT32: case VIDIOC_TRY_FMT32: case VIDIOC_S_HW_FREQ_SEEK: + case VIDIOC_ENUM_FRAMESIZES: + case VIDIOC_ENUM_FRAMEINTERVALS: ret = do_video_ioctl(file, cmd, arg); break; diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 1798b779a25a..16c094f77852 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -1347,7 +1347,7 @@ static void create_proc_cpia_cam(struct cam_data *cam) if (!cpia_proc_root || !cam) return; - snprintf(name, sizeof(name), "video%d", cam->vdev.minor); + snprintf(name, sizeof(name), "video%d", cam->vdev.num); ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root); if (!ent) @@ -1372,7 +1372,7 @@ static void destroy_proc_cpia_cam(struct cam_data *cam) if (!cam || !cam->proc_entry) return; - snprintf(name, sizeof(name), "video%d", cam->vdev.minor); + snprintf(name, sizeof(name), "video%d", cam->vdev.num); remove_proc_entry(name, cpia_proc_root); cam->proc_entry = NULL; } @@ -4005,7 +4005,7 @@ void cpia_unregister_camera(struct cam_data *cam) } #ifdef CONFIG_PROC_FS - DBG("destroying /proc/cpia/video%d\n", cam->vdev.minor); + DBG("destroying /proc/cpia/video%d\n", cam->vdev.num); destroy_proc_cpia_cam(cam); #endif if (!cam->open_count) { diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c index 897e8d1a5c3c..1c6bd633f193 100644 --- a/drivers/media/video/cpia2/cpia2_v4l.c +++ b/drivers/media/video/cpia2/cpia2_v4l.c @@ -1973,7 +1973,7 @@ void cpia2_unregister_camera(struct camera_data *cam) } else { LOG("/dev/video%d removed while open, " "deferring video_unregister_device\n", - cam->vdev->minor); + cam->vdev->num); } } diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 085121c2b47f..7874d9790a51 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -448,7 +448,14 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) mutex_init(&cx->gpio_lock); spin_lock_init(&cx->lock); - spin_lock_init(&cx->dma_reg_lock); + + cx->work_queue = create_singlethread_workqueue(cx->name); + if (cx->work_queue == NULL) { + CX18_ERR("Could not create work queue\n"); + return -1; + } + + INIT_WORK(&cx->work, cx18_work_handler); /* start counting open_id at 1 */ cx->open_id = 1; @@ -581,10 +588,10 @@ static void cx18_load_and_init_modules(struct cx18 *cx) #ifdef MODULE /* load modules */ -#ifndef CONFIG_MEDIA_TUNER +#ifdef CONFIG_MEDIA_TUNER_MODULE hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER); #endif -#ifndef CONFIG_VIDEO_CS5345 +#ifdef CONFIG_VIDEO_CS5345_MODULE hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345); #endif #endif @@ -613,6 +620,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) { int retval = 0; + int i; int vbi_buf_size; u32 devtype; struct cx18 *cx; @@ -698,7 +706,8 @@ static int __devinit cx18_probe(struct pci_dev *dev, /* active i2c */ CX18_DEBUG_INFO("activating i2c...\n"); - if (init_cx18_i2c(cx)) { + retval = init_cx18_i2c(cx); + if (retval) { CX18_ERR("Could not initialize i2c\n"); goto free_map; } @@ -830,14 +839,18 @@ free_map: free_mem: release_mem_region(cx->base_addr, CX18_MEM_SIZE); free_workqueue: + destroy_workqueue(cx->work_queue); err: if (retval == 0) retval = -ENODEV; CX18_ERR("Error %d on initialization\n", retval); cx18_log_statistics(cx); - kfree(cx18_cards[cx18_cards_active]); - cx18_cards[cx18_cards_active] = NULL; + i = cx->num; + spin_lock(&cx18_cards_lock); + kfree(cx18_cards[i]); + cx18_cards[i] = NULL; + spin_unlock(&cx18_cards_lock); return retval; } @@ -927,6 +940,9 @@ static void cx18_remove(struct pci_dev *pci_dev) cx18_halt_firmware(cx); + flush_workqueue(cx->work_queue); + destroy_workqueue(cx->work_queue); + cx18_streams_cleanup(cx, 1); exit_cx18_i2c(cx); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index a4b1708fafe7..bbdd5f25041d 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -199,12 +199,15 @@ struct cx18_options { #define CX18_F_S_APPL_IO 8 /* this stream is used read/written by an application */ /* per-cx18, i_flags */ -#define CX18_F_I_LOADED_FW 0 /* Loaded the firmware the first time */ -#define CX18_F_I_EOS 4 /* End of encoder stream reached */ -#define CX18_F_I_RADIO_USER 5 /* The radio tuner is selected */ -#define CX18_F_I_ENC_PAUSED 13 /* the encoder is paused */ -#define CX18_F_I_INITED 21 /* set after first open */ -#define CX18_F_I_FAILED 22 /* set if first open failed */ +#define CX18_F_I_LOADED_FW 0 /* Loaded firmware 1st time */ +#define CX18_F_I_EOS 4 /* End of encoder stream */ +#define CX18_F_I_RADIO_USER 5 /* radio tuner is selected */ +#define CX18_F_I_ENC_PAUSED 13 /* the encoder is paused */ +#define CX18_F_I_HAVE_WORK 15 /* there is work to be done */ +#define CX18_F_I_WORK_HANDLER_DVB 18 /* work to be done for DVB */ +#define CX18_F_I_INITED 21 /* set after first open */ +#define CX18_F_I_FAILED 22 /* set if first open failed */ +#define CX18_F_I_WORK_INITED 23 /* worker thread initialized */ /* These are the VBI types as they appear in the embedded VBI private packets. */ #define CX18_SLICED_TYPE_TELETEXT_B (1) @@ -402,8 +405,6 @@ struct cx18 { spinlock_t lock; /* lock access to this struct */ int search_pack_header; - spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ - int open_id; /* incremented each time an open occurs, used as unique ID. Starts at 1, so 0 can be used as uninitialized value in the stream->id. */ @@ -433,6 +434,9 @@ struct cx18 { /* when the current DMA is finished this queue is woken up */ wait_queue_head_t dma_waitq; + struct workqueue_struct *work_queue; + struct work_struct work; + /* i2c */ struct i2c_adapter i2c_adap[2]; struct i2c_algo_bit_data i2c_algo[2]; diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index afc694e7bdb2..4542e2e5e3d7 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -23,6 +23,8 @@ #include "cx18-dvb.h" #include "cx18-io.h" #include "cx18-streams.h" +#include "cx18-queue.h" +#include "cx18-scb.h" #include "cx18-cards.h" #include "s5h1409.h" #include "mxl5005s.h" @@ -300,3 +302,24 @@ static int dvb_register(struct cx18_stream *stream) return ret; } + +void cx18_dvb_work_handler(struct cx18 *cx) +{ + struct cx18_buffer *buf; + struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_TS]; + + while ((buf = cx18_dequeue(s, &s->q_full)) != NULL) { + if (s->dvb.enabled) + dvb_dmx_swfilter(&s->dvb.demux, buf->buf, + buf->bytesused); + + cx18_enqueue(s, buf, &s->q_free); + cx18_buf_sync_for_device(s, buf); + if (s->handle == CX18_INVALID_TASK_HANDLE) /* FIXME: improve */ + continue; + + cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, + (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, + 1, buf->id, s->buf_size); + } +} diff --git a/drivers/media/video/cx18/cx18-dvb.h b/drivers/media/video/cx18/cx18-dvb.h index bf8d8f6f5455..bbdcefc87f28 100644 --- a/drivers/media/video/cx18/cx18-dvb.h +++ b/drivers/media/video/cx18/cx18-dvb.h @@ -23,3 +23,4 @@ int cx18_dvb_register(struct cx18_stream *stream); void cx18_dvb_unregister(struct cx18_stream *stream); +void cx18_dvb_work_handler(struct cx18 *cx); diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c index 700ab9439c16..220fae8d4ad7 100644 --- a/drivers/media/video/cx18/cx18-io.c +++ b/drivers/media/video/cx18/cx18-io.c @@ -88,6 +88,19 @@ void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr) cx18_log_write_retries(cx, i, addr); } +void _cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr, + u32 eval, u32 mask) +{ + int i; + eval &= mask; + for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { + cx18_writel_noretry(cx, val, addr); + if (eval == (cx18_readl_noretry(cx, addr) & mask)) + break; + } + cx18_log_write_retries(cx, i, addr); +} + void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr) { int i; @@ -218,7 +231,7 @@ void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count) void cx18_sw1_irq_enable(struct cx18 *cx, u32 val) { u32 r; - cx18_write_reg(cx, val, SW1_INT_STATUS); + cx18_write_reg_expect(cx, val, SW1_INT_STATUS, ~val, val); r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI); } @@ -233,7 +246,7 @@ void cx18_sw1_irq_disable(struct cx18 *cx, u32 val) void cx18_sw2_irq_enable(struct cx18 *cx, u32 val) { u32 r; - cx18_write_reg(cx, val, SW2_INT_STATUS); + cx18_write_reg_expect(cx, val, SW2_INT_STATUS, ~val, val); r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI); } diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h index 197d4fbd9f95..425244453ea7 100644 --- a/drivers/media/video/cx18/cx18-io.h +++ b/drivers/media/video/cx18/cx18-io.h @@ -39,7 +39,7 @@ static inline void cx18_io_delay(struct cx18 *cx) /* Statistics gathering */ static inline -void cx18_log_write_retries(struct cx18 *cx, int i, const void *addr) +void cx18_log_write_retries(struct cx18 *cx, int i, const void __iomem *addr) { if (i > CX18_MAX_MMIO_RETRIES) i = CX18_MAX_MMIO_RETRIES; @@ -48,7 +48,7 @@ void cx18_log_write_retries(struct cx18 *cx, int i, const void *addr) } static inline -void cx18_log_read_retries(struct cx18 *cx, int i, const void *addr) +void cx18_log_read_retries(struct cx18 *cx, int i, const void __iomem *addr) { if (i > CX18_MAX_MMIO_RETRIES) i = CX18_MAX_MMIO_RETRIES; @@ -133,6 +133,8 @@ static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) cx18_writel_noretry(cx, val, addr); } +void _cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr, + u32 eval, u32 mask); static inline void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr) @@ -271,6 +273,21 @@ static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg) cx18_write_reg_noretry(cx, val, reg); } +static inline void _cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg, + u32 eval, u32 mask) +{ + _cx18_writel_expect(cx, val, cx->reg_mem + reg, eval, mask); +} + +static inline void cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg, + u32 eval, u32 mask) +{ + if (cx18_retry_mmio) + _cx18_write_reg_expect(cx, val, reg, eval, mask); + else + cx18_write_reg_noretry(cx, val, reg); +} + static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg) { diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index 360330f5463f..5fbfbd0f1493 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c @@ -29,8 +29,20 @@ #include "cx18-mailbox.h" #include "cx18-vbi.h" #include "cx18-scb.h" +#include "cx18-dvb.h" -#define DMA_MAGIC_COOKIE 0x000001fe +void cx18_work_handler(struct work_struct *work) +{ + struct cx18 *cx = container_of(work, struct cx18, work); + if (test_and_clear_bit(CX18_F_I_WORK_INITED, &cx->i_flags)) { + struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; + /* This thread must use the FIFO scheduler as it + * is realtime sensitive. */ + sched_setscheduler(current, SCHED_FIFO, ¶m); + } + if (test_and_clear_bit(CX18_F_I_WORK_HANDLER_DVB, &cx->i_flags)) + cx18_dvb_work_handler(cx); +} static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) { @@ -67,17 +79,11 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) if (buf) { cx18_buf_sync_for_cpu(s, buf); if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) { - /* process the buffer here */ - CX18_DEBUG_HI_DMA("TS recv and sent bytesused=%d\n", - buf->bytesused); - - dvb_dmx_swfilter(&s->dvb.demux, buf->buf, + CX18_DEBUG_HI_DMA("TS recv bytesused = %d\n", buf->bytesused); - cx18_buf_sync_for_device(s, buf); - cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, - (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, - 1, buf->id, s->buf_size); + set_bit(CX18_F_I_WORK_HANDLER_DVB, &cx->i_flags); + set_bit(CX18_F_I_HAVE_WORK, &cx->i_flags); } else set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); } else { @@ -109,7 +115,7 @@ static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb) CX18_INFO("FW version: %s\n", p - 1); } -static void hpu_cmd(struct cx18 *cx, u32 sw1) +static void epu_cmd(struct cx18 *cx, u32 sw1) { struct cx18_mailbox mb; @@ -125,12 +131,31 @@ static void hpu_cmd(struct cx18 *cx, u32 sw1) epu_debug(cx, &mb); break; default: - CX18_WARN("Unexpected mailbox command %08x\n", mb.cmd); + CX18_WARN("Unknown CPU_TO_EPU mailbox command %#08x\n", + mb.cmd); break; } } - if (sw1 & (IRQ_APU_TO_EPU | IRQ_HPU_TO_EPU)) - CX18_WARN("Unexpected interrupt %08x\n", sw1); + + if (sw1 & IRQ_APU_TO_EPU) { + cx18_memcpy_fromio(cx, &mb, &cx->scb->apu2epu_mb, sizeof(mb)); + CX18_WARN("Unknown APU_TO_EPU mailbox command %#08x\n", mb.cmd); + } + + if (sw1 & IRQ_HPU_TO_EPU) { + cx18_memcpy_fromio(cx, &mb, &cx->scb->hpu2epu_mb, sizeof(mb)); + CX18_WARN("Unknown HPU_TO_EPU mailbox command %#08x\n", mb.cmd); + } +} + +static void xpu_ack(struct cx18 *cx, u32 sw2) +{ + if (sw2 & IRQ_CPU_TO_EPU_ACK) + wake_up(&cx->mb_cpu_waitq); + if (sw2 & IRQ_APU_TO_EPU_ACK) + wake_up(&cx->mb_apu_waitq); + if (sw2 & IRQ_HPU_TO_EPU_ACK) + wake_up(&cx->mb_hpu_waitq); } irqreturn_t cx18_irq_handler(int irq, void *dev_id) @@ -140,43 +165,36 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) u32 sw2, sw2_mask; u32 hw2, hw2_mask; - spin_lock(&cx->dma_reg_lock); - + sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); + sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask; + sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); + sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask; hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI); hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask; - sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK; - sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask; - sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; - sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask; - cx18_write_reg(cx, sw2&sw2_mask, SW2_INT_STATUS); - cx18_write_reg(cx, sw1&sw1_mask, SW1_INT_STATUS); - cx18_write_reg(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS); + if (sw1) + cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1); + if (sw2) + cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2); + if (hw2) + cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2); if (sw1 || sw2 || hw2) CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); /* To do: interrupt-based I2C handling - if (hw2 & 0x00c00000) { + if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) { } */ - if (sw2) { - if (sw2 & (cx18_readl(cx, &cx->scb->cpu2hpu_irq_ack) | - cx18_readl(cx, &cx->scb->cpu2epu_irq_ack))) - wake_up(&cx->mb_cpu_waitq); - if (sw2 & (cx18_readl(cx, &cx->scb->apu2hpu_irq_ack) | - cx18_readl(cx, &cx->scb->apu2epu_irq_ack))) - wake_up(&cx->mb_apu_waitq); - if (sw2 & cx18_readl(cx, &cx->scb->epu2hpu_irq_ack)) - wake_up(&cx->mb_epu_waitq); - if (sw2 & cx18_readl(cx, &cx->scb->hpu2epu_irq_ack)) - wake_up(&cx->mb_hpu_waitq); - } + if (sw2) + xpu_ack(cx, sw2); if (sw1) - hpu_cmd(cx, sw1); - spin_unlock(&cx->dma_reg_lock); + epu_cmd(cx, sw1); + + if (test_and_clear_bit(CX18_F_I_HAVE_WORK, &cx->i_flags)) + queue_work(cx->work_queue, &cx->work); - return (hw2 | sw1 | sw2) ? IRQ_HANDLED : IRQ_NONE; + return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE; } diff --git a/drivers/media/video/cx18/cx18-irq.h b/drivers/media/video/cx18/cx18-irq.h index 379f704f5cba..6173ca3bc9e4 100644 --- a/drivers/media/video/cx18/cx18-irq.h +++ b/drivers/media/video/cx18/cx18-irq.h @@ -32,6 +32,4 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id); -void cx18_irq_work_handler(struct work_struct *work); -void cx18_dma_stream_dec_prepare(struct cx18_stream *s, u32 offset, int lock); -void cx18_unfinished_dma(unsigned long arg); +void cx18_work_handler(struct work_struct *work); diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 9d18dd22de76..acff7dfb60df 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -83,7 +83,7 @@ static const struct cx18_api_info api_info[] = { API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST), - API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, 0), + API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, API_SLOW), API_ENTRY(0, 0, 0), }; @@ -176,7 +176,7 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) cx18_setup_page(cx, SCB_OFFSET); cx18_write_sync(cx, mb->request, &ack_mb->ack); - cx18_write_reg(cx, ack_irq, SW2_INT_SET); + cx18_write_reg_expect(cx, ack_irq, SW2_INT_SET, ack_irq, ack_irq); return 0; } @@ -225,7 +225,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) } if (info->flags & API_FAST) timeout /= 2; - cx18_write_reg(cx, irq, SW1_INT_SET); + cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq); while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request) && cnt < 660) { diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index a33ba04a2686..174682c2582f 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -88,15 +88,13 @@ struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id, if (buf->id != id) continue; + buf->bytesused = bytesused; - /* the transport buffers are handled differently, - they are not moved to the full queue */ - if (s->type != CX18_ENC_STREAM_TYPE_TS) { - atomic_dec(&s->q_free.buffers); - atomic_inc(&s->q_full.buffers); - s->q_full.bytesused += buf->bytesused; - list_move_tail(&buf->list, &s->q_full.list); - } + atomic_dec(&s->q_free.buffers); + atomic_inc(&s->q_full.buffers); + s->q_full.bytesused += buf->bytesused; + list_move_tail(&buf->list, &s->q_full.list); + spin_unlock(&s->qlock); return buf; } diff --git a/drivers/media/video/cx18/cx18-scb.h b/drivers/media/video/cx18/cx18-scb.h index 86b4cb15d163..594713bbed68 100644 --- a/drivers/media/video/cx18/cx18-scb.h +++ b/drivers/media/video/cx18/cx18-scb.h @@ -128,22 +128,22 @@ struct cx18_scb { u32 apu2cpu_irq; /* Value to write to register SW2 register set (0xC7003140) after the command is cleared */ - u32 apu2cpu_irq_ack; + u32 cpu2apu_irq_ack; u32 reserved2[13]; u32 hpu2cpu_mb_offset; u32 hpu2cpu_irq; - u32 hpu2cpu_irq_ack; + u32 cpu2hpu_irq_ack; u32 reserved3[13]; u32 ppu2cpu_mb_offset; u32 ppu2cpu_irq; - u32 ppu2cpu_irq_ack; + u32 cpu2ppu_irq_ack; u32 reserved4[13]; u32 epu2cpu_mb_offset; u32 epu2cpu_irq; - u32 epu2cpu_irq_ack; + u32 cpu2epu_irq_ack; u32 reserved5[13]; u32 reserved6[8]; @@ -153,22 +153,22 @@ struct cx18_scb { u32 reserved11[7]; u32 cpu2apu_mb_offset; u32 cpu2apu_irq; - u32 cpu2apu_irq_ack; + u32 apu2cpu_irq_ack; u32 reserved12[13]; u32 hpu2apu_mb_offset; u32 hpu2apu_irq; - u32 hpu2apu_irq_ack; + u32 apu2hpu_irq_ack; u32 reserved13[13]; u32 ppu2apu_mb_offset; u32 ppu2apu_irq; - u32 ppu2apu_irq_ack; + u32 apu2ppu_irq_ack; u32 reserved14[13]; u32 epu2apu_mb_offset; u32 epu2apu_irq; - u32 epu2apu_irq_ack; + u32 apu2epu_irq_ack; u32 reserved15[13]; u32 reserved16[8]; @@ -178,22 +178,22 @@ struct cx18_scb { u32 reserved21[7]; u32 cpu2hpu_mb_offset; u32 cpu2hpu_irq; - u32 cpu2hpu_irq_ack; + u32 hpu2cpu_irq_ack; u32 reserved22[13]; u32 apu2hpu_mb_offset; u32 apu2hpu_irq; - u32 apu2hpu_irq_ack; + u32 hpu2apu_irq_ack; u32 reserved23[13]; u32 ppu2hpu_mb_offset; u32 ppu2hpu_irq; - u32 ppu2hpu_irq_ack; + u32 hpu2ppu_irq_ack; u32 reserved24[13]; u32 epu2hpu_mb_offset; u32 epu2hpu_irq; - u32 epu2hpu_irq_ack; + u32 hpu2epu_irq_ack; u32 reserved25[13]; u32 reserved26[8]; @@ -203,22 +203,22 @@ struct cx18_scb { u32 reserved31[7]; u32 cpu2ppu_mb_offset; u32 cpu2ppu_irq; - u32 cpu2ppu_irq_ack; + u32 ppu2cpu_irq_ack; u32 reserved32[13]; u32 apu2ppu_mb_offset; u32 apu2ppu_irq; - u32 apu2ppu_irq_ack; + u32 ppu2apu_irq_ack; u32 reserved33[13]; u32 hpu2ppu_mb_offset; u32 hpu2ppu_irq; - u32 hpu2ppu_irq_ack; + u32 ppu2hpu_irq_ack; u32 reserved34[13]; u32 epu2ppu_mb_offset; u32 epu2ppu_irq; - u32 epu2ppu_irq_ack; + u32 ppu2epu_irq_ack; u32 reserved35[13]; u32 reserved36[8]; @@ -228,22 +228,22 @@ struct cx18_scb { u32 reserved41[7]; u32 cpu2epu_mb_offset; u32 cpu2epu_irq; - u32 cpu2epu_irq_ack; + u32 epu2cpu_irq_ack; u32 reserved42[13]; u32 apu2epu_mb_offset; u32 apu2epu_irq; - u32 apu2epu_irq_ack; + u32 epu2apu_irq_ack; u32 reserved43[13]; u32 hpu2epu_mb_offset; u32 hpu2epu_irq; - u32 hpu2epu_irq_ack; + u32 epu2hpu_irq_ack; u32 reserved44[13]; u32 ppu2epu_mb_offset; u32 ppu2epu_irq; - u32 ppu2epu_irq_ack; + u32 epu2ppu_irq_ack; u32 reserved45[13]; u32 reserved46[8]; diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 0c8e7542cf60..e5ff7705b7a1 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -200,16 +200,18 @@ static int cx18_prep_dev(struct cx18 *cx, int type) /* Initialize v4l2 variables and register v4l2 devices */ int cx18_streams_setup(struct cx18 *cx) { - int type; + int type, ret; /* Setup V4L2 Devices */ for (type = 0; type < CX18_MAX_STREAMS; type++) { /* Prepare device */ - if (cx18_prep_dev(cx, type)) + ret = cx18_prep_dev(cx, type); + if (ret < 0) break; /* Allocate Stream */ - if (cx18_stream_alloc(&cx->streams[type])) + ret = cx18_stream_alloc(&cx->streams[type]); + if (ret < 0) break; } if (type == CX18_MAX_STREAMS) @@ -217,14 +219,14 @@ int cx18_streams_setup(struct cx18 *cx) /* One or more streams could not be initialized. Clean 'em all up. */ cx18_streams_cleanup(cx, 0); - return -ENOMEM; + return ret; } static int cx18_reg_dev(struct cx18 *cx, int type) { struct cx18_stream *s = &cx->streams[type]; int vfl_type = cx18_stream_info[type].vfl_type; - int num; + int num, ret; /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something? * We need a VFL_TYPE_TS defined. @@ -233,9 +235,10 @@ static int cx18_reg_dev(struct cx18 *cx, int type) /* just return if no DVB is supported */ if ((cx->card->hw_all & CX18_HW_DVB) == 0) return 0; - if (cx18_dvb_register(s) < 0) { + ret = cx18_dvb_register(s); + if (ret < 0) { CX18_ERR("DVB failed to register\n"); - return -EINVAL; + return ret; } } @@ -252,12 +255,13 @@ static int cx18_reg_dev(struct cx18 *cx, int type) } /* Register device. First try the desired minor, then any free one. */ - if (video_register_device(s->v4l2dev, vfl_type, num)) { + ret = video_register_device(s->v4l2dev, vfl_type, num); + if (ret < 0) { CX18_ERR("Couldn't register v4l2 device for %s kernel number %d\n", s->name, num); video_device_release(s->v4l2dev); s->v4l2dev = NULL; - return -ENOMEM; + return ret; } num = s->v4l2dev->num; @@ -290,18 +294,22 @@ static int cx18_reg_dev(struct cx18 *cx, int type) int cx18_streams_register(struct cx18 *cx) { int type; - int err = 0; + int err; + int ret = 0; /* Register V4L2 devices */ - for (type = 0; type < CX18_MAX_STREAMS; type++) - err |= cx18_reg_dev(cx, type); + for (type = 0; type < CX18_MAX_STREAMS; type++) { + err = cx18_reg_dev(cx, type); + if (err && ret == 0) + ret = err; + } - if (err == 0) + if (ret == 0) return 0; /* One or more streams could not be initialized. Clean 'em all up. */ cx18_streams_cleanup(cx, 1); - return -ENOMEM; + return ret; } /* Unregister v4l2 devices */ diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 395c11fa47ce..00831f3ef8f5 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c @@ -1815,7 +1815,7 @@ int cx23885_417_register(struct cx23885_dev *dev) cx23885_mc417_init(dev); printk(KERN_INFO "%s: registered device video%d [mpeg]\n", - dev->name, dev->v4l_device->minor & 0x1f); + dev->name, dev->v4l_device->num); return 0; } diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index ab3110d6046c..c742a10be5cb 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -1543,7 +1543,7 @@ int cx23885_video_register(struct cx23885_dev *dev) goto fail_unreg; } printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n", - dev->name, dev->video_dev->minor & 0x1f); + dev->name, dev->video_dev->num); /* initial device configuration */ mutex_lock(&dev->lock); cx23885_set_tvnorm(dev, dev->tvnorm); diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index e71369754305..d3ae5b4dfca7 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1078,7 +1078,7 @@ static int mpeg_open(struct inode *inode, struct file *file) } } - if (blackbird_initialize_codec(dev) < 0) { + if (!atomic_read(&dev->core->mpeg_users) && blackbird_initialize_codec(dev) < 0) { if (drv) drv->request_release(drv); unlock_kernel(); @@ -1109,6 +1109,8 @@ static int mpeg_open(struct inode *inode, struct file *file) fh->mpegq.field); unlock_kernel(); + atomic_inc(&dev->core->mpeg_users); + return 0; } @@ -1118,7 +1120,7 @@ static int mpeg_release(struct inode *inode, struct file *file) struct cx8802_dev *dev = fh->dev; struct cx8802_driver *drv = NULL; - if (dev->mpeg_active) + if (dev->mpeg_active && atomic_read(&dev->core->mpeg_users) == 1) blackbird_stop_codec(dev); cx8802_cancel_buffers(fh->dev); @@ -1138,6 +1140,8 @@ static int mpeg_release(struct inode *inode, struct file *file) if (drv) drv->request_release(drv); + atomic_dec(&dev->core->mpeg_users); + return 0; } @@ -1158,6 +1162,10 @@ static unsigned int mpeg_poll(struct file *file, struct poll_table_struct *wait) { struct cx8802_fh *fh = file->private_data; + struct cx8802_dev *dev = fh->dev; + + if (!dev->mpeg_active) + blackbird_start_codec(file, fh); return videobuf_poll_stream(file, &fh->mpegq, wait); } @@ -1285,7 +1293,7 @@ static int blackbird_register_video(struct cx8802_dev *dev) return err; } printk(KERN_INFO "%s/2: registered device video%d [mpeg]\n", - dev->core->name,dev->mpeg_dev->minor & 0x1f); + dev->core->name, dev->mpeg_dev->num); return 0; } diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index fbc224f46e0e..5bcbb4cc7c2a 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -3044,8 +3044,8 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board)); - if (!core->board.num_frontends) - core->board.num_frontends=1; + if (!core->board.num_frontends && (core->board.mpeg & CX88_MPEG_DVB)) + core->board.num_frontends = 1; info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n", pci->subsystem_vendor, pci->subsystem_device, core->board.name, diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 6968ab0181aa..309ca5e68063 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -598,6 +598,11 @@ static int dvb_register(struct cx8802_dev *dev) struct videobuf_dvb_frontend *fe0, *fe1 = NULL; int mfe_shared = 0; /* bus not shared by default */ + if (0 != core->i2c_rc) { + printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name); + goto frontend_detach; + } + /* Get the first frontend */ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); if (!fe0) @@ -789,7 +794,7 @@ static int dvb_register(struct cx8802_dev *dev) if (fe0->dvb.frontend) fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; if (attach_xc3028(0x61, dev) < 0) - return -EINVAL; + goto frontend_detach; break; case CX88_BOARD_PCHDTV_HD3000: fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, @@ -1058,7 +1063,6 @@ static int dvb_register(struct cx8802_dev *dev) goto frontend_detach; core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; - } } break; @@ -1110,10 +1114,7 @@ static int dvb_register(struct cx8802_dev *dev) &dev->pci->dev, adapter_nr, mfe_shared); frontend_detach: - if (fe0->dvb.frontend) { - dvb_frontend_detach(fe0->dvb.frontend); - fe0->dvb.frontend = NULL; - } + videobuf_dvb_dealloc_frontends(&dev->frontends); return -EINVAL; } @@ -1246,8 +1247,11 @@ fail_core: static int cx8802_dvb_remove(struct cx8802_driver *drv) { + struct cx88_core *core = drv->core; struct cx8802_dev *dev = drv->core->dvbdev; + dprintk( 1, "%s\n", __func__); + videobuf_dvb_unregister_bus(&dev->frontends); vp3054_i2c_remove(dev); diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 01de23007095..1ab691d20692 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -116,8 +116,10 @@ static int detach_inform(struct i2c_client *client) void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) { +#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) struct videobuf_dvb_frontends *f = &core->dvbdev->frontends; struct videobuf_dvb_frontend *fe = NULL; +#endif if (0 != core->i2c_rc) return; diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 6df5cf314186..3ebdcd1d83f8 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -768,8 +768,7 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, { struct cx8802_dev *dev; struct cx88_core *core; - struct videobuf_dvb_frontend *demod; - int err,i; + int err; /* general setup */ core = cx88_core_get(pci_dev); @@ -782,11 +781,6 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, if (!core->board.mpeg) goto fail_core; - if (!core->board.num_frontends) { - printk(KERN_ERR "%s() .num_frontends should be non-zero, err = %d\n", __func__, err); - goto fail_core; - } - err = -ENOMEM; dev = kzalloc(sizeof(*dev),GFP_KERNEL); if (NULL == dev) @@ -801,19 +795,28 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, INIT_LIST_HEAD(&dev->drvlist); list_add_tail(&dev->devlist,&cx8802_devlist); +#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) mutex_init(&dev->frontends.lock); INIT_LIST_HEAD(&dev->frontends.felist); - printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, core->board.num_frontends); - - for (i = 1; i <= core->board.num_frontends; i++) { - demod = videobuf_dvb_alloc_frontend(&dev->frontends, i); - if(demod == NULL) { - printk(KERN_ERR "%s() failed to alloc\n", __func__); - err = -ENOMEM; - goto fail_free; + if (core->board.num_frontends) { + struct videobuf_dvb_frontend *fe; + int i; + + printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, + core->board.num_frontends); + for (i = 1; i <= core->board.num_frontends; i++) { + fe = videobuf_dvb_alloc_frontend(&dev->frontends, i); + if(fe == NULL) { + printk(KERN_ERR "%s() failed to alloc\n", + __func__); + videobuf_dvb_dealloc_frontends(&dev->frontends); + err = -ENOMEM; + goto fail_free; + } } } +#endif /* Maintain a reference so cx88-video can query the 8802 device. */ core->dvbdev = dev; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 3904b73f52ee..b96ce991d968 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1216,8 +1216,12 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) struct cx8800_fh *fh = priv; struct cx8800_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + /* We should remember that this driver also supports teletext, */ + /* so we have to test if the v4l2_buf_type is VBI capture data. */ + if (unlikely((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && + (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))) return -EINVAL; + if (unlikely(i != fh->type)) return -EINVAL; @@ -1232,8 +1236,10 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) struct cx8800_dev *dev = fh->dev; int err, res; - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && + (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)) return -EINVAL; + if (i != fh->type) return -EINVAL; @@ -1911,7 +1917,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, goto fail_unreg; } printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n", - core->name,dev->video_dev->minor & 0x1f); + core->name, dev->video_dev->num); dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi"); err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, @@ -1922,7 +1928,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, goto fail_unreg; } printk(KERN_INFO "%s/0: registered device vbi%d\n", - core->name,dev->vbi_dev->minor & 0x1f); + core->name, dev->vbi_dev->num); if (core->board.radio.type == CX88_RADIO) { dev->radio_dev = cx88_vdev_init(core,dev->pci, @@ -1935,7 +1941,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, goto fail_unreg; } printk(KERN_INFO "%s/0: registered device radio%d\n", - core->name,dev->radio_dev->minor & 0x1f); + core->name, dev->radio_dev->num); } /* everything worked */ diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 76207c2856b7..f4240965be32 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -352,6 +352,7 @@ struct cx88_core { /* various v4l controls */ u32 freq; atomic_t users; + atomic_t mpeg_users; /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ struct cx8802_dev *dvbdev; diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index ac3292d7646c..7a8d49ef646e 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -62,7 +62,7 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) dprintk("Stopping isoc\n"); for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { - usb_kill_urb(dev->adev->urb[i]); + usb_unlink_urb(dev->adev->urb[i]); usb_free_urb(dev->adev->urb[i]); dev->adev->urb[i] = NULL; } @@ -75,7 +75,6 @@ static void em28xx_audio_isocirq(struct urb *urb) struct em28xx *dev = urb->context; int i; unsigned int oldptr; - unsigned long flags; int period_elapsed = 0; int status; unsigned char *cp; @@ -96,9 +95,21 @@ static void em28xx_audio_isocirq(struct urb *urb) if (!length) continue; - spin_lock_irqsave(&dev->adev->slock, flags); - oldptr = dev->adev->hwptr_done_capture; + if (oldptr + length >= runtime->buffer_size) { + unsigned int cnt = + runtime->buffer_size - oldptr; + memcpy(runtime->dma_area + oldptr * stride, cp, + cnt * stride); + memcpy(runtime->dma_area, cp + cnt * stride, + length * stride - cnt * stride); + } else { + memcpy(runtime->dma_area + oldptr * stride, cp, + length * stride); + } + + snd_pcm_stream_lock(substream); + dev->adev->hwptr_done_capture += length; if (dev->adev->hwptr_done_capture >= runtime->buffer_size) @@ -113,19 +124,7 @@ static void em28xx_audio_isocirq(struct urb *urb) period_elapsed = 1; } - spin_unlock_irqrestore(&dev->adev->slock, flags); - - if (oldptr + length >= runtime->buffer_size) { - unsigned int cnt = - runtime->buffer_size - oldptr; - memcpy(runtime->dma_area + oldptr * stride, cp, - cnt * stride); - memcpy(runtime->dma_area, cp + cnt * stride, - length * stride - cnt * stride); - } else { - memcpy(runtime->dma_area + oldptr * stride, cp, - length * stride); - } + snd_pcm_stream_unlock(substream); } if (period_elapsed) snd_pcm_period_elapsed(substream); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 5d837c16ee22..15e2b525310d 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -69,19 +69,33 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, int ret, byte; if (dev->state & DEV_DISCONNECTED) - return(-ENODEV); + return -ENODEV; + + if (len > URB_MAX_CTRL_SIZE) + return -EINVAL; em28xx_regdbg("req=%02x, reg=%02x ", req, reg); + mutex_lock(&dev->ctrl_urb_lock); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, reg, buf, len, HZ); + 0x0000, reg, dev->urb_buf, len, HZ); + if (ret < 0) { + if (reg_debug) + printk(" failed!\n"); + mutex_unlock(&dev->ctrl_urb_lock); + return ret; + } + + if (len) + memcpy(buf, dev->urb_buf, len); + + mutex_unlock(&dev->ctrl_urb_lock); if (reg_debug) { - printk(ret < 0 ? " failed!\n" : "%02x values: ", ret); + printk("%02x values: ", ret); for (byte = 0; byte < len; byte++) printk(" %02x", (unsigned char)buf[byte]); - printk("\n"); } @@ -102,16 +116,20 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) em28xx_regdbg("req=%02x, reg=%02x:", req, reg); + mutex_lock(&dev->ctrl_urb_lock); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, reg, &val, 1, HZ); - - if (reg_debug) - printk(ret < 0 ? " failed!\n" : - "%02x\n", (unsigned char) val); + 0x0000, reg, dev->urb_buf, 1, HZ); + val = dev->urb_buf[0]; + mutex_unlock(&dev->ctrl_urb_lock); - if (ret < 0) + if (ret < 0) { + printk(" failed!\n"); return ret; + } + + if (reg_debug) + printk("%02x\n", (unsigned char) val); return val; } @@ -130,19 +148,13 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, { int ret; - /*usb_control_msg seems to expect a kmalloced buffer */ - unsigned char *bufs; - if (dev->state & DEV_DISCONNECTED) return -ENODEV; - if (len < 1) + if ((len < 1) || (len > URB_MAX_CTRL_SIZE)) return -EINVAL; - bufs = kmalloc(len, GFP_KERNEL); - em28xx_regdbg("req=%02x reg=%02x:", req, reg); - if (reg_debug) { int i; for (i = 0; i < len; ++i) @@ -150,16 +162,16 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, printk("\n"); } - if (!bufs) - return -ENOMEM; - memcpy(bufs, buf, len); + mutex_lock(&dev->ctrl_urb_lock); + memcpy(dev->urb_buf, buf, len); ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, reg, bufs, len, HZ); + 0x0000, reg, dev->urb_buf, len, HZ); + mutex_unlock(&dev->ctrl_urb_lock); + if (dev->wait_after_write) msleep(dev->wait_after_write); - kfree(bufs); return ret; } @@ -270,6 +282,8 @@ static int em28xx_set_audio_source(struct em28xx *dev) break; case EM28XX_AMUX_LINE_IN: input = EM28XX_AUDIO_SRC_LINE; + video = disable; + line = enable; break; case EM28XX_AMUX_AC97_VIDEO: input = EM28XX_AUDIO_SRC_LINE; diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 3bab56b997fc..2360c61ddca9 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -337,9 +337,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) /* Check if board has eeprom */ err = i2c_master_recv(&dev->i2c_client, &buf, 0); if (err < 0) { - em28xx_errdev("%s: i2c_master_recv failed! err [%d]\n", - __func__, err); - return err; + em28xx_errdev("board has no eeprom\n"); + memset(eedata, 0, len); + return -ENODEV; } buf = 0; @@ -609,14 +609,16 @@ int em28xx_i2c_register(struct em28xx *dev) dev->i2c_client.adapter = &dev->i2c_adap; retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); - if (retval < 0) { + if ((retval < 0) && (retval != -ENODEV)) { em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", __func__, retval); + return retval; } if (i2c_scan) em28xx_do_i2c_scan(dev); + return 0; } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index c53649e5315b..610f535a257c 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -73,6 +73,7 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); static LIST_HEAD(em28xx_devlist); +static DEFINE_MUTEX(em28xx_devlist_mutex); static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; @@ -1519,7 +1520,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) struct em28xx_fh *fh; enum v4l2_buf_type fh_type = 0; - lock_kernel(); + mutex_lock(&em28xx_devlist_mutex); list_for_each_entry(h, &em28xx_devlist, devlist) { if (h->vdev->minor == minor) { dev = h; @@ -1535,10 +1536,11 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev = h; } } - if (NULL == dev) { - unlock_kernel(); + mutex_unlock(&em28xx_devlist_mutex); + if (NULL == dev) return -ENODEV; - } + + mutex_lock(&dev->lock); em28xx_videodbg("open minor=%d type=%s users=%d\n", minor, v4l2_type_names[fh_type], dev->users); @@ -1547,10 +1549,9 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); if (!fh) { em28xx_errdev("em28xx-video.c: Out of memory?!\n"); - unlock_kernel(); + mutex_unlock(&dev->lock); return -ENOMEM; } - mutex_lock(&dev->lock); fh->dev = dev; fh->radio = radio; fh->type = fh_type; @@ -1584,7 +1585,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) sizeof(struct em28xx_buffer), fh); mutex_unlock(&dev->lock); - unlock_kernel(); return errCode; } @@ -1871,6 +1871,7 @@ int em28xx_register_extension(struct em28xx_ops *ops) { struct em28xx *dev = NULL; + mutex_lock(&em28xx_devlist_mutex); mutex_lock(&em28xx_extension_devlist_lock); list_add_tail(&ops->next, &em28xx_extension_devlist); list_for_each_entry(dev, &em28xx_devlist, devlist) { @@ -1879,6 +1880,7 @@ int em28xx_register_extension(struct em28xx_ops *ops) } printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); mutex_unlock(&em28xx_extension_devlist_lock); + mutex_unlock(&em28xx_devlist_mutex); return 0; } EXPORT_SYMBOL(em28xx_register_extension); @@ -1887,6 +1889,7 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) { struct em28xx *dev = NULL; + mutex_lock(&em28xx_devlist_mutex); list_for_each_entry(dev, &em28xx_devlist, devlist) { if (dev) ops->fini(dev); @@ -1896,6 +1899,7 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); list_del(&ops->next); mutex_unlock(&em28xx_extension_devlist_lock); + mutex_unlock(&em28xx_devlist_mutex); } EXPORT_SYMBOL(em28xx_unregister_extension); @@ -1921,6 +1925,60 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, } +static int register_analog_devices(struct em28xx *dev) +{ + int ret; + + /* allocate and fill video video_device struct */ + dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); + if (!dev->vdev) { + em28xx_errdev("cannot allocate video_device.\n"); + return -ENODEV; + } + + /* register v4l2 video video_device */ + ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER, + video_nr[dev->devno]); + if (ret) { + em28xx_errdev("unable to register video device (error=%i).\n", + ret); + return ret; + } + + /* Allocate and fill vbi video_device struct */ + dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi"); + + /* register v4l2 vbi video_device */ + ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, + vbi_nr[dev->devno]); + if (ret < 0) { + em28xx_errdev("unable to register vbi device\n"); + return ret; + } + + if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { + dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio"); + if (!dev->radio_dev) { + em28xx_errdev("cannot allocate video_device.\n"); + return -ENODEV; + } + ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, + radio_nr[dev->devno]); + if (ret < 0) { + em28xx_errdev("can't register radio device\n"); + return ret; + } + em28xx_info("Registered radio device as /dev/radio%d\n", + dev->radio_dev->num); + } + + em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", + dev->vdev->num, dev->vbi_dev->num); + + return 0; +} + + /* * em28xx_init_dev() * allocates and inits the device structs, registers i2c bus and v4l device @@ -1936,6 +1994,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->udev = udev; mutex_init(&dev->lock); + mutex_init(&dev->ctrl_urb_lock); spin_lock_init(&dev->slock); init_waitqueue_head(&dev->open); init_waitqueue_head(&dev->wait_frame); @@ -1953,8 +2012,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, errCode = em28xx_config(dev); if (errCode) { em28xx_errdev("error configuring device\n"); - em28xx_devused &= ~(1<<dev->devno); - kfree(dev); return -ENOMEM; } @@ -2001,50 +2058,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, return errCode; } - list_add_tail(&dev->devlist, &em28xx_devlist); - - /* allocate and fill video video_device struct */ - dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); - if (NULL == dev->vdev) { - em28xx_errdev("cannot allocate video_device.\n"); - goto fail_unreg; - } - - /* register v4l2 video video_device */ - retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, - video_nr[dev->devno]); - if (retval) { - em28xx_errdev("unable to register video device (error=%i).\n", - retval); - goto fail_unreg; - } - - /* Allocate and fill vbi video_device struct */ - dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi"); - /* register v4l2 vbi video_device */ - if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, - vbi_nr[dev->devno]) < 0) { - em28xx_errdev("unable to register vbi device\n"); - retval = -ENODEV; - goto fail_unreg; - } - - if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { - dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio"); - if (NULL == dev->radio_dev) { - em28xx_errdev("cannot allocate video_device.\n"); - goto fail_unreg; - } - retval = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, - radio_nr[dev->devno]); - if (retval < 0) { - em28xx_errdev("can't register radio device\n"); - goto fail_unreg; - } - em28xx_info("Registered radio device as /dev/radio%d\n", - dev->radio_dev->minor & 0x1f); - } - /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); INIT_LIST_HEAD(&dev->vidq.queued); @@ -2071,8 +2084,14 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, video_mux(dev, 0); - em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", - dev->vdev->num, dev->vbi_dev->num); + mutex_lock(&em28xx_devlist_mutex); + list_add_tail(&dev->devlist, &em28xx_devlist); + retval = register_analog_devices(dev); + if (retval < 0) { + em28xx_release_resources(dev); + mutex_unlock(&em28xx_devlist_mutex); + goto fail_reg_devices; + } mutex_lock(&em28xx_extension_devlist_lock); if (!list_empty(&em28xx_extension_devlist)) { @@ -2082,13 +2101,12 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, } } mutex_unlock(&em28xx_extension_devlist_lock); + mutex_unlock(&em28xx_devlist_mutex); return 0; -fail_unreg: - em28xx_release_resources(dev); +fail_reg_devices: mutex_unlock(&dev->lock); - kfree(dev); return retval; } @@ -2231,8 +2249,12 @@ static int em28xx_usb_probe(struct usb_interface *interface, /* allocate device struct */ retval = em28xx_init_dev(&dev, udev, nr); - if (retval) + if (retval) { + em28xx_devused &= ~(1<<dev->devno); + kfree(dev); + return retval; + } em28xx_info("Found %s\n", em28xx_boards[dev->model].name); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 82781178e0a3..5956e9b3062f 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -102,6 +102,9 @@ #define EM28XX_MIN_BUF 4 #define EM28XX_DEF_BUF 8 +/*Limits the max URB message size */ +#define URB_MAX_CTRL_SIZE 80 + /* Params for validated field */ #define EM28XX_BOARD_NOT_VALIDATED 1 #define EM28XX_BOARD_VALIDATED 0 @@ -430,6 +433,7 @@ struct em28xx { /* locks */ struct mutex lock; + struct mutex ctrl_urb_lock; /* protects urb_buf */ /* spinlock_t queue_lock; */ struct list_head inqueue, outqueue; wait_queue_head_t open, wait_frame, wait_stream; @@ -451,6 +455,8 @@ struct em28xx { unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ + char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ + /* helper funcs that call usb_control_msg */ int (*em28xx_write_regs) (struct em28xx *dev, u16 reg, char *buf, int len); diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 7a85c41b0eea..9d0ef96c23ff 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -588,7 +588,7 @@ static int et61x251_stream_interrupt(struct et61x251_device* cam) cam->state |= DEV_MISCONFIGURED; DBG(1, "URB timeout reached. The camera is misconfigured. To " "use it, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -EIO; } @@ -1195,7 +1195,7 @@ static void et61x251_release_resources(struct kref *kref) cam = container_of(kref, struct et61x251_device, kref); - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); + DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); usb_put_dev(cam->usbdev); @@ -1237,7 +1237,7 @@ static int et61x251_open(struct inode* inode, struct file* filp) if (cam->users) { DBG(2, "Device /dev/video%d is already in use", - cam->v4ldev->minor); + cam->v4ldev->num); DBG(3, "Simultaneous opens are not supported"); if ((filp->f_flags & O_NONBLOCK) || (filp->f_flags & O_NDELAY)) { @@ -1280,7 +1280,7 @@ static int et61x251_open(struct inode* inode, struct file* filp) cam->frame_count = 0; et61x251_empty_framequeues(cam); - DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); + DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num); out: mutex_unlock(&cam->open_mutex); @@ -1304,7 +1304,7 @@ static int et61x251_release(struct inode* inode, struct file* filp) cam->users--; wake_up_interruptible_nr(&cam->wait_open, 1); - DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); + DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num); kref_put(&cam->kref, et61x251_release_resources); @@ -1845,7 +1845,7 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -EIO; } @@ -1858,7 +1858,7 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -ENOMEM; } @@ -2068,7 +2068,7 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -EIO; } @@ -2080,7 +2080,7 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -ENOMEM; } @@ -2128,7 +2128,7 @@ et61x251_vidioc_s_jpegcomp(struct et61x251_device* cam, void __user * arg) cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " "problems. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->minor); + "/dev/video%d again.", cam->v4ldev->num); return -EIO; } @@ -2605,7 +2605,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); + DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num); cam->module_param.force_munmap = force_munmap[dev_nr]; cam->module_param.frame_timeout = frame_timeout[dev_nr]; @@ -2658,7 +2658,7 @@ static void et61x251_usb_disconnect(struct usb_interface* intf) if (cam->users) { DBG(2, "Device /dev/video%d is open! Deregistration and " "memory deallocation are deferred.", - cam->v4ldev->minor); + cam->v4ldev->num); cam->state |= DEV_MISCONFIGURED; et61x251_stop_transfer(cam); cam->state |= DEV_DISCONNECTED; diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 4d0817471c9f..6b557c057fac 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -3,16 +3,16 @@ menuconfig USB_GSPCA depends on VIDEO_V4L2 default m ---help--- - Say Y here if you want to enable selecting webcams based - on the GSPCA framework. + Say Y here if you want to enable selecting webcams based + on the GSPCA framework. - See <file:Documentation/video4linux/gspca.txt> for more info. + See <file:Documentation/video4linux/gspca.txt> for more info. - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" to use this driver. + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" to use this driver. - To compile this driver as modules, choose M here: the - modules will be called gspca_main. + To compile this driver as modules, choose M here: the + modules will be called gspca_main. if USB_GSPCA && VIDEO_V4L2 @@ -23,190 +23,190 @@ config USB_GSPCA_CONEX tristate "Conexant Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the Conexant chip. + Say Y here if you want support for cameras based on the Conexant chip. - To compile this driver as a module, choose M here: the - module will be called gspca_conex. + To compile this driver as a module, choose M here: the + module will be called gspca_conex. config USB_GSPCA_ETOMS tristate "Etoms USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the Etoms chip. + Say Y here if you want support for cameras based on the Etoms chip. - To compile this driver as a module, choose M here: the - module will be called gspca_etoms. + To compile this driver as a module, choose M here: the + module will be called gspca_etoms. config USB_GSPCA_FINEPIX tristate "Fujifilm FinePix USB V4L2 driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the FinePix chip. + Say Y here if you want support for cameras based on the FinePix chip. - To compile this driver as a module, choose M here: the - module will be called gspca_finepix. + To compile this driver as a module, choose M here: the + module will be called gspca_finepix. config USB_GSPCA_MARS tristate "Mars USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the Mars chip. + Say Y here if you want support for cameras based on the Mars chip. - To compile this driver as a module, choose M here: the - module will be called gspca_mars. + To compile this driver as a module, choose M here: the + module will be called gspca_mars. config USB_GSPCA_OV519 tristate "OV519 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the OV519 chip. + Say Y here if you want support for cameras based on the OV519 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_ov519. + To compile this driver as a module, choose M here: the + module will be called gspca_ov519. config USB_GSPCA_PAC207 tristate "Pixart PAC207 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the PAC207 chip. + Say Y here if you want support for cameras based on the PAC207 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_pac207. + To compile this driver as a module, choose M here: the + module will be called gspca_pac207. config USB_GSPCA_PAC7311 tristate "Pixart PAC7311 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the PAC7311 chip. + Say Y here if you want support for cameras based on the PAC7311 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_pac7311. + To compile this driver as a module, choose M here: the + module will be called gspca_pac7311. config USB_GSPCA_SONIXB tristate "SN9C102 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SONIXB chip. + Say Y here if you want support for cameras based on the SONIXB chip. - To compile this driver as a module, choose M here: the - module will be called gspca_sonixb. + To compile this driver as a module, choose M here: the + module will be called gspca_sonixb. config USB_GSPCA_SONIXJ tristate "SONIX JPEG USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SONIXJ chip. + Say Y here if you want support for cameras based on the SONIXJ chip. - To compile this driver as a module, choose M here: the - module will be called gspca_sonixj + To compile this driver as a module, choose M here: the + module will be called gspca_sonixj config USB_GSPCA_SPCA500 tristate "SPCA500 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SPCA500 chip. + Say Y here if you want support for cameras based on the SPCA500 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_spca500. + To compile this driver as a module, choose M here: the + module will be called gspca_spca500. config USB_GSPCA_SPCA501 tristate "SPCA501 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SPCA501 chip. + Say Y here if you want support for cameras based on the SPCA501 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_spca501. + To compile this driver as a module, choose M here: the + module will be called gspca_spca501. config USB_GSPCA_SPCA505 tristate "SPCA505 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SPCA505 chip. + Say Y here if you want support for cameras based on the SPCA505 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_spca505. + To compile this driver as a module, choose M here: the + module will be called gspca_spca505. config USB_GSPCA_SPCA506 tristate "SPCA506 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SPCA506 chip. + Say Y here if you want support for cameras based on the SPCA506 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_spca506. + To compile this driver as a module, choose M here: the + module will be called gspca_spca506. config USB_GSPCA_SPCA508 tristate "SPCA508 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SPCA508 chip. + Say Y here if you want support for cameras based on the SPCA508 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_spca508. + To compile this driver as a module, choose M here: the + module will be called gspca_spca508. config USB_GSPCA_SPCA561 tristate "SPCA561 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SPCA561 chip. + Say Y here if you want support for cameras based on the SPCA561 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_spca561. + To compile this driver as a module, choose M here: the + module will be called gspca_spca561. config USB_GSPCA_STK014 tristate "Syntek DV4000 (STK014) USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the STK014 chip. + Say Y here if you want support for cameras based on the STK014 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_stk014. + To compile this driver as a module, choose M here: the + module will be called gspca_stk014. config USB_GSPCA_SUNPLUS tristate "SUNPLUS USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the Sunplus - SPCA504(abc) SPCA533 SPCA536 chips. + Say Y here if you want support for cameras based on the Sunplus + SPCA504(abc) SPCA533 SPCA536 chips. - To compile this driver as a module, choose M here: the - module will be called gspca_spca5xx. + To compile this driver as a module, choose M here: the + module will be called gspca_spca5xx. config USB_GSPCA_T613 tristate "T613 (JPEG Compliance) USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the T613 chip. + Say Y here if you want support for cameras based on the T613 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_t613. + To compile this driver as a module, choose M here: the + module will be called gspca_t613. config USB_GSPCA_TV8532 tristate "TV8532 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the TV8531 chip. + Say Y here if you want support for cameras based on the TV8531 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_tv8532. + To compile this driver as a module, choose M here: the + module will be called gspca_tv8532. config USB_GSPCA_VC032X tristate "VC032X USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the VC032X chip. + Say Y here if you want support for cameras based on the VC032X chip. - To compile this driver as a module, choose M here: the - module will be called gspca_vc032x. + To compile this driver as a module, choose M here: the + module will be called gspca_vc032x. config USB_GSPCA_ZC3XX - tristate "VC3xx USB Camera Driver" + tristate "ZC3XX USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the ZC3XX chip. + Say Y here if you want support for cameras based on the ZC3XX chip. - To compile this driver as a module, choose M here: the - module will be called gspca_zc3xx. + To compile this driver as a module, choose M here: the + module will be called gspca_zc3xx. endif diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index a9d51ba7c57c..de28354ea5ba 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -846,10 +846,13 @@ static int sd_start(struct gspca_dev *gspca_dev) return 0; } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { int retry = 50; + if (!gspca_dev->present) + return; reg_w_val(gspca_dev, 0x0000, 0x00); reg_r(gspca_dev, 0x0002, 1); reg_w_val(gspca_dev, 0x0053, 0x00); diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c index 65d3cbfe6b27..607942fd7970 100644 --- a/drivers/media/video/gspca/finepix.c +++ b/drivers/media/video/gspca/finepix.c @@ -276,6 +276,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev) /* Stop the state machine */ if (dev->state != FPIX_NOP) wait_for_completion(&dev->can_close); +} + +/* called on streamoff with alt 0 and disconnect */ +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; usb_free_urb(dev->control_urb); dev->control_urb = NULL; @@ -385,6 +391,7 @@ static int sd_start(struct gspca_dev *gspca_dev) error: /* Free the ressources */ sd_stopN(gspca_dev); + sd_stop0(gspca_dev); return ret; } @@ -425,6 +432,7 @@ static const struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, + .stop0 = sd_stop0, }; /* -- device connect -- */ diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index e48fbfc8ad05..748a87e82e44 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -646,15 +646,14 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev) { gspca_dev->streaming = 0; atomic_set(&gspca_dev->nevent, 0); - if (gspca_dev->present) { - if (gspca_dev->sd_desc->stopN) - gspca_dev->sd_desc->stopN(gspca_dev); - destroy_urbs(gspca_dev); - gspca_set_alt0(gspca_dev); - if (gspca_dev->sd_desc->stop0) - gspca_dev->sd_desc->stop0(gspca_dev); - PDEBUG(D_STREAM, "stream off OK"); - } + if (gspca_dev->present + && gspca_dev->sd_desc->stopN) + gspca_dev->sd_desc->stopN(gspca_dev); + destroy_urbs(gspca_dev); + gspca_set_alt0(gspca_dev); + if (gspca_dev->sd_desc->stop0) + gspca_dev->sd_desc->stop0(gspca_dev); + PDEBUG(D_STREAM, "stream off OK"); } static void gspca_set_default_mode(struct gspca_dev *gspca_dev) @@ -863,7 +862,7 @@ static int dev_open(struct inode *inode, struct file *file) int ret; PDEBUG(D_STREAM, "%s open", current->comm); - gspca_dev = (struct gspca_dev *) video_devdata(file); + gspca_dev = video_drvdata(file); if (mutex_lock_interruptible(&gspca_dev->queue_lock)) return -ERESTARTSYS; if (!gspca_dev->present) { @@ -875,6 +874,13 @@ static int dev_open(struct inode *inode, struct file *file) ret = -EBUSY; goto out; } + + /* protect the subdriver against rmmod */ + if (!try_module_get(gspca_dev->module)) { + ret = -ENODEV; + goto out; + } + gspca_dev->users++; /* one more user */ @@ -884,10 +890,10 @@ static int dev_open(struct inode *inode, struct file *file) #ifdef GSPCA_DEBUG /* activate the v4l2 debug */ if (gspca_debug & D_V4L2) - gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL + gspca_dev->vdev->debug |= V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; else - gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL + gspca_dev->vdev->debug &= ~(V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG); #endif ret = 0; @@ -921,6 +927,7 @@ static int dev_close(struct inode *inode, struct file *file) gspca_dev->memory = GSPCA_MEMORY_NO; } file->private_data = NULL; + module_put(gspca_dev->module); mutex_unlock(&gspca_dev->queue_lock); PDEBUG(D_STREAM, "close done"); @@ -1748,11 +1755,6 @@ out: return ret; } -static void dev_release(struct video_device *vfd) -{ - /* nothing */ -} - static struct file_operations dev_fops = { .owner = THIS_MODULE, .open = dev_open, @@ -1800,7 +1802,7 @@ static struct video_device gspca_template = { .name = "gspca main driver", .fops = &dev_fops, .ioctl_ops = &dev_ioctl_ops, - .release = dev_release, /* mandatory */ + .release = video_device_release, .minor = -1, }; @@ -1869,17 +1871,18 @@ int gspca_dev_probe(struct usb_interface *intf, init_waitqueue_head(&gspca_dev->wq); /* init video stuff */ - memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template); - gspca_dev->vdev.parent = &dev->dev; - memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops); - gspca_dev->vdev.fops = &gspca_dev->fops; - gspca_dev->fops.owner = module; /* module protection */ + gspca_dev->vdev = video_device_alloc(); + memcpy(gspca_dev->vdev, &gspca_template, sizeof gspca_template); + gspca_dev->vdev->parent = &dev->dev; + gspca_dev->module = module; gspca_dev->present = 1; - ret = video_register_device(&gspca_dev->vdev, + video_set_drvdata(gspca_dev->vdev, gspca_dev); + ret = video_register_device(gspca_dev->vdev, VFL_TYPE_GRABBER, video_nr); if (ret < 0) { err("video_register_device err %d", ret); + video_device_release(gspca_dev->vdev); goto out; } @@ -1887,7 +1890,8 @@ int gspca_dev_probe(struct usb_interface *intf, PDEBUG(D_PROBE, "probe ok"); return 0; out: - kref_put(&gspca_dev->kref, gspca_delete); + kfree(gspca_dev->usb_buf); + kfree(gspca_dev); return ret; } EXPORT_SYMBOL(gspca_dev_probe); @@ -1905,7 +1909,7 @@ void gspca_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); /* We don't want people trying to open up the device */ - video_unregister_device(&gspca_dev->vdev); + video_unregister_device(gspca_dev->vdev); gspca_dev->present = 0; gspca_dev->streaming = 0; diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 1d9dc90b4791..d25e8d69373b 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -97,7 +97,7 @@ struct sd_desc { cam_pkt_op pkt_scan; /* optional operations */ cam_v_op stopN; /* called on stream off - main alt */ - cam_v_op stop0; /* called on stream off - alt 0 */ + cam_v_op stop0; /* called on stream off & disconnect - alt 0 */ cam_v_op dq_callback; /* called when a frame has been dequeued */ cam_jpg_op get_jcomp; cam_jpg_op set_jcomp; @@ -120,8 +120,8 @@ struct gspca_frame { }; struct gspca_dev { - struct video_device vdev; /* !! must be the first item */ - struct file_operations fops; + struct video_device *vdev; + struct module *module; /* subdriver handling the device */ struct usb_device *dev; struct kref kref; struct file *capt_file; /* file doing video capture */ diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index e5ff9a6199ef..fbd45e235d97 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -749,10 +749,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (!gspca_dev->present) + return; if (sd->sensor == SENSOR_PAC7302) { reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x78, 0x40); diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index b742f260c7ca..e29954c1c38c 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c @@ -2022,8 +2022,11 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00); } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { + if (!gspca_dev->present) + return; reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00); } diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index b345749213cf..895b9fe4018c 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -742,8 +742,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_write(gspca_dev->dev, 0x02, 0x00, 0x00); } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { + if (!gspca_dev->present) + return; + /* This maybe reset or power control */ reg_write(gspca_dev->dev, 0x03, 0x03, 0x20); reg_write(gspca_dev->dev, 0x03, 0x01, 0x0); diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 020a03c466c1..c3de4e44123d 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -766,10 +766,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) } } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (!gspca_dev->present) + return; if (sd->chip_revision == Rev012A) { reg_w_val(gspca_dev->dev, 0x8118, 0x29); reg_w_val(gspca_dev->dev, 0x8114, 0x08); diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index be46d9232540..17af353ddd1c 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -1633,10 +1633,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w(dev, 0xa0, 0x09, 0xb003); } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; + if (!gspca_dev->present) + return; reg_w(dev, 0x89, 0xffff, 0xffff); } diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index d0a4451dc46f..0befacf49855 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -2266,7 +2266,7 @@ static const struct usb_action hdcs2020b_NoFliker[] = { {} }; -static const struct usb_action hv7131bxx_Initial[] = { +static const struct usb_action hv7131bxx_Initial[] = { /* 320x240 */ {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, @@ -2290,7 +2290,7 @@ static const struct usb_action hv7131bxx_Initial[] = { {0xaa, 0x14, 0x0001}, {0xaa, 0x15, 0x00e8}, {0xaa, 0x16, 0x0002}, - {0xaa, 0x17, 0x0086}, + {0xaa, 0x17, 0x0086}, /* 00,17,88,aa */ {0xaa, 0x31, 0x0038}, {0xaa, 0x32, 0x0038}, {0xaa, 0x33, 0x0038}, @@ -2309,7 +2309,7 @@ static const struct usb_action hv7131bxx_Initial[] = { {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xaa, 0x02, 0x0080}, /* {0xaa, 0x02, 0x0090}; */ + {0xaa, 0x02, 0x0090}, /* 00,02,80,aa */ {0xa1, 0x01, 0x0002}, {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT}, {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND}, @@ -2374,7 +2374,7 @@ static const struct usb_action hv7131bxx_Initial[] = { {} }; -static const struct usb_action hv7131bxx_InitialScale[] = { +static const struct usb_action hv7131bxx_InitialScale[] = { /* 640x480*/ {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, @@ -6388,6 +6388,8 @@ static void setbrightness(struct gspca_dev *gspca_dev) /*fixme: is it really write to 011d and 018d for all other sensors? */ brightness = sd->brightness; reg_w(gspca_dev->dev, brightness, 0x011d); + if (sd->sensor == SENSOR_HV7131B) + return; if (brightness < 0x70) brightness += 0x10; else @@ -6529,6 +6531,7 @@ static void setquality(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_GC0305: + case SENSOR_HV7131B: case SENSOR_OV7620: case SENSOR_PO2030: return; @@ -7209,7 +7212,6 @@ static int sd_start(struct gspca_dev *gspca_dev) mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; zc3_init = init_tb[(int) sd->sensor][mode]; switch (sd->sensor) { - case SENSOR_HV7131B: case SENSOR_HV7131C: zcxx_probeSensor(gspca_dev); break; @@ -7334,10 +7336,13 @@ static int sd_start(struct gspca_dev *gspca_dev) return 0; } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (!gspca_dev->present) + return; send_unknown(gspca_dev->dev, sd->sensor); } diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index 0069898bddab..c46bfb1569e3 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig @@ -1,6 +1,6 @@ config VIDEO_IVTV tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" - depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && PCI && I2C depends on INPUT # due to VIDEO_IR select I2C_ALGOBIT select VIDEO_IR @@ -12,7 +12,6 @@ config VIDEO_IVTV select VIDEO_SAA711X select VIDEO_SAA717X select VIDEO_SAA7127 - select VIDEO_TVAUDIO select VIDEO_CS53L32A select VIDEO_M52790 select VIDEO_WM8775 @@ -32,7 +31,7 @@ config VIDEO_IVTV config VIDEO_FB_IVTV tristate "Conexant cx23415 framebuffer support" - depends on VIDEO_IVTV && FB && EXPERIMENTAL + depends on VIDEO_IVTV && FB select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index aeaa13f6cb36..b69cc1d55e5b 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -875,43 +875,43 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) #ifdef MODULE /* load modules */ -#ifndef CONFIG_MEDIA_TUNER +#ifdef CONFIG_MEDIA_TUNER_MODULE hw = ivtv_request_module(itv, hw, "tuner", IVTV_HW_TUNER); #endif -#ifndef CONFIG_VIDEO_CX25840 +#ifdef CONFIG_VIDEO_CX25840_MODULE hw = ivtv_request_module(itv, hw, "cx25840", IVTV_HW_CX25840); #endif -#ifndef CONFIG_VIDEO_SAA711X +#ifdef CONFIG_VIDEO_SAA711X_MODULE hw = ivtv_request_module(itv, hw, "saa7115", IVTV_HW_SAA711X); #endif -#ifndef CONFIG_VIDEO_SAA7127 +#ifdef CONFIG_VIDEO_SAA7127_MODULE hw = ivtv_request_module(itv, hw, "saa7127", IVTV_HW_SAA7127); #endif -#ifndef CONFIG_VIDEO_SAA717X +#ifdef CONFIG_VIDEO_SAA717X_MODULE hw = ivtv_request_module(itv, hw, "saa717x", IVTV_HW_SAA717X); #endif -#ifndef CONFIG_VIDEO_UPD64031A +#ifdef CONFIG_VIDEO_UPD64031A_MODULE hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A); #endif -#ifndef CONFIG_VIDEO_UPD64083 +#ifdef CONFIG_VIDEO_UPD64083_MODULE hw = ivtv_request_module(itv, hw, "upd64083", IVTV_HW_UPD6408X); #endif -#ifndef CONFIG_VIDEO_MSP3400 +#ifdef CONFIG_VIDEO_MSP3400_MODULE hw = ivtv_request_module(itv, hw, "msp3400", IVTV_HW_MSP34XX); #endif -#ifndef CONFIG_VIDEO_VP27SMPX +#ifdef CONFIG_VIDEO_VP27SMPX_MODULE hw = ivtv_request_module(itv, hw, "vp27smpx", IVTV_HW_VP27SMPX); #endif -#ifndef CONFIG_VIDEO_WM8775 +#ifdef CONFIG_VIDEO_WM8775_MODULE hw = ivtv_request_module(itv, hw, "wm8775", IVTV_HW_WM8775); #endif -#ifndef CONFIG_VIDEO_WM8739 +#ifdef CONFIG_VIDEO_WM8739_MODULE hw = ivtv_request_module(itv, hw, "wm8739", IVTV_HW_WM8739); #endif -#ifndef CONFIG_VIDEO_CS53L32A +#ifdef CONFIG_VIDEO_CS53L32A_MODULE hw = ivtv_request_module(itv, hw, "cs53l32a", IVTV_HW_CS53L32A); #endif -#ifndef CONFIG_VIDEO_M52790 +#ifdef CONFIG_VIDEO_M52790_MODULE hw = ivtv_request_module(itv, hw, "m52790", IVTV_HW_M52790); #endif #endif @@ -1211,6 +1211,10 @@ static int __devinit ivtv_probe(struct pci_dev *dev, if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std); + /* Turn off the output signal. The mpeg decoder is not yet + active so without this you would get a green image until the + mpeg decoder becomes active. */ + ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL); } /* clear interrupt mask, effectively disabling interrupts */ @@ -1330,6 +1334,10 @@ int ivtv_init_on_first_open(struct ivtv *itv) ivtv_s_frequency(NULL, &fh, &vf); if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) { + /* Turn on the TV-out: ivtv_init_mpeg_decoder() initializes + the mpeg decoder so now the saa7127 receives a proper + signal. */ + ivtv_saa7127(itv, VIDIOC_STREAMON, NULL); ivtv_init_mpeg_decoder(itv); } ivtv_s_std(NULL, &fh, &itv->tuner_std); @@ -1366,6 +1374,10 @@ static void ivtv_remove(struct pci_dev *pci_dev) /* Stop all decoding */ IVTV_DEBUG_INFO("Stopping decoding\n"); + + /* Turn off the TV-out */ + if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) + ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL); if (atomic_read(&itv->decoding) > 0) { int type; diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 24700c211d52..41dbbe9621a1 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c @@ -726,6 +726,7 @@ int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg) { return ivtv_call_i2c_client(itv, IVTV_SAA7127_I2C_ADDR, cmd, arg); } +EXPORT_SYMBOL(ivtv_saa7127); int ivtv_saa717x(struct ivtv *itv, unsigned int cmd, void *arg) { diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 208fb54842f2..4bae38d21ef6 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1756,12 +1756,12 @@ static int ivtv_default(struct file *file, void *fh, int cmd, void *arg) return 0; } -static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp, +static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, unsigned int cmd, unsigned long arg) { struct video_device *vfd = video_devdata(filp); struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; - int ret; + long ret; /* Filter dvb ioctls that cannot be handled by the v4l ioctl framework */ switch (cmd) { @@ -1830,20 +1830,19 @@ static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct f if (ivtv_debug & IVTV_DBGFLG_IOCTL) vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; - ret = video_ioctl2(inode, filp, cmd, arg); + ret = __video_ioctl2(filp, cmd, arg); vfd->debug = 0; return ret; } -int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; struct ivtv *itv = id->itv; - int res; + long res; mutex_lock(&itv->serialize_lock); - res = ivtv_serialized_ioctl(itv, inode, filp, cmd, arg); + res = ivtv_serialized_ioctl(itv, filp, cmd, arg); mutex_unlock(&itv->serialize_lock); return res; } diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/video/ivtv/ivtv-ioctl.h index 70188588b4f4..58f003412afd 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.h +++ b/drivers/media/video/ivtv/ivtv-ioctl.h @@ -30,7 +30,6 @@ void ivtv_set_funcs(struct video_device *vdev); int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std); int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf); int ivtv_s_input(struct file *file, void *fh, unsigned int inp); -int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg); +long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); #endif diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 5bbf31e39304..9b7aa79eb267 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -48,7 +48,7 @@ static const struct file_operations ivtv_v4l2_enc_fops = { .read = ivtv_v4l2_read, .write = ivtv_v4l2_write, .open = ivtv_v4l2_open, - .ioctl = ivtv_v4l2_ioctl, + .unlocked_ioctl = ivtv_v4l2_ioctl, .compat_ioctl = v4l_compat_ioctl32, .release = ivtv_v4l2_close, .poll = ivtv_v4l2_enc_poll, @@ -59,7 +59,7 @@ static const struct file_operations ivtv_v4l2_dec_fops = { .read = ivtv_v4l2_read, .write = ivtv_v4l2_write, .open = ivtv_v4l2_open, - .ioctl = ivtv_v4l2_ioctl, + .unlocked_ioctl = ivtv_v4l2_ioctl, .compat_ioctl = v4l_compat_ioctl32, .release = ivtv_v4l2_close, .poll = ivtv_v4l2_dec_poll, diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index 8a4a150b12fb..921e281876f8 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -48,6 +48,7 @@ #endif #include "ivtv-driver.h" +#include "ivtv-i2c.h" #include "ivtv-udma.h" #include "ivtv-mailbox.h" @@ -894,11 +895,16 @@ static int ivtvfb_blank(int blank_mode, struct fb_info *info) switch (blank_mode) { case FB_BLANK_UNBLANK: ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1); + ivtv_saa7127(itv, VIDIOC_STREAMON, NULL); break; case FB_BLANK_NORMAL: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_VSYNC_SUSPEND: + ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); + ivtv_saa7127(itv, VIDIOC_STREAMON, NULL); + break; case FB_BLANK_POWERDOWN: + ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL); ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); break; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index a1252d673b41..273d2a1aa220 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -402,6 +402,10 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw) ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0); ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0); + /* prevent the PTSs from slowly drifting away in the generated + MPEG stream */ + ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC, 2, 4, 1); + return ret; } diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 94265bd3d926..5b81ba469641 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -60,7 +60,6 @@ static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL}; static DEFINE_MUTEX(pvr2_unit_mtx); static int ctlchg; -static int initusbreset = 1; static int procreload; static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 }; static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 }; @@ -71,8 +70,6 @@ module_param(ctlchg, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value"); module_param(init_pause_msec, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay"); -module_param(initusbreset, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(initusbreset, "Do USB reset device on probe"); module_param(procreload, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(procreload, "Attempt init failure recovery with firmware reload"); @@ -1967,9 +1964,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) } hdw->fw1_state = FW1_STATE_OK; - if (initusbreset) { - pvr2_hdw_device_reset(hdw); - } if (!pvr2_hdw_dev_ok(hdw)) return; for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) { diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index f048d80b77e5..97ed95957992 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -168,7 +168,7 @@ static const char *get_v4l_name(int v4l_type) * This is part of Video 4 Linux API. The procedure handles ioctl() calls. * */ -static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, +static int __pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct pvr2_v4l2_fh *fh = file->private_data; @@ -863,8 +863,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, #endif default : - ret = v4l_compat_translate_ioctl(inode,file,cmd, - arg,pvr2_v4l2_do_ioctl); + ret = v4l_compat_translate_ioctl(file, cmd, + arg, __pvr2_v4l2_do_ioctl); } pvr2_hdw_commit_ctl(hdw); @@ -890,10 +890,15 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, return ret; } +static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + return __pvr2_v4l2_do_ioctl(file, cmd, arg); +} static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) { - int minor_id = dip->devbase.minor; + int num = dip->devbase.num; struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw; enum pvr2_config cfg = dip->config; int v4l_type = dip->v4l_type; @@ -909,7 +914,7 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) video_unregister_device(&dip->devbase); printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n", - get_v4l_name(v4l_type),minor_id & 0x1f, + get_v4l_name(v4l_type), num, pvr2_config_get_name(cfg)); } @@ -1310,7 +1315,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, } printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n", - get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f, + get_v4l_name(dip->v4l_type), dip->devbase.num, pvr2_config_get_name(dip->config)); pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index ab28389b4cda..f3897a3fdb75 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -1795,7 +1795,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id goto err; } else { - PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F); + PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->num); } /* occupy slot */ diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 5272926db73e..3c3f8cf73108 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -192,7 +192,7 @@ struct s2255_dmaqueue { #define S2255_FW_FAILED 3 #define S2255_FW_DISCONNECTING 4 -#define S2255_FW_MARKER 0x22552f2f +#define S2255_FW_MARKER cpu_to_le32(0x22552f2f) /* 2255 read states */ #define S2255_READ_IDLE 0 #define S2255_READ_FRAME 1 diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index adf2ba79496a..37860698f782 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -47,7 +47,7 @@ module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */ -#define SAA7110_MAX_OUTPUT 0 /* its a decoder only */ +#define SAA7110_MAX_OUTPUT 1 /* 1 YUV */ #define SAA7110_NR_REG 0x35 @@ -327,7 +327,7 @@ saa7110_command (struct i2c_client *client, case DECODER_SET_INPUT: v = *(int *) arg; - if (v < 0 || v > SAA7110_MAX_INPUT) { + if (v < 0 || v >= SAA7110_MAX_INPUT) { v4l_dbg(1, debug, client, "input=%d not available\n", v); return -EINVAL; } diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index b686bfabbde0..dfbe08a9ad9b 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -941,7 +941,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, dev->name,(unsigned long long)pci_resource_start(pci_dev,0)); goto fail1; } - dev->lmmio = ioremap(pci_resource_start(pci_dev,0), 0x1000); + dev->lmmio = ioremap(pci_resource_start(pci_dev, 0), + pci_resource_len(pci_dev, 0)); dev->bmmio = (__u8 __iomem *)dev->lmmio; if (NULL == dev->lmmio) { err = -EIO; @@ -996,7 +997,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, goto fail4; } printk(KERN_INFO "%s: registered device video%d [v4l2]\n", - dev->name,dev->video_dev->minor & 0x1f); + dev->name, dev->video_dev->num); dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi"); @@ -1005,7 +1006,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (err < 0) goto fail4; printk(KERN_INFO "%s: registered device vbi%d\n", - dev->name,dev->vbi_dev->minor & 0x1f); + dev->name, dev->vbi_dev->num); if (card_has_radio(dev)) { dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio"); @@ -1014,7 +1015,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (err < 0) goto fail4; printk(KERN_INFO "%s: registered device radio%d\n", - dev->name,dev->radio_dev->minor & 0x1f); + dev->name, dev->radio_dev->num); } /* everything worked */ diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 9a8766a78a0c..7f40511bcc04 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -534,7 +534,7 @@ static int empress_init(struct saa7134_dev *dev) return err; } printk(KERN_INFO "%s: registered device video%d [mpeg]\n", - dev->name,dev->empress_dev->minor & 0x1f); + dev->name, dev->empress_dev->num); videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops, &dev->pci->dev, &dev->slock, diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c index ae3949180c4e..044a2e94c34d 100644 --- a/drivers/media/video/se401.c +++ b/drivers/media/video/se401.c @@ -1412,7 +1412,7 @@ static int se401_probe(struct usb_interface *intf, return -EIO; } dev_info(&intf->dev, "registered new video device: video%d\n", - se401->vdev.minor); + se401->vdev.num); usb_set_intfdata (intf, se401); return 0; diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 20e30bd9364b..fcd2b62f92c4 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -1008,7 +1008,7 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam) cam->state |= DEV_MISCONFIGURED; DBG(1, "URB timeout reached. The camera is misconfigured. " "To use it, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -EIO; } @@ -1734,7 +1734,7 @@ static void sn9c102_release_resources(struct kref *kref) cam = container_of(kref, struct sn9c102_device, kref); - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); + DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); usb_put_dev(cam->usbdev); @@ -1792,7 +1792,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) if (cam->users) { DBG(2, "Device /dev/video%d is already in use", - cam->v4ldev->minor); + cam->v4ldev->num); DBG(3, "Simultaneous opens are not supported"); /* open() must follow the open flags and should block @@ -1845,7 +1845,7 @@ static int sn9c102_open(struct inode* inode, struct file* filp) cam->frame_count = 0; sn9c102_empty_framequeues(cam); - DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); + DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num); out: mutex_unlock(&cam->open_mutex); @@ -1870,7 +1870,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) cam->users--; wake_up_interruptible_nr(&cam->wait_open, 1); - DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); + DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num); kref_put(&cam->kref, sn9c102_release_resources); @@ -2432,7 +2432,7 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -EIO; } @@ -2445,7 +2445,7 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg) cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -ENOMEM; } @@ -2689,7 +2689,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -EIO; } @@ -2701,7 +2701,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd, cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -ENOMEM; } @@ -2748,7 +2748,7 @@ sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg) cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " "problems. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->minor); + "/dev/video%d again.", cam->v4ldev->num); return -EIO; } @@ -3348,7 +3348,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); + DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num); video_set_drvdata(cam->v4ldev, cam); cam->module_param.force_munmap = force_munmap[dev_nr]; @@ -3402,7 +3402,7 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf) if (cam->users) { DBG(2, "Device /dev/video%d is open! Deregistration and " "memory deallocation are deferred.", - cam->v4ldev->minor); + cam->v4ldev->num); cam->state |= DEV_MISCONFIGURED; sn9c102_stop_transfer(cam); cam->state |= DEV_DISCONNECTED; diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index edaea4964513..e9eb6d754d5c 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -1331,7 +1331,7 @@ static int stk_register_video_device(struct stk_camera *dev) STK_ERROR("v4l registration failed\n"); else STK_INFO("Syntek USB2.0 Camera is now controlling video device" - " /dev/video%d\n", dev->vdev.minor); + " /dev/video%d\n", dev->vdev.num); return err; } @@ -1426,7 +1426,7 @@ static void stk_camera_disconnect(struct usb_interface *interface) stk_remove_sysfs_files(&dev->vdev); STK_INFO("Syntek USB2.0 Camera release resources " - "video device /dev/video%d\n", dev->vdev.minor); + "video device /dev/video%d\n", dev->vdev.num); video_unregister_device(&dev->vdev); } diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c index 9c549d935994..328c41b1517d 100644 --- a/drivers/media/video/stv680.c +++ b/drivers/media/video/stv680.c @@ -1470,7 +1470,8 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id retval = -EIO; goto error_vdev; } - PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev->minor); + PDEBUG(0, "STV(i): registered new video device: video%d", + stv680->vdev->num); usb_set_intfdata (intf, stv680); retval = stv680_create_sysfs_files(stv680->vdev); diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index b59e47272abf..3720f0e03a16 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1,5 +1,5 @@ /* - * experimental driver for simple i2c audio chips. + * Driver for simple i2c audio chips. * * Copyright (c) 2000 Gerd Knorr * based on code by: @@ -7,6 +7,10 @@ * Steve VanDeBogart (vandebo@uclink.berkeley.edu) * Greg Alexander (galexand@acm.org) * + * Copyright(c) 2005-2008 Mauro Carvalho Chehab + * - Some cleanups, code fixes, etc + * - Convert it to V4L2 API + * * This code is placed under the terms of the GNU General Public License * * OPTIONS: @@ -30,6 +34,7 @@ #include <media/tvaudio.h> #include <media/v4l2-common.h> +#include <media/v4l2-ioctl.h> #include <media/v4l2-chip-ident.h> #include <media/v4l2-i2c-drv-legacy.h> @@ -58,7 +63,6 @@ typedef int (*checkit)(struct CHIPSTATE*); typedef int (*initialize)(struct CHIPSTATE*); typedef int (*getmode)(struct CHIPSTATE*); typedef void (*setmode)(struct CHIPSTATE*, int mode); -typedef void (*checkmode)(struct CHIPSTATE*); /* i2c command */ typedef struct AUDIOCMD { @@ -79,6 +83,7 @@ struct CHIPDESC { #define CHIP_HAS_VOLUME 1 #define CHIP_HAS_BASSTREBLE 2 #define CHIP_HAS_INPUTSEL 4 +#define CHIP_NEED_CHECKMODE 8 /* various i2c command sequences */ audiocmd init; @@ -96,23 +101,20 @@ struct CHIPDESC { getmode getmode; setmode setmode; - /* check / autoswitch audio after channel switches */ - checkmode checkmode; - /* input switch register + values for v4l inputs */ int inputreg; int inputmap[4]; int inputmute; int inputmask; }; -static struct CHIPDESC chiplist[]; /* current state of the chip */ struct CHIPSTATE { struct i2c_client *c; - /* index into CHIPDESC array */ - int type; + /* chip-specific description - should point to + an entry at CHIPDESC table */ + struct CHIPDESC *desc; /* shadow register set */ audiocmd shadow; @@ -152,7 +154,7 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) { unsigned char buffer[2]; - if (-1 == subaddr) { + if (subaddr < 0) { v4l_dbg(1, debug, chip->c, "%s: chip_write: 0x%x\n", chip->c->name, val); chip->shadow.bytes[1] = val; @@ -163,6 +165,13 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) return -1; } } else { + if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) { + v4l_info(chip->c, + "Tried to access a non-existent register: %d\n", + subaddr); + return -EINVAL; + } + v4l_dbg(1, debug, chip->c, "%s: chip_write: reg%d=0x%x\n", chip->c->name, subaddr, val); chip->shadow.bytes[subaddr+1] = val; @@ -177,12 +186,20 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) return 0; } -static int chip_write_masked(struct CHIPSTATE *chip, int subaddr, int val, int mask) +static int chip_write_masked(struct CHIPSTATE *chip, + int subaddr, int val, int mask) { if (mask != 0) { - if (-1 == subaddr) { + if (subaddr < 0) { val = (chip->shadow.bytes[1] & ~mask) | (val & mask); } else { + if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) { + v4l_info(chip->c, + "Tried to access a non-existent register: %d\n", + subaddr); + return -EINVAL; + } + val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask); } } @@ -228,6 +245,15 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd) if (0 == cmd->count) return 0; + if (cmd->count + cmd->bytes[0] - 1 >= ARRAY_SIZE(chip->shadow.bytes)) { + v4l_info(chip->c, + "Tried to access a non-existent register range: %d to %d\n", + cmd->bytes[0] + 1, cmd->bytes[0] + cmd->count - 1); + return -EINVAL; + } + + /* FIXME: it seems that the shadow bytes are wrong bellow !*/ + /* update our shadow register set; print bytes if (debug > 0) */ v4l_dbg(1, debug, chip->c, "%s: chip_cmd(%s): reg=%d, data:", chip->c->name, name,cmd->bytes[0]); @@ -263,7 +289,8 @@ static void chip_thread_wake(unsigned long data) static int chip_thread(void *data) { struct CHIPSTATE *chip = data; - struct CHIPDESC *desc = chiplist + chip->type; + struct CHIPDESC *desc = chip->desc; + int mode; v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name); set_freezable(); @@ -282,7 +309,26 @@ static int chip_thread(void *data) continue; /* have a look what's going on */ - desc->checkmode(chip); + mode = desc->getmode(chip); + if (mode == chip->prevmode) + continue; + + /* chip detected a new audio mode - set it */ + v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", + chip->c->name); + + chip->prevmode = mode; + + if (mode & V4L2_TUNER_MODE_STEREO) + desc->setmode(chip, V4L2_TUNER_MODE_STEREO); + if (mode & V4L2_TUNER_MODE_LANG1_LANG2) + desc->setmode(chip, V4L2_TUNER_MODE_STEREO); + else if (mode & V4L2_TUNER_MODE_LANG1) + desc->setmode(chip, V4L2_TUNER_MODE_LANG1); + else if (mode & V4L2_TUNER_MODE_LANG2) + desc->setmode(chip, V4L2_TUNER_MODE_LANG2); + else + desc->setmode(chip, V4L2_TUNER_MODE_MONO); /* schedule next check */ mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); @@ -292,29 +338,6 @@ static int chip_thread(void *data) return 0; } -static void generic_checkmode(struct CHIPSTATE *chip) -{ - struct CHIPDESC *desc = chiplist + chip->type; - int mode = desc->getmode(chip); - - if (mode == chip->prevmode) - return; - - v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", chip->c->name); - chip->prevmode = mode; - - if (mode & V4L2_TUNER_MODE_STEREO) - desc->setmode(chip,V4L2_TUNER_MODE_STEREO); - if (mode & V4L2_TUNER_MODE_LANG1_LANG2) - desc->setmode(chip,V4L2_TUNER_MODE_STEREO); - else if (mode & V4L2_TUNER_MODE_LANG1) - desc->setmode(chip,V4L2_TUNER_MODE_LANG1); - else if (mode & V4L2_TUNER_MODE_LANG2) - desc->setmode(chip,V4L2_TUNER_MODE_LANG2); - else - desc->setmode(chip,V4L2_TUNER_MODE_MONO); -} - /* ---------------------------------------------------------------------- */ /* audio chip descriptions - defines+functions for tda9840 */ @@ -777,7 +800,7 @@ static struct tda9874a_MODES { char *name; audiocmd cmd; } tda9874a_modelist[9] = { - { "A2, B/G", + { "A2, B/G", /* default */ { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x77,0xA0,0x00, 0x00,0x00 }} }, { "A2, M (Korea)", { 9, { TDA9874A_C1FRA, 0x5D,0xC0,0x00, 0x62,0x6A,0xAA, 0x20,0x22 }} }, @@ -791,7 +814,7 @@ static struct tda9874a_MODES { { 9, { TDA9874A_C1FRA, 0x7D,0x00,0x00, 0x88,0x8A,0xAA, 0x08,0x33 }} }, { "NICAM, B/G", { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x79,0xEA,0xAA, 0x08,0x33 }} }, - { "NICAM, D/K", /* default */ + { "NICAM, D/K", { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x08,0x33 }} }, { "NICAM, L", { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x09,0x33 }} } @@ -981,7 +1004,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) { if (tda9874a_SIF > 2) tda9874a_SIF = 1; - if (tda9874a_STD > 8) + if (tda9874a_STD >= ARRAY_SIZE(tda9874a_modelist)) tda9874a_STD = 0; if(tda9874a_AMSEL > 1) tda9874a_AMSEL = 0; @@ -1089,7 +1112,7 @@ static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; } static int tda8425_initialize(struct CHIPSTATE *chip) { - struct CHIPDESC *desc = chiplist + chip->type; + struct CHIPDESC *desc = chip->desc; int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1, /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF}; @@ -1259,27 +1282,28 @@ static struct CHIPDESC chiplist[] = { .addr_lo = I2C_ADDR_TDA9840 >> 1, .addr_hi = I2C_ADDR_TDA9840 >> 1, .registers = 5, + .flags = CHIP_NEED_CHECKMODE, + /* callbacks */ .checkit = tda9840_checkit, .getmode = tda9840_getmode, .setmode = tda9840_setmode, - .checkmode = generic_checkmode, .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN /* ,TDA9840_SW, TDA9840_MONO */} } }, { .name = "tda9873h", - .checkit = tda9873_checkit, .insmodopt = &tda9873, .addr_lo = I2C_ADDR_TDA985x_L >> 1, .addr_hi = I2C_ADDR_TDA985x_H >> 1, .registers = 3, - .flags = CHIP_HAS_INPUTSEL, + .flags = CHIP_HAS_INPUTSEL | CHIP_NEED_CHECKMODE, + /* callbacks */ + .checkit = tda9873_checkit, .getmode = tda9873_getmode, .setmode = tda9873_setmode, - .checkmode = generic_checkmode, .init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } }, .inputreg = TDA9873_SW, @@ -1290,15 +1314,16 @@ static struct CHIPDESC chiplist[] = { }, { .name = "tda9874h/a", - .checkit = tda9874a_checkit, - .initialize = tda9874a_initialize, .insmodopt = &tda9874a, .addr_lo = I2C_ADDR_TDA9874 >> 1, .addr_hi = I2C_ADDR_TDA9874 >> 1, + .flags = CHIP_NEED_CHECKMODE, + /* callbacks */ + .initialize = tda9874a_initialize, + .checkit = tda9874a_checkit, .getmode = tda9874a_getmode, .setmode = tda9874a_setmode, - .checkmode = generic_checkmode, }, { .name = "tda9850", @@ -1324,10 +1349,11 @@ static struct CHIPDESC chiplist[] = { .rightreg = TDA9855_VR, .bassreg = TDA9855_BA, .treblereg = TDA9855_TR, + + /* callbacks */ .volfunc = tda9855_volume, .bassfunc = tda9855_bass, .treblefunc = tda9855_treble, - .getmode = tda985x_getmode, .setmode = tda985x_setmode, @@ -1348,6 +1374,8 @@ static struct CHIPDESC chiplist[] = { .rightreg = TEA6300_VL, .bassreg = TEA6300_BA, .treblereg = TEA6300_TR, + + /* callbacks */ .volfunc = tea6300_shift10, .bassfunc = tea6300_shift12, .treblefunc = tea6300_shift12, @@ -1358,7 +1386,6 @@ static struct CHIPDESC chiplist[] = { }, { .name = "tea6320", - .initialize = tea6320_initialize, .insmodopt = &tea6320, .addr_lo = I2C_ADDR_TEA6300 >> 1, .addr_hi = I2C_ADDR_TEA6300 >> 1, @@ -1369,6 +1396,9 @@ static struct CHIPDESC chiplist[] = { .rightreg = TEA6320_V, .bassreg = TEA6320_BA, .treblereg = TEA6320_TR, + + /* callbacks */ + .initialize = tea6320_initialize, .volfunc = tea6320_volume, .bassfunc = tea6320_shift11, .treblefunc = tea6320_shift11, @@ -1401,16 +1431,18 @@ static struct CHIPDESC chiplist[] = { .rightreg = TDA8425_VR, .bassreg = TDA8425_BA, .treblereg = TDA8425_TR, + + /* callbacks */ + .initialize = tda8425_initialize, .volfunc = tda8425_shift10, .bassfunc = tda8425_shift12, .treblefunc = tda8425_shift12, + .setmode = tda8425_setmode, .inputreg = TDA8425_S1, .inputmap = { TDA8425_S1_CH1, TDA8425_S1_CH1, TDA8425_S1_CH1 }, .inputmute = TDA8425_S1_OFF, - .setmode = tda8425_setmode, - .initialize = tda8425_initialize, }, { .name = "pic16c54 (PV951)", @@ -1434,10 +1466,11 @@ static struct CHIPDESC chiplist[] = { .addr_lo = I2C_ADDR_TDA9840 >> 1, .addr_hi = I2C_ADDR_TDA9840 >> 1, .registers = 2, + .flags = CHIP_NEED_CHECKMODE, + /* callbacks */ .getmode = ta8874z_getmode, .setmode = ta8874z_setmode, - .checkmode = generic_checkmode, .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, }, @@ -1481,6 +1514,7 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) } if (desc->name == NULL) { v4l_dbg(1, debug, client, "no matching chip description found\n"); + kfree(chip); return -EIO; } v4l_info(client, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name); @@ -1494,7 +1528,7 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) /* fill required data structures */ if (!id) strlcpy(client->name, desc->name, I2C_NAME_SIZE); - chip->type = desc-chiplist; + chip->desc = desc; chip->shadow.count = desc->registers+1; chip->prevmode = -1; chip->audmode = V4L2_TUNER_MODE_LANG1; @@ -1506,20 +1540,49 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) chip_cmd(chip,"init",&desc->init); if (desc->flags & CHIP_HAS_VOLUME) { - chip->left = desc->leftinit ? desc->leftinit : 65535; - chip->right = desc->rightinit ? desc->rightinit : 65535; - chip_write(chip,desc->leftreg,desc->volfunc(chip->left)); - chip_write(chip,desc->rightreg,desc->volfunc(chip->right)); + if (!desc->volfunc) { + /* This shouldn't be happen. Warn user, but keep working + without volume controls + */ + v4l_info(chip->c, "volume callback undefined!\n"); + desc->flags &= ~CHIP_HAS_VOLUME; + } else { + chip->left = desc->leftinit ? desc->leftinit : 65535; + chip->right = desc->rightinit ? desc->rightinit : 65535; + chip_write(chip, desc->leftreg, + desc->volfunc(chip->left)); + chip_write(chip, desc->rightreg, + desc->volfunc(chip->right)); + } } if (desc->flags & CHIP_HAS_BASSTREBLE) { - chip->treble = desc->trebleinit ? desc->trebleinit : 32768; - chip->bass = desc->bassinit ? desc->bassinit : 32768; - chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); - chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); + if (!desc->bassfunc || !desc->treblefunc) { + /* This shouldn't be happen. Warn user, but keep working + without bass/treble controls + */ + v4l_info(chip->c, "bass/treble callbacks undefined!\n"); + desc->flags &= ~CHIP_HAS_BASSTREBLE; + } else { + chip->treble = desc->trebleinit ? + desc->trebleinit : 32768; + chip->bass = desc->bassinit ? + desc->bassinit : 32768; + chip_write(chip, desc->bassreg, + desc->bassfunc(chip->bass)); + chip_write(chip, desc->treblereg, + desc->treblefunc(chip->treble)); + } } chip->thread = NULL; - if (desc->checkmode) { + if (desc->flags & CHIP_NEED_CHECKMODE) { + if (!desc->getmode || !desc->setmode) { + /* This shouldn't be happen. Warn user, but keep working + without kthread + */ + v4l_info(chip->c, "set/get mode callbacks undefined!\n"); + return 0; + } /* start async thread */ init_timer(&chip->wt); chip->wt.function = chip_thread_wake; @@ -1552,7 +1615,7 @@ static int chip_remove(struct i2c_client *client) static int tvaudio_get_ctrl(struct CHIPSTATE *chip, struct v4l2_control *ctrl) { - struct CHIPDESC *desc = chiplist + chip->type; + struct CHIPDESC *desc = chip->desc; switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -1576,13 +1639,13 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip, return 0; } case V4L2_CID_AUDIO_BASS: - if (desc->flags & CHIP_HAS_BASSTREBLE) + if (!(desc->flags & CHIP_HAS_BASSTREBLE)) break; ctrl->value = chip->bass; return 0; case V4L2_CID_AUDIO_TREBLE: - if (desc->flags & CHIP_HAS_BASSTREBLE) - return -EINVAL; + if (!(desc->flags & CHIP_HAS_BASSTREBLE)) + break; ctrl->value = chip->treble; return 0; } @@ -1592,7 +1655,7 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip, static int tvaudio_set_ctrl(struct CHIPSTATE *chip, struct v4l2_control *ctrl) { - struct CHIPDESC *desc = chiplist + chip->type; + struct CHIPDESC *desc = chip->desc; switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -1642,16 +1705,15 @@ static int tvaudio_set_ctrl(struct CHIPSTATE *chip, return 0; } case V4L2_CID_AUDIO_BASS: - if (desc->flags & CHIP_HAS_BASSTREBLE) + if (!(desc->flags & CHIP_HAS_BASSTREBLE)) break; chip->bass = ctrl->value; chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); return 0; case V4L2_CID_AUDIO_TREBLE: - if (desc->flags & CHIP_HAS_BASSTREBLE) - return -EINVAL; - + if (!(desc->flags & CHIP_HAS_BASSTREBLE)) + break; chip->treble = ctrl->value; chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); @@ -1668,9 +1730,12 @@ static int chip_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct CHIPSTATE *chip = i2c_get_clientdata(client); - struct CHIPDESC *desc = chiplist + chip->type; + struct CHIPDESC *desc = chip->desc; - v4l_dbg(1, debug, chip->c, "%s: chip_command 0x%x\n", chip->c->name, cmd); + if (debug > 0) { + v4l_i2c_print_ioctl(chip->c, cmd); + printk("\n"); + } switch (cmd) { case AUDC_SET_RADIO: @@ -1695,7 +1760,7 @@ static int chip_command(struct i2c_client *client, break; case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - if (desc->flags & CHIP_HAS_BASSTREBLE) + if (!(desc->flags & CHIP_HAS_BASSTREBLE)) return -EINVAL; break; default: @@ -1792,12 +1857,20 @@ static int chip_command(struct i2c_client *client, break; case VIDIOC_S_FREQUENCY: chip->mode = 0; /* automatic */ - if (desc->checkmode && desc->setmode) { + + /* For chips that provide getmode and setmode, and doesn't + automatically follows the stereo carrier, a kthread is + created to set the audio standard. In this case, when then + the video channel is changed, tvaudio starts on MONO mode. + After waiting for 2 seconds, the kernel thread is called, + to follow whatever audio standard is pointed by the + audio carrier. + */ + if (chip->thread) { desc->setmode(chip,V4L2_TUNER_MODE_MONO); if (chip->prevmode != V4L2_TUNER_MODE_MONO) chip->prevmode = -1; /* reset previous mode */ mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); - /* the thread will call checkmode() later */ } break; @@ -1836,9 +1909,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .legacy_probe = chip_legacy_probe, .id_table = chip_id, }; - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c index 28421d386f1e..c710bcd1df48 100644 --- a/drivers/media/video/usbvideo/ibmcam.c +++ b/drivers/media/video/usbvideo/ibmcam.c @@ -3695,7 +3695,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * unsigned char video_ep = 0; if (debug >= 1) - dev_info(&uvd->dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum); + dev_info(&dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum); /* We don't handle multi-config cameras */ if (dev->descriptor.bNumConfigurations != 1) @@ -3746,7 +3746,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */ break; } - dev_info(&uvd->dev->dev, + dev_info(&dev->dev, "%s USB camera found (model %d, rev. 0x%04x)\n", brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); } while (0); @@ -3754,7 +3754,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * /* Validate found interface: must have one ISO endpoint */ nas = intf->num_altsetting; if (debug > 0) - dev_info(&uvd->dev->dev, "Number of alternate settings=%d.\n", + dev_info(&dev->dev, "Number of alternate settings=%d.\n", nas); if (nas < 2) { err("Too few alternate settings for this camera!"); @@ -3799,7 +3799,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * actInterface = i; maxPS = le16_to_cpu(endpoint->wMaxPacketSize); if (debug > 0) - dev_info(&uvd->dev->dev, + dev_info(&dev->dev, "Active setting=%d. " "maxPS=%d.\n", i, maxPS); } else @@ -3840,7 +3840,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * RESTRICT_TO_RANGE(framerate, 0, 5); break; default: - dev_info(&uvd->dev->dev, "IBM camera: using 320x240\n"); + dev_info(&dev->dev, "IBM camera: using 320x240\n"); size = SIZE_320x240; /* No break here */ case SIZE_320x240: @@ -3869,7 +3869,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * canvasY = 120; break; default: - dev_info(&uvd->dev->dev, "IBM NetCamera: using 176x144\n"); + dev_info(&dev->dev, "IBM NetCamera: using 176x144\n"); size = SIZE_176x144; /* No break here */ case SIZE_176x144: diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c index 07cd87d16f69..7c575bb8184f 100644 --- a/drivers/media/video/usbvideo/usbvideo.c +++ b/drivers/media/video/usbvideo/usbvideo.c @@ -1059,7 +1059,7 @@ int usbvideo_RegisterVideoDevice(struct uvd *uvd) dev_info(&uvd->dev->dev, "%s on /dev/video%d: canvas=%s videosize=%s\n", (uvd->handle != NULL) ? uvd->handle->drvName : "???", - uvd->vdev.minor, tmp2, tmp1); + uvd->vdev.num, tmp2, tmp1); usb_get_dev(uvd->dev); return 0; diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c index 7a127d6bfdee..8e2d58bec481 100644 --- a/drivers/media/video/usbvideo/vicam.c +++ b/drivers/media/video/usbvideo/vicam.c @@ -877,7 +877,8 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id) return -EIO; } - printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor); + printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n", + cam->vdev.num); usb_set_intfdata (intf, cam); diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 92427fdc1459..9907b9aff2b9 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c @@ -236,7 +236,7 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) sizeof(struct i2c_client)); sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name), - " #%d", usbvision->vdev->minor & 0x1f); + " #%d", usbvision->vdev->num); PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name); usbvision->i2c_adap.dev.parent = &usbvision->dev->dev; diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 77aeb39b2750..d185b57fdcd0 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -1440,7 +1440,7 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) // vbi Device: if (usbvision->vbi) { PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]", - usbvision->vbi->minor & 0x1f); + usbvision->vbi->num); if (usbvision->vbi->minor != -1) { video_unregister_device(usbvision->vbi); } else { @@ -1452,7 +1452,7 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) // Radio Device: if (usbvision->rdev) { PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]", - usbvision->rdev->minor & 0x1f); + usbvision->rdev->num); if (usbvision->rdev->minor != -1) { video_unregister_device(usbvision->rdev); } else { @@ -1464,7 +1464,7 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision) // Video Device: if (usbvision->vdev) { PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]", - usbvision->vdev->minor & 0x1f); + usbvision->vdev->num); if (usbvision->vdev->minor != -1) { video_unregister_device(usbvision->vdev); } else { @@ -1490,7 +1490,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) goto err_exit; } printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n", - usbvision->nr,usbvision->vdev->minor & 0x1f); + usbvision->nr, usbvision->vdev->num); // Radio Device: if (usbvision_device_data[usbvision->DevModel].Radio) { @@ -1507,7 +1507,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) goto err_exit; } printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n", - usbvision->nr, usbvision->rdev->minor & 0x1f); + usbvision->nr, usbvision->rdev->num); } // vbi Device: if (usbvision_device_data[usbvision->DevModel].vbi) { @@ -1523,7 +1523,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) goto err_exit; } printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n", - usbvision->nr,usbvision->vbi->minor & 0x1f); + usbvision->nr, usbvision->vbi->num); } // all done return 0; diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 78e4c4e09d89..758dfefaba8d 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -464,7 +464,7 @@ static int uvc_v4l2_release(struct inode *inode, struct file *file) return 0; } -static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file, +static int __uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = video_devdata(file); @@ -978,8 +978,8 @@ static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file, return uvc_xu_ctrl_query(video, arg, 1); default: - if ((ret = v4l_compat_translate_ioctl(inode, file, cmd, arg, - uvc_v4l2_do_ioctl)) == -ENOIOCTLCMD) + if ((ret = v4l_compat_translate_ioctl(file, cmd, arg, + __uvc_v4l2_do_ioctl)) == -ENOIOCTLCMD) uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd); return ret; @@ -988,6 +988,12 @@ static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file, return ret; } +static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + return __uvc_v4l2_do_ioctl(file, cmd, arg); +} + static int uvc_v4l2_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 928cb4037372..f13c0a9d684f 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -57,8 +57,7 @@ MODULE_LICENSE("GPL"); */ static int -get_v4l_control(struct inode *inode, - struct file *file, +get_v4l_control(struct file *file, int cid, v4l2_kioctl drv) { @@ -67,12 +66,12 @@ get_v4l_control(struct inode *inode, int err; qctrl2.id = cid; - err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2); + err = drv(file, VIDIOC_QUERYCTRL, &qctrl2); if (err < 0) dprintk("VIDIOC_QUERYCTRL: %d\n", err); if (err == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) { ctrl2.id = qctrl2.id; - err = drv(inode, file, VIDIOC_G_CTRL, &ctrl2); + err = drv(file, VIDIOC_G_CTRL, &ctrl2); if (err < 0) { dprintk("VIDIOC_G_CTRL: %d\n", err); return 0; @@ -85,8 +84,7 @@ get_v4l_control(struct inode *inode, } static int -set_v4l_control(struct inode *inode, - struct file *file, +set_v4l_control(struct file *file, int cid, int value, v4l2_kioctl drv) @@ -96,7 +94,7 @@ set_v4l_control(struct inode *inode, int err; qctrl2.id = cid; - err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2); + err = drv(file, VIDIOC_QUERYCTRL, &qctrl2); if (err < 0) dprintk("VIDIOC_QUERYCTRL: %d\n", err); if (err == 0 && @@ -114,7 +112,7 @@ set_v4l_control(struct inode *inode, + 32767) / 65535; ctrl2.value += qctrl2.minimum; - err = drv(inode, file, VIDIOC_S_CTRL, &ctrl2); + err = drv(file, VIDIOC_S_CTRL, &ctrl2); if (err < 0) dprintk("VIDIOC_S_CTRL: %d\n", err); } @@ -222,7 +220,6 @@ static int poll_one(struct file *file, struct poll_wqueues *pwq) } static int count_inputs( - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -232,14 +229,13 @@ static int count_inputs( for (i = 0;; i++) { memset(&input2, 0, sizeof(input2)); input2.index = i; - if (0 != drv(inode, file, VIDIOC_ENUMINPUT, &input2)) + if (0 != drv(file, VIDIOC_ENUMINPUT, &input2)) break; } return i; } static int check_size( - struct inode *inode, struct file *file, v4l2_kioctl drv, int *maxw, @@ -252,14 +248,14 @@ static int check_size( memset(&fmt2, 0, sizeof(fmt2)); desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (0 != drv(inode, file, VIDIOC_ENUM_FMT, &desc2)) + if (0 != drv(file, VIDIOC_ENUM_FMT, &desc2)) goto done; fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt2.fmt.pix.width = 10000; fmt2.fmt.pix.height = 10000; fmt2.fmt.pix.pixelformat = desc2.pixelformat; - if (0 != drv(inode, file, VIDIOC_TRY_FMT, &fmt2)) + if (0 != drv(file, VIDIOC_TRY_FMT, &fmt2)) goto done; *maxw = fmt2.fmt.pix.width; @@ -273,7 +269,6 @@ done: static noinline int v4l1_compat_get_capabilities( struct video_capability *cap, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -289,13 +284,13 @@ static noinline int v4l1_compat_get_capabilities( memset(cap, 0, sizeof(*cap)); memset(&fbuf, 0, sizeof(fbuf)); - err = drv(inode, file, VIDIOC_QUERYCAP, cap2); + err = drv(file, VIDIOC_QUERYCAP, cap2); if (err < 0) { dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err); goto done; } if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) { - err = drv(inode, file, VIDIOC_G_FBUF, &fbuf); + err = drv(file, VIDIOC_G_FBUF, &fbuf); if (err < 0) { dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err); memset(&fbuf, 0, sizeof(fbuf)); @@ -317,8 +312,8 @@ static noinline int v4l1_compat_get_capabilities( if (fbuf.capability & V4L2_FBUF_CAP_LIST_CLIPPING) cap->type |= VID_TYPE_CLIPPING; - cap->channels = count_inputs(inode, file, drv); - check_size(inode, file, drv, + cap->channels = count_inputs(file, drv); + check_size(file, drv, &cap->maxwidth, &cap->maxheight); cap->audios = 0; /* FIXME */ cap->minwidth = 48; /* FIXME */ @@ -331,7 +326,6 @@ done: static noinline int v4l1_compat_get_frame_buffer( struct video_buffer *buffer, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -341,7 +335,7 @@ static noinline int v4l1_compat_get_frame_buffer( memset(buffer, 0, sizeof(*buffer)); memset(&fbuf, 0, sizeof(fbuf)); - err = drv(inode, file, VIDIOC_G_FBUF, &fbuf); + err = drv(file, VIDIOC_G_FBUF, &fbuf); if (err < 0) { dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err); goto done; @@ -386,7 +380,6 @@ done: static noinline int v4l1_compat_set_frame_buffer( struct video_buffer *buffer, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -415,7 +408,7 @@ static noinline int v4l1_compat_set_frame_buffer( break; } fbuf.fmt.bytesperline = buffer->bytesperline; - err = drv(inode, file, VIDIOC_S_FBUF, &fbuf); + err = drv(file, VIDIOC_S_FBUF, &fbuf); if (err < 0) dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err); return err; @@ -423,7 +416,6 @@ static noinline int v4l1_compat_set_frame_buffer( static noinline int v4l1_compat_get_win_cap_dimensions( struct video_window *win, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -438,7 +430,7 @@ static noinline int v4l1_compat_get_win_cap_dimensions( memset(win, 0, sizeof(*win)); fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY; - err = drv(inode, file, VIDIOC_G_FMT, fmt); + err = drv(file, VIDIOC_G_FMT, fmt); if (err < 0) dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err); if (err == 0) { @@ -453,7 +445,7 @@ static noinline int v4l1_compat_get_win_cap_dimensions( } fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_G_FMT, fmt); + err = drv(file, VIDIOC_G_FMT, fmt); if (err < 0) { dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err); goto done; @@ -472,7 +464,6 @@ done: static noinline int v4l1_compat_set_win_cap_dimensions( struct video_window *win, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -485,8 +476,8 @@ static noinline int v4l1_compat_set_win_cap_dimensions( return err; } fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - drv(inode, file, VIDIOC_STREAMOFF, &fmt->type); - err1 = drv(inode, file, VIDIOC_G_FMT, fmt); + drv(file, VIDIOC_STREAMOFF, &fmt->type); + err1 = drv(file, VIDIOC_G_FMT, fmt); if (err1 < 0) dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err1); if (err1 == 0) { @@ -494,7 +485,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions( fmt->fmt.pix.height = win->height; fmt->fmt.pix.field = V4L2_FIELD_ANY; fmt->fmt.pix.bytesperline = 0; - err = drv(inode, file, VIDIOC_S_FMT, fmt); + err = drv(file, VIDIOC_S_FMT, fmt); if (err < 0) dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n", err); @@ -511,7 +502,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions( fmt->fmt.win.chromakey = win->chromakey; fmt->fmt.win.clips = (void __user *)win->clips; fmt->fmt.win.clipcount = win->clipcount; - err2 = drv(inode, file, VIDIOC_S_FMT, fmt); + err2 = drv(file, VIDIOC_S_FMT, fmt); if (err2 < 0) dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err2); @@ -525,7 +516,6 @@ static noinline int v4l1_compat_set_win_cap_dimensions( static noinline int v4l1_compat_turn_preview_on_off( int *on, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -536,9 +526,9 @@ static noinline int v4l1_compat_turn_preview_on_off( /* dirty hack time. But v4l1 has no STREAMOFF * equivalent in the API, and this one at * least comes close ... */ - drv(inode, file, VIDIOC_STREAMOFF, &captype); + drv(file, VIDIOC_STREAMOFF, &captype); } - err = drv(inode, file, VIDIOC_OVERLAY, on); + err = drv(file, VIDIOC_OVERLAY, on); if (err < 0) dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err); return err; @@ -546,7 +536,6 @@ static noinline int v4l1_compat_turn_preview_on_off( static noinline int v4l1_compat_get_input_info( struct video_channel *chan, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -556,7 +545,7 @@ static noinline int v4l1_compat_get_input_info( memset(&input2, 0, sizeof(input2)); input2.index = chan->channel; - err = drv(inode, file, VIDIOC_ENUMINPUT, &input2); + err = drv(file, VIDIOC_ENUMINPUT, &input2); if (err < 0) { dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: " "channel=%d err=%d\n", chan->channel, err); @@ -578,7 +567,7 @@ static noinline int v4l1_compat_get_input_info( break; } chan->norm = 0; - err = drv(inode, file, VIDIOC_G_STD, &sid); + err = drv(file, VIDIOC_G_STD, &sid); if (err < 0) dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err); if (err == 0) { @@ -595,14 +584,13 @@ done: static noinline int v4l1_compat_set_input( struct video_channel *chan, - struct inode *inode, struct file *file, v4l2_kioctl drv) { int err; v4l2_std_id sid = 0; - err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel); + err = drv(file, VIDIOC_S_INPUT, &chan->channel); if (err < 0) dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err); switch (chan->norm) { @@ -617,7 +605,7 @@ static noinline int v4l1_compat_set_input( break; } if (0 != sid) { - err = drv(inode, file, VIDIOC_S_STD, &sid); + err = drv(file, VIDIOC_S_STD, &sid); if (err < 0) dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err); } @@ -626,7 +614,6 @@ static noinline int v4l1_compat_set_input( static noinline int v4l1_compat_get_picture( struct video_picture *pict, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -639,19 +626,19 @@ static noinline int v4l1_compat_get_picture( return err; } - pict->brightness = get_v4l_control(inode, file, + pict->brightness = get_v4l_control(file, V4L2_CID_BRIGHTNESS, drv); - pict->hue = get_v4l_control(inode, file, + pict->hue = get_v4l_control(file, V4L2_CID_HUE, drv); - pict->contrast = get_v4l_control(inode, file, + pict->contrast = get_v4l_control(file, V4L2_CID_CONTRAST, drv); - pict->colour = get_v4l_control(inode, file, + pict->colour = get_v4l_control(file, V4L2_CID_SATURATION, drv); - pict->whiteness = get_v4l_control(inode, file, + pict->whiteness = get_v4l_control(file, V4L2_CID_WHITENESS, drv); fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_G_FMT, fmt); + err = drv(file, VIDIOC_G_FMT, fmt); if (err < 0) { dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err); goto done; @@ -669,7 +656,6 @@ done: static noinline int v4l1_compat_set_picture( struct video_picture *pict, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -685,15 +671,15 @@ static noinline int v4l1_compat_set_picture( } memset(&fbuf, 0, sizeof(fbuf)); - set_v4l_control(inode, file, + set_v4l_control(file, V4L2_CID_BRIGHTNESS, pict->brightness, drv); - set_v4l_control(inode, file, + set_v4l_control(file, V4L2_CID_HUE, pict->hue, drv); - set_v4l_control(inode, file, + set_v4l_control(file, V4L2_CID_CONTRAST, pict->contrast, drv); - set_v4l_control(inode, file, + set_v4l_control(file, V4L2_CID_SATURATION, pict->colour, drv); - set_v4l_control(inode, file, + set_v4l_control(file, V4L2_CID_WHITENESS, pict->whiteness, drv); /* * V4L1 uses this ioctl to set both memory capture and overlay @@ -703,7 +689,7 @@ static noinline int v4l1_compat_set_picture( */ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_G_FMT, fmt); + err = drv(file, VIDIOC_G_FMT, fmt); /* If VIDIOC_G_FMT failed, then the driver likely doesn't support memory capture. Trying to set the memory capture parameters would be pointless. */ @@ -714,13 +700,13 @@ static noinline int v4l1_compat_set_picture( palette_to_pixelformat(pict->palette)) { fmt->fmt.pix.pixelformat = palette_to_pixelformat( pict->palette); - mem_err = drv(inode, file, VIDIOC_S_FMT, fmt); + mem_err = drv(file, VIDIOC_S_FMT, fmt); if (mem_err < 0) dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n", mem_err); } - err = drv(inode, file, VIDIOC_G_FBUF, &fbuf); + err = drv(file, VIDIOC_G_FBUF, &fbuf); /* If VIDIOC_G_FBUF failed, then the driver likely doesn't support overlay. Trying to set the overlay parameters would be quite pointless. */ @@ -731,7 +717,7 @@ static noinline int v4l1_compat_set_picture( palette_to_pixelformat(pict->palette)) { fbuf.fmt.pixelformat = palette_to_pixelformat( pict->palette); - ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf); + ovl_err = drv(file, VIDIOC_S_FBUF, &fbuf); if (ovl_err < 0) dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n", ovl_err); @@ -752,7 +738,6 @@ static noinline int v4l1_compat_set_picture( static noinline int v4l1_compat_get_tuner( struct video_tuner *tun, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -762,7 +747,7 @@ static noinline int v4l1_compat_get_tuner( v4l2_std_id sid; memset(&tun2, 0, sizeof(tun2)); - err = drv(inode, file, VIDIOC_G_TUNER, &tun2); + err = drv(file, VIDIOC_G_TUNER, &tun2); if (err < 0) { dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err); goto done; @@ -778,7 +763,7 @@ static noinline int v4l1_compat_get_tuner( for (i = 0; i < 64; i++) { memset(&std2, 0, sizeof(std2)); std2.index = i; - if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2)) + if (0 != drv(file, VIDIOC_ENUMSTD, &std2)) break; if (std2.id & V4L2_STD_PAL) tun->flags |= VIDEO_TUNER_PAL; @@ -788,7 +773,7 @@ static noinline int v4l1_compat_get_tuner( tun->flags |= VIDEO_TUNER_SECAM; } - err = drv(inode, file, VIDIOC_G_STD, &sid); + err = drv(file, VIDIOC_G_STD, &sid); if (err < 0) dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err); if (err == 0) { @@ -811,7 +796,6 @@ done: static noinline int v4l1_compat_select_tuner( struct video_tuner *tun, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -821,7 +805,7 @@ static noinline int v4l1_compat_select_tuner( t.index = tun->tuner; - err = drv(inode, file, VIDIOC_S_INPUT, &t); + err = drv(file, VIDIOC_S_INPUT, &t); if (err < 0) dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err); return err; @@ -829,7 +813,6 @@ static noinline int v4l1_compat_select_tuner( static noinline int v4l1_compat_get_frequency( unsigned long *freq, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -838,7 +821,7 @@ static noinline int v4l1_compat_get_frequency( memset(&freq2, 0, sizeof(freq2)); freq2.tuner = 0; - err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); + err = drv(file, VIDIOC_G_FREQUENCY, &freq2); if (err < 0) dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err); if (0 == err) @@ -848,7 +831,6 @@ static noinline int v4l1_compat_get_frequency( static noinline int v4l1_compat_set_frequency( unsigned long *freq, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -856,9 +838,9 @@ static noinline int v4l1_compat_set_frequency( struct v4l2_frequency freq2; memset(&freq2, 0, sizeof(freq2)); - drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); + drv(file, VIDIOC_G_FREQUENCY, &freq2); freq2.frequency = *freq; - err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2); + err = drv(file, VIDIOC_S_FREQUENCY, &freq2); if (err < 0) dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err); return err; @@ -866,7 +848,6 @@ static noinline int v4l1_compat_set_frequency( static noinline int v4l1_compat_get_audio( struct video_audio *aud, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -876,7 +857,7 @@ static noinline int v4l1_compat_get_audio( struct v4l2_tuner tun2; memset(&aud2, 0, sizeof(aud2)); - err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); + err = drv(file, VIDIOC_G_AUDIO, &aud2); if (err < 0) { dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err); goto done; @@ -886,27 +867,27 @@ static noinline int v4l1_compat_get_audio( aud->name[sizeof(aud->name) - 1] = 0; aud->audio = aud2.index; aud->flags = 0; - i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv); + i = get_v4l_control(file, V4L2_CID_AUDIO_VOLUME, drv); if (i >= 0) { aud->volume = i; aud->flags |= VIDEO_AUDIO_VOLUME; } - i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv); + i = get_v4l_control(file, V4L2_CID_AUDIO_BASS, drv); if (i >= 0) { aud->bass = i; aud->flags |= VIDEO_AUDIO_BASS; } - i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv); + i = get_v4l_control(file, V4L2_CID_AUDIO_TREBLE, drv); if (i >= 0) { aud->treble = i; aud->flags |= VIDEO_AUDIO_TREBLE; } - i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv); + i = get_v4l_control(file, V4L2_CID_AUDIO_BALANCE, drv); if (i >= 0) { aud->balance = i; aud->flags |= VIDEO_AUDIO_BALANCE; } - i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv); + i = get_v4l_control(file, V4L2_CID_AUDIO_MUTE, drv); if (i >= 0) { if (i) aud->flags |= VIDEO_AUDIO_MUTE; @@ -914,13 +895,13 @@ static noinline int v4l1_compat_get_audio( } aud->step = 1; qctrl2.id = V4L2_CID_AUDIO_VOLUME; - if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 && + if (drv(file, VIDIOC_QUERYCTRL, &qctrl2) == 0 && !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED)) aud->step = qctrl2.step; aud->mode = 0; memset(&tun2, 0, sizeof(tun2)); - err = drv(inode, file, VIDIOC_G_TUNER, &tun2); + err = drv(file, VIDIOC_G_TUNER, &tun2); if (err < 0) { dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err); err = 0; @@ -939,7 +920,6 @@ done: static noinline int v4l1_compat_set_audio( struct video_audio *aud, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -951,24 +931,24 @@ static noinline int v4l1_compat_set_audio( memset(&tun2, 0, sizeof(tun2)); aud2.index = aud->audio; - err = drv(inode, file, VIDIOC_S_AUDIO, &aud2); + err = drv(file, VIDIOC_S_AUDIO, &aud2); if (err < 0) { dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err); goto done; } - set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, + set_v4l_control(file, V4L2_CID_AUDIO_VOLUME, aud->volume, drv); - set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, + set_v4l_control(file, V4L2_CID_AUDIO_BASS, aud->bass, drv); - set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, + set_v4l_control(file, V4L2_CID_AUDIO_TREBLE, aud->treble, drv); - set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, + set_v4l_control(file, V4L2_CID_AUDIO_BALANCE, aud->balance, drv); - set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, + set_v4l_control(file, V4L2_CID_AUDIO_MUTE, !!(aud->flags & VIDEO_AUDIO_MUTE), drv); - err = drv(inode, file, VIDIOC_G_TUNER, &tun2); + err = drv(file, VIDIOC_G_TUNER, &tun2); if (err < 0) dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err); if (err == 0) { @@ -985,7 +965,7 @@ static noinline int v4l1_compat_set_audio( tun2.audmode = V4L2_TUNER_MODE_LANG2; break; } - err = drv(inode, file, VIDIOC_S_TUNER, &tun2); + err = drv(file, VIDIOC_S_TUNER, &tun2); if (err < 0) dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err); } @@ -996,7 +976,6 @@ done: static noinline int v4l1_compat_capture_frame( struct video_mmap *mm, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -1013,7 +992,7 @@ static noinline int v4l1_compat_capture_frame( memset(&buf, 0, sizeof(buf)); fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_G_FMT, fmt); + err = drv(file, VIDIOC_G_FMT, fmt); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err); goto done; @@ -1029,7 +1008,7 @@ static noinline int v4l1_compat_capture_frame( palette_to_pixelformat(mm->format); fmt->fmt.pix.field = V4L2_FIELD_ANY; fmt->fmt.pix.bytesperline = 0; - err = drv(inode, file, VIDIOC_S_FMT, fmt); + err = drv(file, VIDIOC_S_FMT, fmt); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err); goto done; @@ -1037,17 +1016,17 @@ static noinline int v4l1_compat_capture_frame( } buf.index = mm->frame; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_QUERYBUF, &buf); + err = drv(file, VIDIOC_QUERYBUF, &buf); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err); goto done; } - err = drv(inode, file, VIDIOC_QBUF, &buf); + err = drv(file, VIDIOC_QBUF, &buf); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err); goto done; } - err = drv(inode, file, VIDIOC_STREAMON, &captype); + err = drv(file, VIDIOC_STREAMON, &captype); if (err < 0) dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err); done: @@ -1057,7 +1036,6 @@ done: static noinline int v4l1_compat_sync( int *i, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -1069,7 +1047,7 @@ static noinline int v4l1_compat_sync( memset(&buf, 0, sizeof(buf)); buf.index = *i; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_QUERYBUF, &buf); + err = drv(file, VIDIOC_QUERYBUF, &buf); if (err < 0) { /* No such buffer */ dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); @@ -1082,7 +1060,7 @@ static noinline int v4l1_compat_sync( } /* make sure capture actually runs so we don't block forever */ - err = drv(inode, file, VIDIOC_STREAMON, &captype); + err = drv(file, VIDIOC_STREAMON, &captype); if (err < 0) { dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err); goto done; @@ -1096,7 +1074,7 @@ static noinline int v4l1_compat_sync( if (err < 0 || /* error or sleep was interrupted */ err == 0) /* timeout? Shouldn't occur. */ break; - err = drv(inode, file, VIDIOC_QUERYBUF, &buf); + err = drv(file, VIDIOC_QUERYBUF, &buf); if (err < 0) dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err); } @@ -1104,7 +1082,7 @@ static noinline int v4l1_compat_sync( if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */ goto done; do { - err = drv(inode, file, VIDIOC_DQBUF, &buf); + err = drv(file, VIDIOC_DQBUF, &buf); if (err < 0) dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err); } while (err == 0 && buf.index != *i); @@ -1114,7 +1092,6 @@ done: static noinline int v4l1_compat_get_vbi_format( struct vbi_format *fmt, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -1128,7 +1105,7 @@ static noinline int v4l1_compat_get_vbi_format( } fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE; - err = drv(inode, file, VIDIOC_G_FMT, fmt2); + err = drv(file, VIDIOC_G_FMT, fmt2); if (err < 0) { dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err); goto done; @@ -1153,7 +1130,6 @@ done: static noinline int v4l1_compat_set_vbi_format( struct vbi_format *fmt, - struct inode *inode, struct file *file, v4l2_kioctl drv) { @@ -1179,7 +1155,7 @@ static noinline int v4l1_compat_set_vbi_format( fmt2->fmt.vbi.start[1] = fmt->start[1]; fmt2->fmt.vbi.count[1] = fmt->count[1]; fmt2->fmt.vbi.flags = fmt->flags; - err = drv(inode, file, VIDIOC_TRY_FMT, fmt2); + err = drv(file, VIDIOC_TRY_FMT, fmt2); if (err < 0) { dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err); goto done; @@ -1196,7 +1172,7 @@ static noinline int v4l1_compat_set_vbi_format( err = -EINVAL; goto done; } - err = drv(inode, file, VIDIOC_S_FMT, fmt2); + err = drv(file, VIDIOC_S_FMT, fmt2); if (err < 0) dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err); done: @@ -1208,8 +1184,7 @@ done: * This function is exported. */ int -v4l_compat_translate_ioctl(struct inode *inode, - struct file *file, +v4l_compat_translate_ioctl(struct file *file, int cmd, void *arg, v4l2_kioctl drv) @@ -1218,64 +1193,64 @@ v4l_compat_translate_ioctl(struct inode *inode, switch (cmd) { case VIDIOCGCAP: /* capability */ - err = v4l1_compat_get_capabilities(arg, inode, file, drv); + err = v4l1_compat_get_capabilities(arg, file, drv); break; case VIDIOCGFBUF: /* get frame buffer */ - err = v4l1_compat_get_frame_buffer(arg, inode, file, drv); + err = v4l1_compat_get_frame_buffer(arg, file, drv); break; case VIDIOCSFBUF: /* set frame buffer */ - err = v4l1_compat_set_frame_buffer(arg, inode, file, drv); + err = v4l1_compat_set_frame_buffer(arg, file, drv); break; case VIDIOCGWIN: /* get window or capture dimensions */ - err = v4l1_compat_get_win_cap_dimensions(arg, inode, file, drv); + err = v4l1_compat_get_win_cap_dimensions(arg, file, drv); break; case VIDIOCSWIN: /* set window and/or capture dimensions */ - err = v4l1_compat_set_win_cap_dimensions(arg, inode, file, drv); + err = v4l1_compat_set_win_cap_dimensions(arg, file, drv); break; case VIDIOCCAPTURE: /* turn on/off preview */ - err = v4l1_compat_turn_preview_on_off(arg, inode, file, drv); + err = v4l1_compat_turn_preview_on_off(arg, file, drv); break; case VIDIOCGCHAN: /* get input information */ - err = v4l1_compat_get_input_info(arg, inode, file, drv); + err = v4l1_compat_get_input_info(arg, file, drv); break; case VIDIOCSCHAN: /* set input */ - err = v4l1_compat_set_input(arg, inode, file, drv); + err = v4l1_compat_set_input(arg, file, drv); break; case VIDIOCGPICT: /* get tone controls & partial capture format */ - err = v4l1_compat_get_picture(arg, inode, file, drv); + err = v4l1_compat_get_picture(arg, file, drv); break; case VIDIOCSPICT: /* set tone controls & partial capture format */ - err = v4l1_compat_set_picture(arg, inode, file, drv); + err = v4l1_compat_set_picture(arg, file, drv); break; case VIDIOCGTUNER: /* get tuner information */ - err = v4l1_compat_get_tuner(arg, inode, file, drv); + err = v4l1_compat_get_tuner(arg, file, drv); break; case VIDIOCSTUNER: /* select a tuner input */ - err = v4l1_compat_select_tuner(arg, inode, file, drv); + err = v4l1_compat_select_tuner(arg, file, drv); break; case VIDIOCGFREQ: /* get frequency */ - err = v4l1_compat_get_frequency(arg, inode, file, drv); + err = v4l1_compat_get_frequency(arg, file, drv); break; case VIDIOCSFREQ: /* set frequency */ - err = v4l1_compat_set_frequency(arg, inode, file, drv); + err = v4l1_compat_set_frequency(arg, file, drv); break; case VIDIOCGAUDIO: /* get audio properties/controls */ - err = v4l1_compat_get_audio(arg, inode, file, drv); + err = v4l1_compat_get_audio(arg, file, drv); break; case VIDIOCSAUDIO: /* set audio controls */ - err = v4l1_compat_set_audio(arg, inode, file, drv); + err = v4l1_compat_set_audio(arg, file, drv); break; case VIDIOCMCAPTURE: /* capture a frame */ - err = v4l1_compat_capture_frame(arg, inode, file, drv); + err = v4l1_compat_capture_frame(arg, file, drv); break; case VIDIOCSYNC: /* wait for a frame */ - err = v4l1_compat_sync(arg, inode, file, drv); + err = v4l1_compat_sync(arg, file, drv); break; case VIDIOCGVBIFMT: /* query VBI data capture format */ - err = v4l1_compat_get_vbi_format(arg, inode, file, drv); + err = v4l1_compat_get_vbi_format(arg, file, drv); break; case VIDIOCSVBIFMT: - err = v4l1_compat_set_vbi_format(arg, inode, file, drv); + err = v4l1_compat_set_vbi_format(arg, file, drv); break; default: err = -ENOIOCTLCMD; diff --git a/drivers/media/video/v4l2-int-device.c b/drivers/media/video/v4l2-int-device.c index 0e4549922f26..a935bae538ef 100644 --- a/drivers/media/video/v4l2-int-device.c +++ b/drivers/media/video/v4l2-int-device.c @@ -32,7 +32,7 @@ static DEFINE_MUTEX(mutex); static LIST_HEAD(int_list); -static void v4l2_int_device_try_attach_all(void) +void v4l2_int_device_try_attach_all(void) { struct v4l2_int_device *m, *s; @@ -66,6 +66,7 @@ static void v4l2_int_device_try_attach_all(void) } } } +EXPORT_SYMBOL_GPL(v4l2_int_device_try_attach_all); static int ioctl_sort_cmp(const void *a, const void *b) { @@ -144,6 +145,7 @@ int v4l2_int_ioctl_0(struct v4l2_int_device *d, int cmd) find_ioctl(d->u.slave, cmd, (v4l2_int_ioctl_func *)no_such_ioctl_0))(d); } +EXPORT_SYMBOL_GPL(v4l2_int_ioctl_0); static int no_such_ioctl_1(struct v4l2_int_device *d, void *arg) { @@ -156,5 +158,6 @@ int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg) find_ioctl(d->u.slave, cmd, (v4l2_int_ioctl_func *)no_such_ioctl_1))(d, arg); } +EXPORT_SYMBOL_GPL(v4l2_int_ioctl_1); MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 155c9d77a463..710e1a40c422 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -625,13 +625,13 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type) return -EINVAL; } -static int __video_do_ioctl(struct inode *inode, struct file *file, +static int __video_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vfd = video_devdata(file); const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; - void *fh = file->private_data; - int ret = -EINVAL; + void *fh = file->private_data; + int ret = -EINVAL; if ((vfd->debug & V4L2_DEBUG_IOCTL) && !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) { @@ -675,7 +675,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, V4L2 ioctls. ********************************************************/ if (_IOC_TYPE(cmd) == 'v' && _IOC_NR(cmd) < BASE_VIDIOCPRIVATE) - return v4l_compat_translate_ioctl(inode, file, cmd, arg, + return v4l_compat_translate_ioctl(file, cmd, arg, __video_do_ioctl); #endif @@ -1768,7 +1768,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, return ret; } -int video_ioctl2(struct inode *inode, struct file *file, +int __video_ioctl2(struct file *file, unsigned int cmd, unsigned long arg) { char sbuf[128]; @@ -1832,7 +1832,7 @@ int video_ioctl2(struct inode *inode, struct file *file, } /* Handles IOCTL */ - err = __video_do_ioctl(inode, file, cmd, parg); + err = __video_do_ioctl(file, cmd, parg); if (err == -ENOIOCTLCMD) err = -EINVAL; if (is_ext_ctrl) { @@ -1860,4 +1860,11 @@ out: kfree(mbuf); return err; } +EXPORT_SYMBOL(__video_ioctl2); + +int video_ioctl2(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return __video_ioctl2(file, cmd, arg); +} EXPORT_SYMBOL(video_ioctl2); diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index 917277d36605..0e7dcba8e4ae 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c @@ -296,29 +296,7 @@ EXPORT_SYMBOL(videobuf_dvb_register_bus); void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f) { - struct list_head *list, *q; - struct videobuf_dvb_frontend *fe; - - mutex_lock(&f->lock); - list_for_each_safe(list, q, &f->felist) { - fe = list_entry(list, struct videobuf_dvb_frontend, felist); - if (fe->dvb.net.dvbdev) { - dvb_net_release(&fe->dvb.net); - fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, - &fe->dvb.fe_mem); - fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, - &fe->dvb.fe_hw); - dvb_dmxdev_release(&fe->dvb.dmxdev); - dvb_dmx_release(&fe->dvb.demux); - dvb_unregister_frontend(fe->dvb.frontend); - } - if (fe->dvb.frontend) - /* always allocated, may have been reset */ - dvb_frontend_detach(fe->dvb.frontend); - list_del(list); - kfree(fe); - } - mutex_unlock(&f->lock); + videobuf_dvb_dealloc_frontends(f); dvb_unregister_adapter(&f->adapter); } @@ -389,3 +367,31 @@ fail_alloc: return fe; } EXPORT_SYMBOL(videobuf_dvb_alloc_frontend); + +void videobuf_dvb_dealloc_frontends(struct videobuf_dvb_frontends *f) +{ + struct list_head *list, *q; + struct videobuf_dvb_frontend *fe; + + mutex_lock(&f->lock); + list_for_each_safe(list, q, &f->felist) { + fe = list_entry(list, struct videobuf_dvb_frontend, felist); + if (fe->dvb.net.dvbdev) { + dvb_net_release(&fe->dvb.net); + fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, + &fe->dvb.fe_mem); + fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, + &fe->dvb.fe_hw); + dvb_dmxdev_release(&fe->dvb.dmxdev); + dvb_dmx_release(&fe->dvb.demux); + dvb_unregister_frontend(fe->dvb.frontend); + } + if (fe->dvb.frontend) + /* always allocated, may have been reset */ + dvb_frontend_detach(fe->dvb.frontend); + list_del(list); /* remove list entry */ + kfree(fe); /* free frontend allocation */ + } + mutex_unlock(&f->lock); +} +EXPORT_SYMBOL(videobuf_dvb_dealloc_frontends); diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 7d7e51def461..e15e48f04be7 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -1163,11 +1163,11 @@ static int vivi_release(void) if (-1 != dev->vfd->minor) { printk(KERN_INFO "%s: unregistering /dev/video%d\n", - VIVI_MODULE_NAME, dev->vfd->minor); + VIVI_MODULE_NAME, dev->vfd->num); video_unregister_device(dev->vfd); } else { printk(KERN_INFO "%s: releasing /dev/video%d\n", - VIVI_MODULE_NAME, dev->vfd->minor); + VIVI_MODULE_NAME, dev->vfd->num); video_device_release(dev->vfd); } @@ -1307,7 +1307,7 @@ static int __init vivi_init(void) dev->vfd = vfd; printk(KERN_INFO "%s: V4L2 device registered as /dev/video%d\n", - VIVI_MODULE_NAME, vfd->minor); + VIVI_MODULE_NAME, vfd->num); } if (ret < 0) { diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index dcd45dbd82dc..4dfb43bd1846 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c @@ -2398,7 +2398,7 @@ error: cam->sensor = CC_UNKNOWN; DBG(1, "Image sensor initialization failed for %s (/dev/video%d). " "Try to detach and attach this device again", - symbolic(camlist, cam->id), cam->v4ldev->minor) + symbolic(camlist, cam->id), cam->v4ldev->num) return err; } @@ -2644,7 +2644,7 @@ static void w9968cf_release_resources(struct w9968cf_device* cam) { mutex_lock(&w9968cf_devlist_mutex); - DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->minor) + DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->num) video_unregister_device(cam->v4ldev); list_del(&cam->v4llist); @@ -2679,7 +2679,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp) DBG(2, "No supported image sensor has been detected by the " "'ovcamchip' module for the %s (/dev/video%d). Make " "sure it is loaded *before* (re)connecting the camera.", - symbolic(camlist, cam->id), cam->v4ldev->minor) + symbolic(camlist, cam->id), cam->v4ldev->num) mutex_unlock(&cam->dev_mutex); up_read(&w9968cf_disconnect); return -ENODEV; @@ -2687,7 +2687,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp) if (cam->users) { DBG(2, "%s (/dev/video%d) has been already occupied by '%s'", - symbolic(camlist, cam->id),cam->v4ldev->minor,cam->command) + symbolic(camlist, cam->id), cam->v4ldev->num, cam->command) if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) { mutex_unlock(&cam->dev_mutex); up_read(&w9968cf_disconnect); @@ -2709,7 +2709,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp) } DBG(5, "Opening '%s', /dev/video%d ...", - symbolic(camlist, cam->id), cam->v4ldev->minor) + symbolic(camlist, cam->id), cam->v4ldev->num) cam->streaming = 0; cam->misconfigured = 0; @@ -2947,7 +2947,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp, .minheight = cam->minheight, }; sprintf(cap.name, "W996[87]CF USB Camera #%d", - cam->v4ldev->minor); + cam->v4ldev->num); cap.maxwidth = (cam->upscaling && w9968cf_vpp) ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) : cam->maxwidth; @@ -3567,7 +3567,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev->minor) + DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev->num) /* Set some basic constants */ w9968cf_configure_camera(cam, udev, mod_id, dev_nr); @@ -3618,7 +3618,7 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf) DBG(2, "The device is open (/dev/video%d)! " "Process name: %s. Deregistration and memory " "deallocation are deferred on close.", - cam->v4ldev->minor, cam->command) + cam->v4ldev->num, cam->command) cam->misconfigured = 1; w9968cf_stop_transfer(cam); wake_up_interruptible(&cam->wait_queue); diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 6a0902bcba6b..9fc581707638 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -539,7 +539,7 @@ static int zc0301_stream_interrupt(struct zc0301_device* cam) cam->state |= DEV_MISCONFIGURED; DBG(1, "URB timeout reached. The camera is misconfigured. To " "use it, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -EIO; } @@ -640,7 +640,7 @@ static void zc0301_release_resources(struct kref *kref) { struct zc0301_device *cam = container_of(kref, struct zc0301_device, kref); - DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor); + DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); usb_put_dev(cam->usbdev); @@ -679,7 +679,7 @@ static int zc0301_open(struct inode* inode, struct file* filp) } if (cam->users) { - DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor); + DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->num); DBG(3, "Simultaneous opens are not supported"); if ((filp->f_flags & O_NONBLOCK) || (filp->f_flags & O_NDELAY)) { @@ -722,7 +722,7 @@ static int zc0301_open(struct inode* inode, struct file* filp) cam->frame_count = 0; zc0301_empty_framequeues(cam); - DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor); + DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num); out: mutex_unlock(&cam->open_mutex); @@ -746,7 +746,7 @@ static int zc0301_release(struct inode* inode, struct file* filp) cam->users--; wake_up_interruptible_nr(&cam->wait_open, 1); - DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor); + DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num); kref_put(&cam->kref, zc0301_release_resources); @@ -1275,7 +1275,7 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To " "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -EIO; } @@ -1288,7 +1288,7 @@ zc0301_vidioc_s_crop(struct zc0301_device* cam, void __user * arg) cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To " "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -ENOMEM; } @@ -1470,7 +1470,7 @@ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To " "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -EIO; } @@ -1482,7 +1482,7 @@ zc0301_vidioc_try_s_fmt(struct zc0301_device* cam, unsigned int cmd, cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To " "use the camera, close and open /dev/video%d again.", - cam->v4ldev->minor); + cam->v4ldev->num); return -ENOMEM; } @@ -1529,7 +1529,7 @@ zc0301_vidioc_s_jpegcomp(struct zc0301_device* cam, void __user * arg) cam->state |= DEV_MISCONFIGURED; DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware " "problems. To use the camera, close and open " - "/dev/video%d again.", cam->v4ldev->minor); + "/dev/video%d again.", cam->v4ldev->num); return -EIO; } @@ -2005,7 +2005,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) goto fail; } - DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor); + DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num); cam->module_param.force_munmap = force_munmap[dev_nr]; cam->module_param.frame_timeout = frame_timeout[dev_nr]; @@ -2044,7 +2044,7 @@ static void zc0301_usb_disconnect(struct usb_interface* intf) if (cam->users) { DBG(2, "Device /dev/video%d is open! Deregistration and " "memory deallocation are deferred.", - cam->v4ldev->minor); + cam->v4ldev->num); cam->state |= DEV_MISCONFIGURED; zc0301_stop_transfer(cam); cam->state |= DEV_DISCONNECTED; diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 7cdac99deea6..a1d81ed44c7c 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -885,7 +885,7 @@ static int zr364xx_probe(struct usb_interface *intf, usb_set_intfdata(intf, cam); dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n", - cam->vdev->minor); + cam->vdev->num); return 0; } |