提交 9e6235e9 编写于 作者: L Linus Torvalds

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (45 commits)
  V4L/DVB (10411): s5h1409: Perform s5h1409 soft reset after tuning
  V4L/DVB (10403): saa7134-alsa: saa7130 doesn't support digital audio
  V4L/DVB (10229): ivtv: fix memory leak
  V4L/DVB (10385): gspca - main: Fix memory leak when USB disconnection while streaming.
  V4L/DVB (10325): em28xx: Fix for fail to submit URB with IRQs and Pre-emption Disabled
  V4L/DVB (10317): radio-mr800: fix radio->muted and radio->stereo
  V4L/DVB (10314): cx25840: ignore TUNER_SET_CONFIG in the command callback.
  V4L/DVB (10288): af9015: bug fix: stick does not work always when plugged
  V4L/DVB (10287): af9015: fix second FE
  V4L/DVB (10270): saa7146: fix unbalanced mutex_lock/unlock
  V4L/DVB (10265): budget.c driver: Kernel oops: "BUG: unable to handle kernel paging request at ffffffff
  V4L/DVB (10261): em28xx: fix kernel panic on audio shutdown
  V4L/DVB (10257): em28xx: Fix for KWorld 330U Board
  V4L/DVB (10256): em28xx: Fix for KWorld 330U AC97
  V4L/DVB (10254): em28xx: Fix audio URB transfer buffer race condition
  V4L/DVB (10250): cx25840: fix regression: fw not loaded on first use
  V4L/DVB (10248): v4l-dvb: fix a bunch of compile warnings.
  V4L/DVB (10243): em28xx: fix compile warning
  V4L/DVB (10240): Fix obvious swapped names in v4l2_subdev logic
  V4L/DVB (10233): [PATCH] Terratec Cinergy DT XS Diversity new USB ID (0ccd:0081)
  ...
