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) ...
This commit is contained in:
Коммит
9e6235e997
|
@ -4,12 +4,21 @@
|
|||
*
|
||||
* Compile with:
|
||||
* gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
|
||||
* Use as:
|
||||
* v4lgrab >image.ppm
|
||||
* Use as:
|
||||
* v4lgrab >image.ppm
|
||||
*
|
||||
* Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
|
||||
* Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
|
||||
* with minor modifications (Dave Forrest, drf5n@virginia.edu).
|
||||
* Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
|
||||
* 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 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/videodev.h>
|
||||
|
||||
#define FILE "/dev/video0"
|
||||
#define VIDEO_DEV "/dev/video0"
|
||||
|
||||
/* Stole this from tvset.c */
|
||||
|
||||
|
@ -90,7 +99,7 @@ int get_brightness_adj(unsigned char *image, long size, int *brightness) {
|
|||
|
||||
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_window win;
|
||||
struct video_picture vpic;
|
||||
|
@ -100,13 +109,13 @@ int main(int argc, char ** argv)
|
|||
unsigned int i, src_depth;
|
||||
|
||||
if (fd < 0) {
|
||||
perror(FILE);
|
||||
perror(VIDEO_DEV);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
|
||||
perror("VIDIOGCAP");
|
||||
fprintf(stderr, "(" FILE " not a video4linux device?)\n");
|
||||
fprintf(stderr, "(" VIDEO_DEV " not a video4linux device?)\n");
|
||||
close(fd);
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
@ -576,6 +576,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
|
|||
vv->vflip = c->value;
|
||||
break;
|
||||
default: {
|
||||
mutex_unlock(&dev->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -657,7 +657,7 @@ static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status)
|
|||
{
|
||||
struct mxl5007t_state *state = fe->tuner_priv;
|
||||
int rf_locked, ref_locked;
|
||||
s32 rf_input_level;
|
||||
s32 rf_input_level = 0;
|
||||
int ret;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
|
|
|
@ -93,6 +93,9 @@ struct dvb_ca_slot {
|
|||
/* current state of the CAM */
|
||||
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 */
|
||||
atomic_t camchange_count;
|
||||
|
||||
|
@ -711,14 +714,20 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b
|
|||
dprintk("%s\n", __func__);
|
||||
|
||||
|
||||
// sanity check
|
||||
/* sanity check */
|
||||
if (bytes_write > ca->slot_info[slot].link_buf_size)
|
||||
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)
|
||||
goto exitnowrite;
|
||||
if (status & (STATUSREG_DA | STATUSREG_RE)) {
|
||||
if (status & STATUSREG_DA)
|
||||
dvb_ca_en50221_thread_wakeup(ca);
|
||||
|
||||
status = -EAGAIN;
|
||||
goto exitnowrite;
|
||||
}
|
||||
|
@ -987,6 +996,8 @@ static int dvb_ca_en50221_thread(void *data)
|
|||
/* go through all the slots processing them */
|
||||
for (slot = 0; slot < ca->slot_count; slot++) {
|
||||
|
||||
mutex_lock(&ca->slot_info[slot].slot_lock);
|
||||
|
||||
// check the cam status + deal with CAMCHANGEs
|
||||
while (dvb_ca_en50221_check_camstatus(ca, slot)) {
|
||||
/* clear down an old CI slot if necessary */
|
||||
|
@ -1122,7 +1133,7 @@ static int dvb_ca_en50221_thread(void *data)
|
|||
|
||||
case DVB_CA_SLOTSTATE_RUNNING:
|
||||
if (!ca->open)
|
||||
continue;
|
||||
break;
|
||||
|
||||
// poll slots for data
|
||||
pktcount = 0;
|
||||
|
@ -1146,6 +1157,8 @@ static int dvb_ca_en50221_thread(void *data)
|
|||
}
|
||||
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,
|
|||
switch (cmd) {
|
||||
case CA_RESET:
|
||||
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) {
|
||||
dvb_ca_en50221_slot_shutdown(ca, slot);
|
||||
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,
|
|||
slot,
|
||||
DVB_CA_EN50221_CAMCHANGE_INSERTED);
|
||||
}
|
||||
mutex_unlock(&ca->slot_info[slot].slot_lock);
|
||||
}
|
||||
ca->next_read_slot = 0;
|
||||
dvb_ca_en50221_thread_wakeup(ca);
|
||||
|
@ -1308,7 +1323,9 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
mutex_lock(&ca->slot_info[slot].slot_lock);
|
||||
status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2);
|
||||
mutex_unlock(&ca->slot_info[slot].slot_lock);
|
||||
if (status == (fraglen + 2)) {
|
||||
written = 1;
|
||||
break;
|
||||
|
@ -1664,6 +1681,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
|
|||
ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE;
|
||||
atomic_set(&ca->slot_info[i].camchange_count, 0);
|
||||
ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED;
|
||||
mutex_init(&ca->slot_info[i].slot_lock);
|
||||
}
|
||||
|
||||
if (signal_pending(current)) {
|
||||
|
|
|
@ -45,8 +45,10 @@ struct dvb_ca_en50221 {
|
|||
/* the module owning this structure */
|
||||
struct module* owner;
|
||||
|
||||
/* NOTE: the read_*, write_* and poll_slot_status functions must use locks as
|
||||
* they may be called from several threads at once */
|
||||
/* NOTE: the read_*, write_* and poll_slot_status functions will be
|
||||
* 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 */
|
||||
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,
|
|||
u16 * abort_count)
|
||||
{
|
||||
u32 loc_cw_count = 0, loc_err_count;
|
||||
u16 loc_abort_count;
|
||||
u16 loc_abort_count = 0;
|
||||
int ret;
|
||||
|
||||
ret =
|
||||
|
|
|
@ -694,7 +694,12 @@ static int af9015_read_config(struct usb_device *udev)
|
|||
|
||||
/* IR remote controller */
|
||||
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)
|
||||
goto error;
|
||||
deb_info("%s: IR mode:%d\n", __func__, val);
|
||||
|
@ -835,18 +840,19 @@ static int af9015_read_config(struct usb_device *udev)
|
|||
if (!dvb_usb_af9015_dual_mode)
|
||||
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++) {
|
||||
/* USB1.1 set smaller buffersize and disable 2nd adapter */
|
||||
if (udev->speed == USB_SPEED_FULL) {
|
||||
af9015_properties[i].adapter->stream.u.bulk.buffersize =
|
||||
TS_USB11_MAX_PACKET_SIZE;
|
||||
af9015_properties[i].adapter[0].stream.u.bulk.buffersize
|
||||
= TS_USB11_MAX_PACKET_SIZE;
|
||||
/* disable 2nd adapter because we don't have
|
||||
PID-filters */
|
||||
af9015_config.dual_mode = 0;
|
||||
} else {
|
||||
af9015_properties[i].adapter->stream.u.bulk.buffersize =
|
||||
TS_USB20_MAX_PACKET_SIZE;
|
||||
af9015_properties[i].adapter[0].stream.u.bulk.buffersize
|
||||
= TS_USB20_MAX_PACKET_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1254,6 +1260,12 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
.type = USB_BULK,
|
||||
.count = 6,
|
||||
.endpoint = 0x85,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize =
|
||||
TS_USB20_MAX_PACKET_SIZE,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
@ -1353,6 +1365,12 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
.type = USB_BULK,
|
||||
.count = 6,
|
||||
.endpoint = 0x85,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize =
|
||||
TS_USB20_MAX_PACKET_SIZE,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1393,6 +1393,9 @@ struct usb_device_id dib0700_usb_id_table[] = {
|
|||
{ USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) },
|
||||
/* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) },
|
||||
{ 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 */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
|
||||
|
@ -1537,7 +1540,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ "DiBcom STK7700D reference design",
|
||||
{ &dib0700_usb_id_table[14], NULL },
|
||||
{ NULL },
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
|
@ -1557,7 +1561,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.num_device_descs = 2,
|
||||
.num_device_descs = 3,
|
||||
.devices = {
|
||||
{ "ASUS My Cinema U3000 Mini DVBT Tuner",
|
||||
{ &dib0700_usb_id_table[23], NULL },
|
||||
|
@ -1566,6 +1570,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ "Yuan EC372S",
|
||||
{ &dib0700_usb_id_table[31], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "Terratec Cinergy T Express",
|
||||
{ &dib0700_usb_id_table[42], NULL },
|
||||
{ NULL },
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1653,7 +1661,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
}
|
||||
},
|
||||
|
||||
.num_device_descs = 4,
|
||||
.num_device_descs = 5,
|
||||
.devices = {
|
||||
{ "DiBcom STK7070PD reference design",
|
||||
{ &dib0700_usb_id_table[17], NULL },
|
||||
|
@ -1670,6 +1678,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ "Hauppauge Nova-TD-500 (84xxx)",
|
||||
{ &dib0700_usb_id_table[36], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "Terratec Cinergy DT USB XS Diversity",
|
||||
{ &dib0700_usb_id_table[43], NULL },
|
||||
{ NULL },
|
||||
}
|
||||
}
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
|
|
@ -162,8 +162,10 @@
|
|||
#define USB_PID_AVERMEDIA_A309 0xa309
|
||||
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
|
||||
#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_EXPRESS 0x0060
|
||||
#define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062
|
||||
#define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078
|
||||
#define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e
|
||||
#define USB_PID_PINNACLE_PCTV2000E 0x022c
|
||||
|
|
|
@ -646,7 +646,7 @@ static int drx_tune(struct drx397xD_state *s,
|
|||
u32 edi = 0, ebx = 0, ebp = 0, edx = 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;
|
||||
pr_debug("%s %d\n", __func__, s->config.d60);
|
||||
|
||||
|
|
|
@ -545,9 +545,6 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe,
|
|||
|
||||
s5h1409_enable_modulation(fe, p->u.vsb.modulation);
|
||||
|
||||
/* Allow the demod to settle */
|
||||
msleep(100);
|
||||
|
||||
if (fe->ops.tuner_ops.set_params) {
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
|
@ -562,6 +559,10 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe,
|
|||
s5h1409_set_qam_interleave_mode(fe);
|
||||
}
|
||||
|
||||
/* Issue a reset to the demod so it knows to resync against the
|
||||
newly tuned frequency */
|
||||
s5h1409_softreset(fe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@ inline u32 stb0899_do_div(u64 n, u32 d)
|
|||
return n;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* These functions are currently unused */
|
||||
/*
|
||||
* stb0899_calc_srate
|
||||
* Compute symbol rate
|
||||
|
@ -63,6 +65,7 @@ static u32 stb0899_get_srate(struct stb0899_state *state)
|
|||
|
||||
return stb0899_calc_srate(internal->master_clk, sfr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* stb0899_set_srate
|
||||
|
|
|
@ -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);
|
||||
if (budget->dvb_frontend) {
|
||||
budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
|
||||
budget->dvb_frontend->tuner_priv = NULL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -1384,7 +1384,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
|
|||
static int ttusb_dec_init_stb(struct ttusb_dec *dec)
|
||||
{
|
||||
int result;
|
||||
unsigned int mode, model, version;
|
||||
unsigned int mode = 0, model = 0, version = 0;
|
||||
|
||||
dprintk("%s\n", __func__);
|
||||
|
||||
|
|
|
@ -194,10 +194,10 @@ static int amradio_start(struct amradio_device *radio)
|
|||
return retval;
|
||||
}
|
||||
|
||||
mutex_unlock(&radio->lock);
|
||||
|
||||
radio->muted = 0;
|
||||
|
||||
mutex_unlock(&radio->lock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -230,10 +230,10 @@ static int amradio_stop(struct amradio_device *radio)
|
|||
return retval;
|
||||
}
|
||||
|
||||
mutex_unlock(&radio->lock);
|
||||
|
||||
radio->muted = 1;
|
||||
|
||||
mutex_unlock(&radio->lock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -284,10 +284,10 @@ static int amradio_setfreq(struct amradio_device *radio, int freq)
|
|||
return retval;
|
||||
}
|
||||
|
||||
mutex_unlock(&radio->lock);
|
||||
|
||||
radio->stereo = 0;
|
||||
|
||||
mutex_unlock(&radio->lock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
|
|
|
@ -1586,7 +1586,8 @@ static int mpeg_open(struct file *file)
|
|||
lock_kernel();
|
||||
list_for_each(list, &cx23885_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;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -730,12 +730,13 @@ static int video_open(struct file *file)
|
|||
lock_kernel();
|
||||
list_for_each(list, &cx23885_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;
|
||||
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
}
|
||||
if (h->vbi_dev &&
|
||||
h->vbi_dev->minor == minor) {
|
||||
h->vbi_dev->minor == minor) {
|
||||
dev = h;
|
||||
type = V4L2_BUF_TYPE_VBI_CAPTURE;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -614,35 +614,42 @@ static struct stv0288_config tevii_tuner_earda_config = {
|
|||
.set_ts_params = cx24116_set_ts_param,
|
||||
};
|
||||
|
||||
static int cx8802_alloc_frontends(struct cx8802_dev *dev)
|
||||
{
|
||||
struct cx88_core *core = dev->core;
|
||||
struct videobuf_dvb_frontend *fe = NULL;
|
||||
int i;
|
||||
|
||||
mutex_init(&dev->frontends.lock);
|
||||
INIT_LIST_HEAD(&dev->frontends.felist);
|
||||
|
||||
if (!core->board.num_frontends)
|
||||
return -ENODEV;
|
||||
|
||||
printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
|
||||
core->board.num_frontends);
|
||||
for (i = 1; i <= core->board.num_frontends; i++) {
|
||||
fe = videobuf_dvb_alloc_frontend(&dev->frontends, i);
|
||||
if (!fe) {
|
||||
printk(KERN_ERR "%s() failed to alloc\n", __func__);
|
||||
videobuf_dvb_dealloc_frontends(&dev->frontends);
|
||||
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 */
|
||||
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);
|
||||
INIT_LIST_HEAD(&dev->frontends.felist);
|
||||
|
||||
printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
|
||||
core->board.num_frontends);
|
||||
for (i = 1; i <= core->board.num_frontends; i++) {
|
||||
fe0 = videobuf_dvb_alloc_frontend(&dev->frontends, i);
|
||||
if (!fe0) {
|
||||
printk(KERN_ERR "%s() failed to alloc\n", __func__);
|
||||
videobuf_dvb_dealloc_frontends(&dev->frontends);
|
||||
goto frontend_detach;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the first frontend */
|
||||
fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
|
||||
if (!fe0)
|
||||
|
@ -1243,6 +1250,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
|
|||
struct cx88_core *core = drv->core;
|
||||
struct cx8802_dev *dev = drv->core->dvbdev;
|
||||
int err;
|
||||
struct videobuf_dvb_frontend *fe;
|
||||
int i;
|
||||
|
||||
dprintk( 1, "%s\n", __func__);
|
||||
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)
|
|||
/* If vp3054 isn't enabled, a stub will just return 0 */
|
||||
err = vp3054_i2c_probe(dev);
|
||||
if (0 != err)
|
||||
goto fail_probe;
|
||||
goto fail_core;
|
||||
|
||||
/* dvb stuff */
|
||||
printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
|
||||
dev->ts_gen_cntrl = 0x0c;
|
||||
|
||||
err = -ENODEV;
|
||||
if (core->board.num_frontends) {
|
||||
struct videobuf_dvb_frontend *fe;
|
||||
int i;
|
||||
err = cx8802_alloc_frontends(dev);
|
||||
if (err)
|
||||
goto fail_core;
|
||||
|
||||
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",
|
||||
err = -ENODEV;
|
||||
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);
|
||||
goto fail_probe;
|
||||
}
|
||||
videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
|
||||
goto fail_probe;
|
||||
}
|
||||
videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
|
||||
&dev->pci->dev, &dev->slock,
|
||||
V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||
V4L2_FIELD_TOP,
|
||||
sizeof(struct cx88_buffer),
|
||||
dev);
|
||||
/* init struct videobuf_dvb */
|
||||
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;
|
||||
/* init struct videobuf_dvb */
|
||||
fe->dvb.name = dev->core->name;
|
||||
}
|
||||
|
||||
err = dvb_register(dev);
|
||||
if (err)
|
||||
/* frontends/adapter de-allocated in dvb_register */
|
||||
|
|
|
@ -336,8 +336,8 @@ struct cx88_core {
|
|||
/* config info -- dvb */
|
||||
#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);
|
||||
void (*gate_ctrl)(struct cx88_core *core, int open);
|
||||
#endif
|
||||
void (*gate_ctrl)(struct cx88_core *core, int open);
|
||||
|
||||
/* state info */
|
||||
struct task_struct *kthread;
|
||||
|
|
|
@ -62,9 +62,15 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev)
|
|||
|
||||
dprintk("Stopping isoc\n");
|
||||
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]);
|
||||
dev->adev.urb[i] = NULL;
|
||||
|
||||
kfree(dev->adev.transfer_buffer[i]);
|
||||
dev->adev.transfer_buffer[i] = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -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
|
||||
*substream)
|
||||
{
|
||||
struct em28xx *dev;
|
||||
unsigned long flags;
|
||||
|
||||
struct em28xx *dev;
|
||||
snd_pcm_uframes_t hwptr_done;
|
||||
|
||||
dev = snd_pcm_substream_chip(substream);
|
||||
spin_lock_irqsave(&dev->adev.slock, flags);
|
||||
hwptr_done = dev->adev.hwptr_done_capture;
|
||||
spin_unlock_irqrestore(&dev->adev.slock, flags);
|
||||
|
||||
return hwptr_done;
|
||||
}
|
||||
|
|
|
@ -102,6 +102,18 @@ static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = {
|
|||
/* Board - EM2870 Kworld 355u
|
||||
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 */
|
||||
static struct em28xx_reg_seq default_tuner_gpio[] = {
|
||||
{EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10},
|
||||
|
@ -1177,29 +1189,33 @@ struct em28xx_board em28xx_boards[] = {
|
|||
.gpio = hauppauge_wintv_hvr_900_analog,
|
||||
} },
|
||||
},
|
||||
[EM2883_BOARD_KWORLD_HYBRID_A316] = {
|
||||
[EM2883_BOARD_KWORLD_HYBRID_330U] = {
|
||||
.name = "Kworld PlusTV HD Hybrid 330",
|
||||
.tuner_type = TUNER_XC2028,
|
||||
.tuner_gpio = default_tuner_gpio,
|
||||
.decoder = EM28XX_TVP5150,
|
||||
.mts_firmware = 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 = { {
|
||||
.type = EM28XX_VMUX_TELEVISION,
|
||||
.vmux = TVP5150_COMPOSITE0,
|
||||
.amux = EM28XX_AMUX_VIDEO,
|
||||
.gpio = default_analog,
|
||||
.gpio = kworld_330u_analog,
|
||||
.aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
|
||||
}, {
|
||||
.type = EM28XX_VMUX_COMPOSITE1,
|
||||
.vmux = TVP5150_COMPOSITE1,
|
||||
.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,
|
||||
.vmux = TVP5150_SVIDEO,
|
||||
.amux = EM28XX_AMUX_LINE_IN,
|
||||
.gpio = hauppauge_wintv_hvr_900_analog,
|
||||
.gpio = kworld_330u_analog,
|
||||
} },
|
||||
},
|
||||
[EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = {
|
||||
|
@ -1249,7 +1265,7 @@ struct usb_device_id em28xx_id_table [] = {
|
|||
{ USB_DEVICE(0xeb1a, 0xe310),
|
||||
.driver_info = EM2880_BOARD_MSI_DIGIVOX_AD },
|
||||
{ USB_DEVICE(0xeb1a, 0xa316),
|
||||
.driver_info = EM2883_BOARD_KWORLD_HYBRID_A316 },
|
||||
.driver_info = EM2883_BOARD_KWORLD_HYBRID_330U },
|
||||
{ USB_DEVICE(0xeb1a, 0xe320),
|
||||
.driver_info = EM2880_BOARD_MSI_DIGIVOX_AD_II },
|
||||
{ USB_DEVICE(0xeb1a, 0xe323),
|
||||
|
@ -1526,6 +1542,10 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
|
|||
/* FIXME: Better to specify the needed IF */
|
||||
ctl->demod = XC3028_FE_DEFAULT;
|
||||
break;
|
||||
case EM2883_BOARD_KWORLD_HYBRID_330U:
|
||||
ctl->demod = XC3028_FE_CHINA;
|
||||
ctl->fname = XC2028_DEFAULT_FIRMWARE;
|
||||
break;
|
||||
default:
|
||||
ctl->demod = XC3028_FE_OREN538;
|
||||
}
|
||||
|
|
|
@ -438,6 +438,10 @@ int em28xx_audio_analog_set(struct em28xx *dev)
|
|||
if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
|
||||
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 */
|
||||
vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8);
|
||||
|
||||
|
@ -454,6 +458,15 @@ int em28xx_audio_analog_set(struct em28xx *dev)
|
|||
em28xx_warn("couldn't setup AC97 register %d\n",
|
||||
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;
|
||||
|
@ -847,8 +860,11 @@ void em28xx_uninit_isoc(struct em28xx *dev)
|
|||
for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
|
||||
urb = dev->isoc_ctl.urb[i];
|
||||
if (urb) {
|
||||
usb_kill_urb(urb);
|
||||
usb_unlink_urb(urb);
|
||||
if (!irqs_disabled())
|
||||
usb_kill_urb(urb);
|
||||
else
|
||||
usb_unlink_urb(urb);
|
||||
|
||||
if (dev->isoc_ctl.transfer_buffer[i]) {
|
||||
usb_buffer_free(dev->udev,
|
||||
urb->transfer_buffer_length,
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "lgdt330x.h"
|
||||
#include "zl10353.h"
|
||||
#include "s5h1409.h"
|
||||
#ifdef EM28XX_DRX397XD_SUPPORT
|
||||
#include "drx397xD.h"
|
||||
#endif
|
||||
|
@ -232,6 +233,15 @@ static struct zl10353_config em28xx_zl10353_with_xc3028 = {
|
|||
.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
|
||||
/* [TODO] djh - not sure yet what the device config needs to contain */
|
||||
static struct drx397xD_config em28xx_drx397xD_with_xc3028 = {
|
||||
|
@ -412,7 +422,6 @@ static int dvb_init(struct em28xx *dev)
|
|||
case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
|
||||
case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
|
||||
case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
|
||||
case EM2883_BOARD_KWORLD_HYBRID_A316:
|
||||
case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
|
||||
dvb->frontend = dvb_attach(lgdt330x_attach,
|
||||
&em2880_lgdt3303_dev,
|
||||
|
@ -433,6 +442,15 @@ static int dvb_init(struct em28xx *dev)
|
|||
goto out_free;
|
||||
}
|
||||
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:
|
||||
#ifdef EM28XX_DRX397XD_SUPPORT
|
||||
/* 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)
|
|||
if (0 == INPUT(i)->type)
|
||||
return -EINVAL;
|
||||
|
||||
dev->ctl_input = i;
|
||||
|
||||
mutex_lock(&dev->lock);
|
||||
|
||||
video_mux(dev, i);
|
||||
|
||||
video_mux(dev, dev->ctl_input);
|
||||
mutex_unlock(&dev->lock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -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 *dev = fh->dev;
|
||||
|
||||
|
||||
if (a->index >= MAX_EM28XX_INPUT)
|
||||
return -EINVAL;
|
||||
if (0 == INPUT(a->index)->type)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&dev->lock);
|
||||
|
||||
dev->ctl_ainput = INPUT(a->index)->amux;
|
||||
|
@ -1950,6 +1956,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
|
|||
|
||||
int em28xx_register_analog_devices(struct em28xx *dev)
|
||||
{
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "%s: v4l2 driver version %d.%d.%d\n",
|
||||
|
@ -1957,23 +1964,6 @@ int em28xx_register_analog_devices(struct em28xx *dev)
|
|||
(EM28XX_VERSION_CODE >> 16) & 0xff,
|
||||
(EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff);
|
||||
|
||||
/* Analog specific initialization */
|
||||
dev->format = &format[0];
|
||||
video_mux(dev, 0);
|
||||
|
||||
/* enable vbi capturing */
|
||||
|
||||
/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
|
||||
/* em28xx_write_reg(dev, EM28XX_R0F_XCLK, 0x80); clk register */
|
||||
em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51);
|
||||
|
||||
dev->mute = 1; /* maybe not the right place... */
|
||||
dev->volume = 0x1f;
|
||||
|
||||
em28xx_set_outfmt(dev);
|
||||
em28xx_colorlevels_set_default(dev);
|
||||
em28xx_compression_disable(dev);
|
||||
|
||||
/* set default norm */
|
||||
dev->norm = em28xx_video_template.current_norm;
|
||||
dev->width = norm_maxw(dev);
|
||||
|
@ -1981,9 +1971,26 @@ int em28xx_register_analog_devices(struct em28xx *dev)
|
|||
dev->interlaced = EM28XX_INTERLACED_DEFAULT;
|
||||
dev->hscale = 0;
|
||||
dev->vscale = 0;
|
||||
dev->ctl_input = 0;
|
||||
|
||||
/* FIXME: This is a very bad hack! Not all devices have TV on input 2 */
|
||||
dev->ctl_input = 2;
|
||||
/* Analog specific initialization */
|
||||
dev->format = &format[0];
|
||||
video_mux(dev, dev->ctl_input);
|
||||
|
||||
/* Audio defaults */
|
||||
dev->mute = 1;
|
||||
dev->volume = 0x1f;
|
||||
|
||||
/* enable vbi capturing */
|
||||
|
||||
/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
|
||||
val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
|
||||
em28xx_write_reg(dev, EM28XX_R0F_XCLK, (EM28XX_XCLK_AUDIO_UNMUTE | val));
|
||||
em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51);
|
||||
|
||||
em28xx_set_outfmt(dev);
|
||||
em28xx_colorlevels_set_default(dev);
|
||||
em28xx_compression_disable(dev);
|
||||
|
||||
/* allocate and fill video video_device struct */
|
||||
dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
#define EM2882_BOARD_KWORLD_VS_DVBT 54
|
||||
#define EM2882_BOARD_TERRATEC_HYBRID_XS 55
|
||||
#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 EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60
|
||||
#define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61
|
||||
|
@ -300,13 +300,32 @@ enum em28xx_amux {
|
|||
};
|
||||
|
||||
enum em28xx_aout {
|
||||
/* AC97 outputs */
|
||||
EM28XX_AOUT_MASTER = 1 << 0,
|
||||
EM28XX_AOUT_LINE = 1 << 1,
|
||||
EM28XX_AOUT_MONO = 1 << 2,
|
||||
EM28XX_AOUT_LFE = 1 << 3,
|
||||
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 {
|
||||
int reg;
|
||||
unsigned char val, mask;
|
||||
|
|
|
@ -423,7 +423,8 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
|
|||
break;
|
||||
|
||||
gspca_dev->urb[i] = NULL;
|
||||
usb_kill_urb(urb);
|
||||
if (!gspca_dev->present)
|
||||
usb_kill_urb(urb);
|
||||
if (urb->transfer_buffer != NULL)
|
||||
usb_buffer_free(gspca_dev->dev,
|
||||
urb->transfer_buffer_length,
|
||||
|
@ -1950,7 +1951,6 @@ void gspca_disconnect(struct usb_interface *intf)
|
|||
struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
|
||||
|
||||
gspca_dev->present = 0;
|
||||
gspca_dev->streaming = 0;
|
||||
|
||||
usb_set_intfdata(intf, NULL);
|
||||
|
||||
|
|
|
@ -949,8 +949,10 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
|
|||
itv->instance = atomic_inc_return(&ivtv_instance) - 1;
|
||||
|
||||
retval = v4l2_device_register(&dev->dev, &itv->device);
|
||||
if (retval)
|
||||
if (retval) {
|
||||
kfree(itv);
|
||||
return retval;
|
||||
}
|
||||
/* "ivtv + PCI ID" is a bit of a mouthful, so use
|
||||
"ivtv + instance" instead. */
|
||||
snprintf(itv->device.name, sizeof(itv->device.name),
|
||||
|
|
|
@ -62,7 +62,6 @@
|
|||
#include <linux/poll.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/version.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include "pwc.h"
|
||||
|
|
|
@ -149,7 +149,7 @@ static const struct i2c_reg_value saa7127_init_config_common[] = {
|
|||
{ SAA7127_REG_COPYGEN_0, 0x77 },
|
||||
{ SAA7127_REG_COPYGEN_1, 0x41 },
|
||||
{ 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_COLORDIFF_RGB, 0x00 },
|
||||
{ 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)
|
|||
break;
|
||||
|
||||
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 */
|
||||
break;
|
||||
|
||||
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 */
|
||||
break;
|
||||
|
||||
|
@ -508,7 +514,10 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output)
|
|||
break;
|
||||
|
||||
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 */
|
||||
break;
|
||||
|
||||
|
@ -731,24 +740,6 @@ static int saa7127_probe(struct i2c_client *client,
|
|||
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 */
|
||||
state->ident = id->driver_data;
|
||||
} else { /* Needs detection */
|
||||
|
@ -770,6 +761,23 @@ static int saa7127_probe(struct i2c_client *client,
|
|||
|
||||
v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->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)
|
||||
saa7127_write_inittab(sd, saa7129_init_config_extra);
|
||||
return 0;
|
||||
|
|
|
@ -1089,7 +1089,11 @@ static int saa7134_alsa_init(void)
|
|||
|
||||
list_for_each(list,&saa7134_devlist) {
|
||||
dev = list_entry(list, struct saa7134_dev, devlist);
|
||||
alsa_device_init(dev);
|
||||
if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130)
|
||||
printk(KERN_INFO "%s/alsa: %s doesn't support digital audio\n",
|
||||
dev->name, saa7134_boards[dev->board].name);
|
||||
else
|
||||
alsa_device_init(dev);
|
||||
}
|
||||
|
||||
if (dev == NULL)
|
||||
|
|
|
@ -660,6 +660,10 @@ static int saa7134_hwinit1(struct saa7134_dev *dev)
|
|||
|
||||
saa_writel(SAA7134_IRQ1, 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);
|
||||
spin_lock_init(&dev->slock);
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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) {
|
||||
case V4L2_CID_AUDIO_VOLUME:
|
||||
|
|
|
@ -427,6 +427,9 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
|
|||
const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" };
|
||||
|
||||
memset(tvee, 0, sizeof(*tvee));
|
||||
tvee->tuner_type = TUNER_ABSENT;
|
||||
tvee->tuner2_type = TUNER_ABSENT;
|
||||
|
||||
done = len = beenhere = 0;
|
||||
|
||||
/* 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)
|
|||
|
||||
decoder->pdata = client->dev.platform_data;
|
||||
if (!decoder->pdata) {
|
||||
v4l_err(client, "No platform data\n!!");
|
||||
v4l_err(client, "No platform data!!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
|
|
|
@ -157,7 +157,7 @@ usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
|
|||
struct i2c_msg *pmsg;
|
||||
struct usb_usbvision *usbvision;
|
||||
int i, ret;
|
||||
unsigned char addr;
|
||||
unsigned char addr = 0;
|
||||
|
||||
usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* uvc_ctrl.c -- USB Video Class driver - Controls
|
||||
*
|
||||
* Copyright (C) 2005-2008
|
||||
* Copyright (C) 2005-2009
|
||||
* Laurent Pinchart (laurent.pinchart@skynet.be)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -12,7 +12,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
@ -29,7 +28,7 @@
|
|||
#define UVC_CTRL_DATA_BACKUP 1
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Control, formats, ...
|
||||
* Controls
|
||||
*/
|
||||
|
||||
static struct uvc_control_info uvc_ctrls[] = {
|
||||
|
@ -635,7 +634,7 @@ static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
|
|||
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)
|
||||
value |= -(value & (1 << (mapping->size - 1)));
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* uvc_driver.c -- USB Video Class driver
|
||||
*
|
||||
* Copyright (C) 2005-2008
|
||||
* Copyright (C) 2005-2009
|
||||
* Laurent Pinchart (laurent.pinchart@skynet.be)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -24,7 +24,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
@ -49,7 +48,7 @@ static unsigned int uvc_quirks_param;
|
|||
unsigned int uvc_trace_param;
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Control, formats, ...
|
||||
* Video formats
|
||||
*/
|
||||
|
||||
static struct uvc_format_desc uvc_fmts[] = {
|
||||
|
@ -474,7 +473,7 @@ static int uvc_parse_format(struct uvc_device *dev,
|
|||
|
||||
/* Several UVC chipsets screw up dwMaxVideoFrameBufferSize
|
||||
* 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
|
||||
* memory usage as well as a wrong image size information. For
|
||||
* uncompressed formats this can be fixed by computing the
|
||||
|
@ -487,7 +486,7 @@ static int uvc_parse_format(struct uvc_device *dev,
|
|||
/* Some bogus devices report dwMinFrameInterval equal to
|
||||
* dwMaxFrameInterval and have dwFrameIntervalStep set to
|
||||
* 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) {
|
||||
interval = get_unaligned_le32(&buffer[26+4*i]);
|
||||
|
@ -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
|
||||
* and containing the following units:
|
||||
*
|
||||
* - a USB Streaming Output Terminal
|
||||
* - one Output Terminal (USB Streaming or Display)
|
||||
* - zero or one Processing Unit
|
||||
* - zero, one or mode single-input Selector Units
|
||||
* - zero or one multiple-input Selector Units, provided all inputs are
|
||||
* connected to input terminals
|
||||
* - 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
|
||||
* extension units.
|
||||
|
@ -1531,10 +1530,6 @@ static int uvc_register_video(struct uvc_device *dev)
|
|||
|
||||
/* Set the driver data before calling video_register_device, otherwise
|
||||
* 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;
|
||||
video_set_drvdata(vdev, &dev->video);
|
||||
|
@ -1569,7 +1564,7 @@ void uvc_delete(struct kref *kref)
|
|||
struct uvc_device *dev = container_of(kref, struct uvc_device, kref);
|
||||
struct list_head *p, *n;
|
||||
|
||||
/* Unregister the video device */
|
||||
/* Unregister the video device. */
|
||||
uvc_unregister_video(dev);
|
||||
usb_put_intf(dev->intf);
|
||||
usb_put_dev(dev->udev);
|
||||
|
@ -1612,7 +1607,7 @@ static int uvc_probe(struct usb_interface *intf,
|
|||
uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",
|
||||
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)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1633,14 +1628,14 @@ static int uvc_probe(struct usb_interface *intf,
|
|||
le16_to_cpu(udev->descriptor.idVendor),
|
||||
le16_to_cpu(udev->descriptor.idProduct));
|
||||
|
||||
/* Parse the Video Class control descriptor */
|
||||
/* Parse the Video Class control descriptor. */
|
||||
if (uvc_parse_control(dev) < 0) {
|
||||
uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
|
||||
"descriptors.\n");
|
||||
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,
|
||||
udev->product ? udev->product : "<unnamed>",
|
||||
le16_to_cpu(udev->descriptor.idVendor),
|
||||
|
@ -1653,18 +1648,18 @@ static int uvc_probe(struct usb_interface *intf,
|
|||
"linux-uvc-devel mailing list.\n");
|
||||
}
|
||||
|
||||
/* Initialize controls */
|
||||
/* Initialize controls. */
|
||||
if (uvc_ctrl_init_device(dev) < 0)
|
||||
goto error;
|
||||
|
||||
/* Register the video devices */
|
||||
/* Register the video devices. */
|
||||
if (uvc_register_video(dev) < 0)
|
||||
goto error;
|
||||
|
||||
/* Save our data pointer in the interface data */
|
||||
/* Save our data pointer in the interface data. */
|
||||
usb_set_intfdata(intf, dev);
|
||||
|
||||
/* Initialize the interrupt URB */
|
||||
/* Initialize the interrupt URB. */
|
||||
if ((ret = uvc_status_init(dev)) < 0) {
|
||||
uvc_printk(KERN_INFO, "Unable to initialize the status "
|
||||
"endpoint (%d), status interrupt will not be "
|
||||
|
@ -1839,24 +1834,24 @@ static struct usb_device_id uvc_ids[] = {
|
|||
.bInterfaceSubClass = 1,
|
||||
.bInterfaceProtocol = 0 },
|
||||
/* Apple Built-In iSight */
|
||||
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
|
||||
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
|
||||
| USB_DEVICE_ID_MATCH_INT_INFO,
|
||||
.idVendor = 0x05ac,
|
||||
.idProduct = 0x8501,
|
||||
.bInterfaceClass = USB_CLASS_VIDEO,
|
||||
.bInterfaceSubClass = 1,
|
||||
.bInterfaceProtocol = 0,
|
||||
.bInterfaceClass = USB_CLASS_VIDEO,
|
||||
.bInterfaceSubClass = 1,
|
||||
.bInterfaceProtocol = 0,
|
||||
.driver_info = UVC_QUIRK_PROBE_MINMAX
|
||||
| UVC_QUIRK_BUILTIN_ISIGHT },
|
||||
/* 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,
|
||||
.idVendor = 0x05e3,
|
||||
.idProduct = 0x0505,
|
||||
.bInterfaceClass = USB_CLASS_VIDEO,
|
||||
.bInterfaceSubClass = 1,
|
||||
.bInterfaceProtocol = 0,
|
||||
.driver_info = UVC_QUIRK_STREAM_NO_FID },
|
||||
.idVendor = 0x05e3,
|
||||
.idProduct = 0x0505,
|
||||
.bInterfaceClass = USB_CLASS_VIDEO,
|
||||
.bInterfaceSubClass = 1,
|
||||
.bInterfaceProtocol = 0,
|
||||
.driver_info = UVC_QUIRK_STREAM_NO_FID },
|
||||
/* MT6227 */
|
||||
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
|
||||
| USB_DEVICE_ID_MATCH_INT_INFO,
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
*
|
||||
* Copyright (C) 2006-2007
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* uvc_queue.c -- USB Video Class driver - Buffers management
|
||||
*
|
||||
* Copyright (C) 2005-2008
|
||||
* Copyright (C) 2005-2009
|
||||
* Laurent Pinchart (laurent.pinchart@skynet.be)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -12,7 +12,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -37,22 +36,22 @@
|
|||
* to user space will return -EBUSY.
|
||||
*
|
||||
* 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
|
||||
* holds all queued buffers (both 'empty' and 'done' buffers), and an irq
|
||||
* queue which holds empty buffers. This design (copied from video-buf)
|
||||
* minimizes locking in interrupt, as only one queue is shared between
|
||||
* interrupt and user contexts.
|
||||
* drivers that use an in queue and an out queue, we use a main queue to hold
|
||||
* all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
|
||||
* hold empty buffers. This design (copied from video-buf) minimizes locking
|
||||
* in interrupt, as only one queue is shared between interrupt and user
|
||||
* contexts.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* The completion handler fetches a buffer from the irq queue and fills it
|
||||
|
@ -60,7 +59,7 @@
|
|||
* returns immediately.
|
||||
*
|
||||
* 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
|
||||
* process tries to dequeue a buffer after it has been marked ready, the
|
||||
* dequeing will succeed immediately.
|
||||
|
@ -91,8 +90,8 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
|
|||
/*
|
||||
* Allocate the video buffers.
|
||||
*
|
||||
* Pages are reserved to make sure they will not be swaped, as they will be
|
||||
* filled in URB completion handler.
|
||||
* Pages are reserved to make sure they will not be swapped, as they will be
|
||||
* filled in the URB completion handler.
|
||||
*
|
||||
* 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,
|
|||
__uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
|
||||
|
||||
done:
|
||||
mutex_unlock(&queue->mutex);
|
||||
return ret;
|
||||
mutex_unlock(&queue->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -236,7 +235,7 @@ int uvc_queue_buffer(struct uvc_video_queue *queue,
|
|||
}
|
||||
|
||||
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");
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
|
@ -429,7 +428,7 @@ done:
|
|||
* Cancel the video buffers queue.
|
||||
*
|
||||
* 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
|
||||
* fail with -ENODEV.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* uvc_status.c -- USB Video Class driver - Status endpoint
|
||||
*
|
||||
* Copyright (C) 2007-2008
|
||||
* Copyright (C) 2007-2009
|
||||
* Laurent Pinchart (laurent.pinchart@skynet.be)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -12,7 +12,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/input.h>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* uvc_v4l2.c -- USB Video Class driver - V4L2 API
|
||||
*
|
||||
* Copyright (C) 2005-2008
|
||||
* Copyright (C) 2005-2009
|
||||
* Laurent Pinchart (laurent.pinchart@skynet.be)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -37,7 +37,7 @@
|
|||
* must be grouped (for instance the Red Balance, Blue Balance and Do White
|
||||
* Balance V4L2 controls use the White Balance Component UVC control) or
|
||||
* 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.
|
||||
*/
|
||||
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,
|
|||
probe->dwMaxVideoFrameSize =
|
||||
video->streaming->ctrl.dwMaxVideoFrameSize;
|
||||
|
||||
/* Probe the device */
|
||||
/* Probe the device. */
|
||||
if ((ret = uvc_probe_video(video, probe)) < 0)
|
||||
goto done;
|
||||
|
||||
|
@ -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
|
||||
* 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
|
||||
* otherwise. Privileges are dismissed when closing the instance.
|
||||
*
|
||||
* Operations which require privileges are:
|
||||
* Operations that require privileges are:
|
||||
*
|
||||
* - VIDIOC_S_INPUT
|
||||
* - VIDIOC_S_PARM
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* uvc_video.c -- USB Video Class driver - Video handling
|
||||
*
|
||||
* Copyright (C) 2005-2008
|
||||
* Copyright (C) 2005-2009
|
||||
* Laurent Pinchart (laurent.pinchart@skynet.be)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -12,7 +12,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
@ -115,7 +114,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
|
|||
ctrl->wCompQuality = le16_to_cpup((__le16 *)data);
|
||||
ret = 0;
|
||||
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
|
||||
* video probe control. Warn once and return, the caller will
|
||||
* fall back to GET_CUR.
|
||||
|
@ -160,7 +159,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
|
|||
}
|
||||
|
||||
/* 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);
|
||||
ret = 0;
|
||||
|
@ -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[14] = cpu_to_le16(ctrl->wCompWindowSize);
|
||||
*(__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->dwMaxPayloadTransferSize, &data[22]);
|
||||
|
||||
|
@ -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
|
||||
* 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.
|
||||
*/
|
||||
if (fid != video->last_fid && buf->buf.bytesused != 0) {
|
||||
|
@ -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,
|
||||
struct uvc_buffer *buf, __u8 *data, int len)
|
||||
{
|
||||
|
@ -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.
|
||||
*
|
||||
* 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)
|
|||
*/
|
||||
|
||||
/*
|
||||
* Initialize the UVC video device by retrieving the default format and
|
||||
* committing it.
|
||||
* Initialize the UVC video device by switching to alternate setting 0 and
|
||||
* retrieve the default format.
|
||||
*
|
||||
* Some cameras (namely the Fuji Finepix) set the format and frame
|
||||
* 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)
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 &&
|
||||
|
|
|
@ -72,149 +72,149 @@ struct uvc_xu_control {
|
|||
* UVC constants
|
||||
*/
|
||||
|
||||
#define SC_UNDEFINED 0x00
|
||||
#define SC_VIDEOCONTROL 0x01
|
||||
#define SC_VIDEOSTREAMING 0x02
|
||||
#define SC_VIDEO_INTERFACE_COLLECTION 0x03
|
||||
#define SC_UNDEFINED 0x00
|
||||
#define SC_VIDEOCONTROL 0x01
|
||||
#define SC_VIDEOSTREAMING 0x02
|
||||
#define SC_VIDEO_INTERFACE_COLLECTION 0x03
|
||||
|
||||
#define PC_PROTOCOL_UNDEFINED 0x00
|
||||
#define PC_PROTOCOL_UNDEFINED 0x00
|
||||
|
||||
#define CS_UNDEFINED 0x20
|
||||
#define CS_DEVICE 0x21
|
||||
#define CS_CONFIGURATION 0x22
|
||||
#define CS_STRING 0x23
|
||||
#define CS_INTERFACE 0x24
|
||||
#define CS_ENDPOINT 0x25
|
||||
#define CS_UNDEFINED 0x20
|
||||
#define CS_DEVICE 0x21
|
||||
#define CS_CONFIGURATION 0x22
|
||||
#define CS_STRING 0x23
|
||||
#define CS_INTERFACE 0x24
|
||||
#define CS_ENDPOINT 0x25
|
||||
|
||||
/* VideoControl class specific interface descriptor */
|
||||
#define VC_DESCRIPTOR_UNDEFINED 0x00
|
||||
#define VC_HEADER 0x01
|
||||
#define VC_INPUT_TERMINAL 0x02
|
||||
#define VC_OUTPUT_TERMINAL 0x03
|
||||
#define VC_SELECTOR_UNIT 0x04
|
||||
#define VC_PROCESSING_UNIT 0x05
|
||||
#define VC_EXTENSION_UNIT 0x06
|
||||
#define VC_DESCRIPTOR_UNDEFINED 0x00
|
||||
#define VC_HEADER 0x01
|
||||
#define VC_INPUT_TERMINAL 0x02
|
||||
#define VC_OUTPUT_TERMINAL 0x03
|
||||
#define VC_SELECTOR_UNIT 0x04
|
||||
#define VC_PROCESSING_UNIT 0x05
|
||||
#define VC_EXTENSION_UNIT 0x06
|
||||
|
||||
/* VideoStreaming class specific interface descriptor */
|
||||
#define VS_UNDEFINED 0x00
|
||||
#define VS_INPUT_HEADER 0x01
|
||||
#define VS_OUTPUT_HEADER 0x02
|
||||
#define VS_STILL_IMAGE_FRAME 0x03
|
||||
#define VS_FORMAT_UNCOMPRESSED 0x04
|
||||
#define VS_FRAME_UNCOMPRESSED 0x05
|
||||
#define VS_FORMAT_MJPEG 0x06
|
||||
#define VS_FRAME_MJPEG 0x07
|
||||
#define VS_FORMAT_MPEG2TS 0x0a
|
||||
#define VS_FORMAT_DV 0x0c
|
||||
#define VS_COLORFORMAT 0x0d
|
||||
#define VS_FORMAT_FRAME_BASED 0x10
|
||||
#define VS_FRAME_FRAME_BASED 0x11
|
||||
#define VS_FORMAT_STREAM_BASED 0x12
|
||||
#define VS_UNDEFINED 0x00
|
||||
#define VS_INPUT_HEADER 0x01
|
||||
#define VS_OUTPUT_HEADER 0x02
|
||||
#define VS_STILL_IMAGE_FRAME 0x03
|
||||
#define VS_FORMAT_UNCOMPRESSED 0x04
|
||||
#define VS_FRAME_UNCOMPRESSED 0x05
|
||||
#define VS_FORMAT_MJPEG 0x06
|
||||
#define VS_FRAME_MJPEG 0x07
|
||||
#define VS_FORMAT_MPEG2TS 0x0a
|
||||
#define VS_FORMAT_DV 0x0c
|
||||
#define VS_COLORFORMAT 0x0d
|
||||
#define VS_FORMAT_FRAME_BASED 0x10
|
||||
#define VS_FRAME_FRAME_BASED 0x11
|
||||
#define VS_FORMAT_STREAM_BASED 0x12
|
||||
|
||||
/* Endpoint type */
|
||||
#define EP_UNDEFINED 0x00
|
||||
#define EP_GENERAL 0x01
|
||||
#define EP_ENDPOINT 0x02
|
||||
#define EP_INTERRUPT 0x03
|
||||
#define EP_UNDEFINED 0x00
|
||||
#define EP_GENERAL 0x01
|
||||
#define EP_ENDPOINT 0x02
|
||||
#define EP_INTERRUPT 0x03
|
||||
|
||||
/* Request codes */
|
||||
#define RC_UNDEFINED 0x00
|
||||
#define SET_CUR 0x01
|
||||
#define GET_CUR 0x81
|
||||
#define GET_MIN 0x82
|
||||
#define GET_MAX 0x83
|
||||
#define GET_RES 0x84
|
||||
#define GET_LEN 0x85
|
||||
#define GET_INFO 0x86
|
||||
#define GET_DEF 0x87
|
||||
#define RC_UNDEFINED 0x00
|
||||
#define SET_CUR 0x01
|
||||
#define GET_CUR 0x81
|
||||
#define GET_MIN 0x82
|
||||
#define GET_MAX 0x83
|
||||
#define GET_RES 0x84
|
||||
#define GET_LEN 0x85
|
||||
#define GET_INFO 0x86
|
||||
#define GET_DEF 0x87
|
||||
|
||||
/* VideoControl interface controls */
|
||||
#define VC_CONTROL_UNDEFINED 0x00
|
||||
#define VC_VIDEO_POWER_MODE_CONTROL 0x01
|
||||
#define VC_REQUEST_ERROR_CODE_CONTROL 0x02
|
||||
#define VC_CONTROL_UNDEFINED 0x00
|
||||
#define VC_VIDEO_POWER_MODE_CONTROL 0x01
|
||||
#define VC_REQUEST_ERROR_CODE_CONTROL 0x02
|
||||
|
||||
/* Terminal controls */
|
||||
#define TE_CONTROL_UNDEFINED 0x00
|
||||
#define TE_CONTROL_UNDEFINED 0x00
|
||||
|
||||
/* Selector Unit controls */
|
||||
#define SU_CONTROL_UNDEFINED 0x00
|
||||
#define SU_INPUT_SELECT_CONTROL 0x01
|
||||
#define SU_CONTROL_UNDEFINED 0x00
|
||||
#define SU_INPUT_SELECT_CONTROL 0x01
|
||||
|
||||
/* Camera Terminal controls */
|
||||
#define CT_CONTROL_UNDEFINED 0x00
|
||||
#define CT_SCANNING_MODE_CONTROL 0x01
|
||||
#define CT_AE_MODE_CONTROL 0x02
|
||||
#define CT_AE_PRIORITY_CONTROL 0x03
|
||||
#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04
|
||||
#define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05
|
||||
#define CT_FOCUS_ABSOLUTE_CONTROL 0x06
|
||||
#define CT_FOCUS_RELATIVE_CONTROL 0x07
|
||||
#define CT_FOCUS_AUTO_CONTROL 0x08
|
||||
#define CT_IRIS_ABSOLUTE_CONTROL 0x09
|
||||
#define CT_IRIS_RELATIVE_CONTROL 0x0a
|
||||
#define CT_ZOOM_ABSOLUTE_CONTROL 0x0b
|
||||
#define CT_ZOOM_RELATIVE_CONTROL 0x0c
|
||||
#define CT_PANTILT_ABSOLUTE_CONTROL 0x0d
|
||||
#define CT_PANTILT_RELATIVE_CONTROL 0x0e
|
||||
#define CT_ROLL_ABSOLUTE_CONTROL 0x0f
|
||||
#define CT_ROLL_RELATIVE_CONTROL 0x10
|
||||
#define CT_PRIVACY_CONTROL 0x11
|
||||
#define CT_CONTROL_UNDEFINED 0x00
|
||||
#define CT_SCANNING_MODE_CONTROL 0x01
|
||||
#define CT_AE_MODE_CONTROL 0x02
|
||||
#define CT_AE_PRIORITY_CONTROL 0x03
|
||||
#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04
|
||||
#define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05
|
||||
#define CT_FOCUS_ABSOLUTE_CONTROL 0x06
|
||||
#define CT_FOCUS_RELATIVE_CONTROL 0x07
|
||||
#define CT_FOCUS_AUTO_CONTROL 0x08
|
||||
#define CT_IRIS_ABSOLUTE_CONTROL 0x09
|
||||
#define CT_IRIS_RELATIVE_CONTROL 0x0a
|
||||
#define CT_ZOOM_ABSOLUTE_CONTROL 0x0b
|
||||
#define CT_ZOOM_RELATIVE_CONTROL 0x0c
|
||||
#define CT_PANTILT_ABSOLUTE_CONTROL 0x0d
|
||||
#define CT_PANTILT_RELATIVE_CONTROL 0x0e
|
||||
#define CT_ROLL_ABSOLUTE_CONTROL 0x0f
|
||||
#define CT_ROLL_RELATIVE_CONTROL 0x10
|
||||
#define CT_PRIVACY_CONTROL 0x11
|
||||
|
||||
/* Processing Unit controls */
|
||||
#define PU_CONTROL_UNDEFINED 0x00
|
||||
#define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01
|
||||
#define PU_BRIGHTNESS_CONTROL 0x02
|
||||
#define PU_CONTRAST_CONTROL 0x03
|
||||
#define PU_GAIN_CONTROL 0x04
|
||||
#define PU_POWER_LINE_FREQUENCY_CONTROL 0x05
|
||||
#define PU_HUE_CONTROL 0x06
|
||||
#define PU_SATURATION_CONTROL 0x07
|
||||
#define PU_SHARPNESS_CONTROL 0x08
|
||||
#define PU_GAMMA_CONTROL 0x09
|
||||
#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a
|
||||
#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b
|
||||
#define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c
|
||||
#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d
|
||||
#define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e
|
||||
#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f
|
||||
#define PU_HUE_AUTO_CONTROL 0x10
|
||||
#define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11
|
||||
#define PU_ANALOG_LOCK_STATUS_CONTROL 0x12
|
||||
#define PU_CONTROL_UNDEFINED 0x00
|
||||
#define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01
|
||||
#define PU_BRIGHTNESS_CONTROL 0x02
|
||||
#define PU_CONTRAST_CONTROL 0x03
|
||||
#define PU_GAIN_CONTROL 0x04
|
||||
#define PU_POWER_LINE_FREQUENCY_CONTROL 0x05
|
||||
#define PU_HUE_CONTROL 0x06
|
||||
#define PU_SATURATION_CONTROL 0x07
|
||||
#define PU_SHARPNESS_CONTROL 0x08
|
||||
#define PU_GAMMA_CONTROL 0x09
|
||||
#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a
|
||||
#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b
|
||||
#define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c
|
||||
#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d
|
||||
#define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e
|
||||
#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f
|
||||
#define PU_HUE_AUTO_CONTROL 0x10
|
||||
#define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11
|
||||
#define PU_ANALOG_LOCK_STATUS_CONTROL 0x12
|
||||
|
||||
#define LXU_MOTOR_PANTILT_RELATIVE_CONTROL 0x01
|
||||
#define LXU_MOTOR_PANTILT_RESET_CONTROL 0x02
|
||||
#define LXU_MOTOR_FOCUS_MOTOR_CONTROL 0x03
|
||||
|
||||
/* VideoStreaming interface controls */
|
||||
#define VS_CONTROL_UNDEFINED 0x00
|
||||
#define VS_PROBE_CONTROL 0x01
|
||||
#define VS_COMMIT_CONTROL 0x02
|
||||
#define VS_STILL_PROBE_CONTROL 0x03
|
||||
#define VS_STILL_COMMIT_CONTROL 0x04
|
||||
#define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05
|
||||
#define VS_STREAM_ERROR_CODE_CONTROL 0x06
|
||||
#define VS_GENERATE_KEY_FRAME_CONTROL 0x07
|
||||
#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08
|
||||
#define VS_SYNC_DELAY_CONTROL 0x09
|
||||
#define VS_CONTROL_UNDEFINED 0x00
|
||||
#define VS_PROBE_CONTROL 0x01
|
||||
#define VS_COMMIT_CONTROL 0x02
|
||||
#define VS_STILL_PROBE_CONTROL 0x03
|
||||
#define VS_STILL_COMMIT_CONTROL 0x04
|
||||
#define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05
|
||||
#define VS_STREAM_ERROR_CODE_CONTROL 0x06
|
||||
#define VS_GENERATE_KEY_FRAME_CONTROL 0x07
|
||||
#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08
|
||||
#define VS_SYNC_DELAY_CONTROL 0x09
|
||||
|
||||
#define TT_VENDOR_SPECIFIC 0x0100
|
||||
#define TT_STREAMING 0x0101
|
||||
#define TT_VENDOR_SPECIFIC 0x0100
|
||||
#define TT_STREAMING 0x0101
|
||||
|
||||
/* Input Terminal types */
|
||||
#define ITT_VENDOR_SPECIFIC 0x0200
|
||||
#define ITT_CAMERA 0x0201
|
||||
#define ITT_MEDIA_TRANSPORT_INPUT 0x0202
|
||||
#define ITT_VENDOR_SPECIFIC 0x0200
|
||||
#define ITT_CAMERA 0x0201
|
||||
#define ITT_MEDIA_TRANSPORT_INPUT 0x0202
|
||||
|
||||
/* Output Terminal types */
|
||||
#define OTT_VENDOR_SPECIFIC 0x0300
|
||||
#define OTT_DISPLAY 0x0301
|
||||
#define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302
|
||||
#define OTT_VENDOR_SPECIFIC 0x0300
|
||||
#define OTT_DISPLAY 0x0301
|
||||
#define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302
|
||||
|
||||
/* External Terminal types */
|
||||
#define EXTERNAL_VENDOR_SPECIFIC 0x0400
|
||||
#define COMPOSITE_CONNECTOR 0x0401
|
||||
#define SVIDEO_CONNECTOR 0x0402
|
||||
#define COMPONENT_CONNECTOR 0x0403
|
||||
#define EXTERNAL_VENDOR_SPECIFIC 0x0400
|
||||
#define COMPOSITE_CONNECTOR 0x0401
|
||||
#define SVIDEO_CONNECTOR 0x0402
|
||||
#define COMPONENT_CONNECTOR 0x0403
|
||||
|
||||
#define UVC_TERM_INPUT 0x0000
|
||||
#define UVC_TERM_OUTPUT 0x8000
|
||||
|
@ -541,11 +541,11 @@ struct uvc_streaming {
|
|||
};
|
||||
|
||||
enum uvc_buffer_state {
|
||||
UVC_BUF_STATE_IDLE = 0,
|
||||
UVC_BUF_STATE_QUEUED = 1,
|
||||
UVC_BUF_STATE_ACTIVE = 2,
|
||||
UVC_BUF_STATE_DONE = 3,
|
||||
UVC_BUF_STATE_ERROR = 4,
|
||||
UVC_BUF_STATE_IDLE = 0,
|
||||
UVC_BUF_STATE_QUEUED = 1,
|
||||
UVC_BUF_STATE_ACTIVE = 2,
|
||||
UVC_BUF_STATE_DONE = 3,
|
||||
UVC_BUF_STATE_ERROR = 4,
|
||||
};
|
||||
|
||||
struct uvc_buffer {
|
||||
|
|
|
@ -28,13 +28,13 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg)
|
|||
{
|
||||
switch (cmd) {
|
||||
case VIDIOC_QUERYCTRL:
|
||||
return v4l2_subdev_call(sd, core, querymenu, arg);
|
||||
return v4l2_subdev_call(sd, core, queryctrl, arg);
|
||||
case VIDIOC_G_CTRL:
|
||||
return v4l2_subdev_call(sd, core, g_ctrl, arg);
|
||||
case VIDIOC_S_CTRL:
|
||||
return v4l2_subdev_call(sd, core, s_ctrl, arg);
|
||||
case VIDIOC_QUERYMENU:
|
||||
return v4l2_subdev_call(sd, core, queryctrl, arg);
|
||||
return v4l2_subdev_call(sd, core, querymenu, arg);
|
||||
case VIDIOC_LOG_STATUS:
|
||||
return v4l2_subdev_call(sd, core, log_status);
|
||||
case VIDIOC_DBG_G_CHIP_IDENT:
|
||||
|
|
|
@ -349,7 +349,6 @@ struct card_info {
|
|||
u16 i2c_decoder, i2c_encoder; /* I2C types */
|
||||
u16 video_vfe, video_codec; /* videocodec types */
|
||||
u16 audio_chip; /* audio type */
|
||||
u16 vendor_id, device_id; /* subsystem vendor/device ID */
|
||||
|
||||
int inputs; /* number of video inputs */
|
||||
struct input {
|
||||
|
@ -401,7 +400,6 @@ struct zoran {
|
|||
char name[32]; /* name of this device */
|
||||
struct pci_dev *pci_dev; /* PCI device */
|
||||
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 */
|
||||
|
||||
spinlock_t spinlock; /* Spinlock */
|
||||
|
@ -490,16 +488,10 @@ struct zoran {
|
|||
wait_queue_head_t test_q;
|
||||
};
|
||||
|
||||
/*The following should be done in more portable way. It depends on define
|
||||
of _ALPHA_BUZ in the Makefile.*/
|
||||
|
||||
#ifdef _ALPHA_BUZ
|
||||
#define btwrite(dat,adr) writel((dat), zr->zr36057_adr+(adr))
|
||||
#define btread(adr) readl(zr->zr36057_adr+(adr))
|
||||
#else
|
||||
/* There was something called _ALPHA_BUZ that used the PCI address instead of
|
||||
* the kernel iomapped address for btread/btwrite. */
|
||||
#define btwrite(dat,adr) writel((dat), zr->zr36057_mem+(adr))
|
||||
#define btread(adr) readl(zr->zr36057_mem+(adr))
|
||||
#endif
|
||||
|
||||
#define btand(dat,adr) btwrite((dat) & btread(adr), adr)
|
||||
#define btor(dat,adr) btwrite((dat) | btread(adr), adr)
|
||||
|
|
|
@ -61,17 +61,17 @@
|
|||
|
||||
extern const struct zoran_format zoran_formats[];
|
||||
|
||||
static int card[BUZ_MAX] = { -1, -1, -1, -1 };
|
||||
static int card[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 };
|
||||
module_param_array(card, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(card, "The type of card");
|
||||
MODULE_PARM_DESC(card, "Card type");
|
||||
|
||||
static int encoder[BUZ_MAX] = { -1, -1, -1, -1 };
|
||||
static int encoder[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 };
|
||||
module_param_array(encoder, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(encoder, "i2c TV encoder");
|
||||
MODULE_PARM_DESC(encoder, "Video encoder chip");
|
||||
|
||||
static int decoder[BUZ_MAX] = { -1, -1, -1, -1 };
|
||||
static int decoder[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 };
|
||||
module_param_array(decoder, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(decoder, "i2c TV decoder");
|
||||
MODULE_PARM_DESC(decoder, "Video decoder chip");
|
||||
|
||||
/*
|
||||
The video mem address of the video card.
|
||||
|
@ -104,9 +104,9 @@ module_param(default_norm, int, 0444);
|
|||
MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)");
|
||||
|
||||
/* /dev/videoN, -1 for autodetect */
|
||||
static int video_nr[BUZ_MAX] = {-1, -1, -1, -1};
|
||||
static int video_nr[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 };
|
||||
module_param_array(video_nr, int, NULL, 0444);
|
||||
MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)");
|
||||
MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)");
|
||||
|
||||
/*
|
||||
Number and size of grab buffers for Video 4 Linux
|
||||
|
@ -153,9 +153,21 @@ MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver");
|
|||
MODULE_AUTHOR("Serguei Miridonov");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#define ZR_DEVICE(subven, subdev, data) { \
|
||||
.vendor = PCI_VENDOR_ID_ZORAN, .device = PCI_DEVICE_ID_ZORAN_36057, \
|
||||
.subvendor = (subven), .subdevice = (subdev), .driver_data = (data) }
|
||||
|
||||
int zoran_num; /* number of Buzs in use */
|
||||
struct zoran *zoran[BUZ_MAX];
|
||||
static struct pci_device_id zr36067_pci_tbl[] = {
|
||||
ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC10PLUS, DC10plus),
|
||||
ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC30PLUS, DC30plus),
|
||||
ZR_DEVICE(PCI_VENDOR_ID_ELECTRONICDESIGNGMBH, PCI_DEVICE_ID_LML_33R10, LML33R10),
|
||||
ZR_DEVICE(PCI_VENDOR_ID_IOMEGA, PCI_DEVICE_ID_IOMEGA_BUZ, BUZ),
|
||||
ZR_DEVICE(PCI_ANY_ID, PCI_ANY_ID, NUM_CARDS),
|
||||
{0}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl);
|
||||
|
||||
static unsigned int zoran_num; /* number of cards found */
|
||||
|
||||
/* videocodec bus functions ZR36060 */
|
||||
static u32
|
||||
|
@ -472,8 +484,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
|
|||
}, {
|
||||
.type = DC10plus,
|
||||
.name = "DC10plus",
|
||||
.vendor_id = PCI_VENDOR_ID_MIRO,
|
||||
.device_id = PCI_DEVICE_ID_MIRO_DC10PLUS,
|
||||
.i2c_decoder = I2C_DRIVERID_SAA7110,
|
||||
.i2c_encoder = I2C_DRIVERID_ADV7175,
|
||||
.video_codec = CODEC_TYPE_ZR36060,
|
||||
|
@ -531,8 +541,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
|
|||
}, {
|
||||
.type = DC30plus,
|
||||
.name = "DC30plus",
|
||||
.vendor_id = PCI_VENDOR_ID_MIRO,
|
||||
.device_id = PCI_DEVICE_ID_MIRO_DC30PLUS,
|
||||
.i2c_decoder = I2C_DRIVERID_VPX3220,
|
||||
.i2c_encoder = I2C_DRIVERID_ADV7175,
|
||||
.video_codec = CODEC_TYPE_ZR36050,
|
||||
|
@ -589,8 +597,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
|
|||
}, {
|
||||
.type = LML33R10,
|
||||
.name = "LML33R10",
|
||||
.vendor_id = PCI_VENDOR_ID_ELECTRONICDESIGNGMBH,
|
||||
.device_id = PCI_DEVICE_ID_LML_33R10,
|
||||
.i2c_decoder = I2C_DRIVERID_SAA7114,
|
||||
.i2c_encoder = I2C_DRIVERID_ADV7170,
|
||||
.video_codec = CODEC_TYPE_ZR36060,
|
||||
|
@ -618,8 +624,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
|
|||
}, {
|
||||
.type = BUZ,
|
||||
.name = "Buz",
|
||||
.vendor_id = PCI_VENDOR_ID_IOMEGA,
|
||||
.device_id = PCI_DEVICE_ID_IOMEGA_BUZ,
|
||||
.i2c_decoder = I2C_DRIVERID_SAA7111A,
|
||||
.i2c_encoder = I2C_DRIVERID_SAA7185B,
|
||||
.video_codec = CODEC_TYPE_ZR36060,
|
||||
|
@ -649,8 +653,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
|
|||
.name = "6-Eyes",
|
||||
/* AverMedia chose not to brand the 6-Eyes. Thus it
|
||||
can't be autodetected, and requires card=x. */
|
||||
.vendor_id = -1,
|
||||
.device_id = -1,
|
||||
.i2c_decoder = I2C_DRIVERID_KS0127,
|
||||
.i2c_encoder = I2C_DRIVERID_BT866,
|
||||
.video_codec = CODEC_TYPE_ZR36060,
|
||||
|
@ -1138,7 +1140,8 @@ zr36057_init (struct zoran *zr)
|
|||
strcpy(zr->video_dev->name, ZR_DEVNAME(zr));
|
||||
err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]);
|
||||
if (err < 0)
|
||||
goto exit_unregister;
|
||||
goto exit_free;
|
||||
video_set_drvdata(zr->video_dev, zr);
|
||||
|
||||
zoran_init_hardware(zr);
|
||||
if (zr36067_debug > 2)
|
||||
|
@ -1153,19 +1156,19 @@ zr36057_init (struct zoran *zr)
|
|||
zr->initialized = 1;
|
||||
return 0;
|
||||
|
||||
exit_unregister:
|
||||
zoran_unregister_i2c(zr);
|
||||
exit_free:
|
||||
kfree(zr->stat_com);
|
||||
kfree(zr->video_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
zoran_release (struct zoran *zr)
|
||||
static void __devexit zoran_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct zoran *zr = pci_get_drvdata(pdev);
|
||||
|
||||
if (!zr->initialized)
|
||||
goto exit_free;
|
||||
|
||||
/* unregister videocodec bus */
|
||||
if (zr->codec) {
|
||||
struct videocodec_master *master = zr->codec->master_data;
|
||||
|
@ -1194,6 +1197,7 @@ zoran_release (struct zoran *zr)
|
|||
pci_disable_device(zr->pci_dev);
|
||||
video_unregister_device(zr->video_dev);
|
||||
exit_free:
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
kfree(zr);
|
||||
}
|
||||
|
||||
|
@ -1256,338 +1260,329 @@ zoran_setup_videocodec (struct zoran *zr,
|
|||
* Scan for a Buz card (actually for the PCI controller ZR36057),
|
||||
* request the irq and map the io memory
|
||||
*/
|
||||
static int __devinit
|
||||
find_zr36057 (void)
|
||||
static int __devinit zoran_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
unsigned char latency, need_latency;
|
||||
struct zoran *zr;
|
||||
struct pci_dev *dev = NULL;
|
||||
int result;
|
||||
struct videocodec_master *master_vfe = NULL;
|
||||
struct videocodec_master *master_codec = NULL;
|
||||
int card_num;
|
||||
char *i2c_enc_name, *i2c_dec_name, *codec_name, *vfe_name;
|
||||
unsigned int nr;
|
||||
|
||||
zoran_num = 0;
|
||||
while (zoran_num < BUZ_MAX &&
|
||||
(dev = pci_get_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057, dev)) != NULL) {
|
||||
card_num = card[zoran_num];
|
||||
zr = kzalloc(sizeof(struct zoran), GFP_KERNEL);
|
||||
if (!zr) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - kzalloc failed\n",
|
||||
ZORAN_NAME);
|
||||
continue;
|
||||
}
|
||||
zr->pci_dev = dev;
|
||||
//zr->zr36057_mem = NULL;
|
||||
zr->id = zoran_num;
|
||||
snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id);
|
||||
spin_lock_init(&zr->spinlock);
|
||||
mutex_init(&zr->resource_lock);
|
||||
if (pci_enable_device(dev))
|
||||
goto zr_free_mem;
|
||||
zr->zr36057_adr = pci_resource_start(zr->pci_dev, 0);
|
||||
pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION,
|
||||
&zr->revision);
|
||||
|
||||
nr = zoran_num++;
|
||||
if (nr >= BUZ_MAX) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: driver limited to %d card(s) maximum\n",
|
||||
ZORAN_NAME, BUZ_MAX);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
zr = kzalloc(sizeof(struct zoran), GFP_KERNEL);
|
||||
if (!zr) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - kzalloc failed\n",
|
||||
ZORAN_NAME);
|
||||
return -ENOMEM;
|
||||
}
|
||||
zr->pci_dev = pdev;
|
||||
zr->id = nr;
|
||||
snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id);
|
||||
spin_lock_init(&zr->spinlock);
|
||||
mutex_init(&zr->resource_lock);
|
||||
if (pci_enable_device(pdev))
|
||||
goto zr_free_mem;
|
||||
pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, &zr->revision);
|
||||
|
||||
dprintk(1,
|
||||
KERN_INFO
|
||||
"%s: Zoran ZR360%c7 (rev %d), irq: %d, memory: 0x%08llx\n",
|
||||
ZR_DEVNAME(zr), zr->revision < 2 ? '5' : '6', zr->revision,
|
||||
zr->pci_dev->irq, (uint64_t)pci_resource_start(zr->pci_dev, 0));
|
||||
if (zr->revision >= 2) {
|
||||
dprintk(1,
|
||||
KERN_INFO
|
||||
"%s: Subsystem vendor=0x%04x id=0x%04x\n",
|
||||
ZR_DEVNAME(zr), zr->pci_dev->subsystem_vendor,
|
||||
zr->pci_dev->subsystem_device);
|
||||
}
|
||||
|
||||
/* Use auto-detected card type? */
|
||||
if (card[nr] == -1) {
|
||||
if (zr->revision < 2) {
|
||||
dprintk(1,
|
||||
KERN_INFO
|
||||
"%s: Zoran ZR36057 (rev %d) irq: %d, memory: 0x%08x.\n",
|
||||
ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq,
|
||||
zr->zr36057_adr);
|
||||
|
||||
if (card_num == -1) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - no card specified, please use the card=X insmod option\n",
|
||||
ZR_DEVNAME(zr));
|
||||
goto zr_free_mem;
|
||||
}
|
||||
} else {
|
||||
int i;
|
||||
unsigned short ss_vendor, ss_device;
|
||||
|
||||
ss_vendor = zr->pci_dev->subsystem_vendor;
|
||||
ss_device = zr->pci_dev->subsystem_device;
|
||||
dprintk(1,
|
||||
KERN_INFO
|
||||
"%s: Zoran ZR36067 (rev %d) irq: %d, memory: 0x%08x\n",
|
||||
ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq,
|
||||
zr->zr36057_adr);
|
||||
dprintk(1,
|
||||
KERN_INFO
|
||||
"%s: subsystem vendor=0x%04x id=0x%04x\n",
|
||||
ZR_DEVNAME(zr), ss_vendor, ss_device);
|
||||
if (card_num == -1) {
|
||||
dprintk(3,
|
||||
KERN_DEBUG
|
||||
"%s: find_zr36057() - trying to autodetect card type\n",
|
||||
ZR_DEVNAME(zr));
|
||||
for (i=0;i<NUM_CARDS;i++) {
|
||||
if (ss_vendor == zoran_cards[i].vendor_id &&
|
||||
ss_device == zoran_cards[i].device_id) {
|
||||
dprintk(3,
|
||||
KERN_DEBUG
|
||||
"%s: find_zr36057() - card %s detected\n",
|
||||
ZR_DEVNAME(zr),
|
||||
zoran_cards[i].name);
|
||||
card_num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == NUM_CARDS) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - unknown card\n",
|
||||
ZR_DEVNAME(zr));
|
||||
goto zr_free_mem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (card_num < 0 || card_num >= NUM_CARDS) {
|
||||
dprintk(2,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - invalid cardnum %d\n",
|
||||
ZR_DEVNAME(zr), card_num);
|
||||
goto zr_free_mem;
|
||||
}
|
||||
|
||||
/* even though we make this a non pointer and thus
|
||||
* theoretically allow for making changes to this struct
|
||||
* on a per-individual card basis at runtime, this is
|
||||
* strongly discouraged. This structure is intended to
|
||||
* keep general card information, no settings or anything */
|
||||
zr->card = zoran_cards[card_num];
|
||||
snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)),
|
||||
"%s[%u]", zr->card.name, zr->id);
|
||||
|
||||
zr->zr36057_mem = ioremap_nocache(zr->zr36057_adr, 0x1000);
|
||||
if (!zr->zr36057_mem) {
|
||||
"%s: No card type specified, please use the card=X module parameter\n",
|
||||
ZR_DEVNAME(zr));
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - ioremap failed\n",
|
||||
"%s: It is not possible to auto-detect ZR36057 based cards\n",
|
||||
ZR_DEVNAME(zr));
|
||||
goto zr_free_mem;
|
||||
}
|
||||
|
||||
result = request_irq(zr->pci_dev->irq,
|
||||
zoran_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED,
|
||||
ZR_DEVNAME(zr),
|
||||
(void *) zr);
|
||||
if (result < 0) {
|
||||
if (result == -EINVAL) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - bad irq number or handler\n",
|
||||
ZR_DEVNAME(zr));
|
||||
} else if (result == -EBUSY) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n",
|
||||
ZR_DEVNAME(zr), zr->pci_dev->irq);
|
||||
} else {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - can't assign irq, error code %d\n",
|
||||
ZR_DEVNAME(zr), result);
|
||||
}
|
||||
goto zr_unmap;
|
||||
}
|
||||
|
||||
/* set PCI latency timer */
|
||||
pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
|
||||
&latency);
|
||||
need_latency = zr->revision > 1 ? 32 : 48;
|
||||
if (latency != need_latency) {
|
||||
dprintk(2,
|
||||
KERN_INFO
|
||||
"%s: Changing PCI latency from %d to %d.\n",
|
||||
ZR_DEVNAME(zr), latency, need_latency);
|
||||
pci_write_config_byte(zr->pci_dev,
|
||||
PCI_LATENCY_TIMER,
|
||||
need_latency);
|
||||
}
|
||||
|
||||
zr36057_restart(zr);
|
||||
/* i2c */
|
||||
dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n",
|
||||
ZR_DEVNAME(zr));
|
||||
|
||||
/* i2c decoder */
|
||||
if (decoder[zr->id] != -1) {
|
||||
i2c_dec_name = i2cid_to_modulename(decoder[zr->id]);
|
||||
zr->card.i2c_decoder = decoder[zr->id];
|
||||
} else if (zr->card.i2c_decoder != 0) {
|
||||
i2c_dec_name =
|
||||
i2cid_to_modulename(zr->card.i2c_decoder);
|
||||
} else {
|
||||
i2c_dec_name = NULL;
|
||||
}
|
||||
|
||||
if (i2c_dec_name) {
|
||||
if ((result = request_module(i2c_dec_name)) < 0) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: failed to load module %s: %d\n",
|
||||
ZR_DEVNAME(zr), i2c_dec_name, result);
|
||||
}
|
||||
}
|
||||
|
||||
/* i2c encoder */
|
||||
if (encoder[zr->id] != -1) {
|
||||
i2c_enc_name = i2cid_to_modulename(encoder[zr->id]);
|
||||
zr->card.i2c_encoder = encoder[zr->id];
|
||||
} else if (zr->card.i2c_encoder != 0) {
|
||||
i2c_enc_name =
|
||||
i2cid_to_modulename(zr->card.i2c_encoder);
|
||||
} else {
|
||||
i2c_enc_name = NULL;
|
||||
}
|
||||
|
||||
if (i2c_enc_name) {
|
||||
if ((result = request_module(i2c_enc_name)) < 0) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: failed to load module %s: %d\n",
|
||||
ZR_DEVNAME(zr), i2c_enc_name, result);
|
||||
}
|
||||
}
|
||||
|
||||
if (zoran_register_i2c(zr) < 0) {
|
||||
card_num = ent->driver_data;
|
||||
if (card_num >= NUM_CARDS) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - can't initialize i2c bus\n",
|
||||
"%s: Unknown card, try specifying card=X module parameter\n",
|
||||
ZR_DEVNAME(zr));
|
||||
goto zr_free_irq;
|
||||
goto zr_free_mem;
|
||||
}
|
||||
dprintk(3,
|
||||
KERN_DEBUG
|
||||
"%s: %s() - card %s detected\n",
|
||||
ZR_DEVNAME(zr), __func__, zoran_cards[card_num].name);
|
||||
} else {
|
||||
card_num = card[nr];
|
||||
if (card_num >= NUM_CARDS || card_num < 0) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: User specified card type %d out of range (0 .. %d)\n",
|
||||
ZR_DEVNAME(zr), card_num, NUM_CARDS - 1);
|
||||
goto zr_free_mem;
|
||||
}
|
||||
}
|
||||
|
||||
/* even though we make this a non pointer and thus
|
||||
* theoretically allow for making changes to this struct
|
||||
* on a per-individual card basis at runtime, this is
|
||||
* strongly discouraged. This structure is intended to
|
||||
* keep general card information, no settings or anything */
|
||||
zr->card = zoran_cards[card_num];
|
||||
snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)),
|
||||
"%s[%u]", zr->card.name, zr->id);
|
||||
|
||||
zr->zr36057_mem = pci_ioremap_bar(zr->pci_dev, 0);
|
||||
if (!zr->zr36057_mem) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: %s() - ioremap failed\n",
|
||||
ZR_DEVNAME(zr), __func__);
|
||||
goto zr_free_mem;
|
||||
}
|
||||
|
||||
result = request_irq(zr->pci_dev->irq, zoran_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED, ZR_DEVNAME(zr), zr);
|
||||
if (result < 0) {
|
||||
if (result == -EINVAL) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - bad irq number or handler\n",
|
||||
ZR_DEVNAME(zr));
|
||||
} else if (result == -EBUSY) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n",
|
||||
ZR_DEVNAME(zr), zr->pci_dev->irq);
|
||||
} else {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - can't assign irq, error code %d\n",
|
||||
ZR_DEVNAME(zr), result);
|
||||
}
|
||||
goto zr_unmap;
|
||||
}
|
||||
|
||||
/* set PCI latency timer */
|
||||
pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
|
||||
&latency);
|
||||
need_latency = zr->revision > 1 ? 32 : 48;
|
||||
if (latency != need_latency) {
|
||||
dprintk(2,
|
||||
KERN_INFO "%s: Initializing videocodec bus...\n",
|
||||
ZR_DEVNAME(zr));
|
||||
KERN_INFO
|
||||
"%s: Changing PCI latency from %d to %d\n",
|
||||
ZR_DEVNAME(zr), latency, need_latency);
|
||||
pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
|
||||
need_latency);
|
||||
}
|
||||
|
||||
if (zr->card.video_codec != 0 &&
|
||||
(codec_name =
|
||||
codecid_to_modulename(zr->card.video_codec)) != NULL) {
|
||||
if ((result = request_module(codec_name)) < 0) {
|
||||
zr36057_restart(zr);
|
||||
/* i2c */
|
||||
dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n",
|
||||
ZR_DEVNAME(zr));
|
||||
|
||||
/* i2c decoder */
|
||||
if (decoder[zr->id] != -1) {
|
||||
i2c_dec_name = i2cid_to_modulename(decoder[zr->id]);
|
||||
zr->card.i2c_decoder = decoder[zr->id];
|
||||
} else if (zr->card.i2c_decoder != 0) {
|
||||
i2c_dec_name = i2cid_to_modulename(zr->card.i2c_decoder);
|
||||
} else {
|
||||
i2c_dec_name = NULL;
|
||||
}
|
||||
|
||||
if (i2c_dec_name) {
|
||||
result = request_module(i2c_dec_name);
|
||||
if (result < 0) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: failed to load module %s: %d\n",
|
||||
ZR_DEVNAME(zr), i2c_dec_name, result);
|
||||
}
|
||||
}
|
||||
|
||||
/* i2c encoder */
|
||||
if (encoder[zr->id] != -1) {
|
||||
i2c_enc_name = i2cid_to_modulename(encoder[zr->id]);
|
||||
zr->card.i2c_encoder = encoder[zr->id];
|
||||
} else if (zr->card.i2c_encoder != 0) {
|
||||
i2c_enc_name = i2cid_to_modulename(zr->card.i2c_encoder);
|
||||
} else {
|
||||
i2c_enc_name = NULL;
|
||||
}
|
||||
|
||||
if (i2c_enc_name) {
|
||||
result = request_module(i2c_enc_name);
|
||||
if (result < 0) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: failed to load module %s: %d\n",
|
||||
ZR_DEVNAME(zr), i2c_enc_name, result);
|
||||
}
|
||||
}
|
||||
|
||||
if (zoran_register_i2c(zr) < 0) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - can't initialize i2c bus\n",
|
||||
ZR_DEVNAME(zr));
|
||||
goto zr_free_irq;
|
||||
}
|
||||
|
||||
dprintk(2,
|
||||
KERN_INFO "%s: Initializing videocodec bus...\n",
|
||||
ZR_DEVNAME(zr));
|
||||
|
||||
if (zr->card.video_codec) {
|
||||
codec_name = codecid_to_modulename(zr->card.video_codec);
|
||||
if (codec_name) {
|
||||
result = request_module(codec_name);
|
||||
if (result) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: failed to load modules %s: %d\n",
|
||||
ZR_DEVNAME(zr), codec_name, result);
|
||||
}
|
||||
}
|
||||
if (zr->card.video_vfe != 0 &&
|
||||
(vfe_name =
|
||||
codecid_to_modulename(zr->card.video_vfe)) != NULL) {
|
||||
if ((result = request_module(vfe_name)) < 0) {
|
||||
}
|
||||
if (zr->card.video_vfe) {
|
||||
vfe_name = codecid_to_modulename(zr->card.video_vfe);
|
||||
if (vfe_name) {
|
||||
result = request_module(vfe_name);
|
||||
if (result < 0) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: failed to load modules %s: %d\n",
|
||||
ZR_DEVNAME(zr), vfe_name, result);
|
||||
}
|
||||
}
|
||||
|
||||
/* reset JPEG codec */
|
||||
jpeg_codec_sleep(zr, 1);
|
||||
jpeg_codec_reset(zr);
|
||||
/* video bus enabled */
|
||||
/* display codec revision */
|
||||
if (zr->card.video_codec != 0) {
|
||||
master_codec = zoran_setup_videocodec(zr,
|
||||
zr->card.video_codec);
|
||||
if (!master_codec)
|
||||
goto zr_unreg_i2c;
|
||||
zr->codec = videocodec_attach(master_codec);
|
||||
if (!zr->codec) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - no codec found\n",
|
||||
ZR_DEVNAME(zr));
|
||||
goto zr_free_codec;
|
||||
}
|
||||
if (zr->codec->type != zr->card.video_codec) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - wrong codec\n",
|
||||
ZR_DEVNAME(zr));
|
||||
goto zr_detach_codec;
|
||||
}
|
||||
}
|
||||
if (zr->card.video_vfe != 0) {
|
||||
master_vfe = zoran_setup_videocodec(zr,
|
||||
zr->card.video_vfe);
|
||||
if (!master_vfe)
|
||||
goto zr_detach_codec;
|
||||
zr->vfe = videocodec_attach(master_vfe);
|
||||
if (!zr->vfe) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - no VFE found\n",
|
||||
ZR_DEVNAME(zr));
|
||||
goto zr_free_vfe;
|
||||
}
|
||||
if (zr->vfe->type != zr->card.video_vfe) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() = wrong VFE\n",
|
||||
ZR_DEVNAME(zr));
|
||||
goto zr_detach_vfe;
|
||||
}
|
||||
}
|
||||
/* Success so keep the pci_dev referenced */
|
||||
pci_dev_get(zr->pci_dev);
|
||||
zoran[zoran_num++] = zr;
|
||||
continue;
|
||||
|
||||
// Init errors
|
||||
zr_detach_vfe:
|
||||
videocodec_detach(zr->vfe);
|
||||
zr_free_vfe:
|
||||
kfree(master_vfe);
|
||||
zr_detach_codec:
|
||||
videocodec_detach(zr->codec);
|
||||
zr_free_codec:
|
||||
kfree(master_codec);
|
||||
zr_unreg_i2c:
|
||||
zoran_unregister_i2c(zr);
|
||||
zr_free_irq:
|
||||
btwrite(0, ZR36057_SPGPPCR);
|
||||
free_irq(zr->pci_dev->irq, zr);
|
||||
zr_unmap:
|
||||
iounmap(zr->zr36057_mem);
|
||||
zr_free_mem:
|
||||
kfree(zr);
|
||||
continue;
|
||||
}
|
||||
if (dev) /* Clean up ref count on early exit */
|
||||
pci_dev_put(dev);
|
||||
|
||||
if (zoran_num == 0) {
|
||||
dprintk(1, KERN_INFO "No known MJPEG cards found.\n");
|
||||
/* reset JPEG codec */
|
||||
jpeg_codec_sleep(zr, 1);
|
||||
jpeg_codec_reset(zr);
|
||||
/* video bus enabled */
|
||||
/* display codec revision */
|
||||
if (zr->card.video_codec != 0) {
|
||||
master_codec = zoran_setup_videocodec(zr, zr->card.video_codec);
|
||||
if (!master_codec)
|
||||
goto zr_unreg_i2c;
|
||||
zr->codec = videocodec_attach(master_codec);
|
||||
if (!zr->codec) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - no codec found\n",
|
||||
ZR_DEVNAME(zr));
|
||||
goto zr_free_codec;
|
||||
}
|
||||
if (zr->codec->type != zr->card.video_codec) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - wrong codec\n",
|
||||
ZR_DEVNAME(zr));
|
||||
goto zr_detach_codec;
|
||||
}
|
||||
}
|
||||
return zoran_num;
|
||||
if (zr->card.video_vfe != 0) {
|
||||
master_vfe = zoran_setup_videocodec(zr, zr->card.video_vfe);
|
||||
if (!master_vfe)
|
||||
goto zr_detach_codec;
|
||||
zr->vfe = videocodec_attach(master_vfe);
|
||||
if (!zr->vfe) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() - no VFE found\n",
|
||||
ZR_DEVNAME(zr));
|
||||
goto zr_free_vfe;
|
||||
}
|
||||
if (zr->vfe->type != zr->card.video_vfe) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: find_zr36057() = wrong VFE\n",
|
||||
ZR_DEVNAME(zr));
|
||||
goto zr_detach_vfe;
|
||||
}
|
||||
}
|
||||
|
||||
/* take care of Natoma chipset and a revision 1 zr36057 */
|
||||
if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) {
|
||||
zr->jpg_buffers.need_contiguous = 1;
|
||||
dprintk(1,
|
||||
KERN_INFO
|
||||
"%s: ZR36057/Natoma bug, max. buffer size is 128K\n",
|
||||
ZR_DEVNAME(zr));
|
||||
}
|
||||
|
||||
if (zr36057_init(zr) < 0)
|
||||
goto zr_detach_vfe;
|
||||
|
||||
zoran_proc_init(zr);
|
||||
|
||||
pci_set_drvdata(pdev, zr);
|
||||
|
||||
return 0;
|
||||
|
||||
zr_detach_vfe:
|
||||
videocodec_detach(zr->vfe);
|
||||
zr_free_vfe:
|
||||
kfree(master_vfe);
|
||||
zr_detach_codec:
|
||||
videocodec_detach(zr->codec);
|
||||
zr_free_codec:
|
||||
kfree(master_codec);
|
||||
zr_unreg_i2c:
|
||||
zoran_unregister_i2c(zr);
|
||||
zr_free_irq:
|
||||
btwrite(0, ZR36057_SPGPPCR);
|
||||
free_irq(zr->pci_dev->irq, zr);
|
||||
zr_unmap:
|
||||
iounmap(zr->zr36057_mem);
|
||||
zr_free_mem:
|
||||
kfree(zr);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int __init
|
||||
init_dc10_cards (void)
|
||||
{
|
||||
int i;
|
||||
static struct pci_driver zoran_driver = {
|
||||
.name = "zr36067",
|
||||
.id_table = zr36067_pci_tbl,
|
||||
.probe = zoran_probe,
|
||||
.remove = zoran_remove,
|
||||
};
|
||||
|
||||
static int __init zoran_init(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
memset(zoran, 0, sizeof(zoran));
|
||||
printk(KERN_INFO "Zoran MJPEG board driver version %d.%d.%d\n",
|
||||
MAJOR_VERSION, MINOR_VERSION, RELEASE_VERSION);
|
||||
|
||||
/* Look for cards */
|
||||
if (find_zr36057() < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
if (zoran_num == 0)
|
||||
return -ENODEV;
|
||||
dprintk(1, KERN_INFO "%s: %d card(s) found\n", ZORAN_NAME,
|
||||
zoran_num);
|
||||
/* check the parameters we have been given, adjust if necessary */
|
||||
if (v4l_nbufs < 2)
|
||||
v4l_nbufs = 2;
|
||||
|
@ -1629,37 +1624,22 @@ init_dc10_cards (void)
|
|||
ZORAN_NAME);
|
||||
}
|
||||
|
||||
/* take care of Natoma chipset and a revision 1 zr36057 */
|
||||
for (i = 0; i < zoran_num; i++) {
|
||||
struct zoran *zr = zoran[i];
|
||||
|
||||
if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) {
|
||||
zr->jpg_buffers.need_contiguous = 1;
|
||||
dprintk(1,
|
||||
KERN_INFO
|
||||
"%s: ZR36057/Natoma bug, max. buffer size is 128K\n",
|
||||
ZR_DEVNAME(zr));
|
||||
}
|
||||
|
||||
if (zr36057_init(zr) < 0) {
|
||||
for (i = 0; i < zoran_num; i++)
|
||||
zoran_release(zoran[i]);
|
||||
return -EIO;
|
||||
}
|
||||
zoran_proc_init(zr);
|
||||
res = pci_register_driver(&zoran_driver);
|
||||
if (res) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: Unable to register ZR36057 driver\n",
|
||||
ZORAN_NAME);
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit
|
||||
unload_dc10_cards (void)
|
||||
static void __exit zoran_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < zoran_num; i++)
|
||||
zoran_release(zoran[i]);
|
||||
pci_unregister_driver(&zoran_driver);
|
||||
}
|
||||
|
||||
module_init(init_dc10_cards);
|
||||
module_exit(unload_dc10_cards);
|
||||
module_init(zoran_init);
|
||||
module_exit(zoran_exit);
|
||||
|
|
|
@ -40,8 +40,6 @@ extern int zr36067_debug;
|
|||
|
||||
/* Anybody who uses more than four? */
|
||||
#define BUZ_MAX 4
|
||||
extern int zoran_num;
|
||||
extern struct zoran *zoran[BUZ_MAX];
|
||||
|
||||
extern struct video_device zoran_template;
|
||||
|
||||
|
|
|
@ -1196,83 +1196,54 @@ zoran_close_end_session (struct file *file)
|
|||
* Open a zoran card. Right now the flags stuff is just playing
|
||||
*/
|
||||
|
||||
static int
|
||||
zoran_open(struct file *file)
|
||||
static int zoran_open(struct file *file)
|
||||
{
|
||||
unsigned int minor = video_devdata(file)->minor;
|
||||
struct zoran *zr = NULL;
|
||||
struct zoran *zr = video_drvdata(file);
|
||||
struct zoran_fh *fh;
|
||||
int i, res, first_open = 0, have_module_locks = 0;
|
||||
int res, first_open = 0;
|
||||
|
||||
dprintk(2, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n",
|
||||
ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user + 1);
|
||||
|
||||
lock_kernel();
|
||||
/* find the device */
|
||||
for (i = 0; i < zoran_num; i++) {
|
||||
if (zoran[i]->video_dev->minor == minor) {
|
||||
zr = zoran[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!zr) {
|
||||
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(),
|
||||
* so locking ourselves only causes deadlocks */
|
||||
/*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) {
|
||||
dprintk(1,
|
||||
KERN_ERR "%s: no TV decoder loaded for device!\n",
|
||||
ZR_DEVNAME(zr));
|
||||
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)) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: failed to grab ownership of i2c decoder\n",
|
||||
"%s: failed to grab ownership of video decoder\n",
|
||||
ZR_DEVNAME(zr));
|
||||
res = -EIO;
|
||||
module_put(THIS_MODULE);
|
||||
goto open_unlock_and_return;
|
||||
goto fail_unlock;
|
||||
}
|
||||
if (zr->encoder &&
|
||||
!try_module_get(zr->encoder->driver->driver.owner)) {
|
||||
dprintk(1,
|
||||
KERN_ERR
|
||||
"%s: failed to grab ownership of i2c encoder\n",
|
||||
"%s: failed to grab ownership of video encoder\n",
|
||||
ZR_DEVNAME(zr));
|
||||
res = -EIO;
|
||||
module_put(zr->decoder->driver->driver.owner);
|
||||
module_put(THIS_MODULE);
|
||||
goto open_unlock_and_return;
|
||||
goto fail_decoder;
|
||||
}
|
||||
|
||||
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 */
|
||||
fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL);
|
||||
if (!fh) {
|
||||
|
@ -1281,7 +1252,7 @@ zoran_open(struct file *file)
|
|||
"%s: zoran_open() - allocation of zoran_fh failed\n",
|
||||
ZR_DEVNAME(zr));
|
||||
res = -ENOMEM;
|
||||
goto open_unlock_and_return;
|
||||
goto fail_encoder;
|
||||
}
|
||||
/* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
|
||||
* on norm-change! */
|
||||
|
@ -1292,9 +1263,8 @@ zoran_open(struct file *file)
|
|||
KERN_ERR
|
||||
"%s: zoran_open() - allocation of overlay_mask failed\n",
|
||||
ZR_DEVNAME(zr));
|
||||
kfree(fh);
|
||||
res = -ENOMEM;
|
||||
goto open_unlock_and_return;
|
||||
goto fail_fh;
|
||||
}
|
||||
|
||||
if (zr->user++ == 0)
|
||||
|
@ -1319,22 +1289,19 @@ zoran_open(struct file *file)
|
|||
|
||||
return 0;
|
||||
|
||||
open_unlock_and_return:
|
||||
/* if we grabbed locks, release them accordingly */
|
||||
if (have_module_locks) {
|
||||
module_put(zr->decoder->driver->driver.owner);
|
||||
if (zr->encoder) {
|
||||
module_put(zr->encoder->driver->driver.owner);
|
||||
}
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
/* if there's no device found, we didn't obtain the lock either */
|
||||
if (zr) {
|
||||
/*mutex_unlock(&zr->resource_lock);*/
|
||||
}
|
||||
fail_fh:
|
||||
kfree(fh);
|
||||
fail_encoder:
|
||||
if (zr->encoder)
|
||||
module_put(zr->encoder->driver->driver.owner);
|
||||
fail_decoder:
|
||||
module_put(zr->decoder->driver->driver.owner);
|
||||
fail_unlock:
|
||||
unlock_kernel();
|
||||
|
||||
dprintk(2, KERN_INFO "%s: open failed (%d), users(-)=%d\n",
|
||||
ZR_DEVNAME(zr), res, zr->user);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1344,8 +1311,8 @@ zoran_close(struct file *file)
|
|||
struct zoran_fh *fh = file->private_data;
|
||||
struct zoran *zr = fh->zr;
|
||||
|
||||
dprintk(1, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n",
|
||||
ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user);
|
||||
dprintk(2, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n",
|
||||
ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user - 1);
|
||||
|
||||
/* kernel locks (fs/device.c), so don't do that ourselves
|
||||
* (prevents deadlocks) */
|
||||
|
@ -1391,10 +1358,8 @@ zoran_close(struct file *file)
|
|||
|
||||
/* release locks on the i2c modules */
|
||||
module_put(zr->decoder->driver->driver.owner);
|
||||
if (zr->encoder) {
|
||||
module_put(zr->encoder->driver->driver.owner);
|
||||
}
|
||||
module_put(THIS_MODULE);
|
||||
if (zr->encoder)
|
||||
module_put(zr->encoder->driver->driver.owner);
|
||||
|
||||
/*mutex_unlock(&zr->resource_lock);*/
|
||||
|
||||
|
|
|
@ -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
|
||||
match them all). Ignore any errors. Note that you cannot add or delete
|
||||
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, \
|
||||
!(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
|
||||
match them all). If the callback returns an error other than 0 or
|
||||
-ENOIOCTLCMD, then return with that error code. Note that you cannot
|
||||
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, \
|
||||
!(grp_id) || sd->grp_id == (grp_id), o, f , ##args)
|
||||
!(grpid) || sd->grp_id == (grpid), o, f , ##args)
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче