summaryrefslogtreecommitdiff
path: root/drivers/media/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb')
-rw-r--r--drivers/media/usb/Kconfig1
-rw-r--r--drivers/media/usb/Makefile1
-rw-r--r--drivers/media/usb/au0828/au0828-cards.c2
-rw-r--r--drivers/media/usb/au0828/au0828-video.c7
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-audio.c42
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-cards.c48
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-i2c.c16
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf.c16
-rw-r--r--drivers/media/usb/dvb-usb/cxusb.c163
-rw-r--r--drivers/media/usb/dvb-usb/dib0700_core.c3
-rw-r--r--drivers/media/usb/dvb-usb/dibusb-mc-common.c2
-rw-r--r--drivers/media/usb/dvb-usb/digitv.c3
-rw-r--r--drivers/media/usb/dvb-usb/dw2102.c54
-rw-r--r--drivers/media/usb/dvb-usb/ttusb2.c19
-rw-r--r--drivers/media/usb/em28xx/Kconfig7
-rw-r--r--drivers/media/usb/em28xx/em28xx-camera.c107
-rw-r--r--drivers/media/usb/em28xx/em28xx-cards.c15
-rw-r--r--drivers/media/usb/em28xx/em28xx-reg.h18
-rw-r--r--drivers/media/usb/em28xx/em28xx-video.c13
-rw-r--r--drivers/media/usb/em28xx/em28xx.h1
-rw-r--r--drivers/media/usb/go7007/go7007-v4l2.c5
-rw-r--r--drivers/media/usb/gspca/konica.c3
-rw-r--r--drivers/media/usb/pulse8-cec/Kconfig2
-rw-r--r--drivers/media/usb/pulse8-cec/pulse8-cec.c6
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-eeprom.c13
-rw-r--r--drivers/media/usb/rainshadow-cec/Kconfig10
-rw-r--r--drivers/media/usb/rainshadow-cec/Makefile1
-rw-r--r--drivers/media/usb/rainshadow-cec/rainshadow-cec.c388
-rw-r--r--drivers/media/usb/stk1160/Kconfig6
-rw-r--r--drivers/media/usb/tm6000/tm6000-video.c2
-rw-r--r--drivers/media/usb/usbvision/usbvision-video.c9
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c15
-rw-r--r--drivers/media/usb/uvc/uvc_video.c12
-rw-r--r--drivers/media/usb/uvc/uvcvideo.h9
-rw-r--r--drivers/media/usb/zr364xx/zr364xx.c8
35 files changed, 852 insertions, 175 deletions
diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig
index c9644b62f91a..b24e753c4766 100644
--- a/drivers/media/usb/Kconfig
+++ b/drivers/media/usb/Kconfig
@@ -63,6 +63,7 @@ endif
if MEDIA_CEC_SUPPORT
comment "USB HDMI CEC adapters"
source "drivers/media/usb/pulse8-cec/Kconfig"
+source "drivers/media/usb/rainshadow-cec/Kconfig"
endif
endif #MEDIA_USB_SUPPORT
diff --git a/drivers/media/usb/Makefile b/drivers/media/usb/Makefile
index 0f15e3351ddc..738b993ec8b0 100644
--- a/drivers/media/usb/Makefile
+++ b/drivers/media/usb/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_VIDEO_USBTV) += usbtv/
obj-$(CONFIG_VIDEO_GO7007) += go7007/
obj-$(CONFIG_DVB_AS102) += as102/
obj-$(CONFIG_USB_PULSE8_CEC) += pulse8-cec/
+obj-$(CONFIG_USB_RAINSHADOW_CEC) += rainshadow-cec/
diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c
index 313f659f0bfb..43bfa778b070 100644
--- a/drivers/media/usb/au0828/au0828-cards.c
+++ b/drivers/media/usb/au0828/au0828-cards.c
@@ -153,7 +153,7 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
{
struct tveeprom tv;
- tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
+ tveeprom_hauppauge_analog(&tv, eeprom_data);
dev->board.tuner_type = tv.tuner_type;
/* Make sure we support the board model */
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 16f9125a985a..2a255bd32bb3 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -809,16 +809,9 @@ static void au0828_analog_stream_reset(struct au0828_dev *dev)
*/
static int au0828_stream_interrupt(struct au0828_dev *dev)
{
- int ret = 0;
-
dev->stream_state = STREAM_INTERRUPT;
if (test_bit(DEV_DISCONNECTED, &dev->dev_state))
return -ENODEV;
- else if (ret) {
- set_bit(DEV_MISCONFIGURED, &dev->dev_state);
- dprintk(1, "%s device is misconfigured!\n", __func__);
- return ret;
- }
return 0;
}
diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c
index cf80842dfa08..a050d125934c 100644
--- a/drivers/media/usb/cx231xx/cx231xx-audio.c
+++ b/drivers/media/usb/cx231xx/cx231xx-audio.c
@@ -670,10 +670,8 @@ static int cx231xx_audio_init(struct cx231xx *dev)
spin_lock_init(&adev->slock);
err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm);
- if (err < 0) {
- snd_card_free(card);
- return err;
- }
+ if (err < 0)
+ goto err_free_card;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
&snd_cx231xx_pcm_capture);
@@ -687,10 +685,9 @@ static int cx231xx_audio_init(struct cx231xx *dev)
INIT_WORK(&dev->wq_trigger, audio_trigger);
err = snd_card_register(card);
- if (err < 0) {
- snd_card_free(card);
- return err;
- }
+ if (err < 0)
+ goto err_free_card;
+
adev->sndcard = card;
adev->udev = dev->udev;
@@ -700,6 +697,11 @@ static int cx231xx_audio_init(struct cx231xx *dev)
hs_config_info[0].interface_info.
audio_index + 1];
+ if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) {
+ err = -ENODEV;
+ goto err_free_card;
+ }
+
adev->end_point_addr =
uif->altsetting[0].endpoint[isoc_pipe].desc.
bEndpointAddress;
@@ -709,13 +711,20 @@ static int cx231xx_audio_init(struct cx231xx *dev)
"audio EndPoint Addr 0x%x, Alternate settings: %i\n",
adev->end_point_addr, adev->num_alt);
adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL);
-
- if (adev->alt_max_pkt_size == NULL)
- return -ENOMEM;
+ if (!adev->alt_max_pkt_size) {
+ err = -ENOMEM;
+ goto err_free_card;
+ }
for (i = 0; i < adev->num_alt; i++) {
- u16 tmp =
- le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
+ u16 tmp;
+
+ if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) {
+ err = -ENODEV;
+ goto err_free_pkt_size;
+ }
+
+ tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
wMaxPacketSize);
adev->alt_max_pkt_size[i] =
(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
@@ -725,6 +734,13 @@ static int cx231xx_audio_init(struct cx231xx *dev)
}
return 0;
+
+err_free_pkt_size:
+ kfree(adev->alt_max_pkt_size);
+err_free_card:
+ snd_card_free(card);
+
+ return err;
}
static int cx231xx_audio_fini(struct cx231xx *dev)
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c
index f730fdbc9156..a1007d005290 100644
--- a/drivers/media/usb/cx231xx/cx231xx-cards.c
+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
@@ -1165,8 +1165,7 @@ void cx231xx_card_setup(struct cx231xx *dev)
e->client.addr = 0xa0 >> 1;
read_eeprom(dev, &e->client, e->eeprom, sizeof(e->eeprom));
- tveeprom_hauppauge_analog(&e->client,
- &e->tvee, e->eeprom + 0xc0);
+ tveeprom_hauppauge_analog(&e->tvee, e->eeprom + 0xc0);
kfree(e);
break;
}
@@ -1426,6 +1425,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev,
uif = udev->actconfig->interface[idx];
+ if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1)
+ return -ENODEV;
+
dev->video_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress;
dev->video_mode.num_alt = uif->num_altsetting;
@@ -1439,7 +1441,12 @@ static int cx231xx_init_v4l2(struct cx231xx *dev,
return -ENOMEM;
for (i = 0; i < dev->video_mode.num_alt; i++) {
- u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
+ u16 tmp;
+
+ if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1)
+ return -ENODEV;
+
+ tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
dev->video_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
dev_dbg(dev->dev,
"Alternate setting %i, max size= %i\n", i,
@@ -1456,6 +1463,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev,
}
uif = udev->actconfig->interface[idx];
+ if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1)
+ return -ENODEV;
+
dev->vbi_mode.end_point_addr =
uif->altsetting[0].endpoint[isoc_pipe].desc.
bEndpointAddress;
@@ -1472,8 +1482,12 @@ static int cx231xx_init_v4l2(struct cx231xx *dev,
return -ENOMEM;
for (i = 0; i < dev->vbi_mode.num_alt; i++) {
- u16 tmp =
- le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
+ u16 tmp;
+
+ if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1)
+ return -ENODEV;
+
+ tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
desc.wMaxPacketSize);
dev->vbi_mode.alt_max_pkt_size[i] =
(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
@@ -1493,6 +1507,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev,
}
uif = udev->actconfig->interface[idx];
+ if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1)
+ return -ENODEV;
+
dev->sliced_cc_mode.end_point_addr =
uif->altsetting[0].endpoint[isoc_pipe].desc.
bEndpointAddress;
@@ -1507,7 +1524,12 @@ static int cx231xx_init_v4l2(struct cx231xx *dev,
return -ENOMEM;
for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) {
- u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
+ u16 tmp;
+
+ if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1)
+ return -ENODEV;
+
+ tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
desc.wMaxPacketSize);
dev->sliced_cc_mode.alt_max_pkt_size[i] =
(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
@@ -1676,6 +1698,11 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
}
uif = udev->actconfig->interface[idx];
+ if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) {
+ retval = -ENODEV;
+ goto err_video_alt;
+ }
+
dev->ts1_mode.end_point_addr =
uif->altsetting[0].endpoint[isoc_pipe].
desc.bEndpointAddress;
@@ -1693,7 +1720,14 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
}
for (i = 0; i < dev->ts1_mode.num_alt; i++) {
- u16 tmp = le16_to_cpu(uif->altsetting[i].
+ u16 tmp;
+
+ if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) {
+ retval = -ENODEV;
+ goto err_video_alt;
+ }
+
+ tmp = le16_to_cpu(uif->altsetting[i].
endpoint[isoc_pipe].desc.
wMaxPacketSize);
dev->ts1_mode.alt_max_pkt_size[i] =
diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c b/drivers/media/usb/cx231xx/cx231xx-i2c.c
index dff514e147da..8d95b1154e12 100644
--- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
+++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
@@ -491,20 +491,24 @@ void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port)
{
unsigned char buf;
int i, rc;
- struct i2c_client client;
+ struct i2c_adapter *adap;
+ struct i2c_msg msg = {
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = &buf,
+ };
if (!i2c_scan)
return;
/* Don't generate I2C errors during scan */
dev->i2c_scan_running = true;
-
- memset(&client, 0, sizeof(client));
- client.adapter = cx231xx_get_i2c_adap(dev, i2c_port);
+ adap = cx231xx_get_i2c_adap(dev, i2c_port);
for (i = 0; i < 128; i++) {
- client.addr = i;
- rc = i2c_master_recv(&client, &buf, 0);
+ msg.addr = i;
+ rc = i2c_transfer(adap, &msg, 1);
+
if (rc < 0)
continue;
dev_info(dev->dev,
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
index 80c635980526..abf69d8fa469 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
@@ -919,7 +919,12 @@ static int mxl111sf_init(struct dvb_usb_device *d)
struct mxl111sf_state *state = d_to_priv(d);
int ret;
static u8 eeprom[256];
- struct i2c_client c;
+ u8 reg = 0;
+ struct i2c_msg msg[2] = {
+ { .addr = 0xa0 >> 1, .len = 1, .buf = &reg },
+ { .addr = 0xa0 >> 1, .flags = I2C_M_RD,
+ .len = sizeof(eeprom), .buf = eeprom },
+ };
ret = get_chip_info(state);
if (mxl_fail(ret))
@@ -930,14 +935,11 @@ static int mxl111sf_init(struct dvb_usb_device *d)
if (state->chip_rev > MXL111SF_V6)
mxl111sf_config_pin_mux_modes(state, PIN_MUX_TS_SPI_IN_MODE_1);
- c.adapter = &d->i2c_adap;
- c.addr = 0xa0 >> 1;
-
- ret = tveeprom_read(&c, eeprom, sizeof(eeprom));
+ ret = i2c_transfer(&d->i2c_adap, msg, 2);
if (mxl_fail(ret))
return 0;
- tveeprom_hauppauge_analog(&c, &state->tv, (0x84 == eeprom[0xa0]) ?
- eeprom + 0xa0 : eeprom + 0x80);
+ tveeprom_hauppauge_analog(&state->tv, (0x84 == eeprom[0xa0]) ?
+ eeprom + 0xa0 : eeprom + 0x80);
#if 0
switch (state->tv.model) {
case 117001:
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c
index 51620e02292f..99a3f3625944 100644
--- a/drivers/media/usb/dvb-usb/cxusb.c
+++ b/drivers/media/usb/dvb-usb/cxusb.c
@@ -458,8 +458,8 @@ static int cxusb_rc_query(struct dvb_usb_device *d)
cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4);
if (ircode[2] || ircode[3])
- rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN,
- RC_SCANCODE_RC5(ircode[2], ircode[3]), 0);
+ rc_keydown(d->rc_dev, RC_TYPE_NEC,
+ RC_SCANCODE_NEC(~ircode[2] & 0xff, ircode[3]), 0);
return 0;
}
@@ -473,8 +473,8 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d)
return 0;
if (ircode[1] || ircode[2])
- rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN,
- RC_SCANCODE_RC5(ircode[1], ircode[2]), 0);
+ rc_keydown(d->rc_dev, RC_TYPE_NEC,
+ RC_SCANCODE_NEC(~ircode[1] & 0xff, ircode[2]), 0);
return 0;
}
@@ -1239,6 +1239,82 @@ static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap)
return 0;
}
+static int cxusb_mygica_t230c_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ struct dvb_usb_device *d = adap->dev;
+ struct cxusb_state *st = d->priv;
+ struct i2c_adapter *adapter;
+ struct i2c_client *client_demod;
+ struct i2c_client *client_tuner;
+ struct i2c_board_info info;
+ struct si2168_config si2168_config;
+ struct si2157_config si2157_config;
+
+ /* Select required USB configuration */
+ if (usb_set_interface(d->udev, 0, 0) < 0)
+ err("set interface failed");
+
+ /* Unblock all USB pipes */
+ usb_clear_halt(d->udev,
+ usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
+ usb_clear_halt(d->udev,
+ usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
+ usb_clear_halt(d->udev,
+ usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
+
+ /* attach frontend */
+ memset(&si2168_config, 0, sizeof(si2168_config));
+ si2168_config.i2c_adapter = &adapter;
+ si2168_config.fe = &adap->fe_adap[0].fe;
+ si2168_config.ts_mode = SI2168_TS_PARALLEL;
+ si2168_config.ts_clock_inv = 1;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+ info.addr = 0x64;
+ info.platform_data = &si2168_config;
+ request_module(info.type);
+ client_demod = i2c_new_device(&d->i2c_adap, &info);
+ if (client_demod == NULL || client_demod->dev.driver == NULL)
+ return -ENODEV;
+
+ if (!try_module_get(client_demod->dev.driver->owner)) {
+ i2c_unregister_device(client_demod);
+ return -ENODEV;
+ }
+
+ /* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
+ si2157_config.fe = adap->fe_adap[0].fe;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2141", I2C_NAME_SIZE);
+ info.addr = 0x60;
+ info.platform_data = &si2157_config;
+ request_module("si2157");
+ client_tuner = i2c_new_device(adapter, &info);
+ if (client_tuner == NULL || client_tuner->dev.driver == NULL) {
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ return -ENODEV;
+ }
+ if (!try_module_get(client_tuner->dev.driver->owner)) {
+ i2c_unregister_device(client_tuner);
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ return -ENODEV;
+ }
+
+ st->i2c_client_demod = client_demod;
+ st->i2c_client_tuner = client_tuner;
+
+ /* hook fe: need to resync the slave fifo when signal locks. */
+ mutex_init(&st->stream_mutex);
+ st->last_lock = 0;
+ st->fe_read_status = adap->fe_adap[0].fe->ops.read_status;
+ adap->fe_adap[0].fe->ops.read_status = cxusb_read_status;
+
+ return 0;
+}
+
/*
* DViCO has shipped two devices with the same USB ID, but only one of them
* needs a firmware download. Check the device class details to see if they
@@ -1321,6 +1397,7 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
static struct dvb_usb_device_properties cxusb_d680_dmb_properties;
static struct dvb_usb_device_properties cxusb_mygica_d689_properties;
static struct dvb_usb_device_properties cxusb_mygica_t230_properties;
+static struct dvb_usb_device_properties cxusb_mygica_t230c_properties;
static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -1353,6 +1430,8 @@ static int cxusb_probe(struct usb_interface *intf,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties,
THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &cxusb_mygica_t230c_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
0)
return 0;
@@ -1404,6 +1483,7 @@ enum cxusb_table_index {
CONEXANT_D680_DMB,
MYGICA_D689,
MYGICA_T230,
+ MYGICA_T230C,
NR__cxusb_table_index
};
@@ -1471,6 +1551,9 @@ static struct usb_device_id cxusb_table[NR__cxusb_table_index + 1] = {
[MYGICA_T230] = {
USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230)
},
+ [MYGICA_T230C] = {
+ USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230+1)
+ },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -1563,7 +1646,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
.rc_codes = RC_MAP_DVICO_PORTABLE,
.module_name = KBUILD_MODNAME,
.rc_query = cxusb_rc_query,
- .allowed_protos = RC_BIT_UNKNOWN,
+ .allowed_protos = RC_BIT_NEC,
},
.generic_bulk_ctrl_endpoint = 0x01,
@@ -1620,7 +1703,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
.rc_codes = RC_MAP_DVICO_MCE,
.module_name = KBUILD_MODNAME,
.rc_query = cxusb_rc_query,
- .allowed_protos = RC_BIT_UNKNOWN,
+ .allowed_protos = RC_BIT_NEC,
},
.generic_bulk_ctrl_endpoint = 0x01,
@@ -1685,7 +1768,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
.rc_codes = RC_MAP_DVICO_PORTABLE,
.module_name = KBUILD_MODNAME,
.rc_query = cxusb_rc_query,
- .allowed_protos = RC_BIT_UNKNOWN,
+ .allowed_protos = RC_BIT_NEC,
},
.generic_bulk_ctrl_endpoint = 0x01,
@@ -1741,7 +1824,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
.rc_codes = RC_MAP_DVICO_PORTABLE,
.module_name = KBUILD_MODNAME,
.rc_query = cxusb_rc_query,
- .allowed_protos = RC_BIT_UNKNOWN,
+ .allowed_protos = RC_BIT_NEC,
},
.generic_bulk_ctrl_endpoint = 0x01,
@@ -1796,7 +1879,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
.rc_codes = RC_MAP_DVICO_MCE,
.module_name = KBUILD_MODNAME,
.rc_query = cxusb_bluebird2_rc_query,
- .allowed_protos = RC_BIT_UNKNOWN,
+ .allowed_protos = RC_BIT_NEC,
},
.num_device_descs = 1,
@@ -1850,7 +1933,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
.rc_codes = RC_MAP_DVICO_PORTABLE,
.module_name = KBUILD_MODNAME,
.rc_query = cxusb_bluebird2_rc_query,
- .allowed_protos = RC_BIT_UNKNOWN,
+ .allowed_protos = RC_BIT_NEC,
},
.num_device_descs = 1,
@@ -1906,7 +1989,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
.rc_codes = RC_MAP_DVICO_PORTABLE,
.module_name = KBUILD_MODNAME,
.rc_query = cxusb_rc_query,
- .allowed_protos = RC_BIT_UNKNOWN,
+ .allowed_protos = RC_BIT_NEC,
},
.num_device_descs = 1,
@@ -2005,7 +2088,7 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
.rc_codes = RC_MAP_DVICO_MCE,
.module_name = KBUILD_MODNAME,
.rc_query = cxusb_rc_query,
- .allowed_protos = RC_BIT_UNKNOWN,
+ .allowed_protos = RC_BIT_NEC,
},
.num_device_descs = 1,
@@ -2165,7 +2248,7 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties = {
.rc.core = {
.rc_interval = 100,
- .rc_codes = RC_MAP_D680_DMB,
+ .rc_codes = RC_MAP_TOTAL_MEDIA_IN_HAND_02,
.module_name = KBUILD_MODNAME,
.rc_query = cxusb_d680_dmb_rc_query,
.allowed_protos = RC_BIT_UNKNOWN,
@@ -2181,6 +2264,60 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties = {
}
};
+static struct dvb_usb_device_properties cxusb_mygica_t230c_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = CYPRESS_FX2,
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .num_frontends = 1,
+ .fe = {{
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .frontend_attach = cxusb_mygica_t230c_frontend_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 5,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+ } },
+ },
+ },
+
+ .power_ctrl = cxusb_d680_dmb_power_ctrl,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+
+ .rc.core = {
+ .rc_interval = 100,
+ .rc_codes = RC_MAP_TOTAL_MEDIA_IN_HAND_02,
+ .module_name = KBUILD_MODNAME,
+ .rc_query = cxusb_d680_dmb_rc_query,
+ .allowed_protos = RC_BIT_UNKNOWN,
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ {
+ "Mygica T230C DVB-T/T2/C",
+ { NULL },
+ { &cxusb_table[MYGICA_T230C], NULL },
+ },
+ }
+};
+
static struct usb_driver cxusb_driver = {
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,
diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c
index dd5edd3a17ee..08acdd32e412 100644
--- a/drivers/media/usb/dvb-usb/dib0700_core.c
+++ b/drivers/media/usb/dvb-usb/dib0700_core.c
@@ -809,6 +809,9 @@ int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf)
/* Starting in firmware 1.20, the RC info is provided on a bulk pipe */
+ if (intf->altsetting[0].desc.bNumEndpoints < rc_ep + 1)
+ return -ENODEV;
+
purb = usb_alloc_urb(0, GFP_KERNEL);
if (purb == NULL)
return -ENOMEM;
diff --git a/drivers/media/usb/dvb-usb/dibusb-mc-common.c b/drivers/media/usb/dvb-usb/dibusb-mc-common.c
index c989cac9343d..0c2bc97436d5 100644
--- a/drivers/media/usb/dvb-usb/dibusb-mc-common.c
+++ b/drivers/media/usb/dvb-usb/dibusb-mc-common.c
@@ -11,6 +11,8 @@
#include "dibusb.h"
+MODULE_LICENSE("GPL");
+
/* 3000MC/P stuff */
// Config Adjacent channels Perf -cal22
static struct dibx000_agc_config dib3000p_mt2060_agc_config = {
diff --git a/drivers/media/usb/dvb-usb/digitv.c b/drivers/media/usb/dvb-usb/digitv.c
index 4284f6984dc1..475a3c0cdee7 100644
--- a/drivers/media/usb/dvb-usb/digitv.c
+++ b/drivers/media/usb/dvb-usb/digitv.c
@@ -33,6 +33,9 @@ static int digitv_ctrl_msg(struct dvb_usb_device *d,
wo = (rbuf == NULL || rlen == 0); /* write-only */
+ if (wlen > 4 || rlen > 4)
+ return -EIO;
+
memset(st->sndbuf, 0, 7);
memset(st->rcvbuf, 0, 7);
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
index 4f42d57f81d9..6e654e5026dd 100644
--- a/drivers/media/usb/dvb-usb/dw2102.c
+++ b/drivers/media/usb/dvb-usb/dw2102.c
@@ -204,6 +204,20 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
switch (num) {
case 2:
+ if (msg[0].len != 1) {
+ warn("i2c rd: len=%d is not 1!\n",
+ msg[0].len);
+ num = -EOPNOTSUPP;
+ break;
+ }
+
+ if (2 + msg[1].len > sizeof(buf6)) {
+ warn("i2c rd: len=%d is too big!\n",
+ msg[1].len);
+ num = -EOPNOTSUPP;
+ break;
+ }
+
/* read si2109 register by number */
buf6[0] = msg[0].addr << 1;
buf6[1] = msg[0].len;
@@ -219,6 +233,13 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
case 1:
switch (msg[0].addr) {
case 0x68:
+ if (2 + msg[0].len > sizeof(buf6)) {
+ warn("i2c wr: len=%d is too big!\n",
+ msg[0].len);
+ num = -EOPNOTSUPP;
+ break;
+ }
+
/* write to si2109 register */
buf6[0] = msg[0].addr << 1;
buf6[1] = msg[0].len;
@@ -262,6 +283,13 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
/* first write first register number */
u8 ibuf[MAX_XFER_SIZE], obuf[3];
+ if (2 + msg[0].len != sizeof(obuf)) {
+ warn("i2c rd: len=%d is not 1!\n",
+ msg[0].len);
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
+
if (2 + msg[1].len > sizeof(ibuf)) {
warn("i2c rd: len=%d is too big!\n",
msg[1].len);
@@ -462,6 +490,12 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
/* first write first register number */
u8 ibuf[MAX_XFER_SIZE], obuf[3];
+ if (2 + msg[0].len != sizeof(obuf)) {
+ warn("i2c rd: len=%d is not 1!\n",
+ msg[0].len);
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
if (2 + msg[1].len > sizeof(ibuf)) {
warn("i2c rd: len=%d is too big!\n",
msg[1].len);
@@ -696,6 +730,13 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
msg[0].buf[0] = state->data[1];
break;
default:
+ if (3 + msg[0].len > sizeof(state->data)) {
+ warn("i2c wr: len=%d is too big!\n",
+ msg[0].len);
+ num = -EOPNOTSUPP;
+ break;
+ }
+
/* always i2c write*/
state->data[0] = 0x08;
state->data[1] = msg[0].addr;
@@ -711,6 +752,19 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
break;
case 2:
/* always i2c read */
+ if (4 + msg[0].len > sizeof(state->data)) {
+ warn("i2c rd: len=%d is too big!\n",
+ msg[0].len);
+ num = -EOPNOTSUPP;
+ break;
+ }
+ if (1 + msg[1].len > sizeof(state->data)) {
+ warn("i2c rd: len=%d is too big!\n",
+ msg[1].len);
+ num = -EOPNOTSUPP;
+ break;
+ }
+
state->data[0] = 0x09;
state->data[1] = msg[0].len;
state->data[2] = msg[1].len;
diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c
index ecc207fbaf3c..9e0d6a4166d2 100644
--- a/drivers/media/usb/dvb-usb/ttusb2.c
+++ b/drivers/media/usb/dvb-usb/ttusb2.c
@@ -78,6 +78,9 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
u8 *s, *r = NULL;
int ret = 0;
+ if (4 + rlen > 64)
+ return -EIO;
+
s = kzalloc(wlen+4, GFP_KERNEL);
if (!s)
return -ENOMEM;
@@ -381,6 +384,22 @@ static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
read = msg[i].flags & I2C_M_RD;
+ if (3 + msg[i].len > sizeof(obuf)) {
+ err("i2c wr len=%d too high", msg[i].len);
+ break;
+ }
+ if (write_read) {
+ if (3 + msg[i+1].len > sizeof(ibuf)) {
+ err("i2c rd len=%d too high", msg[i+1].len);
+ break;
+ }
+ } else if (read) {
+ if (3 + msg[i].len > sizeof(ibuf)) {
+ err("i2c rd len=%d too high", msg[i].len);
+ break;
+ }
+ }
+
obuf[0] = (msg[i].addr << 1) | (write_read | read);
if (read)
obuf[1] = 0;
diff --git a/drivers/media/usb/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig
index aa131cf9989b..4cc029f18aa8 100644
--- a/drivers/media/usb/em28xx/Kconfig
+++ b/drivers/media/usb/em28xx/Kconfig
@@ -12,7 +12,7 @@ config VIDEO_EM28XX_V4L2
select VIDEO_TVP5150 if MEDIA_SUBDRV_AUTOSELECT
select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT
select VIDEO_MT9V011 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_CAMERA_SUPPORT
-
+ select VIDEO_OV2640 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_CAMERA_SUPPORT
---help---
This is a video4linux driver for Empia 28xx based TV cards.
@@ -39,6 +39,7 @@ config VIDEO_EM28XX_DVB
depends on VIDEO_EM28XX && DVB_CORE
select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_LGDT3306A if MEDIA_SUBDRV_AUTOSELECT
select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT
select DVB_S921 if MEDIA_SUBDRV_AUTOSELECT
@@ -61,6 +62,10 @@ config VIDEO_EM28XX_DVB
select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
select DVB_TC90522 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_QM1D1C0042 if MEDIA_SUBDRV_AUTOSELECT
+ select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
+ select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
+ select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
+ select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
---help---
This adds support for DVB cards based on the
Empiatech em28xx chips.
diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c
index 89c890ba7dd6..ae87dd3e671f 100644
--- a/drivers/media/usb/em28xx/em28xx-camera.c
+++ b/drivers/media/usb/em28xx/em28xx-camera.c
@@ -23,9 +23,7 @@
#include <linux/i2c.h>
#include <linux/usb.h>
-#include <media/soc_camera.h>
#include <media/i2c/mt9v011.h>
-#include <media/v4l2-clk.h>
#include <media/v4l2-common.h>
/* Possible i2c addresses of Micron sensors */
@@ -43,13 +41,6 @@ static unsigned short omnivision_sensor_addrs[] = {
I2C_CLIENT_END
};
-static struct soc_camera_link camlink = {
- .bus_id = 0,
- .flags = 0,
- .module_name = "em28xx",
- .unbalanced_power = true,
-};
-
/* FIXME: Should be replaced by a proper mt9m111 driver */
static int em28xx_initialize_mt9m111(struct em28xx *dev)
{
@@ -106,55 +97,35 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev)
{
int ret, i;
char *name;
- u8 reg;
- __be16 id_be;
u16 id;
- struct i2c_client client = dev->i2c_client[dev->def_i2c_bus];
+ struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus];
dev->em28xx_sensor = EM28XX_NOSENSOR;
for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) {
- client.addr = micron_sensor_addrs[i];
- /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */
+ client->addr = micron_sensor_addrs[i];
/* Read chip ID from register 0x00 */
- reg = 0x00;
- ret = i2c_master_send(&client, &reg, 1);
+ ret = i2c_smbus_read_word_data(client, 0x00); /* assumes LE */
if (ret < 0) {
if (ret != -ENXIO)
dev_err(&dev->intf->dev,
"couldn't read from i2c device 0x%02x: error %i\n",
- client.addr << 1, ret);
- continue;
- }
- ret = i2c_master_recv(&client, (u8 *)&id_be, 2);
- if (ret < 0) {
- dev_err(&dev->intf->dev,
- "couldn't read from i2c device 0x%02x: error %i\n",
- client.addr << 1, ret);
+ client->addr << 1, ret);
continue;
}
- id = be16_to_cpu(id_be);
+ id = swab16(ret); /* LE -> BE */
/* Read chip ID from register 0xff */
- reg = 0xff;
- ret = i2c_master_send(&client, &reg, 1);
+ ret = i2c_smbus_read_word_data(client, 0xff);
if (ret < 0) {
dev_err(&dev->intf->dev,
"couldn't read from i2c device 0x%02x: error %i\n",
- client.addr << 1, ret);
- continue;
- }
- ret = i2c_master_recv(&client, (u8 *)&id_be, 2);
- if (ret < 0) {
- dev_err(&dev->intf->dev,
- "couldn't read from i2c device 0x%02x: error %i\n",
- client.addr << 1, ret);
+ client->addr << 1, ret);
continue;
}
/* Validate chip ID to be sure we have a Micron device */
- if (id != be16_to_cpu(id_be))
+ if (id != swab16(ret))
continue;
/* Check chip ID */
- id = be16_to_cpu(id_be);
switch (id) {
case 0x1222:
name = "MT9V012"; /* MI370 */ /* 640x480 */
@@ -197,7 +168,6 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev)
dev_info(&dev->intf->dev,
"sensor %s detected\n", name);
- dev->i2c_client[dev->def_i2c_bus].addr = client.addr;
return 0;
}
@@ -213,30 +183,30 @@ static int em28xx_probe_sensor_omnivision(struct em28xx *dev)
char *name;
u8 reg;
u16 id;
- struct i2c_client client = dev->i2c_client[dev->def_i2c_bus];
+ struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus];
dev->em28xx_sensor = EM28XX_NOSENSOR;
/* NOTE: these devices have the register auto incrementation disabled
* by default, so we have to use single byte reads ! */
for (i = 0; omnivision_sensor_addrs[i] != I2C_CLIENT_END; i++) {
- client.addr = omnivision_sensor_addrs[i];
+ client->addr = omnivision_sensor_addrs[i];
/* Read manufacturer ID from registers 0x1c-0x1d (BE) */
reg = 0x1c;
- ret = i2c_smbus_read_byte_data(&client, reg);
+ ret = i2c_smbus_read_byte_data(client, reg);
if (ret < 0) {
if (ret != -ENXIO)
dev_err(&dev->intf->dev,
"couldn't read from i2c device 0x%02x: error %i\n",
- client.addr << 1, ret);
+ client->addr << 1, ret);
continue;
}
id = ret << 8;
reg = 0x1d;
- ret = i2c_smbus_read_byte_data(&client, reg);
+ ret = i2c_smbus_read_byte_data(client, reg);
if (ret < 0) {
dev_err(&dev->intf->dev,
"couldn't read from i2c device 0x%02x: error %i\n",
- client.addr << 1, ret);
+ client->addr << 1, ret);
continue;
}
id += ret;
@@ -245,20 +215,20 @@ static int em28xx_probe_sensor_omnivision(struct em28xx *dev)
continue;
/* Read product ID from registers 0x0a-0x0b (BE) */
reg = 0x0a;
- ret = i2c_smbus_read_byte_data(&client, reg);
+ ret = i2c_smbus_read_byte_data(client, reg);
if (ret < 0) {
dev_err(&dev->intf->dev,
"couldn't read from i2c device 0x%02x: error %i\n",
- client.addr << 1, ret);
+ client->addr << 1, ret);
continue;
}
id = ret << 8;
reg = 0x0b;
- ret = i2c_smbus_read_byte_data(&client, reg);
+ ret = i2c_smbus_read_byte_data(client, reg);
if (ret < 0) {
dev_err(&dev->intf->dev,
"couldn't read from i2c device 0x%02x: error %i\n",
- client.addr << 1, ret);
+ client->addr << 1, ret);
continue;
}
id += ret;
@@ -309,7 +279,6 @@ static int em28xx_probe_sensor_omnivision(struct em28xx *dev)
dev_info(&dev->intf->dev,
"sensor %s detected\n", name);
- dev->i2c_client[dev->def_i2c_bus].addr = client.addr;
return 0;
}
@@ -341,17 +310,9 @@ int em28xx_detect_sensor(struct em28xx *dev)
int em28xx_init_camera(struct em28xx *dev)
{
- char clk_name[V4L2_CLK_NAME_SIZE];
struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus];
struct i2c_adapter *adap = &dev->i2c_adap[dev->def_i2c_bus];
struct em28xx_v4l2 *v4l2 = dev->v4l2;
- int ret = 0;
-
- v4l2_clk_name_i2c(clk_name, sizeof(clk_name),
- i2c_adapter_id(adap), client->addr);
- v4l2->clk = v4l2_clk_register_fixed(clk_name, -EINVAL);
- if (IS_ERR(v4l2->clk))
- return PTR_ERR(v4l2->clk);
switch (dev->em28xx_sensor) {
case EM28XX_MT9V011:
@@ -381,12 +342,9 @@ int em28xx_init_camera(struct em28xx *dev)
pdata.xtal = v4l2->sensor_xtal;
if (NULL ==
v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
- &mt9v011_info, NULL)) {
- ret = -ENODEV;
- break;
- }
- /* probably means GRGB 16 bit bayer */
- v4l2->vinmode = 0x0d;
+ &mt9v011_info, NULL))
+ return -ENODEV;
+ v4l2->vinmode = EM28XX_VINMODE_RGB8_GRBG;
v4l2->vinctl = 0x00;
break;
@@ -397,8 +355,7 @@ int em28xx_init_camera(struct em28xx *dev)
em28xx_initialize_mt9m001(dev);
- /* probably means BGGR 16 bit bayer */
- v4l2->vinmode = 0x0c;
+ v4l2->vinmode = EM28XX_VINMODE_RGB8_BGGR;
v4l2->vinctl = 0x00;
break;
@@ -410,7 +367,7 @@ int em28xx_init_camera(struct em28xx *dev)
em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
em28xx_initialize_mt9m111(dev);
- v4l2->vinmode = 0x0a;
+ v4l2->vinmode = EM28XX_VINMODE_YUV422_UYVY;
v4l2->vinctl = 0x00;
break;
@@ -421,7 +378,6 @@ int em28xx_init_camera(struct em28xx *dev)
.type = "ov2640",
.flags = I2C_CLIENT_SCCB,
.addr = client->addr,
- .platform_data = &camlink,
};
struct v4l2_subdev_format format = {
.which = V4L2_SUBDEV_FORMAT_ACTIVE,
@@ -441,10 +397,8 @@ int em28xx_init_camera(struct em28xx *dev)
subdev =
v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap,
&ov2640_info, NULL);
- if (NULL == subdev) {
- ret = -ENODEV;
- break;
- }
+ if (subdev == NULL)
+ return -ENODEV;
format.format.code = MEDIA_BUS_FMT_YUYV8_2X8;
format.format.width = 640;
@@ -454,21 +408,16 @@ int em28xx_init_camera(struct em28xx *dev)
/* NOTE: for UXGA=1600x1200 switch to 12MHz */
dev->board.xclk = EM28XX_XCLK_FREQUENCY_24MHZ;
em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk);
- v4l2->vinmode = 0x08;
+ v4l2->vinmode = EM28XX_VINMODE_YUV422_YUYV;
v4l2->vinctl = 0x00;
break;
}
case EM28XX_NOSENSOR:
default:
- ret = -EINVAL;
+ return -EINVAL;
}
- if (ret < 0) {
- v4l2_clk_unregister_fixed(v4l2->clk);
- v4l2->clk = NULL;
- }
-
- return ret;
+ return 0;
}
EXPORT_SYMBOL_GPL(em28xx_init_camera);
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index 5f90d0899a45..a12b599a1fa2 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -2600,6 +2600,8 @@ struct usb_device_id em28xx_id_table[] = {
.driver_info = EM28178_BOARD_TERRATEC_T2_STICK_HD },
{ USB_DEVICE(0x3275, 0x0085),
.driver_info = EM28178_BOARD_PLEX_PX_BCUD },
+ { USB_DEVICE(0xeb1a, 0x5051), /* Ion Video 2 PC MKII / Startech svid2usb23 / Raygo R12-41373 */
+ .driver_info = EM2860_BOARD_TVP5150_REFERENCE_DESIGN },
{ },
};
MODULE_DEVICE_TABLE(usb, em28xx_id_table);
@@ -2917,7 +2919,9 @@ static void em28xx_card_setup(struct em28xx *dev)
* If sensor is not found, then it isn't a webcam.
*/
if (dev->board.is_webcam) {
- if (em28xx_detect_sensor(dev) < 0)
+ em28xx_detect_sensor(dev);
+ if (dev->em28xx_sensor == EM28XX_NOSENSOR)
+ /* NOTE: error/unknown sensor/no sensor */
dev->board.is_webcam = 0;
}
@@ -2974,8 +2978,7 @@ static void em28xx_card_setup(struct em28xx *dev)
#endif
/* Call first TVeeprom */
- dev->i2c_client[dev->def_i2c_bus].addr = 0xa0 >> 1;
- tveeprom_hauppauge_analog(&dev->i2c_client[dev->def_i2c_bus], &tv, dev->eedata);
+ tveeprom_hauppauge_analog(&tv, dev->eedata);
dev->tuner_type = tv.tuner_type;
@@ -3666,9 +3669,11 @@ static int em28xx_usb_probe(struct usb_interface *interface,
try_bulk = usb_xfer_mode > 0;
}
- /* Disable V4L2 if the device doesn't have a decoder */
+ /* Disable V4L2 if the device doesn't have a decoder or image sensor */
if (has_video &&
- dev->board.decoder == EM28XX_NODECODER && !dev->board.is_webcam) {
+ dev->board.decoder == EM28XX_NODECODER &&
+ dev->em28xx_sensor == EM28XX_NOSENSOR) {
+
dev_err(&interface->dev,
"Currently, V4L2 is not supported on this model\n");
has_video = false;
diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h
index afe7a66d7dc8..747525ca7ed5 100644
--- a/drivers/media/usb/em28xx/em28xx-reg.h
+++ b/drivers/media/usb/em28xx/em28xx-reg.h
@@ -93,6 +93,24 @@
#define EM28XX_XCLK_FREQUENCY_24MHZ 0x0b
#define EM28XX_R10_VINMODE 0x10
+ /* used by all non-camera devices: */
+#define EM28XX_VINMODE_YUV422_CbYCrY 0x10
+ /* used by camera devices: */
+#define EM28XX_VINMODE_YUV422_YUYV 0x08
+#define EM28XX_VINMODE_YUV422_YVYU 0x09
+#define EM28XX_VINMODE_YUV422_UYVY 0x0a
+#define EM28XX_VINMODE_YUV422_VYUY 0x0b
+#define EM28XX_VINMODE_RGB8_BGGR 0x0c
+#define EM28XX_VINMODE_RGB8_GRBG 0x0d
+#define EM28XX_VINMODE_RGB8_GBRG 0x0e
+#define EM28XX_VINMODE_RGB8_RGGB 0x0f
+ /*
+ * apparently:
+ * bit 0: swap component 1+2 with 3+4
+ * => e.g.: YUYV => YVYU, BGGR => GRBG
+ * bit 1: swap component 1 with 2 and 3 with 4
+ * => e.g.: YUYV => UYVY, BGGR => GBRG
+ */
#define EM28XX_R11_VINCTRL 0x11
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 8d93100334ea..8d253a5df0a9 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -43,7 +43,6 @@
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-event.h>
-#include <media/v4l2-clk.h>
#include <media/drv-intf/msp3400.h>
#include <media/tuner.h>
@@ -117,6 +116,11 @@ static struct em28xx_fmt format[] = {
.depth = 16,
.reg = EM28XX_OUTFMT_RGB_16_656,
}, {
+ .name = "8 bpp Bayer RGRG..GBGB",
+ .fourcc = V4L2_PIX_FMT_SRGGB8,
+ .depth = 8,
+ .reg = EM28XX_OUTFMT_RGB_8_RGRG,
+ }, {
.name = "8 bpp Bayer BGBG..GRGR",
.fourcc = V4L2_PIX_FMT_SBGGR8,
.depth = 8,
@@ -2140,11 +2144,6 @@ static int em28xx_v4l2_fini(struct em28xx *dev)
v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
v4l2_device_unregister(&v4l2->v4l2_dev);
- if (v4l2->clk) {
- v4l2_clk_unregister_fixed(v4l2->clk);
- v4l2->clk = NULL;
- }
-
kref_put(&v4l2->ref, em28xx_free_v4l2);
mutex_unlock(&dev->lock);
@@ -2465,7 +2464,7 @@ static int em28xx_v4l2_init(struct em28xx *dev)
/*
* Default format, used for tvp5150 or saa711x output formats
*/
- v4l2->vinmode = 0x10;
+ v4l2->vinmode = EM28XX_VINMODE_YUV422_CbYCrY;
v4l2->vinctl = EM28XX_VINCTRL_INTERLACED |
EM28XX_VINCTRL_CCIR656_ENABLE;
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index e9f379959fa5..e8d97d5ec161 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -510,7 +510,6 @@ struct em28xx_v4l2 {
struct v4l2_device v4l2_dev;
struct v4l2_ctrl_handler ctrl_handler;
- struct v4l2_clk *clk;
struct video_device vdev;
struct video_device vbi_dev;
diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c
index 4eaba0c24629..ed5ec9773969 100644
--- a/drivers/media/usb/go7007/go7007-v4l2.c
+++ b/drivers/media/usb/go7007/go7007-v4l2.c
@@ -792,14 +792,13 @@ static int vidioc_subscribe_event(struct v4l2_fh *fh,
{
switch (sub->type) {
- case V4L2_EVENT_CTRL:
- return v4l2_ctrl_subscribe_event(fh, sub);
case V4L2_EVENT_MOTION_DET:
/* Allow for up to 30 events (1 second for NTSC) to be
* stored. */
return v4l2_event_subscribe(fh, sub, 30, NULL);
+ default:
+ return v4l2_ctrl_subscribe_event(fh, sub);
}
- return -EINVAL;
}
diff --git a/drivers/media/usb/gspca/konica.c b/drivers/media/usb/gspca/konica.c
index 71f273377f83..31b2117e8f1d 100644
--- a/drivers/media/usb/gspca/konica.c
+++ b/drivers/media/usb/gspca/konica.c
@@ -184,6 +184,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
return -EIO;
}
+ if (alt->desc.bNumEndpoints < 2)
+ return -ENODEV;
+
packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
n = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
diff --git a/drivers/media/usb/pulse8-cec/Kconfig b/drivers/media/usb/pulse8-cec/Kconfig
index 6ffc407de62f..8937f3986a01 100644
--- a/drivers/media/usb/pulse8-cec/Kconfig
+++ b/drivers/media/usb/pulse8-cec/Kconfig
@@ -1,6 +1,6 @@
config USB_PULSE8_CEC
tristate "Pulse Eight HDMI CEC"
- depends on USB_ACM && MEDIA_CEC_SUPPORT
+ depends on USB_ACM && CEC_CORE
select SERIO
select SERIO_SERPORT
---help---
diff --git a/drivers/media/usb/pulse8-cec/pulse8-cec.c b/drivers/media/usb/pulse8-cec/pulse8-cec.c
index 7c18daeb0ade..1dfc2de1fe77 100644
--- a/drivers/media/usb/pulse8-cec/pulse8-cec.c
+++ b/drivers/media/usb/pulse8-cec/pulse8-cec.c
@@ -461,7 +461,7 @@ static int pulse8_apply_persistent_config(struct pulse8 *pulse8,
static int pulse8_cec_adap_enable(struct cec_adapter *adap, bool enable)
{
- struct pulse8 *pulse8 = adap->priv;
+ struct pulse8 *pulse8 = cec_get_drvdata(adap);
u8 cmd[16];
int err;
@@ -474,7 +474,7 @@ static int pulse8_cec_adap_enable(struct cec_adapter *adap, bool enable)
static int pulse8_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
{
- struct pulse8 *pulse8 = adap->priv;
+ struct pulse8 *pulse8 = cec_get_drvdata(adap);
u16 mask = 0;
u16 pa = adap->phys_addr;
u8 cmd[16];
@@ -594,7 +594,7 @@ unlock:
static int pulse8_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
u32 signal_free_time, struct cec_msg *msg)
{
- struct pulse8 *pulse8 = adap->priv;
+ struct pulse8 *pulse8 = cec_get_drvdata(adap);
u8 cmd[2];
unsigned int i;
int err;
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
index 4af2fb5c85d5..8b643d511a0b 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
@@ -118,15 +118,10 @@ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw)
memset(&tvdata,0,sizeof(tvdata));
eeprom = pvr2_eeprom_fetch(hdw);
- if (!eeprom) return -EINVAL;
-
- {
- struct i2c_client fake_client;
- /* Newer version expects a useless client interface */
- fake_client.addr = hdw->eeprom_addr;
- fake_client.adapter = &hdw->i2c_adap;
- tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom);
- }
+ if (!eeprom)
+ return -EINVAL;
+
+ tveeprom_hauppauge_analog(&tvdata, eeprom);
trace_eeprom("eeprom assumed v4l tveeprom module");
trace_eeprom("eeprom direct call results:");
diff --git a/drivers/media/usb/rainshadow-cec/Kconfig b/drivers/media/usb/rainshadow-cec/Kconfig
new file mode 100644
index 000000000000..3eb86607efb8
--- /dev/null
+++ b/drivers/media/usb/rainshadow-cec/Kconfig
@@ -0,0 +1,10 @@
+config USB_RAINSHADOW_CEC
+ tristate "RainShadow Tech HDMI CEC"
+ depends on USB_ACM && CEC_CORE
+ select SERIO
+ select SERIO_SERPORT
+ ---help---
+ This is a cec driver for the RainShadow Tech HDMI CEC device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rainshadow-cec.
diff --git a/drivers/media/usb/rainshadow-cec/Makefile b/drivers/media/usb/rainshadow-cec/Makefile
new file mode 100644
index 000000000000..a79fbc77e1f7
--- /dev/null
+++ b/drivers/media/usb/rainshadow-cec/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_RAINSHADOW_CEC) += rainshadow-cec.o
diff --git a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c
new file mode 100644
index 000000000000..541ca543f71f
--- /dev/null
+++ b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c
@@ -0,0 +1,388 @@
+/*
+ * RainShadow Tech HDMI CEC driver
+ *
+ * Copyright 2016 Hans Verkuil <hverkuil@xs4all.nl
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version of 2 of the License, or (at your
+ * option) any later version. See the file COPYING in the main directory of
+ * this archive for more details.
+ */
+
+/*
+ * Notes:
+ *
+ * The higher level protocols are currently disabled. This can be added
+ * later, similar to how this is done for the Pulse Eight CEC driver.
+ *
+ * Documentation of the protocol is available here:
+ *
+ * http://rainshadowtech.com/doc/HDMICECtoUSBandRS232v2.0.pdf
+ */
+
+#include <linux/completion.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <linux/workqueue.h>
+
+#include <media/cec.h>
+
+MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>");
+MODULE_DESCRIPTION("RainShadow Tech HDMI CEC driver");
+MODULE_LICENSE("GPL");
+
+#define DATA_SIZE 256
+
+struct rain {
+ struct device *dev;
+ struct serio *serio;
+ struct cec_adapter *adap;
+ struct completion cmd_done;
+ struct work_struct work;
+
+ /* Low-level ringbuffer, collecting incoming characters */
+ char buf[DATA_SIZE];
+ unsigned int buf_rd_idx;
+ unsigned int buf_wr_idx;
+ unsigned int buf_len;
+ spinlock_t buf_lock;
+
+ /* command buffer */
+ char cmd[DATA_SIZE];
+ unsigned int cmd_idx;
+ bool cmd_started;
+
+ /* reply to a command, only used to store the firmware version */
+ char cmd_reply[DATA_SIZE];
+
+ struct mutex write_lock;
+};
+
+static void rain_process_msg(struct rain *rain)
+{
+ struct cec_msg msg = {};
+ const char *cmd = rain->cmd + 3;
+ int stat = -1;
+
+ for (; *cmd; cmd++) {
+ if (!isxdigit(*cmd))
+ continue;
+ if (isxdigit(cmd[0]) && isxdigit(cmd[1])) {
+ if (msg.len == CEC_MAX_MSG_SIZE)
+ break;
+ if (hex2bin(msg.msg + msg.len, cmd, 1))
+ continue;
+ msg.len++;
+ cmd++;
+ continue;
+ }
+ if (!cmd[1])
+ stat = hex_to_bin(cmd[0]);
+ break;
+ }
+
+ if (rain->cmd[0] == 'R') {
+ if (stat == 1 || stat == 2)
+ cec_received_msg(rain->adap, &msg);
+ return;
+ }
+
+ switch (stat) {
+ case 1:
+ cec_transmit_done(rain->adap, CEC_TX_STATUS_OK,
+ 0, 0, 0, 0);
+ break;
+ case 2:
+ cec_transmit_done(rain->adap, CEC_TX_STATUS_NACK,
+ 0, 1, 0, 0);
+ break;
+ default:
+ cec_transmit_done(rain->adap, CEC_TX_STATUS_LOW_DRIVE,
+ 0, 0, 0, 1);
+ break;
+ }
+}
+
+static void rain_irq_work_handler(struct work_struct *work)
+{
+ struct rain *rain =
+ container_of(work, struct rain, work);
+
+ while (true) {
+ unsigned long flags;
+ bool exit_loop;
+ char data;
+
+ spin_lock_irqsave(&rain->buf_lock, flags);
+ exit_loop = rain->buf_len == 0;
+ if (rain->buf_len) {
+ data = rain->buf[rain->buf_rd_idx];
+ rain->buf_len--;
+ rain->buf_rd_idx = (rain->buf_rd_idx + 1) & 0xff;
+ }
+ spin_unlock_irqrestore(&rain->buf_lock, flags);
+
+ if (exit_loop)
+ break;
+
+ if (!rain->cmd_started && data != '?')
+ continue;
+
+ switch (data) {
+ case '\r':
+ rain->cmd[rain->cmd_idx] = '\0';
+ dev_dbg(rain->dev, "received: %s\n", rain->cmd);
+ if (!memcmp(rain->cmd, "REC", 3) ||
+ !memcmp(rain->cmd, "STA", 3)) {
+ rain_process_msg(rain);
+ } else {
+ strcpy(rain->cmd_reply, rain->cmd);
+ complete(&rain->cmd_done);
+ }
+ rain->cmd_idx = 0;
+ rain->cmd_started = false;
+ break;
+
+ case '\n':
+ rain->cmd_idx = 0;
+ rain->cmd_started = false;
+ break;
+
+ case '?':
+ rain->cmd_idx = 0;
+ rain->cmd_started = true;
+ break;
+
+ default:
+ if (rain->cmd_idx >= DATA_SIZE - 1) {
+ dev_dbg(rain->dev,
+ "throwing away %d bytes of garbage\n", rain->cmd_idx);
+ rain->cmd_idx = 0;
+ }
+ rain->cmd[rain->cmd_idx++] = data;
+ break;
+ }
+ }
+}
+
+static irqreturn_t rain_interrupt(struct serio *serio, unsigned char data,
+ unsigned int flags)
+{
+ struct rain *rain = serio_get_drvdata(serio);
+
+ if (rain->buf_len == DATA_SIZE) {
+ dev_warn_once(rain->dev, "buffer overflow\n");
+ return IRQ_HANDLED;
+ }
+ spin_lock(&rain->buf_lock);
+ rain->buf_len++;
+ rain->buf[rain->buf_wr_idx] = data;
+ rain->buf_wr_idx = (rain->buf_wr_idx + 1) & 0xff;
+ spin_unlock(&rain->buf_lock);
+ schedule_work(&rain->work);
+ return IRQ_HANDLED;
+}
+
+static void rain_disconnect(struct serio *serio)
+{
+ struct rain *rain = serio_get_drvdata(serio);
+
+ cancel_work_sync(&rain->work);
+ cec_unregister_adapter(rain->adap);
+ dev_info(&serio->dev, "disconnected\n");
+ serio_close(serio);
+ serio_set_drvdata(serio, NULL);
+ kfree(rain);
+}
+
+static int rain_send(struct rain *rain, const char *command)
+{
+ int err = serio_write(rain->serio, '!');
+
+ dev_dbg(rain->dev, "send: %s\n", command);
+ while (!err && *command)
+ err = serio_write(rain->serio, *command++);
+ if (!err)
+ err = serio_write(rain->serio, '~');
+
+ return err;
+}
+
+static int rain_send_and_wait(struct rain *rain,
+ const char *cmd, const char *reply)
+{
+ int err;
+
+ init_completion(&rain->cmd_done);
+
+ mutex_lock(&rain->write_lock);
+ err = rain_send(rain, cmd);
+ if (err)
+ goto err;
+
+ if (!wait_for_completion_timeout(&rain->cmd_done, HZ)) {
+ err = -ETIMEDOUT;
+ goto err;
+ }
+ if (reply && strncmp(rain->cmd_reply, reply, strlen(reply))) {
+ dev_dbg(rain->dev,
+ "transmit of '%s': received '%s' instead of '%s'\n",
+ cmd, rain->cmd_reply, reply);
+ err = -EIO;
+ }
+err:
+ mutex_unlock(&rain->write_lock);
+ return err;
+}
+
+static int rain_setup(struct rain *rain, struct serio *serio,
+ struct cec_log_addrs *log_addrs, u16 *pa)
+{
+ int err;
+
+ err = rain_send_and_wait(rain, "R", "REV");
+ if (err)
+ return err;
+ dev_info(rain->dev, "Firmware version %s\n", rain->cmd_reply + 4);
+
+ err = rain_send_and_wait(rain, "Q 1", "QTY");
+ if (err)
+ return err;
+ err = rain_send_and_wait(rain, "c0000", "CFG");
+ if (err)
+ return err;
+ return rain_send_and_wait(rain, "A F 0000", "ADR");
+}
+
+static int rain_cec_adap_enable(struct cec_adapter *adap, bool enable)
+{
+ return 0;
+}
+
+static int rain_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
+{
+ struct rain *rain = cec_get_drvdata(adap);
+ u8 cmd[16];
+
+ if (log_addr == CEC_LOG_ADDR_INVALID)
+ log_addr = CEC_LOG_ADDR_UNREGISTERED;
+ snprintf(cmd, sizeof(cmd), "A %x", log_addr);
+ return rain_send_and_wait(rain, cmd, "ADR");
+}
+
+static int rain_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
+ u32 signal_free_time, struct cec_msg *msg)
+{
+ struct rain *rain = cec_get_drvdata(adap);
+ char cmd[2 * CEC_MAX_MSG_SIZE + 16];
+ unsigned int i;
+ int err;
+
+ if (msg->len == 1) {
+ snprintf(cmd, sizeof(cmd), "x%x", cec_msg_destination(msg));
+ } else {
+ char hex[3];
+
+ snprintf(cmd, sizeof(cmd), "x%x %02x ",
+ cec_msg_destination(msg), msg->msg[1]);
+ for (i = 2; i < msg->len; i++) {
+ snprintf(hex, sizeof(hex), "%02x", msg->msg[i]);
+ strncat(cmd, hex, sizeof(cmd));
+ }
+ }
+ mutex_lock(&rain->write_lock);
+ err = rain_send(rain, cmd);
+ mutex_unlock(&rain->write_lock);
+ return err;
+}
+
+static const struct cec_adap_ops rain_cec_adap_ops = {
+ .adap_enable = rain_cec_adap_enable,
+ .adap_log_addr = rain_cec_adap_log_addr,
+ .adap_transmit = rain_cec_adap_transmit,
+};
+
+static int rain_connect(struct serio *serio, struct serio_driver *drv)
+{
+ u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS | CEC_CAP_PHYS_ADDR |
+ CEC_CAP_PASSTHROUGH | CEC_CAP_RC | CEC_CAP_MONITOR_ALL;
+ struct rain *rain;
+ int err = -ENOMEM;
+ struct cec_log_addrs log_addrs = {};
+ u16 pa = CEC_PHYS_ADDR_INVALID;
+
+ rain = kzalloc(sizeof(*rain), GFP_KERNEL);
+
+ if (!rain)
+ return -ENOMEM;
+
+ rain->serio = serio;
+ rain->adap = cec_allocate_adapter(&rain_cec_adap_ops, rain,
+ "HDMI CEC", caps, 1);
+ err = PTR_ERR_OR_ZERO(rain->adap);
+ if (err < 0)
+ goto free_device;
+
+ rain->dev = &serio->dev;
+ serio_set_drvdata(serio, rain);
+ INIT_WORK(&rain->work, rain_irq_work_handler);
+ mutex_init(&rain->write_lock);
+
+ err = serio_open(serio, drv);
+ if (err)
+ goto delete_adap;
+
+ err = rain_setup(rain, serio, &log_addrs, &pa);
+ if (err)
+ goto close_serio;
+
+ err = cec_register_adapter(rain->adap, &serio->dev);
+ if (err < 0)
+ goto close_serio;
+
+ rain->dev = &rain->adap->devnode.dev;
+ return 0;
+
+close_serio:
+ serio_close(serio);
+delete_adap:
+ cec_delete_adapter(rain->adap);
+ serio_set_drvdata(serio, NULL);
+free_device:
+ kfree(rain);
+ return err;
+}
+
+static struct serio_device_id rain_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_RAINSHADOW_CEC,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, rain_serio_ids);
+
+static struct serio_driver rain_drv = {
+ .driver = {
+ .name = "rainshadow-cec",
+ },
+ .description = "RainShadow Tech HDMI CEC driver",
+ .id_table = rain_serio_ids,
+ .interrupt = rain_interrupt,
+ .connect = rain_connect,
+ .disconnect = rain_disconnect,
+};
+
+module_serio_driver(rain_drv);
diff --git a/drivers/media/usb/stk1160/Kconfig b/drivers/media/usb/stk1160/Kconfig
index 22dff4f3b921..425ed00e2599 100644
--- a/drivers/media/usb/stk1160/Kconfig
+++ b/drivers/media/usb/stk1160/Kconfig
@@ -6,7 +6,11 @@ config VIDEO_STK1160_COMMON
This is a video4linux driver for STK1160 based video capture devices.
To compile this driver as a module, choose M here: the
- module will be called stk1160
+ module will be called stk1160.
+
+ This driver only provides support for video capture. For audio
+ capture, you need to select the snd-usb-audio driver (i.e.
+ CONFIG_SND_USB_AUDIO).
config VIDEO_STK1160
tristate
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c
index c4fdc1fa32ef..7e960d0a5b92 100644
--- a/drivers/media/usb/tm6000/tm6000-video.c
+++ b/drivers/media/usb/tm6000/tm6000-video.c
@@ -631,7 +631,7 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev)
urb = usb_alloc_urb(max_packets, GFP_KERNEL);
if (!urb) {
tm6000_uninit_isoc(dev);
- usb_free_urb(urb);
+ tm6000_free_urb_buffers(dev);
return -ENOMEM;
}
dev->isoc_ctl.urb[i] = urb;
diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c
index f5c635a67d74..f9c3325aa4d4 100644
--- a/drivers/media/usb/usbvision/usbvision-video.c
+++ b/drivers/media/usb/usbvision/usbvision-video.c
@@ -1501,7 +1501,14 @@ static int usbvision_probe(struct usb_interface *intf,
}
for (i = 0; i < usbvision->num_alt; i++) {
- u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
+ u16 tmp;
+
+ if (uif->altsetting[i].desc.bNumEndpoints < 2) {
+ ret = -ENODEV;
+ goto err_pkt;
+ }
+
+ tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
wMaxPacketSize);
usbvision->alt_max_pkt_size[i] =
(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 04bf35063c4c..46d6be0bb316 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -188,6 +188,21 @@ static struct uvc_format_desc uvc_fmts[] = {
.guid = UVC_GUID_FORMAT_GR16,
.fcc = V4L2_PIX_FMT_SGRBG16,
},
+ {
+ .name = "Depth data 16-bit (Z16)",
+ .guid = UVC_GUID_FORMAT_INVZ,
+ .fcc = V4L2_PIX_FMT_Z16,
+ },
+ {
+ .name = "Greyscale 10-bit (Y10 )",
+ .guid = UVC_GUID_FORMAT_INVI,
+ .fcc = V4L2_PIX_FMT_Y10,
+ },
+ {
+ .name = "IR:Depth 26-bit (INZI)",
+ .guid = UVC_GUID_FORMAT_INZI,
+ .fcc = V4L2_PIX_FMT_INZI,
+ },
};
/* ------------------------------------------------------------------------
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 07a6c833ef7b..47d93a938dde 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -818,7 +818,7 @@ static void uvc_video_stats_decode(struct uvc_streaming *stream,
/* Update the packets counters. */
stream->stats.frame.nb_packets++;
- if (len > header_size)
+ if (len <= header_size)
stream->stats.frame.nb_empty++;
if (data[1] & UVC_STREAM_ERR)
@@ -868,14 +868,8 @@ size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf,
struct timespec ts;
size_t count = 0;
- ts.tv_sec = stream->stats.stream.stop_ts.tv_sec
- - stream->stats.stream.start_ts.tv_sec;
- ts.tv_nsec = stream->stats.stream.stop_ts.tv_nsec
- - stream->stats.stream.start_ts.tv_nsec;
- if (ts.tv_nsec < 0) {
- ts.tv_sec--;
- ts.tv_nsec += 1000000000;
- }
+ ts = timespec_sub(stream->stats.stream.stop_ts,
+ stream->stats.stream.start_ts);
/* Compute the SCR.SOF frequency estimate. At the nominal 1kHz SOF
* frequency this will not overflow before more than 1h.
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 4205e7a423f0..15e415e32c7f 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -143,6 +143,15 @@
#define UVC_GUID_FORMAT_RW10 \
{ 'R', 'W', '1', '0', 0x00, 0x00, 0x10, 0x00, \
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_INVZ \
+ { 'I', 'N', 'V', 'Z', 0x90, 0x2d, 0x58, 0x4a, \
+ 0x92, 0x0b, 0x77, 0x3f, 0x1f, 0x2c, 0x55, 0x6b}
+#define UVC_GUID_FORMAT_INZI \
+ { 'I', 'N', 'Z', 'I', 0x66, 0x1a, 0x42, 0xa2, \
+ 0x90, 0x65, 0xd0, 0x18, 0x14, 0xa8, 0xef, 0x8a}
+#define UVC_GUID_FORMAT_INVI \
+ { 'I', 'N', 'V', 'I', 0xdb, 0x57, 0x49, 0x5e, \
+ 0x8e, 0x3f, 0xf4, 0x79, 0x53, 0x2b, 0x94, 0x6f}
/* ------------------------------------------------------------------------
* Driver specific constants.
diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c
index f2d6fc03dda0..efdcd5bd6a4c 100644
--- a/drivers/media/usb/zr364xx/zr364xx.c
+++ b/drivers/media/usb/zr364xx/zr364xx.c
@@ -600,6 +600,14 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam,
ptr = pdest = frm->lpvbits;
if (frm->ulState == ZR364XX_READ_IDLE) {
+ if (purb->actual_length < 128) {
+ /* header incomplete */
+ dev_info(&cam->udev->dev,
+ "%s: buffer (%d bytes) too small to hold jpeg header. Discarding.\n",
+ __func__, purb->actual_length);
+ return -EINVAL;
+ }
+
frm->ulState = ZR364XX_READ_FRAME;
frm->cur_size = 0;