...@@ -4,12 +4,21 @@ ...@@ -4,12 +4,21 @@
* *
* Compile with: * Compile with:
* gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab * gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
* Use as: * Use as:
* v4lgrab >image.ppm * v4lgrab >image.ppm
* *
* Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org> * Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
* Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
* with minor modifications (Dave Forrest, drf5n@virginia.edu). * with minor modifications (Dave Forrest, drf5n@virginia.edu).
*
*
* For some cameras you may need to pre-load libv4l to perform
* the necessary decompression, e.g.:
*
* export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so
* ./v4lgrab >image.ppm
*
* see http://hansdegoede.livejournal.com/3636.html for details.
* *
*/ */
...@@ -24,7 +33,7 @@ ...@@ -24,7 +33,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/videodev.h> #include <linux/videodev.h>
#define FILE "/dev/video0" #define VIDEO_DEV "/dev/video0"
/* Stole this from tvset.c */ /* Stole this from tvset.c */
...@@ -90,7 +99,7 @@ int get_brightness_adj(unsigned char *image, long size, int *brightness) { ...@@ -90,7 +99,7 @@ int get_brightness_adj(unsigned char *image, long size, int *brightness) {
int main(int argc, char ** argv) int main(int argc, char ** argv)
{ {
int fd = open(FILE, O_RDONLY), f; int fd = open(VIDEO_DEV, O_RDONLY), f;
struct video_capability cap; struct video_capability cap;
struct video_window win; struct video_window win;
struct video_picture vpic; struct video_picture vpic;
...@@ -100,13 +109,13 @@ int main(int argc, char ** argv) ...@@ -100,13 +109,13 @@ int main(int argc, char ** argv)
unsigned int i, src_depth; unsigned int i, src_depth;
if (fd < 0) { if (fd < 0) {
perror(FILE); perror(VIDEO_DEV);
exit(1); exit(1);
} }
if (ioctl(fd, VIDIOCGCAP, &cap) < 0) { if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
perror("VIDIOGCAP"); perror("VIDIOGCAP");
fprintf(stderr, "(" FILE " not a video4linux device?)\n"); fprintf(stderr, "(" VIDEO_DEV " not a video4linux device?)\n");
close(fd); close(fd);
exit(1); exit(1);
} }
......
...@@ -576,6 +576,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) ...@@ -576,6 +576,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
vv->vflip = c->value; vv->vflip = c->value;
break; break;
default: { default: {
mutex_unlock(&dev->lock);
return -EINVAL; return -EINVAL;
} }
} }
......
...@@ -657,7 +657,7 @@ static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status) ...@@ -657,7 +657,7 @@ static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status)
{ {
struct mxl5007t_state *state = fe->tuner_priv; struct mxl5007t_state *state = fe->tuner_priv;
int rf_locked, ref_locked; int rf_locked, ref_locked;
s32 rf_input_level; s32 rf_input_level = 0;
int ret; int ret;
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
......
...@@ -93,6 +93,9 @@ struct dvb_ca_slot { ...@@ -93,6 +93,9 @@ struct dvb_ca_slot {
/* current state of the CAM */ /* current state of the CAM */
int slot_state; int slot_state;
/* mutex used for serializing access to one CI slot */
struct mutex slot_lock;
/* Number of CAMCHANGES that have occurred since last processing */ /* Number of CAMCHANGES that have occurred since last processing */
atomic_t camchange_count; atomic_t camchange_count;
...@@ -711,14 +714,20 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b ...@@ -711,14 +714,20 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
// sanity check /* sanity check */
if (bytes_write > ca->slot_info[slot].link_buf_size) if (bytes_write > ca->slot_info[slot].link_buf_size)
return -EINVAL; return -EINVAL;
/* check if interface is actually waiting for us to read from it, or if a read is in progress */ /* it is possible we are dealing with a single buffer implementation,
thus if there is data available for read or if there is even a read
already in progress, we do nothing but awake the kernel thread to
process the data if necessary. */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
goto exitnowrite; goto exitnowrite;
if (status & (STATUSREG_DA | STATUSREG_RE)) { if (status & (STATUSREG_DA | STATUSREG_RE)) {
if (status & STATUSREG_DA)
dvb_ca_en50221_thread_wakeup(ca);
status = -EAGAIN; status = -EAGAIN;
goto exitnowrite; goto exitnowrite;
} }
...@@ -987,6 +996,8 @@ static int dvb_ca_en50221_thread(void *data) ...@@ -987,6 +996,8 @@ static int dvb_ca_en50221_thread(void *data)
/* go through all the slots processing them */ /* go through all the slots processing them */
for (slot = 0; slot < ca->slot_count; slot++) { for (slot = 0; slot < ca->slot_count; slot++) {
mutex_lock(&ca->slot_info[slot].slot_lock);
// check the cam status + deal with CAMCHANGEs // check the cam status + deal with CAMCHANGEs
while (dvb_ca_en50221_check_camstatus(ca, slot)) { while (dvb_ca_en50221_check_camstatus(ca, slot)) {
/* clear down an old CI slot if necessary */ /* clear down an old CI slot if necessary */
...@@ -1122,7 +1133,7 @@ static int dvb_ca_en50221_thread(void *data) ...@@ -1122,7 +1133,7 @@ static int dvb_ca_en50221_thread(void *data)
case DVB_CA_SLOTSTATE_RUNNING: case DVB_CA_SLOTSTATE_RUNNING:
if (!ca->open) if (!ca->open)
continue; break;
// poll slots for data // poll slots for data
pktcount = 0; pktcount = 0;
...@@ -1146,6 +1157,8 @@ static int dvb_ca_en50221_thread(void *data) ...@@ -1146,6 +1157,8 @@ static int dvb_ca_en50221_thread(void *data)
} }
break; break;
} }
mutex_unlock(&ca->slot_info[slot].slot_lock);
} }
} }
...@@ -1181,6 +1194,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, ...@@ -1181,6 +1194,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
switch (cmd) { switch (cmd) {
case CA_RESET: case CA_RESET:
for (slot = 0; slot < ca->slot_count; slot++) { for (slot = 0; slot < ca->slot_count; slot++) {
mutex_lock(&ca->slot_info[slot].slot_lock);
if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) { if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) {
dvb_ca_en50221_slot_shutdown(ca, slot); dvb_ca_en50221_slot_shutdown(ca, slot);
if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)
...@@ -1188,6 +1202,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, ...@@ -1188,6 +1202,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
slot, slot,
DVB_CA_EN50221_CAMCHANGE_INSERTED); DVB_CA_EN50221_CAMCHANGE_INSERTED);
} }
mutex_unlock(&ca->slot_info[slot].slot_lock);
} }
ca->next_read_slot = 0; ca->next_read_slot = 0;
dvb_ca_en50221_thread_wakeup(ca); dvb_ca_en50221_thread_wakeup(ca);
...@@ -1308,7 +1323,9 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file, ...@@ -1308,7 +1323,9 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
goto exit; goto exit;
} }
mutex_lock(&ca->slot_info[slot].slot_lock);
status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2); status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2);
mutex_unlock(&ca->slot_info[slot].slot_lock);
if (status == (fraglen + 2)) { if (status == (fraglen + 2)) {
written = 1; written = 1;
break; break;
...@@ -1664,6 +1681,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, ...@@ -1664,6 +1681,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE;
atomic_set(&ca->slot_info[i].camchange_count, 0); atomic_set(&ca->slot_info[i].camchange_count, 0);
ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED;
mutex_init(&ca->slot_info[i].slot_lock);
} }
if (signal_pending(current)) { if (signal_pending(current)) {
......
...@@ -45,8 +45,10 @@ struct dvb_ca_en50221 { ...@@ -45,8 +45,10 @@ struct dvb_ca_en50221 {
/* the module owning this structure */ /* the module owning this structure */
struct module* owner; struct module* owner;
/* NOTE: the read_*, write_* and poll_slot_status functions must use locks as /* NOTE: the read_*, write_* and poll_slot_status functions will be
* they may be called from several threads at once */ * called for different slots concurrently and need to use locks where
* and if appropriate. There will be no concurrent access to one slot.
*/
/* functions for accessing attribute memory on the CAM */ /* functions for accessing attribute memory on the CAM */
int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address); int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address);
......
...@@ -220,7 +220,7 @@ static int af9005_get_post_vit_ber(struct dvb_frontend *fe, ...@@ -220,7 +220,7 @@ static int af9005_get_post_vit_ber(struct dvb_frontend *fe,
u16 * abort_count) u16 * abort_count)
{ {
u32 loc_cw_count = 0, loc_err_count; u32 loc_cw_count = 0, loc_err_count;
u16 loc_abort_count; u16 loc_abort_count = 0;
int ret; int ret;
ret = ret =
......
...@@ -694,7 +694,12 @@ static int af9015_read_config(struct usb_device *udev) ...@@ -694,7 +694,12 @@ static int af9015_read_config(struct usb_device *udev)
/* IR remote controller */ /* IR remote controller */
req.addr = AF9015_EEPROM_IR_MODE; req.addr = AF9015_EEPROM_IR_MODE;
ret = af9015_rw_udev(udev, &req); /* first message will timeout often due to possible hw bug */
for (i = 0; i < 4; i++) {
ret = af9015_rw_udev(udev, &req);
if (!ret)
break;
}
if (ret) if (ret)
goto error; goto error;
deb_info("%s: IR mode:%d\n", __func__, val); deb_info("%s: IR mode:%d\n", __func__, val);
...@@ -835,18 +840,19 @@ static int af9015_read_config(struct usb_device *udev) ...@@ -835,18 +840,19 @@ static int af9015_read_config(struct usb_device *udev)
if (!dvb_usb_af9015_dual_mode) if (!dvb_usb_af9015_dual_mode)
af9015_config.dual_mode = 0; af9015_config.dual_mode = 0;
/* set buffer size according to USB port speed */ /* Set adapter0 buffer size according to USB port speed, adapter1 buffer
size can be static because it is enabled only USB2.0 */
for (i = 0; i < af9015_properties_count; i++) { for (i = 0; i < af9015_properties_count; i++) {
/* USB1.1 set smaller buffersize and disable 2nd adapter */ /* USB1.1 set smaller buffersize and disable 2nd adapter */
if (udev->speed == USB_SPEED_FULL) { if (udev->speed == USB_SPEED_FULL) {
af9015_properties[i].adapter->stream.u.bulk.buffersize = af9015_properties[i].adapter[0].stream.u.bulk.buffersize
TS_USB11_MAX_PACKET_SIZE; = TS_USB11_MAX_PACKET_SIZE;
/* disable 2nd adapter because we don't have /* disable 2nd adapter because we don't have
PID-filters */ PID-filters */
af9015_config.dual_mode = 0; af9015_config.dual_mode = 0;
} else { } else {
af9015_properties[i].adapter->stream.u.bulk.buffersize = af9015_properties[i].adapter[0].stream.u.bulk.buffersize
TS_USB20_MAX_PACKET_SIZE; = TS_USB20_MAX_PACKET_SIZE;
} }
} }
...@@ -1254,6 +1260,12 @@ static struct dvb_usb_device_properties af9015_properties[] = { ...@@ -1254,6 +1260,12 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.type = USB_BULK, .type = USB_BULK,
.count = 6, .count = 6,
.endpoint = 0x85, .endpoint = 0x85,
.u = {
.bulk = {
.buffersize =
TS_USB20_MAX_PACKET_SIZE,
}
}
}, },
} }
}, },
...@@ -1353,6 +1365,12 @@ static struct dvb_usb_device_properties af9015_properties[] = { ...@@ -1353,6 +1365,12 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.type = USB_BULK, .type = USB_BULK,
.count = 6, .count = 6,
.endpoint = 0x85, .endpoint = 0x85,
.u = {
.bulk = {
.buffersize =
TS_USB20_MAX_PACKET_SIZE,
}
}
}, },
} }
}, },
......
...@@ -1393,6 +1393,9 @@ struct usb_device_id dib0700_usb_id_table[] = { ...@@ -1393,6 +1393,9 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) }, { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) },
/* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) }, /* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) },
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E_SE) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E_SE) },
{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_EXPRESS) },
{ USB_DEVICE(USB_VID_TERRATEC,
USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2) },
{ 0 } /* Terminating entry */ { 0 } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
...@@ -1537,7 +1540,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { ...@@ -1537,7 +1540,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "DiBcom STK7700D reference design", { "DiBcom STK7700D reference design",
{ &dib0700_usb_id_table[14], NULL }, { &dib0700_usb_id_table[14], NULL },
{ NULL }, { NULL },
} },
}, },
.rc_interval = DEFAULT_RC_INTERVAL, .rc_interval = DEFAULT_RC_INTERVAL,
...@@ -1557,7 +1561,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { ...@@ -1557,7 +1561,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
}, },
}, },
.num_device_descs = 2, .num_device_descs = 3,
.devices = { .devices = {
{ "ASUS My Cinema U3000 Mini DVBT Tuner", { "ASUS My Cinema U3000 Mini DVBT Tuner",
{ &dib0700_usb_id_table[23], NULL }, { &dib0700_usb_id_table[23], NULL },
...@@ -1566,6 +1570,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { ...@@ -1566,6 +1570,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "Yuan EC372S", { "Yuan EC372S",
{ &dib0700_usb_id_table[31], NULL }, { &dib0700_usb_id_table[31], NULL },
{ NULL }, { NULL },
},
{ "Terratec Cinergy T Express",
{ &dib0700_usb_id_table[42], NULL },
{ NULL },
} }
}, },
...@@ -1653,7 +1661,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { ...@@ -1653,7 +1661,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
} }
}, },
.num_device_descs = 4, .num_device_descs = 5,
.devices = { .devices = {
{ "DiBcom STK7070PD reference design", { "DiBcom STK7070PD reference design",
{ &dib0700_usb_id_table[17], NULL }, { &dib0700_usb_id_table[17], NULL },
...@@ -1670,6 +1678,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { ...@@ -1670,6 +1678,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "Hauppauge Nova-TD-500 (84xxx)", { "Hauppauge Nova-TD-500 (84xxx)",
{ &dib0700_usb_id_table[36], NULL }, { &dib0700_usb_id_table[36], NULL },
{ NULL }, { NULL },
},
{ "Terratec Cinergy DT USB XS Diversity",
{ &dib0700_usb_id_table[43], NULL },
{ NULL },
} }
} }
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
......
...@@ -162,8 +162,10 @@ ...@@ -162,8 +162,10 @@
#define USB_PID_AVERMEDIA_A309 0xa309 #define USB_PID_AVERMEDIA_A309 0xa309
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058
#define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060 #define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060
#define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062
#define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078
#define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e
#define USB_PID_PINNACLE_PCTV2000E 0x022c #define USB_PID_PINNACLE_PCTV2000E 0x022c
......
...@@ -646,7 +646,7 @@ static int drx_tune(struct drx397xD_state *s, ...@@ -646,7 +646,7 @@ static int drx_tune(struct drx397xD_state *s,
u32 edi = 0, ebx = 0, ebp = 0, edx = 0; u32 edi = 0, ebx = 0, ebp = 0, edx = 0;
u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0; u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0;
int rc, df_tuner; int rc, df_tuner = 0;
int a, b, c, d; int a, b, c, d;
pr_debug("%s %d\n", __func__, s->config.d60); pr_debug("%s %d\n", __func__, s->config.d60);
......
...@@ -545,9 +545,6 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe, ...@@ -545,9 +545,6 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe,
s5h1409_enable_modulation(fe, p->u.vsb.modulation); s5h1409_enable_modulation(fe, p->u.vsb.modulation);
/* Allow the demod to settle */
msleep(100);
if (fe->ops.tuner_ops.set_params) { if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.i2c_gate_ctrl(fe, 1);
...@@ -562,6 +559,10 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe, ...@@ -562,6 +559,10 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe,
s5h1409_set_qam_interleave_mode(fe); s5h1409_set_qam_interleave_mode(fe);
} }
/* Issue a reset to the demod so it knows to resync against the
newly tuned frequency */
s5h1409_softreset(fe);
return 0; return 0;
} }
......
...@@ -31,6 +31,8 @@ inline u32 stb0899_do_div(u64 n, u32 d) ...@@ -31,6 +31,8 @@ inline u32 stb0899_do_div(u64 n, u32 d)
return n; return n;
} }
#if 0
/* These functions are currently unused */
/* /*
* stb0899_calc_srate * stb0899_calc_srate
* Compute symbol rate * Compute symbol rate
...@@ -63,6 +65,7 @@ static u32 stb0899_get_srate(struct stb0899_state *state) ...@@ -63,6 +65,7 @@ static u32 stb0899_get_srate(struct stb0899_state *state)
return stb0899_calc_srate(internal->master_clk, sfr); return stb0899_calc_srate(internal->master_clk, sfr);
} }
#endif
/* /*
* stb0899_set_srate * stb0899_set_srate
......
...@@ -470,6 +470,7 @@ static void frontend_init(struct budget *budget) ...@@ -470,6 +470,7 @@ static void frontend_init(struct budget *budget)
budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap); budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap);
if (budget->dvb_frontend) { if (budget->dvb_frontend) {
budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
budget->dvb_frontend->tuner_priv = NULL;
break; break;
} }
break; break;
......
...@@ -1384,7 +1384,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) ...@@ -1384,7 +1384,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
static int ttusb_dec_init_stb(struct ttusb_dec *dec) static int ttusb_dec_init_stb(struct ttusb_dec *dec)
{ {
int result; int result;
unsigned int mode, model, version; unsigned int mode = 0, model = 0, version = 0;
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
......
...@@ -194,10 +194,10 @@ static int amradio_start(struct amradio_device *radio) ...@@ -194,10 +194,10 @@ static int amradio_start(struct amradio_device *radio)
return retval; return retval;
} }
mutex_unlock(&radio->lock);
radio->muted = 0; radio->muted = 0;
mutex_unlock(&radio->lock);
return retval; return retval;
} }
...@@ -230,10 +230,10 @@ static int amradio_stop(struct amradio_device *radio) ...@@ -230,10 +230,10 @@ static int amradio_stop(struct amradio_device *radio)
return retval; return retval;
} }
mutex_unlock(&radio->lock);
radio->muted = 1; radio->muted = 1;
mutex_unlock(&radio->lock);
return retval; return retval;
} }
...@@ -284,10 +284,10 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) ...@@ -284,10 +284,10 @@ static int amradio_setfreq(struct amradio_device *radio, int freq)
return retval; return retval;
} }
mutex_unlock(&radio->lock);
radio->stereo = 0; radio->stereo = 0;
mutex_unlock(&radio->lock);
return retval; return retval;
} }
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
*/ */
#include <linux/version.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/i2c.h> #include <linux/i2c.h>
......
...@@ -1586,7 +1586,8 @@ static int mpeg_open(struct file *file) ...@@ -1586,7 +1586,8 @@ static int mpeg_open(struct file *file)
lock_kernel(); lock_kernel();
list_for_each(list, &cx23885_devlist) { list_for_each(list, &cx23885_devlist) {
h = list_entry(list, struct cx23885_dev, devlist); h = list_entry(list, struct cx23885_dev, devlist);
if (h->v4l_device->minor == minor) { if (h->v4l_device &&
h->v4l_device->minor == minor) {
dev = h; dev = h;
break; break;
} }
......
...@@ -730,12 +730,13 @@ static int video_open(struct file *file) ...@@ -730,12 +730,13 @@ static int video_open(struct file *file)
lock_kernel(); lock_kernel();
list_for_each(list, &cx23885_devlist) { list_for_each(list, &cx23885_devlist) {
h = list_entry(list, struct cx23885_dev, devlist); h = list_entry(list, struct cx23885_dev, devlist);
if (h->video_dev->minor == minor) { if (h->video_dev &&
h->video_dev->minor == minor) {
dev = h; dev = h;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE; type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
} }
if (h->vbi_dev && if (h->vbi_dev &&
h->vbi_dev->minor == minor) { h->vbi_dev->minor == minor) {
dev = h; dev = h;
type = V4L2_BUF_TYPE_VBI_CAPTURE; type = V4L2_BUF_TYPE_VBI_CAPTURE;
} }
......
...@@ -1382,6 +1382,14 @@ static int cx25840_log_status(struct v4l2_subdev *sd) ...@@ -1382,6 +1382,14 @@ static int cx25840_log_status(struct v4l2_subdev *sd)
static int cx25840_command(struct i2c_client *client, unsigned cmd, void *arg) static int cx25840_command(struct i2c_client *client, unsigned cmd, void *arg)
{ {
/* ignore this command */
if (cmd == TUNER_SET_TYPE_ADDR || cmd == TUNER_SET_CONFIG)
return 0;
/* Old-style drivers rely on initialization on first use, so
call the init whenever a command is issued to this driver.
New-style drivers using v4l2_subdev should call init explicitly. */
cx25840_init(i2c_get_clientdata(client), 0);
return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
} }
......
...@@ -614,34 +614,41 @@ static struct stv0288_config tevii_tuner_earda_config = { ...@@ -614,34 +614,41 @@ static struct stv0288_config tevii_tuner_earda_config = {
.set_ts_params = cx24116_set_ts_param, .set_ts_params = cx24116_set_ts_param,
}; };
static int dvb_register(struct cx8802_dev *dev) static int cx8802_alloc_frontends(struct cx8802_dev *dev)
{ {
struct cx88_core *core = dev->core; struct cx88_core *core = dev->core;
struct videobuf_dvb_frontend *fe0, *fe1 = NULL; struct videobuf_dvb_frontend *fe = NULL;
int mfe_shared = 0; /* bus not shared by default */
int i; int i;
if (0 != core->i2c_rc) {
printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name);
goto frontend_detach;
}
if (!core->board.num_frontends)
return -EINVAL;
mutex_init(&dev->frontends.lock); mutex_init(&dev->frontends.lock);
INIT_LIST_HEAD(&dev->frontends.felist); INIT_LIST_HEAD(&dev->frontends.felist);
if (!core->board.num_frontends)
return -ENODEV;
printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
core->board.num_frontends); core->board.num_frontends);
for (i = 1; i <= core->board.num_frontends; i++) { for (i = 1; i <= core->board.num_frontends; i++) {
fe0 = videobuf_dvb_alloc_frontend(&dev->frontends, i); fe = videobuf_dvb_alloc_frontend(&dev->frontends, i);
if (!fe0) { if (!fe) {
printk(KERN_ERR "%s() failed to alloc\n", __func__); printk(KERN_ERR "%s() failed to alloc\n", __func__);
videobuf_dvb_dealloc_frontends(&dev->frontends); videobuf_dvb_dealloc_frontends(&dev->frontends);
goto frontend_detach; return -ENOMEM;
} }
} }
return 0;
}
static int dvb_register(struct cx8802_dev *dev)
{
struct cx88_core *core = dev->core;
struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
int mfe_shared = 0; /* bus not shared by default */
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 */ /* Get the first frontend */
fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
...@@ -1243,6 +1250,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) ...@@ -1243,6 +1250,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
struct cx88_core *core = drv->core; struct cx88_core *core = drv->core;
struct cx8802_dev *dev = drv->core->dvbdev; struct cx8802_dev *dev = drv->core->dvbdev;
int err; int err;
struct videobuf_dvb_frontend *fe;
int i;
dprintk( 1, "%s\n", __func__); dprintk( 1, "%s\n", __func__);
dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
...@@ -1258,39 +1267,34 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) ...@@ -1258,39 +1267,34 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
/* If vp3054 isn't enabled, a stub will just return 0 */ /* If vp3054 isn't enabled, a stub will just return 0 */
err = vp3054_i2c_probe(dev); err = vp3054_i2c_probe(dev);
if (0 != err) if (0 != err)
goto fail_probe; goto fail_core;
/* dvb stuff */ /* dvb stuff */
printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
dev->ts_gen_cntrl = 0x0c; dev->ts_gen_cntrl = 0x0c;
err = cx8802_alloc_frontends(dev);
if (err)
goto fail_core;
err = -ENODEV; err = -ENODEV;
if (core->board.num_frontends) { for (i = 1; i <= core->board.num_frontends; i++) {
struct videobuf_dvb_frontend *fe; fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
int i; if (fe == NULL) {
printk(KERN_ERR "%s() failed to get frontend(%d)\n",
for (i = 1; i <= core->board.num_frontends; i++) {
fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
if (fe == NULL) {
printk(KERN_ERR "%s() failed to get frontend(%d)\n",
__func__, i); __func__, i);
goto fail_probe; goto fail_probe;
} }
videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops, videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
&dev->pci->dev, &dev->slock, &dev->pci->dev, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_TOP, V4L2_FIELD_TOP,
sizeof(struct cx88_buffer), sizeof(struct cx88_buffer),
dev); dev);
/* init struct videobuf_dvb */ /* init struct videobuf_dvb */
fe->dvb.name = dev->core->name; fe->dvb.name = dev->core->name;
}
} else {
/* no frontends allocated */
printk(KERN_ERR "%s/2 .num_frontends should be non-zero\n",
core->name);
goto fail_core;
} }
err = dvb_register(dev); err = dvb_register(dev);
if (err) if (err)
/* frontends/adapter de-allocated in dvb_register */ /* frontends/adapter de-allocated in dvb_register */
......
...@@ -336,8 +336,8 @@ struct cx88_core { ...@@ -336,8 +336,8 @@ struct cx88_core {
/* config info -- dvb */ /* config info -- dvb */
#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
int (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); int (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
void (*gate_ctrl)(struct cx88_core *core, int open);
#endif #endif
void (*gate_ctrl)(struct cx88_core *core, int open);
/* state info */ /* state info */
struct task_struct *kthread; struct task_struct *kthread;
......
...@@ -62,9 +62,15 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) ...@@ -62,9 +62,15 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev)
dprintk("Stopping isoc\n"); dprintk("Stopping isoc\n");
for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
usb_unlink_urb(dev->adev.urb[i]); if (!irqs_disabled())
usb_kill_urb(dev->adev.urb[i]);
else
usb_unlink_urb(dev->adev.urb[i]);
usb_free_urb(dev->adev.urb[i]); usb_free_urb(dev->adev.urb[i]);
dev->adev.urb[i] = NULL; dev->adev.urb[i] = NULL;
kfree(dev->adev.transfer_buffer[i]);
dev->adev.transfer_buffer[i] = NULL;
} }
return 0; return 0;
...@@ -389,11 +395,15 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, ...@@ -389,11 +395,15 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream,
static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream
*substream) *substream)
{ {
struct em28xx *dev; unsigned long flags;
struct em28xx *dev;
snd_pcm_uframes_t hwptr_done; snd_pcm_uframes_t hwptr_done;
dev = snd_pcm_substream_chip(substream); dev = snd_pcm_substream_chip(substream);
spin_lock_irqsave(&dev->adev.slock, flags);
hwptr_done = dev->adev.hwptr_done_capture; hwptr_done = dev->adev.hwptr_done_capture;
spin_unlock_irqrestore(&dev->adev.slock, flags);
return hwptr_done; return hwptr_done;
} }
......
...@@ -102,6 +102,18 @@ static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { ...@@ -102,6 +102,18 @@ static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = {
/* Board - EM2870 Kworld 355u /* Board - EM2870 Kworld 355u
Analog - No input analog */ Analog - No input analog */
static struct em28xx_reg_seq kworld_330u_analog[] = {
{EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10},
{EM2880_R04_GPO, 0x00, 0xff, 10},
{ -1, -1, -1, -1},
};
static struct em28xx_reg_seq kworld_330u_digital[] = {
{EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10},
{EM2880_R04_GPO, 0x08, 0xff, 10},
{ -1, -1, -1, -1},
};
/* Callback for the most boards */ /* Callback for the most boards */
static struct em28xx_reg_seq default_tuner_gpio[] = { static struct em28xx_reg_seq default_tuner_gpio[] = {
{EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10},
...@@ -1177,29 +1189,33 @@ struct em28xx_board em28xx_boards[] = { ...@@ -1177,29 +1189,33 @@ struct em28xx_board em28xx_boards[] = {
.gpio = hauppauge_wintv_hvr_900_analog, .gpio = hauppauge_wintv_hvr_900_analog,
} }, } },
}, },
[EM2883_BOARD_KWORLD_HYBRID_A316] = { [EM2883_BOARD_KWORLD_HYBRID_330U] = {
.name = "Kworld PlusTV HD Hybrid 330", .name = "Kworld PlusTV HD Hybrid 330",
.tuner_type = TUNER_XC2028, .tuner_type = TUNER_XC2028,
.tuner_gpio = default_tuner_gpio, .tuner_gpio = default_tuner_gpio,
.decoder = EM28XX_TVP5150, .decoder = EM28XX_TVP5150,
.mts_firmware = 1, .mts_firmware = 1,
.has_dvb = 1, .has_dvb = 1,
.dvb_gpio = default_digital, .dvb_gpio = kworld_330u_digital,
.xclk = EM28XX_XCLK_FREQUENCY_12MHZ,
.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_EEPROM_ON_BOARD | EM28XX_I2C_EEPROM_KEY_VALID,
.input = { { .input = { {
.type = EM28XX_VMUX_TELEVISION, .type = EM28XX_VMUX_TELEVISION,
.vmux = TVP5150_COMPOSITE0, .vmux = TVP5150_COMPOSITE0,
.amux = EM28XX_AMUX_VIDEO, .amux = EM28XX_AMUX_VIDEO,
.gpio = default_analog, .gpio = kworld_330u_analog,
.aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
}, { }, {
.type = EM28XX_VMUX_COMPOSITE1, .type = EM28XX_VMUX_COMPOSITE1,
.vmux = TVP5150_COMPOSITE1, .vmux = TVP5150_COMPOSITE1,
.amux = EM28XX_AMUX_LINE_IN, .amux = EM28XX_AMUX_LINE_IN,
.gpio = hauppauge_wintv_hvr_900_analog, .gpio = kworld_330u_analog,
.aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
}, { }, {
.type = EM28XX_VMUX_SVIDEO, .type = EM28XX_VMUX_SVIDEO,
.vmux = TVP5150_SVIDEO, .vmux = TVP5150_SVIDEO,
.amux = EM28XX_AMUX_LINE_IN, .amux = EM28XX_AMUX_LINE_IN,
.gpio = hauppauge_wintv_hvr_900_analog, .gpio = kworld_330u_analog,
} }, } },
}, },
[EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = { [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = {
...@@ -1249,7 +1265,7 @@ struct usb_device_id em28xx_id_table [] = { ...@@ -1249,7 +1265,7 @@ struct usb_device_id em28xx_id_table [] = {
{ USB_DEVICE(0xeb1a, 0xe310), { USB_DEVICE(0xeb1a, 0xe310),
.driver_info = EM2880_BOARD_MSI_DIGIVOX_AD }, .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD },
{ USB_DEVICE(0xeb1a, 0xa316), { USB_DEVICE(0xeb1a, 0xa316),
.driver_info = EM2883_BOARD_KWORLD_HYBRID_A316 }, .driver_info = EM2883_BOARD_KWORLD_HYBRID_330U },
{ USB_DEVICE(0xeb1a, 0xe320), { USB_DEVICE(0xeb1a, 0xe320),
.driver_info = EM2880_BOARD_MSI_DIGIVOX_AD_II }, .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD_II },
{ USB_DEVICE(0xeb1a, 0xe323), { USB_DEVICE(0xeb1a, 0xe323),
...@@ -1526,6 +1542,10 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) ...@@ -1526,6 +1542,10 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
/* FIXME: Better to specify the needed IF */ /* FIXME: Better to specify the needed IF */
ctl->demod = XC3028_FE_DEFAULT; ctl->demod = XC3028_FE_DEFAULT;
break; break;
case EM2883_BOARD_KWORLD_HYBRID_330U:
ctl->demod = XC3028_FE_CHINA;
ctl->fname = XC2028_DEFAULT_FIRMWARE;
break;
default: default:
ctl->demod = XC3028_FE_OREN538; ctl->demod = XC3028_FE_OREN538;
} }
......
...@@ -438,6 +438,10 @@ int em28xx_audio_analog_set(struct em28xx *dev) ...@@ -438,6 +438,10 @@ int em28xx_audio_analog_set(struct em28xx *dev)
if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
int vol; int vol;
em28xx_write_ac97(dev, AC97_POWER_DOWN_CTRL, 0x4200);
em28xx_write_ac97(dev, AC97_EXT_AUD_CTRL, 0x0031);
em28xx_write_ac97(dev, AC97_PCM_IN_SRATE, 0xbb80);
/* LSB: left channel - both channels with the same level */ /* LSB: left channel - both channels with the same level */
vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8); vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8);
...@@ -454,6 +458,15 @@ int em28xx_audio_analog_set(struct em28xx *dev) ...@@ -454,6 +458,15 @@ int em28xx_audio_analog_set(struct em28xx *dev)
em28xx_warn("couldn't setup AC97 register %d\n", em28xx_warn("couldn't setup AC97 register %d\n",
outputs[i].reg); outputs[i].reg);
} }
if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) {
int sel = ac97_return_record_select(dev->ctl_aoutput);
/* Use the same input for both left and right channels */
sel |= (sel << 8);
em28xx_write_ac97(dev, AC97_RECORD_SELECT, sel);
}
} }
return ret; return ret;
...@@ -847,8 +860,11 @@ void em28xx_uninit_isoc(struct em28xx *dev) ...@@ -847,8 +860,11 @@ void em28xx_uninit_isoc(struct em28xx *dev)
for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
urb = dev->isoc_ctl.urb[i]; urb = dev->isoc_ctl.urb[i];
if (urb) { if (urb) {
usb_kill_urb(urb); if (!irqs_disabled())
usb_unlink_urb(urb); usb_kill_urb(urb);
else
usb_unlink_urb(urb);
if (dev->isoc_ctl.transfer_buffer[i]) { if (dev->isoc_ctl.transfer_buffer[i]) {
usb_buffer_free(dev->udev, usb_buffer_free(dev->udev,
urb->transfer_buffer_length, urb->transfer_buffer_length,
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "lgdt330x.h" #include "lgdt330x.h"
#include "zl10353.h" #include "zl10353.h"
#include "s5h1409.h"
#ifdef EM28XX_DRX397XD_SUPPORT #ifdef EM28XX_DRX397XD_SUPPORT
#include "drx397xD.h" #include "drx397xD.h"
#endif #endif
...@@ -232,6 +233,15 @@ static struct zl10353_config em28xx_zl10353_with_xc3028 = { ...@@ -232,6 +233,15 @@ static struct zl10353_config em28xx_zl10353_with_xc3028 = {
.if2 = 45600, .if2 = 45600,
}; };
static struct s5h1409_config em28xx_s5h1409_with_xc3028 = {
.demod_address = 0x32 >> 1,
.output_mode = S5H1409_PARALLEL_OUTPUT,
.gpio = S5H1409_GPIO_OFF,
.inversion = S5H1409_INVERSION_OFF,
.status_mode = S5H1409_DEMODLOCKING,
.mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
};
#ifdef EM28XX_DRX397XD_SUPPORT #ifdef EM28XX_DRX397XD_SUPPORT
/* [TODO] djh - not sure yet what the device config needs to contain */ /* [TODO] djh - not sure yet what the device config needs to contain */
static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { static struct drx397xD_config em28xx_drx397xD_with_xc3028 = {
...@@ -412,7 +422,6 @@ static int dvb_init(struct em28xx *dev) ...@@ -412,7 +422,6 @@ static int dvb_init(struct em28xx *dev)
case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
case EM2883_BOARD_KWORLD_HYBRID_A316:
case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
dvb->frontend = dvb_attach(lgdt330x_attach, dvb->frontend = dvb_attach(lgdt330x_attach,
&em2880_lgdt3303_dev, &em2880_lgdt3303_dev,
...@@ -433,6 +442,15 @@ static int dvb_init(struct em28xx *dev) ...@@ -433,6 +442,15 @@ static int dvb_init(struct em28xx *dev)
goto out_free; goto out_free;
} }
break; break;
case EM2883_BOARD_KWORLD_HYBRID_330U:
dvb->frontend = dvb_attach(s5h1409_attach,
&em28xx_s5h1409_with_xc3028,
&dev->i2c_adap);
if (attach_xc3028(0x61, dev) < 0) {
result = -EINVAL;
goto out_free;
}
break;
case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
#ifdef EM28XX_DRX397XD_SUPPORT #ifdef EM28XX_DRX397XD_SUPPORT
/* We don't have the config structure properly populated, so /* We don't have the config structure properly populated, so
......
...@@ -886,10 +886,10 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) ...@@ -886,10 +886,10 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
if (0 == INPUT(i)->type) if (0 == INPUT(i)->type)
return -EINVAL; return -EINVAL;
mutex_lock(&dev->lock); dev->ctl_input = i;
video_mux(dev, i);
mutex_lock(&dev->lock);
video_mux(dev, dev->ctl_input);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
return 0; return 0;
} }
...@@ -939,6 +939,12 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) ...@@ -939,6 +939,12 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
struct em28xx_fh *fh = priv; struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev; struct em28xx *dev = fh->dev;
if (a->index >= MAX_EM28XX_INPUT)
return -EINVAL;
if (0 == INPUT(a->index)->type)
return -EINVAL;
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
dev->ctl_ainput = INPUT(a->index)->amux; dev->ctl_ainput = INPUT(a->index)->amux;
...@@ -1950,6 +1956,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, ...@@ -1950,6 +1956,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
int em28xx_register_analog_devices(struct em28xx *dev) int em28xx_register_analog_devices(struct em28xx *dev)
{ {
u8 val;
int ret; int ret;
printk(KERN_INFO "%s: v4l2 driver version %d.%d.%d\n", printk(KERN_INFO "%s: v4l2 driver version %d.%d.%d\n",
...@@ -1957,34 +1964,34 @@ int em28xx_register_analog_devices(struct em28xx *dev) ...@@ -1957,34 +1964,34 @@ int em28xx_register_analog_devices(struct em28xx *dev)
(EM28XX_VERSION_CODE >> 16) & 0xff, (EM28XX_VERSION_CODE >> 16) & 0xff,
(EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff); (EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff);
/* set default norm */
dev->norm = em28xx_video_template.current_norm;
dev->width = norm_maxw(dev);
dev->height = norm_maxh(dev);
dev->interlaced = EM28XX_INTERLACED_DEFAULT;
dev->hscale = 0;
dev->vscale = 0;
dev->ctl_input = 0;
/* Analog specific initialization */ /* Analog specific initialization */
dev->format = &format[0]; dev->format = &format[0];
video_mux(dev, 0); video_mux(dev, dev->ctl_input);
/* Audio defaults */
dev->mute = 1;
dev->volume = 0x1f;
/* enable vbi capturing */ /* enable vbi capturing */
/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ /* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
/* em28xx_write_reg(dev, EM28XX_R0F_XCLK, 0x80); clk register */ val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
em28xx_write_reg(dev, EM28XX_R0F_XCLK, (EM28XX_XCLK_AUDIO_UNMUTE | val));
em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51); em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51);
dev->mute = 1; /* maybe not the right place... */
dev->volume = 0x1f;
em28xx_set_outfmt(dev); em28xx_set_outfmt(dev);
em28xx_colorlevels_set_default(dev); em28xx_colorlevels_set_default(dev);
em28xx_compression_disable(dev); em28xx_compression_disable(dev);
/* set default norm */
dev->norm = em28xx_video_template.current_norm;
dev->width = norm_maxw(dev);
dev->height = norm_maxh(dev);
dev->interlaced = EM28XX_INTERLACED_DEFAULT;
dev->hscale = 0;
dev->vscale = 0;
/* FIXME: This is a very bad hack! Not all devices have TV on input 2 */
dev->ctl_input = 2;
/* allocate and fill video video_device struct */ /* allocate and fill video video_device struct */
dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
if (!dev->vdev) { if (!dev->vdev) {
......
...@@ -94,7 +94,7 @@ ...@@ -94,7 +94,7 @@
#define EM2882_BOARD_KWORLD_VS_DVBT 54 #define EM2882_BOARD_KWORLD_VS_DVBT 54
#define EM2882_BOARD_TERRATEC_HYBRID_XS 55 #define EM2882_BOARD_TERRATEC_HYBRID_XS 55
#define EM2882_BOARD_PINNACLE_HYBRID_PRO 56 #define EM2882_BOARD_PINNACLE_HYBRID_PRO 56
#define EM2883_BOARD_KWORLD_HYBRID_A316 57 #define EM2883_BOARD_KWORLD_HYBRID_330U 57
#define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58 #define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58
#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60
#define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 #define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61
...@@ -300,13 +300,32 @@ enum em28xx_amux { ...@@ -300,13 +300,32 @@ enum em28xx_amux {
}; };
enum em28xx_aout { enum em28xx_aout {
/* AC97 outputs */
EM28XX_AOUT_MASTER = 1 << 0, EM28XX_AOUT_MASTER = 1 << 0,
EM28XX_AOUT_LINE = 1 << 1, EM28XX_AOUT_LINE = 1 << 1,
EM28XX_AOUT_MONO = 1 << 2, EM28XX_AOUT_MONO = 1 << 2,
EM28XX_AOUT_LFE = 1 << 3, EM28XX_AOUT_LFE = 1 << 3,
EM28XX_AOUT_SURR = 1 << 4, EM28XX_AOUT_SURR = 1 << 4,
/* PCM IN Mixer - used by AC97_RECORD_SELECT register */
EM28XX_AOUT_PCM_IN = 1 << 7,
/* Bits 10-8 are used to indicate the PCM IN record select */
EM28XX_AOUT_PCM_MIC_PCM = 0 << 8,
EM28XX_AOUT_PCM_CD = 1 << 8,
EM28XX_AOUT_PCM_VIDEO = 2 << 8,
EM28XX_AOUT_PCM_AUX = 3 << 8,
EM28XX_AOUT_PCM_LINE = 4 << 8,
EM28XX_AOUT_PCM_STEREO = 5 << 8,
EM28XX_AOUT_PCM_MONO = 6 << 8,
EM28XX_AOUT_PCM_PHONE = 7 << 8,
}; };
static inline int ac97_return_record_select(int a_out)
{
return (a_out & 0x700) >> 8;
}
struct em28xx_reg_seq { struct em28xx_reg_seq {
int reg; int reg;
unsigned char val, mask; unsigned char val, mask;
......
...@@ -423,7 +423,8 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) ...@@ -423,7 +423,8 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
break; break;
gspca_dev->urb[i] = NULL; gspca_dev->urb[i] = NULL;
usb_kill_urb(urb); if (!gspca_dev->present)
usb_kill_urb(urb);
if (urb->transfer_buffer != NULL) if (urb->transfer_buffer != NULL)
usb_buffer_free(gspca_dev->dev, usb_buffer_free(gspca_dev->dev,
urb->transfer_buffer_length, urb->transfer_buffer_length,
...@@ -1950,7 +1951,6 @@ void gspca_disconnect(struct usb_interface *intf) ...@@ -1950,7 +1951,6 @@ void gspca_disconnect(struct usb_interface *intf)
struct gspca_dev *gspca_dev = usb_get_intfdata(intf); struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
gspca_dev->present = 0; gspca_dev->present = 0;
gspca_dev->streaming = 0;
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
......
...@@ -949,8 +949,10 @@ static int __devinit ivtv_probe(struct pci_dev *dev, ...@@ -949,8 +949,10 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
itv->instance = atomic_inc_return(&ivtv_instance) - 1; itv->instance = atomic_inc_return(&ivtv_instance) - 1;
retval = v4l2_device_register(&dev->dev, &itv->device); retval = v4l2_device_register(&dev->dev, &itv->device);
if (retval) if (retval) {
kfree(itv);
return retval; return retval;
}
/* "ivtv + PCI ID" is a bit of a mouthful, so use /* "ivtv + PCI ID" is a bit of a mouthful, so use
"ivtv + instance" instead. */ "ivtv + instance" instead. */
snprintf(itv->device.name, sizeof(itv->device.name), snprintf(itv->device.name, sizeof(itv->device.name),
......
...@@ -62,7 +62,6 @@ ...@@ -62,7 +62,6 @@
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/version.h>
#include <asm/io.h> #include <asm/io.h>
#include "pwc.h" #include "pwc.h"
......
...@@ -149,7 +149,7 @@ static const struct i2c_reg_value saa7127_init_config_common[] = { ...@@ -149,7 +149,7 @@ static const struct i2c_reg_value saa7127_init_config_common[] = {
{ SAA7127_REG_COPYGEN_0, 0x77 }, { SAA7127_REG_COPYGEN_0, 0x77 },
{ SAA7127_REG_COPYGEN_1, 0x41 }, { SAA7127_REG_COPYGEN_1, 0x41 },
{ SAA7127_REG_COPYGEN_2, 0x00 }, /* Macrovision enable/disable */ { SAA7127_REG_COPYGEN_2, 0x00 }, /* Macrovision enable/disable */
{ SAA7127_REG_OUTPUT_PORT_CONTROL, 0x9e }, { SAA7127_REG_OUTPUT_PORT_CONTROL, 0xbf },
{ SAA7127_REG_GAIN_LUMINANCE_RGB, 0x00 }, { SAA7127_REG_GAIN_LUMINANCE_RGB, 0x00 },
{ SAA7127_REG_GAIN_COLORDIFF_RGB, 0x00 }, { SAA7127_REG_GAIN_COLORDIFF_RGB, 0x00 },
{ SAA7127_REG_INPUT_PORT_CONTROL_1, 0x80 }, /* for color bars */ { SAA7127_REG_INPUT_PORT_CONTROL_1, 0x80 }, /* for color bars */
...@@ -488,12 +488,18 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output) ...@@ -488,12 +488,18 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output)
break; break;
case SAA7127_OUTPUT_TYPE_COMPOSITE: case SAA7127_OUTPUT_TYPE_COMPOSITE:
state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */ if (state->ident == V4L2_IDENT_SAA7129)
state->reg_2d = 0x20; /* CVBS only */
else
state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */
state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */
break; break;
case SAA7127_OUTPUT_TYPE_SVIDEO: case SAA7127_OUTPUT_TYPE_SVIDEO:
state->reg_2d = 0xff; /* 11111111 croma -> R, luma -> CVBS + G + B */ if (state->ident == V4L2_IDENT_SAA7129)
state->reg_2d = 0x18; /* Y + C */
else
state->reg_2d = 0xff; /*11111111 croma -> R, luma -> CVBS + G + B */
state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */
break; break;
...@@ -508,7 +514,10 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output) ...@@ -508,7 +514,10 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output)
break; break;
case SAA7127_OUTPUT_TYPE_BOTH: case SAA7127_OUTPUT_TYPE_BOTH:
state->reg_2d = 0xbf; if (state->ident == V4L2_IDENT_SAA7129)
state->reg_2d = 0x38;
else
state->reg_2d = 0xbf;
state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */
break; break;
...@@ -731,24 +740,6 @@ static int saa7127_probe(struct i2c_client *client, ...@@ -731,24 +740,6 @@ static int saa7127_probe(struct i2c_client *client,
return -ENODEV; return -ENODEV;
} }
/* Configure Encoder */
v4l2_dbg(1, debug, sd, "Configuring encoder\n");
saa7127_write_inittab(sd, saa7127_init_config_common);
saa7127_set_std(sd, V4L2_STD_NTSC);
saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH);
saa7127_set_vps(sd, &vbi);
saa7127_set_wss(sd, &vbi);
saa7127_set_cc(sd, &vbi);
saa7127_set_xds(sd, &vbi);
if (test_image == 1)
/* The Encoder has an internal Colorbar generator */
/* This can be used for debugging */
saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE);
else
saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL);
saa7127_set_video_enable(sd, 1);
if (id->driver_data) { /* Chip type is already known */ if (id->driver_data) { /* Chip type is already known */
state->ident = id->driver_data; state->ident = id->driver_data;
} else { /* Needs detection */ } else { /* Needs detection */
...@@ -770,6 +761,23 @@ static int saa7127_probe(struct i2c_client *client, ...@@ -770,6 +761,23 @@ static int saa7127_probe(struct i2c_client *client,
v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
v4l2_dbg(1, debug, sd, "Configuring encoder\n");
saa7127_write_inittab(sd, saa7127_init_config_common);
saa7127_set_std(sd, V4L2_STD_NTSC);
saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH);
saa7127_set_vps(sd, &vbi);
saa7127_set_wss(sd, &vbi);
saa7127_set_cc(sd, &vbi);
saa7127_set_xds(sd, &vbi);
if (test_image == 1)
/* The Encoder has an internal Colorbar generator */
/* This can be used for debugging */
saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE);
else
saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL);
saa7127_set_video_enable(sd, 1);
if (state->ident == V4L2_IDENT_SAA7129) if (state->ident == V4L2_IDENT_SAA7129)
saa7127_write_inittab(sd, saa7129_init_config_extra); saa7127_write_inittab(sd, saa7129_init_config_extra);
return 0; return 0;
......
...@@ -1089,7 +1089,11 @@ static int saa7134_alsa_init(void) ...@@ -1089,7 +1089,11 @@ static int saa7134_alsa_init(void)
list_for_each(list,&saa7134_devlist) { list_for_each(list,&saa7134_devlist) {
dev = list_entry(list, struct saa7134_dev, devlist); dev = list_entry(list, struct saa7134_dev, devlist);
alsa_device_init(dev); if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130)
printk(KERN_INFO "%s/alsa: %s doesn't support digital audio\n",
dev->name, saa7134_boards[dev->board].name);
else
alsa_device_init(dev);
} }
if (dev == NULL) if (dev == NULL)
......
...@@ -660,6 +660,10 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) ...@@ -660,6 +660,10 @@ static int saa7134_hwinit1(struct saa7134_dev *dev)
saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ1, 0);
saa_writel(SAA7134_IRQ2, 0); saa_writel(SAA7134_IRQ2, 0);
/* Clear any stale IRQ reports */
saa_writel(SAA7134_IRQ_REPORT, saa_readl(SAA7134_IRQ_REPORT));
mutex_init(&dev->lock); mutex_init(&dev->lock);
spin_lock_init(&dev->slock); spin_lock_init(&dev->slock);
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/version.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
......
...@@ -242,7 +242,7 @@ static int tda9875_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) ...@@ -242,7 +242,7 @@ static int tda9875_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
static int tda9875_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int tda9875_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{ {
struct tda9875 *t = to_state(sd); struct tda9875 *t = to_state(sd);
int chvol=0, volume, balance, left, right; int chvol = 0, volume = 0, balance = 0, left, right;
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_VOLUME:
......
...@@ -427,6 +427,9 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, ...@@ -427,6 +427,9 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" }; const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" };
memset(tvee, 0, sizeof(*tvee)); memset(tvee, 0, sizeof(*tvee));
tvee->tuner_type = TUNER_ABSENT;
tvee->tuner2_type = TUNER_ABSENT;
done = len = beenhere = 0; done = len = beenhere = 0;
/* Different eeprom start offsets for em28xx, cx2388x and cx23418 */ /* Different eeprom start offsets for em28xx, cx2388x and cx23418 */
......
...@@ -1401,7 +1401,7 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -1401,7 +1401,7 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
decoder->pdata = client->dev.platform_data; decoder->pdata = client->dev.platform_data;
if (!decoder->pdata) { if (!decoder->pdata) {
v4l_err(client, "No platform data\n!!"); v4l_err(client, "No platform data!!\n");
return -ENODEV; return -ENODEV;
} }
/* /*
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
*/ */
#include <linux/version.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/i2c.h> #include <linux/i2c.h>
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
#include <linux/version.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/i2c.h> #include <linux/i2c.h>
......
...@@ -157,7 +157,7 @@ usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) ...@@ -157,7 +157,7 @@ usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
struct i2c_msg *pmsg; struct i2c_msg *pmsg;
struct usb_usbvision *usbvision; struct usb_usbvision *usbvision;
int i, ret; int i, ret;
unsigned char addr; unsigned char addr = 0;
usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap); usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap);
......
/* /*
* uvc_ctrl.c -- USB Video Class driver - Controls * uvc_ctrl.c -- USB Video Class driver - Controls
* *
* Copyright (C) 2005-2008 * Copyright (C) 2005-2009
* Laurent Pinchart (laurent.pinchart@skynet.be) * Laurent Pinchart (laurent.pinchart@skynet.be)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/version.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
...@@ -29,7 +28,7 @@ ...@@ -29,7 +28,7 @@
#define UVC_CTRL_DATA_BACKUP 1 #define UVC_CTRL_DATA_BACKUP 1
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
* Control, formats, ... * Controls
*/ */
static struct uvc_control_info uvc_ctrls[] = { static struct uvc_control_info uvc_ctrls[] = {
...@@ -635,7 +634,7 @@ static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping, ...@@ -635,7 +634,7 @@ static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
mask = (1 << bits) - 1; mask = (1 << bits) - 1;
} }
/* Sign-extend the value if needed */ /* Sign-extend the value if needed. */
if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED)
value |= -(value & (1 << (mapping->size - 1))); value |= -(value & (1 << (mapping->size - 1)));
......
/* /*
* uvc_driver.c -- USB Video Class driver * uvc_driver.c -- USB Video Class driver
* *
* Copyright (C) 2005-2008 * Copyright (C) 2005-2009
* Laurent Pinchart (laurent.pinchart@skynet.be) * Laurent Pinchart (laurent.pinchart@skynet.be)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/version.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/usb.h> #include <linux/usb.h>
...@@ -49,7 +48,7 @@ static unsigned int uvc_quirks_param; ...@@ -49,7 +48,7 @@ static unsigned int uvc_quirks_param;
unsigned int uvc_trace_param; unsigned int uvc_trace_param;
/* ------------------------------------------------------------------------ /* ------------------------------------------------------------------------
* Control, formats, ... * Video formats
*/ */
static struct uvc_format_desc uvc_fmts[] = { static struct uvc_format_desc uvc_fmts[] = {
...@@ -474,7 +473,7 @@ static int uvc_parse_format(struct uvc_device *dev, ...@@ -474,7 +473,7 @@ static int uvc_parse_format(struct uvc_device *dev,
/* Several UVC chipsets screw up dwMaxVideoFrameBufferSize /* Several UVC chipsets screw up dwMaxVideoFrameBufferSize
* completely. Observed behaviours range from setting the * completely. Observed behaviours range from setting the
* value to 1.1x the actual frame size of hardwiring the * value to 1.1x the actual frame size to hardwiring the
* 16 low bits to 0. This results in a higher than necessary * 16 low bits to 0. This results in a higher than necessary
* memory usage as well as a wrong image size information. For * memory usage as well as a wrong image size information. For
* uncompressed formats this can be fixed by computing the * uncompressed formats this can be fixed by computing the
...@@ -487,7 +486,7 @@ static int uvc_parse_format(struct uvc_device *dev, ...@@ -487,7 +486,7 @@ static int uvc_parse_format(struct uvc_device *dev,
/* Some bogus devices report dwMinFrameInterval equal to /* Some bogus devices report dwMinFrameInterval equal to
* dwMaxFrameInterval and have dwFrameIntervalStep set to * dwMaxFrameInterval and have dwFrameIntervalStep set to
* zero. Setting all null intervals to 1 fixes the problem and * zero. Setting all null intervals to 1 fixes the problem and
* some other divisions by zero which could happen. * some other divisions by zero that could happen.
*/ */
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
interval = get_unaligned_le32(&buffer[26+4*i]); interval = get_unaligned_le32(&buffer[26+4*i]);
...@@ -1200,13 +1199,13 @@ static void uvc_unregister_video(struct uvc_device *dev) ...@@ -1200,13 +1199,13 @@ static void uvc_unregister_video(struct uvc_device *dev)
* Scan the UVC descriptors to locate a chain starting at an Output Terminal * Scan the UVC descriptors to locate a chain starting at an Output Terminal
* and containing the following units: * and containing the following units:
* *
* - a USB Streaming Output Terminal * - one Output Terminal (USB Streaming or Display)
* - zero or one Processing Unit * - zero or one Processing Unit
* - zero, one or mode single-input Selector Units * - zero, one or mode single-input Selector Units
* - zero or one multiple-input Selector Units, provided all inputs are * - zero or one multiple-input Selector Units, provided all inputs are
* connected to input terminals * connected to input terminals
* - zero, one or mode single-input Extension Units * - zero, one or mode single-input Extension Units
* - one Camera Input Terminal, or one or more External terminals. * - one or more Input Terminals (Camera, External or USB Streaming)
* *
* A side forward scan is made on each detected entity to check for additional * A side forward scan is made on each detected entity to check for additional
* extension units. * extension units.
...@@ -1531,10 +1530,6 @@ static int uvc_register_video(struct uvc_device *dev) ...@@ -1531,10 +1530,6 @@ static int uvc_register_video(struct uvc_device *dev)
/* Set the driver data before calling video_register_device, otherwise /* Set the driver data before calling video_register_device, otherwise
* uvc_v4l2_open might race us. * uvc_v4l2_open might race us.
*
* FIXME: usb_set_intfdata hasn't been called so far. Is that a
* problem ? Does any function which could be called here get
* a pointer to the usb_interface ?
*/ */
dev->video.vdev = vdev; dev->video.vdev = vdev;
video_set_drvdata(vdev, &dev->video); video_set_drvdata(vdev, &dev->video);
...@@ -1569,7 +1564,7 @@ void uvc_delete(struct kref *kref) ...@@ -1569,7 +1564,7 @@ void uvc_delete(struct kref *kref)
struct uvc_device *dev = container_of(kref, struct uvc_device, kref); struct uvc_device *dev = container_of(kref, struct uvc_device, kref);
struct list_head *p, *n; struct list_head *p, *n;
/* Unregister the video device */ /* Unregister the video device. */
uvc_unregister_video(dev); uvc_unregister_video(dev);
usb_put_intf(dev->intf); usb_put_intf(dev->intf);
usb_put_dev(dev->udev); usb_put_dev(dev->udev);
...@@ -1612,7 +1607,7 @@ static int uvc_probe(struct usb_interface *intf, ...@@ -1612,7 +1607,7 @@ static int uvc_probe(struct usb_interface *intf,
uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n", uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",
udev->devpath); udev->devpath);
/* Allocate memory for the device and initialize it */ /* Allocate memory for the device and initialize it. */
if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL) if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -1633,14 +1628,14 @@ static int uvc_probe(struct usb_interface *intf, ...@@ -1633,14 +1628,14 @@ static int uvc_probe(struct usb_interface *intf,
le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct)); le16_to_cpu(udev->descriptor.idProduct));
/* Parse the Video Class control descriptor */ /* Parse the Video Class control descriptor. */
if (uvc_parse_control(dev) < 0) { if (uvc_parse_control(dev) < 0) {
uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC " uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
"descriptors.\n"); "descriptors.\n");
goto error; goto error;
} }
uvc_printk(KERN_INFO, "Found UVC %u.%02u device %s (%04x:%04x)\n", uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",
dev->uvc_version >> 8, dev->uvc_version & 0xff, dev->uvc_version >> 8, dev->uvc_version & 0xff,
udev->product ? udev->product : "<unnamed>", udev->product ? udev->product : "<unnamed>",
le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idVendor),
...@@ -1653,18 +1648,18 @@ static int uvc_probe(struct usb_interface *intf, ...@@ -1653,18 +1648,18 @@ static int uvc_probe(struct usb_interface *intf,
"linux-uvc-devel mailing list.\n"); "linux-uvc-devel mailing list.\n");
} }
/* Initialize controls */ /* Initialize controls. */
if (uvc_ctrl_init_device(dev) < 0) if (uvc_ctrl_init_device(dev) < 0)
goto error; goto error;
/* Register the video devices */ /* Register the video devices. */
if (uvc_register_video(dev) < 0) if (uvc_register_video(dev) < 0)
goto error; goto error;
/* Save our data pointer in the interface data */ /* Save our data pointer in the interface data. */
usb_set_intfdata(intf, dev); usb_set_intfdata(intf, dev);
/* Initialize the interrupt URB */ /* Initialize the interrupt URB. */
if ((ret = uvc_status_init(dev)) < 0) { if ((ret = uvc_status_init(dev)) < 0) {
uvc_printk(KERN_INFO, "Unable to initialize the status " uvc_printk(KERN_INFO, "Unable to initialize the status "
"endpoint (%d), status interrupt will not be " "endpoint (%d), status interrupt will not be "
...@@ -1839,24 +1834,24 @@ static struct usb_device_id uvc_ids[] = { ...@@ -1839,24 +1834,24 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1, .bInterfaceSubClass = 1,
.bInterfaceProtocol = 0 }, .bInterfaceProtocol = 0 },
/* Apple Built-In iSight */ /* Apple Built-In iSight */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO, | USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x05ac, .idVendor = 0x05ac,
.idProduct = 0x8501, .idProduct = 0x8501,
.bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1, .bInterfaceSubClass = 1,
.bInterfaceProtocol = 0, .bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX .driver_info = UVC_QUIRK_PROBE_MINMAX
| UVC_QUIRK_BUILTIN_ISIGHT }, | UVC_QUIRK_BUILTIN_ISIGHT },
/* Genesys Logic USB 2.0 PC Camera */ /* Genesys Logic USB 2.0 PC Camera */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO, | USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x05e3, .idVendor = 0x05e3,
.idProduct = 0x0505, .idProduct = 0x0505,
.bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1, .bInterfaceSubClass = 1,
.bInterfaceProtocol = 0, .bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_STREAM_NO_FID }, .driver_info = UVC_QUIRK_STREAM_NO_FID },
/* MT6227 */ /* MT6227 */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO, | USB_DEVICE_ID_MATCH_INT_INFO,
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
* *
* Copyright (C) 2006-2007 * Copyright (C) 2006-2007
* Ivan N. Zlatev <contact@i-nz.net> * Ivan N. Zlatev <contact@i-nz.net>
* Copyright (C) 2008-2009
* Laurent Pinchart <laurent.pinchart@skynet.be>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
......
/* /*
* uvc_queue.c -- USB Video Class driver - Buffers management * uvc_queue.c -- USB Video Class driver - Buffers management
* *
* Copyright (C) 2005-2008 * Copyright (C) 2005-2009
* Laurent Pinchart (laurent.pinchart@skynet.be) * Laurent Pinchart (laurent.pinchart@skynet.be)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/version.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -37,22 +36,22 @@ ...@@ -37,22 +36,22 @@
* to user space will return -EBUSY. * to user space will return -EBUSY.
* *
* Video buffers are managed using two queues. However, unlike most USB video * Video buffers are managed using two queues. However, unlike most USB video
* drivers which use an in queue and an out queue, we use a main queue which * drivers that use an in queue and an out queue, we use a main queue to hold
* holds all queued buffers (both 'empty' and 'done' buffers), and an irq * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
* queue which holds empty buffers. This design (copied from video-buf) * hold empty buffers. This design (copied from video-buf) minimizes locking
* minimizes locking in interrupt, as only one queue is shared between * in interrupt, as only one queue is shared between interrupt and user
* interrupt and user contexts. * contexts.
* *
* Use cases * Use cases
* --------- * ---------
* *
* Unless stated otherwise, all operations which modify the irq buffers queue * Unless stated otherwise, all operations that modify the irq buffers queue
* are protected by the irq spinlock. * are protected by the irq spinlock.
* *
* 1. The user queues the buffers, starts streaming and dequeues a buffer. * 1. The user queues the buffers, starts streaming and dequeues a buffer.
* *
* The buffers are added to the main and irq queues. Both operations are * The buffers are added to the main and irq queues. Both operations are
* protected by the queue lock, and the latert is protected by the irq * protected by the queue lock, and the later is protected by the irq
* spinlock as well. * spinlock as well.
* *
* The completion handler fetches a buffer from the irq queue and fills it * The completion handler fetches a buffer from the irq queue and fills it
...@@ -60,7 +59,7 @@ ...@@ -60,7 +59,7 @@
* returns immediately. * returns immediately.
* *
* When the buffer is full, the completion handler removes it from the irq * When the buffer is full, the completion handler removes it from the irq
* queue, marks it as ready (UVC_BUF_STATE_DONE) and wake its wait queue. * queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue.
* At that point, any process waiting on the buffer will be woken up. If a * At that point, any process waiting on the buffer will be woken up. If a
* process tries to dequeue a buffer after it has been marked ready, the * process tries to dequeue a buffer after it has been marked ready, the
* dequeing will succeed immediately. * dequeing will succeed immediately.
...@@ -91,8 +90,8 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) ...@@ -91,8 +90,8 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
/* /*
* Allocate the video buffers. * Allocate the video buffers.
* *
* Pages are reserved to make sure they will not be swaped, as they will be * Pages are reserved to make sure they will not be swapped, as they will be
* filled in URB completion handler. * filled in the URB completion handler.
* *
* Buffers will be individually mapped, so they must all be page aligned. * Buffers will be individually mapped, so they must all be page aligned.
*/ */
...@@ -210,8 +209,8 @@ int uvc_query_buffer(struct uvc_video_queue *queue, ...@@ -210,8 +209,8 @@ int uvc_query_buffer(struct uvc_video_queue *queue,
__uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf); __uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
done: done:
mutex_unlock(&queue->mutex); mutex_unlock(&queue->mutex);
return ret; return ret;
} }
/* /*
...@@ -236,7 +235,7 @@ int uvc_queue_buffer(struct uvc_video_queue *queue, ...@@ -236,7 +235,7 @@ int uvc_queue_buffer(struct uvc_video_queue *queue,
} }
mutex_lock(&queue->mutex); mutex_lock(&queue->mutex);
if (v4l2_buf->index >= queue->count) { if (v4l2_buf->index >= queue->count) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n"); uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
ret = -EINVAL; ret = -EINVAL;
goto done; goto done;
...@@ -429,7 +428,7 @@ int uvc_queue_enable(struct uvc_video_queue *queue, int enable) ...@@ -429,7 +428,7 @@ int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
* Cancel the video buffers queue. * Cancel the video buffers queue.
* *
* Cancelling the queue marks all buffers on the irq queue as erroneous, * Cancelling the queue marks all buffers on the irq queue as erroneous,
* wakes them up and remove them from the queue. * wakes them up and removes them from the queue.
* *
* If the disconnect parameter is set, further calls to uvc_queue_buffer will * If the disconnect parameter is set, further calls to uvc_queue_buffer will
* fail with -ENODEV. * fail with -ENODEV.
......
/* /*
* uvc_status.c -- USB Video Class driver - Status endpoint * uvc_status.c -- USB Video Class driver - Status endpoint
* *
* Copyright (C) 2007-2008 * Copyright (C) 2007-2009
* Laurent Pinchart (laurent.pinchart@skynet.be) * Laurent Pinchart (laurent.pinchart@skynet.be)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/version.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb/input.h> #include <linux/usb/input.h>
......
/* /*
* uvc_v4l2.c -- USB Video Class driver - V4L2 API * uvc_v4l2.c -- USB Video Class driver - V4L2 API
* *
* Copyright (C) 2005-2008 * Copyright (C) 2005-2009
* Laurent Pinchart (laurent.pinchart@skynet.be) * Laurent Pinchart (laurent.pinchart@skynet.be)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* must be grouped (for instance the Red Balance, Blue Balance and Do White * must be grouped (for instance the Red Balance, Blue Balance and Do White
* Balance V4L2 controls use the White Balance Component UVC control) or * Balance V4L2 controls use the White Balance Component UVC control) or
* otherwise translated. The approach we take here is to use a translation * otherwise translated. The approach we take here is to use a translation
* table for the controls which can be mapped directly, and handle the others * table for the controls that can be mapped directly, and handle the others
* manually. * manually.
*/ */
static int uvc_v4l2_query_menu(struct uvc_video_device *video, static int uvc_v4l2_query_menu(struct uvc_video_device *video,
...@@ -189,7 +189,7 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video, ...@@ -189,7 +189,7 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video,
probe->dwMaxVideoFrameSize = probe->dwMaxVideoFrameSize =
video->streaming->ctrl.dwMaxVideoFrameSize; video->streaming->ctrl.dwMaxVideoFrameSize;
/* Probe the device */ /* Probe the device. */
if ((ret = uvc_probe_video(video, probe)) < 0) if ((ret = uvc_probe_video(video, probe)) < 0)
goto done; goto done;
...@@ -354,11 +354,11 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, ...@@ -354,11 +354,11 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video,
* *
* Each open instance of a UVC device can either be in a privileged or * Each open instance of a UVC device can either be in a privileged or
* unprivileged state. Only a single instance can be in a privileged state at * unprivileged state. Only a single instance can be in a privileged state at
* a given time. Trying to perform an operation which requires privileges will * a given time. Trying to perform an operation that requires privileges will
* automatically acquire the required privileges if possible, or return -EBUSY * automatically acquire the required privileges if possible, or return -EBUSY
* otherwise. Privileges are dismissed when closing the instance. * otherwise. Privileges are dismissed when closing the instance.
* *
* Operations which require privileges are: * Operations that require privileges are:
* *
* - VIDIOC_S_INPUT * - VIDIOC_S_INPUT
* - VIDIOC_S_PARM * - VIDIOC_S_PARM
......
/* /*
* uvc_video.c -- USB Video Class driver - Video handling * uvc_video.c -- USB Video Class driver - Video handling
* *
* Copyright (C) 2005-2008 * Copyright (C) 2005-2009
* Laurent Pinchart (laurent.pinchart@skynet.be) * Laurent Pinchart (laurent.pinchart@skynet.be)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/version.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/usb.h> #include <linux/usb.h>
...@@ -115,7 +114,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, ...@@ -115,7 +114,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
ctrl->wCompQuality = le16_to_cpup((__le16 *)data); ctrl->wCompQuality = le16_to_cpup((__le16 *)data);
ret = 0; ret = 0;
goto out; goto out;
} else if (query == GET_DEF && probe == 1) { } else if (query == GET_DEF && probe == 1 && ret != size) {
/* Many cameras don't support the GET_DEF request on their /* Many cameras don't support the GET_DEF request on their
* video probe control. Warn once and return, the caller will * video probe control. Warn once and return, the caller will
* fall back to GET_CUR. * fall back to GET_CUR.
...@@ -160,7 +159,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, ...@@ -160,7 +159,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
} }
/* Some broken devices return a null or wrong dwMaxVideoFrameSize. /* Some broken devices return a null or wrong dwMaxVideoFrameSize.
* Try to get the value from the format and frame descriptor. * Try to get the value from the format and frame descriptors.
*/ */
uvc_fixup_buffer_size(video, ctrl); uvc_fixup_buffer_size(video, ctrl);
ret = 0; ret = 0;
...@@ -191,9 +190,6 @@ static int uvc_set_video_ctrl(struct uvc_video_device *video, ...@@ -191,9 +190,6 @@ static int uvc_set_video_ctrl(struct uvc_video_device *video,
*(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality); *(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality);
*(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize); *(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize);
*(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay); *(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay);
/* Note: Some of the fields below are not required for IN devices (see
* UVC spec, 4.3.1.1), but we still copy them in case support for OUT
* devices is added in the future. */
put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]); put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]);
put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]); put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]);
...@@ -400,7 +396,7 @@ static int uvc_video_decode_start(struct uvc_video_device *video, ...@@ -400,7 +396,7 @@ static int uvc_video_decode_start(struct uvc_video_device *video,
* *
* Empty buffers (bytesused == 0) don't trigger end of frame detection * Empty buffers (bytesused == 0) don't trigger end of frame detection
* as it doesn't make sense to return an empty buffer. This also * as it doesn't make sense to return an empty buffer. This also
* avoids detecting and of frame conditions at FID toggling if the * avoids detecting end of frame conditions at FID toggling if the
* previous payload had the EOF bit set. * previous payload had the EOF bit set.
*/ */
if (fid != video->last_fid && buf->buf.bytesused != 0) { if (fid != video->last_fid && buf->buf.bytesused != 0) {
...@@ -453,6 +449,17 @@ static void uvc_video_decode_end(struct uvc_video_device *video, ...@@ -453,6 +449,17 @@ static void uvc_video_decode_end(struct uvc_video_device *video,
} }
} }
/* Video payload encoding is handled by uvc_video_encode_header() and
* uvc_video_encode_data(). Only bulk transfers are currently supported.
*
* uvc_video_encode_header is called at the start of a payload. It adds header
* data to the transfer buffer and returns the header size. As the only known
* UVC output device transfers a whole frame in a single payload, the EOF bit
* is always set in the header.
*
* uvc_video_encode_data is called for every URB and copies the data from the
* video buffer to the transfer buffer.
*/
static int uvc_video_encode_header(struct uvc_video_device *video, static int uvc_video_encode_header(struct uvc_video_device *video,
struct uvc_buffer *buf, __u8 *data, int len) struct uvc_buffer *buf, __u8 *data, int len)
{ {
...@@ -953,7 +960,7 @@ int uvc_video_suspend(struct uvc_video_device *video) ...@@ -953,7 +960,7 @@ int uvc_video_suspend(struct uvc_video_device *video)
} }
/* /*
* Reconfigure the video interface and restart streaming if it was enable * Reconfigure the video interface and restart streaming if it was enabled
* before suspend. * before suspend.
* *
* If an error occurs, disable the video queue. This will wake all pending * If an error occurs, disable the video queue. This will wake all pending
...@@ -985,8 +992,8 @@ int uvc_video_resume(struct uvc_video_device *video) ...@@ -985,8 +992,8 @@ int uvc_video_resume(struct uvc_video_device *video)
*/ */
/* /*
* Initialize the UVC video device by retrieving the default format and * Initialize the UVC video device by switching to alternate setting 0 and
* committing it. * retrieve the default format.
* *
* Some cameras (namely the Fuji Finepix) set the format and frame * Some cameras (namely the Fuji Finepix) set the format and frame
* indexes to zero. The UVC standard doesn't clearly make this a spec * indexes to zero. The UVC standard doesn't clearly make this a spec
...@@ -1014,7 +1021,7 @@ int uvc_video_init(struct uvc_video_device *video) ...@@ -1014,7 +1021,7 @@ int uvc_video_init(struct uvc_video_device *video)
*/ */
usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); usb_set_interface(video->dev->udev, video->streaming->intfnum, 0);
/* Some webcams don't suport GET_DEF request on the probe control. We /* Some webcams don't suport GET_DEF requests on the probe control. We
* fall back to GET_CUR if GET_DEF fails. * fall back to GET_CUR if GET_DEF fails.
*/ */
if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 && if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 &&
......
...@@ -72,149 +72,149 @@ struct uvc_xu_control { ...@@ -72,149 +72,149 @@ struct uvc_xu_control {
* UVC constants * UVC constants
*/ */
#define SC_UNDEFINED 0x00 #define SC_UNDEFINED 0x00
#define SC_VIDEOCONTROL 0x01 #define SC_VIDEOCONTROL 0x01
#define SC_VIDEOSTREAMING 0x02 #define SC_VIDEOSTREAMING 0x02
#define SC_VIDEO_INTERFACE_COLLECTION 0x03 #define SC_VIDEO_INTERFACE_COLLECTION 0x03
#define PC_PROTOCOL_UNDEFINED 0x00 #define PC_PROTOCOL_UNDEFINED 0x00
#define CS_UNDEFINED 0x20 #define CS_UNDEFINED 0x20
#define CS_DEVICE 0x21 #define CS_DEVICE 0x21
#define CS_CONFIGURATION 0x22 #define CS_CONFIGURATION 0x22
#define CS_STRING 0x23 #define CS_STRING 0x23
#define CS_INTERFACE 0x24 #define CS_INTERFACE 0x24
#define CS_ENDPOINT 0x25 #define CS_ENDPOINT 0x25
/* VideoControl class specific interface descriptor */ /* VideoControl class specific interface descriptor */
#define VC_DESCRIPTOR_UNDEFINED 0x00 #define VC_DESCRIPTOR_UNDEFINED 0x00
#define VC_HEADER 0x01 #define VC_HEADER 0x01
#define VC_INPUT_TERMINAL 0x02 #define VC_INPUT_TERMINAL 0x02
#define VC_OUTPUT_TERMINAL 0x03 #define VC_OUTPUT_TERMINAL 0x03
#define VC_SELECTOR_UNIT 0x04 #define VC_SELECTOR_UNIT 0x04
#define VC_PROCESSING_UNIT 0x05 #define VC_PROCESSING_UNIT 0x05
#define VC_EXTENSION_UNIT 0x06 #define VC_EXTENSION_UNIT 0x06
/* VideoStreaming class specific interface descriptor */ /* VideoStreaming class specific interface descriptor */
#define VS_UNDEFINED 0x00 #define VS_UNDEFINED 0x00
#define VS_INPUT_HEADER 0x01 #define VS_INPUT_HEADER 0x01
#define VS_OUTPUT_HEADER 0x02 #define VS_OUTPUT_HEADER 0x02
#define VS_STILL_IMAGE_FRAME 0x03 #define VS_STILL_IMAGE_FRAME 0x03
#define VS_FORMAT_UNCOMPRESSED 0x04 #define VS_FORMAT_UNCOMPRESSED 0x04
#define VS_FRAME_UNCOMPRESSED 0x05 #define VS_FRAME_UNCOMPRESSED 0x05
#define VS_FORMAT_MJPEG 0x06 #define VS_FORMAT_MJPEG 0x06
#define VS_FRAME_MJPEG 0x07 #define VS_FRAME_MJPEG 0x07
#define VS_FORMAT_MPEG2TS 0x0a #define VS_FORMAT_MPEG2TS 0x0a
#define VS_FORMAT_DV 0x0c #define VS_FORMAT_DV 0x0c
#define VS_COLORFORMAT 0x0d #define VS_COLORFORMAT 0x0d
#define VS_FORMAT_FRAME_BASED 0x10 #define VS_FORMAT_FRAME_BASED 0x10
#define VS_FRAME_FRAME_BASED 0x11 #define VS_FRAME_FRAME_BASED 0x11
#define VS_FORMAT_STREAM_BASED 0x12 #define VS_FORMAT_STREAM_BASED 0x12
/* Endpoint type */ /* Endpoint type */
#define EP_UNDEFINED 0x00 #define EP_UNDEFINED 0x00
#define EP_GENERAL 0x01 #define EP_GENERAL 0x01
#define EP_ENDPOINT 0x02 #define EP_ENDPOINT 0x02
#define EP_INTERRUPT 0x03 #define EP_INTERRUPT 0x03
/* Request codes */ /* Request codes */
#define RC_UNDEFINED 0x00 #define RC_UNDEFINED 0x00
#define SET_CUR 0x01 #define SET_CUR 0x01
#define GET_CUR 0x81 #define GET_CUR 0x81
#define GET_MIN 0x82 #define GET_MIN 0x82
#define GET_MAX 0x83 #define GET_MAX 0x83
#define GET_RES 0x84 #define GET_RES 0x84
#define GET_LEN 0x85 #define GET_LEN 0x85
#define GET_INFO 0x86 #define GET_INFO 0x86
#define GET_DEF 0x87 #define GET_DEF 0x87
/* VideoControl interface controls */ /* VideoControl interface controls */
#define VC_CONTROL_UNDEFINED 0x00 #define VC_CONTROL_UNDEFINED 0x00
#define VC_VIDEO_POWER_MODE_CONTROL 0x01 #define VC_VIDEO_POWER_MODE_CONTROL 0x01
#define VC_REQUEST_ERROR_CODE_CONTROL 0x02 #define VC_REQUEST_ERROR_CODE_CONTROL 0x02
/* Terminal controls */ /* Terminal controls */
#define TE_CONTROL_UNDEFINED 0x00 #define TE_CONTROL_UNDEFINED 0x00
/* Selector Unit controls */ /* Selector Unit controls */
#define SU_CONTROL_UNDEFINED 0x00 #define SU_CONTROL_UNDEFINED 0x00
#define SU_INPUT_SELECT_CONTROL 0x01 #define SU_INPUT_SELECT_CONTROL 0x01
/* Camera Terminal controls */ /* Camera Terminal controls */
#define CT_CONTROL_UNDEFINED 0x00 #define CT_CONTROL_UNDEFINED 0x00
#define CT_SCANNING_MODE_CONTROL 0x01 #define CT_SCANNING_MODE_CONTROL 0x01
#define CT_AE_MODE_CONTROL 0x02 #define CT_AE_MODE_CONTROL 0x02
#define CT_AE_PRIORITY_CONTROL 0x03 #define CT_AE_PRIORITY_CONTROL 0x03
#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 #define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04
#define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 #define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05
#define CT_FOCUS_ABSOLUTE_CONTROL 0x06 #define CT_FOCUS_ABSOLUTE_CONTROL 0x06
#define CT_FOCUS_RELATIVE_CONTROL 0x07 #define CT_FOCUS_RELATIVE_CONTROL 0x07
#define CT_FOCUS_AUTO_CONTROL 0x08 #define CT_FOCUS_AUTO_CONTROL 0x08
#define CT_IRIS_ABSOLUTE_CONTROL 0x09 #define CT_IRIS_ABSOLUTE_CONTROL 0x09
#define CT_IRIS_RELATIVE_CONTROL 0x0a #define CT_IRIS_RELATIVE_CONTROL 0x0a
#define CT_ZOOM_ABSOLUTE_CONTROL 0x0b #define CT_ZOOM_ABSOLUTE_CONTROL 0x0b
#define CT_ZOOM_RELATIVE_CONTROL 0x0c #define CT_ZOOM_RELATIVE_CONTROL 0x0c
#define CT_PANTILT_ABSOLUTE_CONTROL 0x0d #define CT_PANTILT_ABSOLUTE_CONTROL 0x0d
#define CT_PANTILT_RELATIVE_CONTROL 0x0e #define CT_PANTILT_RELATIVE_CONTROL 0x0e
#define CT_ROLL_ABSOLUTE_CONTROL 0x0f #define CT_ROLL_ABSOLUTE_CONTROL 0x0f
#define CT_ROLL_RELATIVE_CONTROL 0x10 #define CT_ROLL_RELATIVE_CONTROL 0x10
#define CT_PRIVACY_CONTROL 0x11 #define CT_PRIVACY_CONTROL 0x11
/* Processing Unit controls */ /* Processing Unit controls */
#define PU_CONTROL_UNDEFINED 0x00 #define PU_CONTROL_UNDEFINED 0x00
#define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 #define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01
#define PU_BRIGHTNESS_CONTROL 0x02 #define PU_BRIGHTNESS_CONTROL 0x02
#define PU_CONTRAST_CONTROL 0x03 #define PU_CONTRAST_CONTROL 0x03
#define PU_GAIN_CONTROL 0x04 #define PU_GAIN_CONTROL 0x04
#define PU_POWER_LINE_FREQUENCY_CONTROL 0x05 #define PU_POWER_LINE_FREQUENCY_CONTROL 0x05
#define PU_HUE_CONTROL 0x06 #define PU_HUE_CONTROL 0x06
#define PU_SATURATION_CONTROL 0x07 #define PU_SATURATION_CONTROL 0x07
#define PU_SHARPNESS_CONTROL 0x08 #define PU_SHARPNESS_CONTROL 0x08
#define PU_GAMMA_CONTROL 0x09 #define PU_GAMMA_CONTROL 0x09
#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a #define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a
#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b #define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b
#define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c #define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c
#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d #define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d
#define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e #define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e
#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f #define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f
#define PU_HUE_AUTO_CONTROL 0x10 #define PU_HUE_AUTO_CONTROL 0x10
#define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 #define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11
#define PU_ANALOG_LOCK_STATUS_CONTROL 0x12 #define PU_ANALOG_LOCK_STATUS_CONTROL 0x12
#define LXU_MOTOR_PANTILT_RELATIVE_CONTROL 0x01 #define LXU_MOTOR_PANTILT_RELATIVE_CONTROL 0x01
#define LXU_MOTOR_PANTILT_RESET_CONTROL 0x02 #define LXU_MOTOR_PANTILT_RESET_CONTROL 0x02
#define LXU_MOTOR_FOCUS_MOTOR_CONTROL 0x03 #define LXU_MOTOR_FOCUS_MOTOR_CONTROL 0x03
/* VideoStreaming interface controls */ /* VideoStreaming interface controls */
#define VS_CONTROL_UNDEFINED 0x00 #define VS_CONTROL_UNDEFINED 0x00
#define VS_PROBE_CONTROL 0x01 #define VS_PROBE_CONTROL 0x01
#define VS_COMMIT_CONTROL 0x02 #define VS_COMMIT_CONTROL 0x02
#define VS_STILL_PROBE_CONTROL 0x03 #define VS_STILL_PROBE_CONTROL 0x03
#define VS_STILL_COMMIT_CONTROL 0x04 #define VS_STILL_COMMIT_CONTROL 0x04
#define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 #define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05
#define VS_STREAM_ERROR_CODE_CONTROL 0x06 #define VS_STREAM_ERROR_CODE_CONTROL 0x06
#define VS_GENERATE_KEY_FRAME_CONTROL 0x07 #define VS_GENERATE_KEY_FRAME_CONTROL 0x07
#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 #define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08
#define VS_SYNC_DELAY_CONTROL 0x09 #define VS_SYNC_DELAY_CONTROL 0x09
#define TT_VENDOR_SPECIFIC 0x0100 #define TT_VENDOR_SPECIFIC 0x0100
#define TT_STREAMING 0x0101 #define TT_STREAMING 0x0101
/* Input Terminal types */ /* Input Terminal types */
#define ITT_VENDOR_SPECIFIC 0x0200 #define ITT_VENDOR_SPECIFIC 0x0200
#define ITT_CAMERA 0x0201 #define ITT_CAMERA 0x0201
#define ITT_MEDIA_TRANSPORT_INPUT 0x0202 #define ITT_MEDIA_TRANSPORT_INPUT 0x0202
/* Output Terminal types */ /* Output Terminal types */
#define OTT_VENDOR_SPECIFIC 0x0300 #define OTT_VENDOR_SPECIFIC 0x0300
#define OTT_DISPLAY 0x0301 #define OTT_DISPLAY 0x0301
#define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302 #define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302
/* External Terminal types */ /* External Terminal types */
#define EXTERNAL_VENDOR_SPECIFIC 0x0400 #define EXTERNAL_VENDOR_SPECIFIC 0x0400
#define COMPOSITE_CONNECTOR 0x0401 #define COMPOSITE_CONNECTOR 0x0401
#define SVIDEO_CONNECTOR 0x0402 #define SVIDEO_CONNECTOR 0x0402
#define COMPONENT_CONNECTOR 0x0403 #define COMPONENT_CONNECTOR 0x0403
#define UVC_TERM_INPUT 0x0000 #define UVC_TERM_INPUT 0x0000
#define UVC_TERM_OUTPUT 0x8000 #define UVC_TERM_OUTPUT 0x8000
...@@ -541,11 +541,11 @@ struct uvc_streaming { ...@@ -541,11 +541,11 @@ struct uvc_streaming {
}; };
enum uvc_buffer_state { enum uvc_buffer_state {
UVC_BUF_STATE_IDLE = 0, UVC_BUF_STATE_IDLE = 0,
UVC_BUF_STATE_QUEUED = 1, UVC_BUF_STATE_QUEUED = 1,
UVC_BUF_STATE_ACTIVE = 2, UVC_BUF_STATE_ACTIVE = 2,
UVC_BUF_STATE_DONE = 3, UVC_BUF_STATE_DONE = 3,
UVC_BUF_STATE_ERROR = 4, UVC_BUF_STATE_ERROR = 4,
}; };
struct uvc_buffer { struct uvc_buffer {
......
...@@ -28,13 +28,13 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) ...@@ -28,13 +28,13 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg)
{ {
switch (cmd) { switch (cmd) {
case VIDIOC_QUERYCTRL: case VIDIOC_QUERYCTRL:
return v4l2_subdev_call(sd, core, querymenu, arg); return v4l2_subdev_call(sd, core, queryctrl, arg);
case VIDIOC_G_CTRL: case VIDIOC_G_CTRL:
return v4l2_subdev_call(sd, core, g_ctrl, arg); return v4l2_subdev_call(sd, core, g_ctrl, arg);
case VIDIOC_S_CTRL: case VIDIOC_S_CTRL:
return v4l2_subdev_call(sd, core, s_ctrl, arg); return v4l2_subdev_call(sd, core, s_ctrl, arg);
case VIDIOC_QUERYMENU: case VIDIOC_QUERYMENU:
return v4l2_subdev_call(sd, core, queryctrl, arg); return v4l2_subdev_call(sd, core, querymenu, arg);
case VIDIOC_LOG_STATUS: case VIDIOC_LOG_STATUS:
return v4l2_subdev_call(sd, core, log_status); return v4l2_subdev_call(sd, core, log_status);
case VIDIOC_DBG_G_CHIP_IDENT: case VIDIOC_DBG_G_CHIP_IDENT:
......
...@@ -349,7 +349,6 @@ struct card_info { ...@@ -349,7 +349,6 @@ struct card_info {
u16 i2c_decoder, i2c_encoder; /* I2C types */ u16 i2c_decoder, i2c_encoder; /* I2C types */
u16 video_vfe, video_codec; /* videocodec types */ u16 video_vfe, video_codec; /* videocodec types */
u16 audio_chip; /* audio type */ u16 audio_chip; /* audio type */
u16 vendor_id, device_id; /* subsystem vendor/device ID */
int inputs; /* number of video inputs */ int inputs; /* number of video inputs */
struct input { struct input {
...@@ -401,7 +400,6 @@ struct zoran { ...@@ -401,7 +400,6 @@ struct zoran {
char name[32]; /* name of this device */ char name[32]; /* name of this device */
struct pci_dev *pci_dev; /* PCI device */ struct pci_dev *pci_dev; /* PCI device */
unsigned char revision; /* revision of zr36057 */ unsigned char revision; /* revision of zr36057 */
unsigned int zr36057_adr; /* bus address of IO mem returned by PCI BIOS */
unsigned char __iomem *zr36057_mem;/* pointer to mapped IO memory */ unsigned char __iomem *zr36057_mem;/* pointer to mapped IO memory */
spinlock_t spinlock; /* Spinlock */ spinlock_t spinlock; /* Spinlock */
...@@ -490,16 +488,10 @@ struct zoran { ...@@ -490,16 +488,10 @@ struct zoran {
wait_queue_head_t test_q; wait_queue_head_t test_q;
}; };
/*The following should be done in more portable way. It depends on define /* There was something called _ALPHA_BUZ that used the PCI address instead of
of _ALPHA_BUZ in the Makefile.*/ * the kernel iomapped address for btread/btwrite. */
#ifdef _ALPHA_BUZ
#define btwrite(dat,adr) writel((dat), zr->zr36057_adr+(adr))
#define btread(adr) readl(zr->zr36057_adr+(adr))
#else
#define btwrite(dat,adr) writel((dat), zr->zr36057_mem+(adr)) #define btwrite(dat,adr) writel((dat), zr->zr36057_mem+(adr))
#define btread(adr) readl(zr->zr36057_mem+(adr)) #define btread(adr) readl(zr->zr36057_mem+(adr))
#endif
#define btand(dat,adr) btwrite((dat) & btread(adr), adr) #define btand(dat,adr) btwrite((dat) & btread(adr), adr)
#define btor(dat,adr) btwrite((dat) | btread(adr), adr) #define btor(dat,adr) btwrite((dat) | btread(adr), adr)
......
...@@ -40,8 +40,6 @@ extern int zr36067_debug; ...@@ -40,8 +40,6 @@ extern int zr36067_debug;
/* Anybody who uses more than four? */ /* Anybody who uses more than four? */
#define BUZ_MAX 4 #define BUZ_MAX 4
extern int zoran_num;
extern struct zoran *zoran[BUZ_MAX];
extern struct video_device zoran_template; extern struct video_device zoran_template;
......
...@@ -1196,83 +1196,54 @@ zoran_close_end_session (struct file *file) ...@@ -1196,83 +1196,54 @@ zoran_close_end_session (struct file *file)
* Open a zoran card. Right now the flags stuff is just playing * Open a zoran card. Right now the flags stuff is just playing
*/ */
static int static int zoran_open(struct file *file)
zoran_open(struct file *file)
{ {
unsigned int minor = video_devdata(file)->minor; struct zoran *zr = video_drvdata(file);
struct zoran *zr = NULL;
struct zoran_fh *fh; struct zoran_fh *fh;
int i, res, first_open = 0, have_module_locks = 0; int res, first_open = 0;
lock_kernel(); dprintk(2, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n",
/* find the device */ ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user + 1);
for (i = 0; i < zoran_num; i++) {
if (zoran[i]->video_dev->minor == minor) {
zr = zoran[i];
break;
}
}
if (!zr) { lock_kernel();
dprintk(1, KERN_ERR "%s: device not found!\n", ZORAN_NAME);
res = -ENODEV;
goto open_unlock_and_return;
}
/* see fs/device.c - the kernel already locks during open(), /* see fs/device.c - the kernel already locks during open(),
* so locking ourselves only causes deadlocks */ * so locking ourselves only causes deadlocks */
/*mutex_lock(&zr->resource_lock);*/ /*mutex_lock(&zr->resource_lock);*/
if (zr->user >= 2048) {
dprintk(1, KERN_ERR "%s: too many users (%d) on device\n",
ZR_DEVNAME(zr), zr->user);
res = -EBUSY;
goto fail_unlock;
}
if (!zr->decoder) { if (!zr->decoder) {
dprintk(1, dprintk(1,
KERN_ERR "%s: no TV decoder loaded for device!\n", KERN_ERR "%s: no TV decoder loaded for device!\n",
ZR_DEVNAME(zr)); ZR_DEVNAME(zr));
res = -EIO; res = -EIO;
goto open_unlock_and_return; goto fail_unlock;
} }
/* try to grab a module lock */
if (!try_module_get(THIS_MODULE)) {
dprintk(1,
KERN_ERR
"%s: failed to acquire my own lock! PANIC!\n",
ZR_DEVNAME(zr));
res = -ENODEV;
goto open_unlock_and_return;
}
if (!try_module_get(zr->decoder->driver->driver.owner)) { if (!try_module_get(zr->decoder->driver->driver.owner)) {
dprintk(1, dprintk(1,
KERN_ERR KERN_ERR
"%s: failed to grab ownership of i2c decoder\n", "%s: failed to grab ownership of video decoder\n",
ZR_DEVNAME(zr)); ZR_DEVNAME(zr));
res = -EIO; res = -EIO;
module_put(THIS_MODULE); goto fail_unlock;
goto open_unlock_and_return;
} }
if (zr->encoder && if (zr->encoder &&
!try_module_get(zr->encoder->driver->driver.owner)) { !try_module_get(zr->encoder->driver->driver.owner)) {
dprintk(1, dprintk(1,
KERN_ERR KERN_ERR
"%s: failed to grab ownership of i2c encoder\n", "%s: failed to grab ownership of video encoder\n",
ZR_DEVNAME(zr)); ZR_DEVNAME(zr));
res = -EIO; res = -EIO;
module_put(zr->decoder->driver->driver.owner); goto fail_decoder;
module_put(THIS_MODULE);
goto open_unlock_and_return;
} }
have_module_locks = 1;
if (zr->user >= 2048) {
dprintk(1, KERN_ERR "%s: too many users (%d) on device\n",
ZR_DEVNAME(zr), zr->user);
res = -EBUSY;
goto open_unlock_and_return;
}
dprintk(1, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n",
ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user);
/* now, create the open()-specific file_ops struct */ /* now, create the open()-specific file_ops struct */
fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL); fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL);
if (!fh) { if (!fh) {
...@@ -1281,7 +1252,7 @@ zoran_open(struct file *file) ...@@ -1281,7 +1252,7 @@ zoran_open(struct file *file)
"%s: zoran_open() - allocation of zoran_fh failed\n", "%s: zoran_open() - allocation of zoran_fh failed\n",
ZR_DEVNAME(zr)); ZR_DEVNAME(zr));
res = -ENOMEM; res = -ENOMEM;
goto open_unlock_and_return; goto fail_encoder;
} }
/* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows /* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
* on norm-change! */ * on norm-change! */
...@@ -1292,9 +1263,8 @@ zoran_open(struct file *file) ...@@ -1292,9 +1263,8 @@ zoran_open(struct file *file)
KERN_ERR KERN_ERR
"%s: zoran_open() - allocation of overlay_mask failed\n", "%s: zoran_open() - allocation of overlay_mask failed\n",
ZR_DEVNAME(zr)); ZR_DEVNAME(zr));
kfree(fh);
res = -ENOMEM; res = -ENOMEM;
goto open_unlock_and_return; goto fail_fh;
} }
if (zr->user++ == 0) if (zr->user++ == 0)
...@@ -1319,22 +1289,19 @@ zoran_open(struct file *file) ...@@ -1319,22 +1289,19 @@ zoran_open(struct file *file)
return 0; return 0;
open_unlock_and_return: fail_fh:
/* if we grabbed locks, release them accordingly */ kfree(fh);
if (have_module_locks) { fail_encoder:
module_put(zr->decoder->driver->driver.owner); if (zr->encoder)
if (zr->encoder) { module_put(zr->encoder->driver->driver.owner);
module_put(zr->encoder->driver->driver.owner); fail_decoder:
} module_put(zr->decoder->driver->driver.owner);
module_put(THIS_MODULE); fail_unlock:
}
/* if there's no device found, we didn't obtain the lock either */
if (zr) {
/*mutex_unlock(&zr->resource_lock);*/
}
unlock_kernel(); unlock_kernel();
dprintk(2, KERN_INFO "%s: open failed (%d), users(-)=%d\n",
ZR_DEVNAME(zr), res, zr->user);
return res; return res;
} }
...@@ -1344,8 +1311,8 @@ zoran_close(struct file *file) ...@@ -1344,8 +1311,8 @@ zoran_close(struct file *file)
struct zoran_fh *fh = file->private_data; struct zoran_fh *fh = file->private_data;
struct zoran *zr = fh->zr; struct zoran *zr = fh->zr;
dprintk(1, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n", dprintk(2, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n",
ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user); ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user - 1);
/* kernel locks (fs/device.c), so don't do that ourselves /* kernel locks (fs/device.c), so don't do that ourselves
* (prevents deadlocks) */ * (prevents deadlocks) */
...@@ -1391,10 +1358,8 @@ zoran_close(struct file *file) ...@@ -1391,10 +1358,8 @@ zoran_close(struct file *file)
/* release locks on the i2c modules */ /* release locks on the i2c modules */
module_put(zr->decoder->driver->driver.owner); module_put(zr->decoder->driver->driver.owner);
if (zr->encoder) { if (zr->encoder)
module_put(zr->encoder->driver->driver.owner); module_put(zr->encoder->driver->driver.owner);
}
module_put(THIS_MODULE);
/*mutex_unlock(&zr->resource_lock);*/ /*mutex_unlock(&zr->resource_lock);*/
......
...@@ -94,16 +94,16 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); ...@@ -94,16 +94,16 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd);
/* Call the specified callback for all subdevs matching grp_id (if 0, then /* Call the specified callback for all subdevs matching grp_id (if 0, then
match them all). Ignore any errors. Note that you cannot add or delete match them all). Ignore any errors. Note that you cannot add or delete
a subdev while walking the subdevs list. */ a subdev while walking the subdevs list. */
#define v4l2_device_call_all(dev, grp_id, o, f, args...) \ #define v4l2_device_call_all(dev, grpid, o, f, args...) \
__v4l2_device_call_subdevs(dev, \ __v4l2_device_call_subdevs(dev, \
!(grp_id) || sd->grp_id == (grp_id), o, f , ##args) !(grpid) || sd->grp_id == (grpid), o, f , ##args)
/* Call the specified callback for all subdevs matching grp_id (if 0, then /* Call the specified callback for all subdevs matching grp_id (if 0, then
match them all). If the callback returns an error other than 0 or match them all). If the callback returns an error other than 0 or
-ENOIOCTLCMD, then return with that error code. Note that you cannot -ENOIOCTLCMD, then return with that error code. Note that you cannot
add or delete a subdev while walking the subdevs list. */ add or delete a subdev while walking the subdevs list. */
#define v4l2_device_call_until_err(dev, grp_id, o, f, args...) \ #define v4l2_device_call_until_err(dev, grpid, o, f, args...) \
__v4l2_device_call_subdevs_until_err(dev, \ __v4l2_device_call_subdevs_until_err(dev, \
!(grp_id) || sd->grp_id == (grp_id), o, f , ##args) !(grpid) || sd->grp_id == (grpid), o, f , ##args)
#endif #endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册