summaryrefslogtreecommitdiff
path: root/linux/drivers
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-02-17 23:44:45 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-02-17 23:44:45 -0300
commitb6705f84947f09dd3858f839267c9662fdbd667b (patch)
treec6a5dea386c7c837b17cbb4b44a158b78ca4c65e /linux/drivers
parent9446aad394fc912dc47f17e7638357edfd470ded (diff)
parentaedda303081b327f1be76710db7032c675509d40 (diff)
downloadmediapointer-dvb-s2-b6705f84947f09dd3858f839267c9662fdbd667b.tar.gz
mediapointer-dvb-s2-b6705f84947f09dd3858f839267c9662fdbd667b.tar.bz2
merge: http://www.linuxtv.org/hg/~hverkuil/v4l-dvb
From: Mauro Carvalho Chehab <mchehab@redhat.com> Priority: normal Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'linux/drivers')
-rw-r--r--linux/drivers/media/Kconfig2
-rw-r--r--linux/drivers/media/common/ir-keymaps.c59
-rw-r--r--linux/drivers/media/common/tuners/mt2060.c2
-rw-r--r--linux/drivers/media/dvb/dvb-core/dmxdev.c16
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_demux.c16
-rw-r--r--linux/drivers/media/video/gspca/Kconfig9
-rw-r--r--linux/drivers/media/video/gspca/Makefile2
-rw-r--r--linux/drivers/media/video/gspca/gspca.c104
-rw-r--r--linux/drivers/media/video/gspca/mr97310a.c2
-rw-r--r--linux/drivers/media/video/gspca/sonixj.c49
-rw-r--r--linux/drivers/media/video/gspca/spca505.c8
-rw-r--r--linux/drivers/media/video/gspca/sq905.c438
-rw-r--r--linux/drivers/media/video/gspca/t613.c10
-rw-r--r--linux/drivers/media/video/gspca/vc032x.c5
-rw-r--r--linux/drivers/media/video/ir-kbd-i2c.c64
-rw-r--r--linux/drivers/media/video/ivtv/ivtv-ioctl.c26
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-cards.c11
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-i2c.c2
-rw-r--r--linux/drivers/media/video/tcm825x.c22
-rw-r--r--linux/drivers/media/video/tcm825x.h2
-rw-r--r--linux/drivers/media/video/tvp514x.c2
-rw-r--r--linux/drivers/media/video/tw9910.c13
-rw-r--r--linux/drivers/media/video/zoran/zoran_driver.c4
23 files changed, 765 insertions, 103 deletions
diff --git a/linux/drivers/media/Kconfig b/linux/drivers/media/Kconfig
index 93ea201f4..223c36ede 100644
--- a/linux/drivers/media/Kconfig
+++ b/linux/drivers/media/Kconfig
@@ -117,7 +117,7 @@ source "drivers/media/dvb/Kconfig"
config DAB
boolean "DAB adapters"
---help---
- Allow selecting support for for Digital Audio Broadcasting (DAB)
+ Allow selecting support for Digital Audio Broadcasting (DAB)
Receiver adapters.
if DAB
diff --git a/linux/drivers/media/common/ir-keymaps.c b/linux/drivers/media/common/ir-keymaps.c
index 03fabc86c..827e65582 100644
--- a/linux/drivers/media/common/ir-keymaps.c
+++ b/linux/drivers/media/common/ir-keymaps.c
@@ -154,6 +154,65 @@ IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE] = {
};
EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a);
+/* Oldrich Jedlicka <oldium.pro@seznam.cz> */
+IR_KEYTAB_TYPE ir_codes_avermedia_cardbus[IR_KEYTAB_SIZE] = {
+ [0x00] = KEY_POWER,
+ [0x01] = KEY_TUNER, /* TV/FM */
+ [0x03] = KEY_TEXT, /* Teletext */
+ [0x04] = KEY_EPG,
+ [0x05] = KEY_1,
+ [0x06] = KEY_2,
+ [0x07] = KEY_3,
+ [0x08] = KEY_AUDIO,
+ [0x09] = KEY_4,
+ [0x0a] = KEY_5,
+ [0x0b] = KEY_6,
+ [0x0c] = KEY_ZOOM, /* Full screen */
+ [0x0d] = KEY_7,
+ [0x0e] = KEY_8,
+ [0x0f] = KEY_9,
+ [0x10] = KEY_PAGEUP, /* 16-CH PREV */
+ [0x11] = KEY_0,
+ [0x12] = KEY_INFO,
+ [0x13] = KEY_AGAIN, /* CH RTN - channel return */
+ [0x14] = KEY_MUTE,
+ [0x15] = KEY_EDIT, /* Autoscan */
+ [0x17] = KEY_SAVE, /* Screenshot */
+ [0x18] = KEY_PLAYPAUSE,
+ [0x19] = KEY_RECORD,
+ [0x1a] = KEY_PLAY,
+ [0x1b] = KEY_STOP,
+ [0x1c] = KEY_FASTFORWARD,
+ [0x1d] = KEY_REWIND,
+ [0x1e] = KEY_VOLUMEDOWN,
+ [0x1f] = KEY_VOLUMEUP,
+ [0x22] = KEY_SLEEP, /* Sleep */
+ [0x23] = KEY_ZOOM, /* Aspect */
+ [0x26] = KEY_SCREEN, /* Pos */
+ [0x27] = KEY_ANGLE, /* Size */
+ [0x28] = KEY_SELECT, /* Select */
+ [0x29] = KEY_BLUE, /* Blue/Picture */
+ [0x2a] = KEY_BACKSPACE, /* Back */
+ [0x2b] = KEY_MEDIA, /* PIP (Picture-in-picture) */
+ [0x2c] = KEY_DOWN,
+ [0x2e] = KEY_DOT,
+ [0x2f] = KEY_TV, /* Live TV */
+ [0x32] = KEY_LEFT,
+ [0x33] = KEY_CLEAR, /* Clear */
+ [0x35] = KEY_RED, /* Red/TV */
+ [0x36] = KEY_UP,
+ [0x37] = KEY_HOME, /* Home */
+ [0x39] = KEY_GREEN, /* Green/Video */
+ [0x3d] = KEY_YELLOW, /* Yellow/Music */
+ [0x3e] = KEY_OK, /* Ok */
+ [0x3f] = KEY_RIGHT,
+ [0x40] = KEY_NEXT, /* Next */
+ [0x41] = KEY_PREVIOUS, /* Previous */
+ [0x42] = KEY_CHANNELDOWN, /* Channel down */
+ [0x43] = KEY_CHANNELUP /* Channel up */
+};
+EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus);
+
/* Attila Kondoros <attila.kondoros@chello.hu> */
IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
diff --git a/linux/drivers/media/common/tuners/mt2060.c b/linux/drivers/media/common/tuners/mt2060.c
index d1962bb24..1f1fe90cb 100644
--- a/linux/drivers/media/common/tuners/mt2060.c
+++ b/linux/drivers/media/common/tuners/mt2060.c
@@ -285,7 +285,7 @@ static void mt2060_calibrate(struct mt2060_priv *priv)
while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0)
msleep(20);
- if (i < 10) {
+ if (i <= 10) {
mt2060_readreg(priv, REG_FM_FREQ, &priv->fmfreq); // now find out, what is fmreq used for :)
dprintk("calibration was successful: %d", (int)priv->fmfreq);
} else
diff --git a/linux/drivers/media/dvb/dvb-core/dmxdev.c b/linux/drivers/media/dvb/dvb-core/dmxdev.c
index cc143929a..c35fbb8d8 100644
--- a/linux/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/linux/drivers/media/dvb/dvb-core/dmxdev.c
@@ -364,16 +364,15 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
enum dmx_success success)
{
struct dmxdev_filter *dmxdevfilter = filter->priv;
- unsigned long flags;
int ret;
if (dmxdevfilter->buffer.error) {
wake_up(&dmxdevfilter->buffer.queue);
return 0;
}
- spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
+ spin_lock(&dmxdevfilter->dev->lock);
if (dmxdevfilter->state != DMXDEV_STATE_GO) {
- spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+ spin_unlock(&dmxdevfilter->dev->lock);
return 0;
}
del_timer(&dmxdevfilter->timer);
@@ -392,7 +391,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
}
if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
dmxdevfilter->state = DMXDEV_STATE_DONE;
- spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+ spin_unlock(&dmxdevfilter->dev->lock);
wake_up(&dmxdevfilter->buffer.queue);
return 0;
}
@@ -404,12 +403,11 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
{
struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dvb_ringbuffer *buffer;
- unsigned long flags;
int ret;
- spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
+ spin_lock(&dmxdevfilter->dev->lock);
if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
- spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+ spin_unlock(&dmxdevfilter->dev->lock);
return 0;
}
@@ -419,7 +417,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
else
buffer = &dmxdevfilter->dev->dvr_buffer;
if (buffer->error) {
- spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+ spin_unlock(&dmxdevfilter->dev->lock);
wake_up(&buffer->queue);
return 0;
}
@@ -430,7 +428,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
dvb_ringbuffer_flush(buffer);
buffer->error = ret;
}
- spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+ spin_unlock(&dmxdevfilter->dev->lock);
wake_up(&buffer->queue);
return 0;
}
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_demux.c b/linux/drivers/media/dvb/dvb-core/dvb_demux.c
index a2c1fd5d2..e2eca0b1f 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -399,9 +399,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
size_t count)
{
- unsigned long flags;
-
- spin_lock_irqsave(&demux->lock, flags);
+ spin_lock(&demux->lock);
while (count--) {
if (buf[0] == 0x47)
@@ -409,17 +407,16 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
buf += 188;
}
- spin_unlock_irqrestore(&demux->lock, flags);
+ spin_unlock(&demux->lock);
}
EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
{
- unsigned long flags;
int p = 0, i, j;
- spin_lock_irqsave(&demux->lock, flags);
+ spin_lock(&demux->lock);
if (demux->tsbufp) {
i = demux->tsbufp;
@@ -452,18 +449,17 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
}
bailout:
- spin_unlock_irqrestore(&demux->lock, flags);
+ spin_unlock(&demux->lock);
}
EXPORT_SYMBOL(dvb_dmx_swfilter);
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
{
- unsigned long flags;
int p = 0, i, j;
u8 tmppack[188];
- spin_lock_irqsave(&demux->lock, flags);
+ spin_lock(&demux->lock);
if (demux->tsbufp) {
i = demux->tsbufp;
@@ -504,7 +500,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
}
bailout:
- spin_unlock_irqrestore(&demux->lock, flags);
+ spin_unlock(&demux->lock);
}
EXPORT_SYMBOL(dvb_dmx_swfilter_204);
diff --git a/linux/drivers/media/video/gspca/Kconfig b/linux/drivers/media/video/gspca/Kconfig
index 11c5d2fc2..a0f05ef5c 100644
--- a/linux/drivers/media/video/gspca/Kconfig
+++ b/linux/drivers/media/video/gspca/Kconfig
@@ -176,6 +176,15 @@ config USB_GSPCA_SPCA561
To compile this driver as a module, choose M here: the
module will be called gspca_spca561.
+config USB_GSPCA_SQ905
+ tristate "SQ Technologies SQ905 based USB Camera Driver"
+ depends on VIDEO_V4L2 && USB_GSPCA
+ help
+ Say Y here if you want support for cameras based on the SQ905 chip.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gspca_sq905.
+
config USB_GSPCA_STK014
tristate "Syntek DV4000 (STK014) USB Camera Driver"
depends on VIDEO_V4L2 && USB_GSPCA
diff --git a/linux/drivers/media/video/gspca/Makefile b/linux/drivers/media/video/gspca/Makefile
index b3cbcc176..b6ec61185 100644
--- a/linux/drivers/media/video/gspca/Makefile
+++ b/linux/drivers/media/video/gspca/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_USB_GSPCA_SPCA505) += gspca_spca505.o
obj-$(CONFIG_USB_GSPCA_SPCA506) += gspca_spca506.o
obj-$(CONFIG_USB_GSPCA_SPCA508) += gspca_spca508.o
obj-$(CONFIG_USB_GSPCA_SPCA561) += gspca_spca561.o
+obj-$(CONFIG_USB_GSPCA_SQ905) += gspca_sq905.o
obj-$(CONFIG_USB_GSPCA_SUNPLUS) += gspca_sunplus.o
obj-$(CONFIG_USB_GSPCA_STK014) += gspca_stk014.o
obj-$(CONFIG_USB_GSPCA_T613) += gspca_t613.o
@@ -41,6 +42,7 @@ gspca_spca505-objs := spca505.o
gspca_spca506-objs := spca506.o
gspca_spca508-objs := spca508.o
gspca_spca561-objs := spca561.o
+gspca_sq905-objs := sq905.o
gspca_stk014-objs := stk014.o
gspca_sunplus-objs := sunplus.o
gspca_t613-objs := t613.o
diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c
index cac937040..8d78b9287 100644
--- a/linux/drivers/media/video/gspca/gspca.c
+++ b/linux/drivers/media/video/gspca/gspca.c
@@ -136,11 +136,13 @@ static void fill_frame(struct gspca_dev *gspca_dev,
cam_pkt_op pkt_scan;
if (urb->status != 0) {
+ if (urb->status == -ESHUTDOWN)
+ return; /* disconnection */
#ifdef CONFIG_PM
if (!gspca_dev->frozen)
#endif
PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
- return; /* disconnection ? */
+ return;
}
pkt_scan = gspca_dev->sd_desc->pkt_scan;
for (i = 0; i < urb->number_of_packets; i++) {
@@ -220,6 +222,8 @@ static void bulk_irq(struct urb *urb)
switch (urb->status) {
case 0:
break;
+ case -ESHUTDOWN:
+ return; /* disconnection */
case -ECONNRESET:
urb->status = 0;
break;
@@ -228,7 +232,7 @@ static void bulk_irq(struct urb *urb)
if (!gspca_dev->frozen)
#endif
PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
- return; /* disconnection ? */
+ return;
}
/* check the availability of the frame buffer */
@@ -435,8 +439,7 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
break;
gspca_dev->urb[i] = NULL;
- if (!gspca_dev->present)
- usb_kill_urb(urb);
+ usb_kill_urb(urb);
if (urb->transfer_buffer != NULL)
usb_buffer_free(gspca_dev->dev,
urb->transfer_buffer_length,
@@ -604,6 +607,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
+ if (!gspca_dev->present) {
+ ret = -ENODEV;
+ goto out;
+ }
+
/* set the higher alternate setting and
* loop until urb submit succeeds */
gspca_dev->alt = gspca_dev->nbalt;
@@ -673,12 +681,14 @@ static int gspca_set_alt0(struct gspca_dev *gspca_dev)
static void gspca_stream_off(struct gspca_dev *gspca_dev)
{
gspca_dev->streaming = 0;
- if (gspca_dev->present
- && gspca_dev->sd_desc->stopN)
- gspca_dev->sd_desc->stopN(gspca_dev);
- destroy_urbs(gspca_dev);
- if (gspca_dev->present)
+ if (gspca_dev->present) {
+ if (gspca_dev->sd_desc->stopN)
+ gspca_dev->sd_desc->stopN(gspca_dev);
+ destroy_urbs(gspca_dev);
gspca_set_alt0(gspca_dev);
+ }
+
+ /* always call stop0 to free the subdriver's resources */
if (gspca_dev->sd_desc->stop0)
gspca_dev->sd_desc->stop0(gspca_dev);
PDEBUG(D_STREAM, "stream off OK");
@@ -960,8 +970,17 @@ static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
struct gspca_dev *gspca_dev = priv;
+ int ret;
memset(cap, 0, sizeof *cap);
+
+ /* protect the access to the usb device */
+ if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+ return -ERESTARTSYS;
+ if (!gspca_dev->present) {
+ ret = -ENODEV;
+ goto out;
+ }
strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
if (gspca_dev->dev->product != NULL) {
strncpy(cap->card, gspca_dev->dev->product,
@@ -977,7 +996,10 @@ static int vidioc_querycap(struct file *file, void *priv,
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_STREAMING
| V4L2_CAP_READWRITE;
- return 0;
+ ret = 0;
+out:
+ mutex_unlock(&gspca_dev->usb_lock);
+ return ret;
}
static int vidioc_queryctrl(struct file *file, void *priv,
@@ -1040,7 +1062,10 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
- ret = ctrls->set(gspca_dev, ctrl->value);
+ if (gspca_dev->present)
+ ret = ctrls->set(gspca_dev, ctrl->value);
+ else
+ ret = -ENODEV;
mutex_unlock(&gspca_dev->usb_lock);
return ret;
}
@@ -1064,7 +1089,10 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
return -EINVAL;
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
- ret = ctrls->get(gspca_dev, &ctrl->value);
+ if (gspca_dev->present)
+ ret = ctrls->get(gspca_dev, &ctrl->value);
+ else
+ ret = -ENODEV;
mutex_unlock(&gspca_dev->usb_lock);
return ret;
}
@@ -1226,10 +1254,7 @@ static int vidioc_streamon(struct file *file, void *priv,
return -EINVAL;
if (mutex_lock_interruptible(&gspca_dev->queue_lock))
return -ERESTARTSYS;
- if (!gspca_dev->present) {
- ret = -ENODEV;
- goto out;
- }
+
if (gspca_dev->nframes == 0
|| !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) {
ret = -EINVAL;
@@ -1297,7 +1322,10 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv,
return -EINVAL;
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
- ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
+ if (gspca_dev->present)
+ ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
+ else
+ ret = -ENODEV;
mutex_unlock(&gspca_dev->usb_lock);
return ret;
}
@@ -1312,7 +1340,10 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv,
return -EINVAL;
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
- ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
+ if (gspca_dev->present)
+ ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
+ else
+ ret = -ENODEV;
mutex_unlock(&gspca_dev->usb_lock);
return ret;
}
@@ -1331,7 +1362,11 @@ static int vidioc_g_parm(struct file *filp, void *priv,
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
- ret = gspca_dev->sd_desc->get_streamparm(gspca_dev, parm);
+ if (gspca_dev->present)
+ ret = gspca_dev->sd_desc->get_streamparm(gspca_dev,
+ parm);
+ else
+ ret = -ENODEV;
mutex_unlock(&gspca_dev->usb_lock);
return ret;
}
@@ -1356,7 +1391,11 @@ static int vidioc_s_parm(struct file *filp, void *priv,
if (mutex_lock_interruptible(&gspca_dev->usb_lock))
return -ERESTARTSYS;
- ret = gspca_dev->sd_desc->set_streamparm(gspca_dev, parm);
+ if (gspca_dev->present)
+ ret = gspca_dev->sd_desc->set_streamparm(gspca_dev,
+ parm);
+ else
+ ret = -ENODEV;
mutex_unlock(&gspca_dev->usb_lock);
return ret;
}
@@ -1530,7 +1569,8 @@ static int frame_wait(struct gspca_dev *gspca_dev,
if (gspca_dev->sd_desc->dq_callback) {
mutex_lock(&gspca_dev->usb_lock);
- gspca_dev->sd_desc->dq_callback(gspca_dev);
+ if (gspca_dev->present)
+ gspca_dev->sd_desc->dq_callback(gspca_dev);
mutex_unlock(&gspca_dev->usb_lock);
}
return j;
@@ -1552,6 +1592,9 @@ static int vidioc_dqbuf(struct file *file, void *priv,
if (v4l2_buf->memory != gspca_dev->memory)
return -EINVAL;
+ if (!gspca_dev->present)
+ return -ENODEV;
+
/* if not streaming, be sure the application will not loop forever */
if (!(file->f_flags & O_NONBLOCK)
&& !gspca_dev->streaming && gspca_dev->users == 1)
@@ -1702,8 +1745,6 @@ static unsigned int dev_poll(struct file *file, poll_table *wait)
PDEBUG(D_FRAM, "poll");
poll_wait(file, &gspca_dev->wq, wait);
- if (!gspca_dev->present)
- return POLLERR;
/* if reqbufs is not done, the user would use read() */
if (gspca_dev->nframes == 0) {
@@ -1716,10 +1757,6 @@ static unsigned int dev_poll(struct file *file, poll_table *wait)
if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0)
return POLLERR;
- if (!gspca_dev->present) {
- ret = POLLERR;
- goto out;
- }
/* check the next incoming buffer */
i = gspca_dev->fr_o;
@@ -1728,8 +1765,9 @@ static unsigned int dev_poll(struct file *file, poll_table *wait)
ret = POLLIN | POLLRDNORM; /* something to read */
else
ret = 0;
-out:
mutex_unlock(&gspca_dev->queue_lock);
+ if (!gspca_dev->present)
+ return POLLHUP;
return ret;
}
@@ -1953,8 +1991,18 @@ void gspca_disconnect(struct usb_interface *intf)
{
struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+ mutex_lock(&gspca_dev->usb_lock);
gspca_dev->present = 0;
+ if (gspca_dev->streaming) {
+ destroy_urbs(gspca_dev);
+ wake_up_interruptible(&gspca_dev->wq);
+ }
+
+ /* the device is freed at exit of this function */
+ gspca_dev->dev = NULL;
+ mutex_unlock(&gspca_dev->usb_lock);
+
usb_set_intfdata(intf, NULL);
/* release the device */
diff --git a/linux/drivers/media/video/gspca/mr97310a.c b/linux/drivers/media/video/gspca/mr97310a.c
index 3a5ddff8f..5ec5ce6e3 100644
--- a/linux/drivers/media/video/gspca/mr97310a.c
+++ b/linux/drivers/media/video/gspca/mr97310a.c
@@ -73,7 +73,7 @@ static int reg_w(struct gspca_dev *gspca_dev, int len)
rc = usb_bulk_msg(gspca_dev->dev,
usb_sndbulkpipe(gspca_dev->dev, 4),
- gspca_dev->usb_buf, len, 0, 500);
+ gspca_dev->usb_buf, len, NULL, 500);
if (rc < 0)
PDEBUG(D_ERR, "reg write [%02x] error %d",
gspca_dev->usb_buf[0], rc);
diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c
index 0aa4649bd..5cdb643b8 100644
--- a/linux/drivers/media/video/gspca/sonixj.c
+++ b/linux/drivers/media/video/gspca/sonixj.c
@@ -45,7 +45,7 @@ struct sd {
u8 blue;
u8 red;
u8 gamma;
- u8 vflip; /* ov7630 only */
+ u8 vflip; /* ov7630/ov7648 only */
u8 infrared; /* mt9v111 only */
s8 ag_cnt;
@@ -192,7 +192,7 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setautogain,
.get = sd_getautogain,
},
-/* ov7630 only */
+/* ov7630/ov7648 only */
#define VFLIP_IDX 6
{
{
@@ -202,7 +202,7 @@ static struct ctrl sd_ctrls[] = {
.minimum = 0,
.maximum = 1,
.step = 1,
-#define VFLIP_DEF 1
+#define VFLIP_DEF 0 /* vflip def = 1 for ov7630 */
.default_value = VFLIP_DEF,
},
.set = sd_setvflip,
@@ -235,16 +235,16 @@ static __u32 ctrl_dis[] = {
(1 << INFRARED_IDX) | (1 << VFLIP_IDX),
/* SENSOR_MO4000 2 */
#if 1
- 0,
+ (1 << VFLIP_IDX),
#else
- (1 << AUTOGAIN_IDX),
+ (1 << AUTOGAIN_IDX) | (1 << VFLIP_IDX),
#endif
/* SENSOR_MT9V111 3 */
(1 << INFRARED_IDX) | (1 << VFLIP_IDX),
/* SENSOR_OM6802 4 */
(1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX),
/* SENSOR_OV7630 5 */
- (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+ (1 << INFRARED_IDX),
/* SENSOR_OV7648 6 */
(1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
/* SENSOR_OV7660 7 */
@@ -677,7 +677,8 @@ static const u8 ov7648_sensor_init[][8] = {
{0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10},
/*...*/
/* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
-/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN
+ * set by setvflip */
{0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
{0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
@@ -1031,7 +1032,7 @@ static void mi0360_probe(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int i, j;
- u16 val;
+ u16 val = 0;
static const u8 probe_tb[][4][8] = {
{ /* mi0360 */
{0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
@@ -1319,7 +1320,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->gamma = GAMMA_DEF;
sd->autogain = AUTOGAIN_DEF;
sd->ag_cnt = -1;
- sd->vflip = VFLIP_DEF;
+ if (sd->sensor != SENSOR_OV7630)
+ sd->vflip = 0;
+ else
+ sd->vflip = 1;
sd->infrared = INFRARED_DEF;
gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
@@ -1589,16 +1593,39 @@ static void setautogain(struct gspca_dev *gspca_dev)
if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
return;
+ switch (sd->sensor) {
+ case SENSOR_OV7630:
+ case SENSOR_OV7648: {
+ u8 comb;
+
+ if (sd->sensor == SENSOR_OV7630)
+ comb = 0xc0;
+ else
+ comb = 0xa0;
+ if (sd->autogain)
+ comb |= 0x02;
+ i2c_w1(&sd->gspca_dev, 0x13, comb);
+ return;
+ }
+ }
if (sd->autogain)
sd->ag_cnt = AG_CNT_START;
else
sd->ag_cnt = -1;
}
+/* ov7630/ov7648 only */
static void setvflip(struct sd *sd)
{
- i2c_w1(&sd->gspca_dev, 0x75, /* COMN */
- sd->vflip ? 0x82 : 0x02);
+ u8 comn;
+
+ if (sd->sensor == SENSOR_OV7630)
+ comn = 0x02;
+ else
+ comn = 0x06;
+ if (sd->vflip)
+ comn |= 0x80;
+ i2c_w1(&sd->gspca_dev, 0x75, comn);
}
static void setinfrared(struct sd *sd)
diff --git a/linux/drivers/media/video/gspca/spca505.c b/linux/drivers/media/video/gspca/spca505.c
index 4fc54d8b8..2acec58b1 100644
--- a/linux/drivers/media/video/gspca/spca505.c
+++ b/linux/drivers/media/video/gspca/spca505.c
@@ -426,8 +426,8 @@ static const u8 spca505b_open_data_ccd[][3] = {
{0x05, 0x00, 0x11},
{0x05, 0x00, 0x12},
{0x05, 0x6f, 0x00},
- {0x05, (u8) (initial_brightness >> 6), 0x00},
- {0x05, (u8) (initial_brightness << 2), 0x01},
+ {0x05, initial_brightness >> 6, 0x00},
+ {0x05, (initial_brightness << 2) & 0xff, 0x01},
{0x05, 0x00, 0x02},
{0x05, 0x01, 0x03},
{0x05, 0x00, 0x04},
@@ -560,8 +560,8 @@ static const u8 spca505b_open_data_ccd[][3] = {
{0x06, 0x5f, 0x1f},
{0x06, 0x32, 0x20},
- {0x05, (u8) (initial_brightness >> 6), 0x00},
- {0x05, (u8) (initial_brightness << 2), 0x01},
+ {0x05, initial_brightness >> 6, 0x00},
+ {0x05, (initial_brightness << 2) & 0xff, 0x01},
{0x05, 0x06, 0xc1},
{0x05, 0x58, 0xc2},
{0x05, 0x00, 0xca},
diff --git a/linux/drivers/media/video/gspca/sq905.c b/linux/drivers/media/video/gspca/sq905.c
new file mode 100644
index 000000000..dafaed69e
--- /dev/null
+++ b/linux/drivers/media/video/gspca/sq905.c
@@ -0,0 +1,438 @@
+/*
+ * SQ905 subdriver
+ *
+ * Copyright (C) 2008, 2009 Adam Baker and Theodore Kilgore
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * History and Acknowledgments
+ *
+ * The original Linux driver for SQ905 based cameras was written by
+ * Marcell Lengyel and furter developed by many other contributers
+ * and is available from http://sourceforge.net/projects/sqcam/
+ *
+ * This driver takes advantage of the reverse engineering work done for
+ * that driver and for libgphoto2 but shares no code with them.
+ *
+ * This driver has used as a base the finepix driver and other gspca
+ * based drivers and may still contain code fragments taken from those
+ * drivers.
+ */
+
+#define MODULE_NAME "sq905"
+
+#include <linux/workqueue.h>
+#include "gspca.h"
+
+MODULE_AUTHOR("Adam Baker <linux@baker-net.org.uk>, "
+ "Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_DESCRIPTION("GSPCA/SQ905 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeouts, in ms */
+#define SQ905_CMD_TIMEOUT 500
+#define SQ905_DATA_TIMEOUT 1000
+
+/* Maximum transfer size to use. */
+#define SQ905_MAX_TRANSFER 0x8000
+#define FRAME_HEADER_LEN 64
+
+/* The known modes, or registers. These go in the "value" slot. */
+
+/* 00 is "none" obviously */
+
+#define SQ905_BULK_READ 0x03 /* precedes any bulk read */
+#define SQ905_COMMAND 0x06 /* precedes the command codes below */
+#define SQ905_PING 0x07 /* when reading an "idling" command */
+#define SQ905_READ_DONE 0xc0 /* ack bulk read completed */
+
+/* Some command codes. These go in the "index" slot. */
+
+#define SQ905_ID 0xf0 /* asks for model string */
+#define SQ905_CONFIG 0x20 /* gets photo alloc. table, not used here */
+#define SQ905_DATA 0x30 /* accesses photo data, not used here */
+#define SQ905_CLEAR 0xa0 /* clear everything */
+#define SQ905_CAPTURE_LOW 0x60 /* Starts capture at 160x120 */
+#define SQ905_CAPTURE_MED 0x61 /* Starts capture at 320x240 */
+/* note that the capture command also controls the output dimensions */
+/* 0x60 -> 160x120, 0x61 -> 320x240 0x62 -> 640x480 depends on camera */
+/* 0x62 is not correct, at least for some cams. Should be 0x63 ? */
+
+/* Structure to hold all of our device specific stuff */
+struct sd {
+ struct gspca_dev gspca_dev; /* !! must be the first item */
+
+ u8 cam_type;
+
+ /*
+ * Driver stuff
+ */
+ struct work_struct work_struct;
+ struct workqueue_struct *work_thread;
+};
+
+/* The driver only supports 320x240 so far. */
+static struct v4l2_pix_format sq905_mode[1] = {
+ { 320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+ .bytesperline = 320,
+ .sizeimage = 320 * 240,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = 0}
+};
+
+struct cam_type {
+ u32 ident_word;
+ char *name;
+ struct v4l2_pix_format *min_mode;
+ u8 num_modes;
+ u8 sensor_flags;
+};
+
+#define SQ905_FLIP_HORIZ (1 << 0)
+#define SQ905_FLIP_VERT (1 << 1)
+
+/* Last entry is default if nothing else matches */
+static struct cam_type cam_types[] = {
+ { 0x19010509, "PocketCam", &sq905_mode[0], 1, SQ905_FLIP_HORIZ },
+ { 0x32010509, "Magpix", &sq905_mode[0], 1, SQ905_FLIP_HORIZ },
+ { 0, "Default", &sq905_mode[0], 1, SQ905_FLIP_HORIZ | SQ905_FLIP_VERT }
+};
+
+/*
+ * Send a command to the camera.
+ */
+static int sq905_command(struct gspca_dev *gspca_dev, u16 index)
+{
+ int ret;
+
+ gspca_dev->usb_buf[0] = '\0';
+ ret = usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ USB_REQ_SYNCH_FRAME, /* request */
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ SQ905_COMMAND, index, gspca_dev->usb_buf, 1,
+ SQ905_CMD_TIMEOUT);
+ if (ret < 0) {
+ PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ USB_REQ_SYNCH_FRAME, /* request */
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ SQ905_PING, 0, gspca_dev->usb_buf, 1,
+ SQ905_CMD_TIMEOUT);
+ if (ret < 0) {
+ PDEBUG(D_ERR, "%s: usb_control_msg failed 2 (%d)",
+ __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * Acknowledge the end of a frame - see warning on sq905_command.
+ */
+static int sq905_ack_frame(struct gspca_dev *gspca_dev)
+{
+ int ret;
+
+ gspca_dev->usb_buf[0] = '\0';
+ ret = usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ USB_REQ_SYNCH_FRAME, /* request */
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ SQ905_READ_DONE, 0, gspca_dev->usb_buf, 1,
+ SQ905_CMD_TIMEOUT);
+ if (ret < 0) {
+ PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * request and read a block of data - see warning on sq905_command.
+ */
+static int
+sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size)
+{
+ int ret;
+ int act_len;
+
+ gspca_dev->usb_buf[0] = '\0';
+ ret = usb_control_msg(gspca_dev->dev,
+ usb_sndctrlpipe(gspca_dev->dev, 0),
+ USB_REQ_SYNCH_FRAME, /* request */
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ SQ905_BULK_READ, size, gspca_dev->usb_buf,
+ 1, SQ905_CMD_TIMEOUT);
+ if (ret < 0) {
+ PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", __func__, ret);
+ return ret;
+ }
+ ret = usb_bulk_msg(gspca_dev->dev,
+ usb_rcvbulkpipe(gspca_dev->dev, 0x81),
+ data, size, &act_len, SQ905_DATA_TIMEOUT);
+
+ /* successful, it returns 0, otherwise negative */
+ if (ret < 0 || act_len != size) {
+ PDEBUG(D_ERR, "bulk read fail (%d) len %d/%d",
+ ret, act_len, size);
+ return -EIO;
+ }
+ return 0;
+}
+
+/* This function is called as a workqueue function and runs whenever the camera
+ * is streaming data. Because it is a workqueue function it is allowed to sleep
+ * so we can use synchronous USB calls. To avoid possible collisions with other
+ * threads attempting to use the camera's USB interface we take the gspca
+ * usb_lock when performing USB operations. In practice the only thing we need
+ * to protect against is the usb_set_interface call that gspca makes during
+ * stream_off as the camera doesn't provide any controls that the user could try
+ * to change.
+ */
+static void sq905_dostream(struct work_struct *work)
+{
+ struct sd *dev = container_of(work, struct sd, work_struct);
+ struct gspca_dev *gspca_dev = &dev->gspca_dev;
+ struct gspca_frame *frame;
+ int bytes_left; /* bytes remaining in current frame. */
+ int data_len; /* size to use for the next read. */
+ int header_read; /* true if we have already read the frame header. */
+ int discarding; /* true if we failed to get space for frame. */
+ int packet_type;
+ int ret;
+ u8 *data;
+ u8 *buffer;
+
+ buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
+ mutex_lock(&gspca_dev->usb_lock);
+ if (!buffer) {
+ PDEBUG(D_ERR, "Couldn't allocate USB buffer");
+ goto quit_stream;
+ }
+
+ while (gspca_dev->present && gspca_dev->streaming) {
+ /* Need a short delay to ensure streaming flag was set by
+ * gspca and to make sure gspca can grab the mutex. */
+ mutex_unlock(&gspca_dev->usb_lock);
+ msleep(1);
+
+ /* request some data and then read it until we have
+ * a complete frame. */
+ bytes_left = sq905_mode[0].sizeimage + FRAME_HEADER_LEN;
+ header_read = 0;
+ discarding = 0;
+
+ while (bytes_left > 0) {
+ data_len = bytes_left > SQ905_MAX_TRANSFER ?
+ SQ905_MAX_TRANSFER : bytes_left;
+ mutex_lock(&gspca_dev->usb_lock);
+ if (!gspca_dev->present)
+ goto quit_stream;
+ ret = sq905_read_data(gspca_dev, buffer, data_len);
+ if (ret < 0)
+ goto quit_stream;
+ mutex_unlock(&gspca_dev->usb_lock);
+ PDEBUG(D_STREAM,
+ "Got %d bytes out of %d for frame",
+ data_len, bytes_left);
+ bytes_left -= data_len;
+ data = buffer;
+ if (!header_read) {
+ packet_type = FIRST_PACKET;
+ /* The first 64 bytes of each frame are
+ * a header full of FF 00 bytes */
+ data += FRAME_HEADER_LEN;
+ data_len -= FRAME_HEADER_LEN;
+ header_read = 1;
+ } else if (bytes_left == 0) {
+ packet_type = LAST_PACKET;
+ } else {
+ packet_type = INTER_PACKET;
+ }
+ frame = gspca_get_i_frame(gspca_dev);
+ if (frame && !discarding)
+ gspca_frame_add(gspca_dev, packet_type,
+ frame, data, data_len);
+ else
+ discarding = 1;
+ }
+ /* acknowledge the frame */
+ mutex_lock(&gspca_dev->usb_lock);
+ if (!gspca_dev->present)
+ goto quit_stream;
+ ret = sq905_ack_frame(gspca_dev);
+ if (ret < 0)
+ goto quit_stream;
+ }
+quit_stream:
+ /* the usb_lock is already acquired */
+ if (gspca_dev->present)
+ sq905_command(gspca_dev, SQ905_CLEAR);
+ mutex_unlock(&gspca_dev->usb_lock);
+ kfree(buffer);
+}
+
+/* This function is called at probe time just before sd_init */
+static int sd_config(struct gspca_dev *gspca_dev,
+ const struct usb_device_id *id)
+{
+ struct cam *cam = &gspca_dev->cam;
+ struct sd *dev = (struct sd *) gspca_dev;
+
+ cam->cam_mode = sq905_mode;
+ cam->nmodes = 1;
+ /* We don't use the buffer gspca allocates so make it small. */
+ cam->bulk_size = 64;
+
+ INIT_WORK(&dev->work_struct, sq905_dostream);
+
+ return 0;
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+ struct sd *dev = (struct sd *) gspca_dev;
+
+ /* wait for the work queue to terminate */
+ mutex_unlock(&gspca_dev->usb_lock);
+ /* This waits for sq905_dostream to finish */
+ destroy_workqueue(dev->work_thread);
+ dev->work_thread = NULL;
+ mutex_lock(&gspca_dev->usb_lock);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+ struct sd *dev = (struct sd *) gspca_dev;
+ u32 ident;
+ int ret;
+
+ /* connect to the camera and read
+ * the model ID and process that and put it away.
+ */
+ ret = sq905_command(gspca_dev, SQ905_CLEAR);
+ if (ret < 0)
+ return ret;
+ ret = sq905_command(gspca_dev, SQ905_ID);
+ if (ret < 0)
+ return ret;
+ ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4);
+ if (ret < 0)
+ return ret;
+ /* usb_buf is allocated with kmalloc so is aligned. */
+ ident = le32_to_cpup((u32 *)gspca_dev->usb_buf);
+ ret = sq905_command(gspca_dev, SQ905_CLEAR);
+ if (ret < 0)
+ return ret;
+ dev->cam_type = 0;
+ while (dev->cam_type < ARRAY_SIZE(cam_types) - 1 &&
+ ident != cam_types[dev->cam_type].ident_word)
+ dev->cam_type++;
+ PDEBUG(D_CONF, "SQ905 camera %s, ID %08x detected",
+ cam_types[dev->cam_type].name, ident);
+ return 0;
+}
+
+/* Set up for getting frames. */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+ struct sd *dev = (struct sd *) gspca_dev;
+ int ret;
+
+ /* "Open the shutter" and set size, to start capture */
+ ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED);
+ if (ret < 0) {
+ PDEBUG(D_ERR, "Start streaming command failed");
+ return ret;
+ }
+
+ /* Start the workqueue function to do the streaming */
+ dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
+ queue_work(dev->work_thread, &dev->work_struct);
+
+ return 0;
+}
+
+/* Table of supported USB devices */
+static const __devinitdata struct usb_device_id device_table[] = {
+ {USB_DEVICE(0x2770, 0x9120)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+ .name = MODULE_NAME,
+ .config = sd_config,
+ .init = sd_init,
+ .start = sd_start,
+ .stop0 = sd_stop0,
+};
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return gspca_dev_probe(intf, id,
+ &sd_desc,
+ sizeof(struct sd),
+ THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+ .name = MODULE_NAME,
+ .id_table = device_table,
+ .probe = sd_probe,
+ .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+ int ret;
+
+ ret = usb_register(&sd_driver);
+ if (ret < 0)
+ return ret;
+ PDEBUG(D_PROBE, "registered");
+ return 0;
+}
+
+static void __exit sd_mod_exit(void)
+{
+ usb_deregister(&sd_driver);
+ PDEBUG(D_PROBE, "deregistered");
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c
index adec0767c..f60a4c21a 100644
--- a/linux/drivers/media/video/gspca/t613.c
+++ b/linux/drivers/media/video/gspca/t613.c
@@ -272,7 +272,7 @@ struct additional_sensor_data {
const u8 stream[4];
};
-const static struct additional_sensor_data sensor_data[] = {
+static const struct additional_sensor_data sensor_data[] = {
{ /* OM6802 */
.data1 =
{0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
@@ -681,19 +681,19 @@ static int sd_init(struct gspca_dev *gspca_dev)
| reg_r(gspca_dev, 0x07);
switch (sensor_id) {
case 0x0801:
- PDEBUG(D_CONF, "sensor tas5130a");
+ PDEBUG(D_PROBE, "sensor tas5130a");
sd->sensor = SENSOR_TAS5130A;
break;
case 0x0803:
- PDEBUG(D_CONF, "sensor om6802");
+ PDEBUG(D_PROBE, "sensor 'other'");
sd->sensor = SENSOR_OTHER;
break;
case 0x0807:
- PDEBUG(D_CONF, "sensor om6802");
+ PDEBUG(D_PROBE, "sensor om6802");
sd->sensor = SENSOR_OM6802;
break;
default:
- PDEBUG(D_CONF, "unknown sensor %04x", sensor_id);
+ PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
return -EINVAL;
}
diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c
index 1832d241f..72cbf56c9 100644
--- a/linux/drivers/media/video/gspca/vc032x.c
+++ b/linux/drivers/media/video/gspca/vc032x.c
@@ -2098,6 +2098,7 @@ static void usb_exchange(struct gspca_dev *gspca_dev,
/*not reached*/
}
+#if 0
static void vc0321_reset(struct gspca_dev *gspca_dev)
{
reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb04d);
@@ -2106,6 +2107,7 @@ static void vc0321_reset(struct gspca_dev *gspca_dev)
reg_w(gspca_dev->dev, 0xa0, 0x01, 0xb003);
msleep(100);
}
+#endif
/* this function is called at probe time */
static int sd_config(struct gspca_dev *gspca_dev,
@@ -2118,8 +2120,9 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam = &gspca_dev->cam;
sd->bridge = id->driver_info;
-
+#if 0
vc0321_reset(gspca_dev);
+#endif
sensor = vc032x_probe_sensor(gspca_dev);
switch (sensor) {
case -1:
diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c
index a67bed7d7..a99aea49a 100644
--- a/linux/drivers/media/video/ir-kbd-i2c.c
+++ b/linux/drivers/media/video/ir-kbd-i2c.c
@@ -16,6 +16,8 @@
* Henry Wong <henry@stuffedcow.net>
* Mark Schultz <n9xmj@yahoo.com>
* Brian Rogers <brian_rogers@comcast.net>
+ * modified for AVerMedia Cardbus by
+ * Oldrich Jedlicka <oldium.pro@seznam.cz>
*
* 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
@@ -217,6 +219,46 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return 1;
}
+static int get_key_avermedia_cardbus(struct IR_i2c *ir,
+ u32 *ir_key, u32 *ir_raw)
+{
+ unsigned char subaddr, key, keygroup;
+ struct i2c_msg msg[] = { { .addr = ir->c.addr, .flags = 0,
+ .buf = &subaddr, .len = 1},
+ { .addr = ir->c.addr, .flags = I2C_M_RD,
+ .buf = &key, .len = 1} };
+ subaddr = 0x0d;
+ if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+ dprintk(1, "read error\n");
+ return -EIO;
+ }
+
+ if (key == 0xff)
+ return 0;
+
+ subaddr = 0x0b;
+ msg[1].buf = &keygroup;
+ if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
+ dprintk(1, "read error\n");
+ return -EIO;
+ }
+
+ if (keygroup == 0xff)
+ return 0;
+
+ dprintk(1, "read key 0x%02x/0x%02x\n", key, keygroup);
+ if (keygroup < 2 || keygroup > 3) {
+ /* Only a warning */
+ dprintk(1, "warning: invalid key group 0x%02x for key 0x%02x\n",
+ keygroup, key);
+ }
+ key |= (keygroup & 1) << 6;
+
+ *ir_key = key;
+ *ir_raw = key;
+ return 1;
+}
+
/* ----------------------------------------------------------------------- */
static void ir_key_poll(struct IR_i2c *ir)
@@ -369,6 +411,12 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
ir_type = IR_TYPE_OTHER;
}
break;
+ case 0x40:
+ name = "AVerMedia Cardbus remote";
+ ir->get_key = get_key_avermedia_cardbus;
+ ir_type = IR_TYPE_OTHER;
+ ir_codes = ir_codes_avermedia_cardbus;
+ break;
default:
/* shouldn't happen */
printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr);
@@ -537,6 +585,22 @@ static int ir_probe(struct i2c_adapter *adap)
ir_attach(adap, msg.addr, 0, 0);
}
+ /* Special case for AVerMedia Cardbus remote */
+ if (adap->id == I2C_HW_SAA7134) {
+ unsigned char subaddr, data;
+ struct i2c_msg msg[] = { { .addr = 0x40, .flags = 0,
+ .buf = &subaddr, .len = 1},
+ { .addr = 0x40, .flags = I2C_M_RD,
+ .buf = &data, .len = 1} };
+ subaddr = 0x0d;
+ rc = i2c_transfer(adap, msg, 2);
+ dprintk(1, "probe 0x%02x/0x%02x @ %s: %s\n",
+ msg[0].addr, subaddr, adap->name,
+ (2 == rc) ? "yes" : "no");
+ if (2 == rc)
+ ir_attach(adap, msg[0].addr, 0, 0);
+ }
+
return 0;
}
diff --git a/linux/drivers/media/video/ivtv/ivtv-ioctl.c b/linux/drivers/media/video/ivtv/ivtv-ioctl.c
index aa55a3cc4..9a0424298 100644
--- a/linux/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/linux/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -391,7 +391,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo
return 0;
}
- v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
+ v4l2_subdev_call(itv->sd_video, video, g_fmt, fmt);
vbifmt->service_set = ivtv_get_service_set(vbifmt);
return 0;
}
@@ -1752,6 +1752,18 @@ static long ivtv_default(struct file *file, void *fh, int cmd, void *arg)
break;
}
+ case IVTV_IOC_DMA_FRAME:
+ case VIDEO_GET_PTS:
+ case VIDEO_GET_FRAME_COUNT:
+ case VIDEO_GET_EVENT:
+ case VIDEO_PLAY:
+ case VIDEO_STOP:
+ case VIDEO_FREEZE:
+ case VIDEO_CONTINUE:
+ case VIDEO_COMMAND:
+ case VIDEO_TRY_COMMAND:
+ return ivtv_decoder_ioctls(file, cmd, (void *)arg);
+
default:
return -EINVAL;
}
@@ -1794,18 +1806,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
return 0;
- case IVTV_IOC_DMA_FRAME:
- case VIDEO_GET_PTS:
- case VIDEO_GET_FRAME_COUNT:
- case VIDEO_GET_EVENT:
- case VIDEO_PLAY:
- case VIDEO_STOP:
- case VIDEO_FREEZE:
- case VIDEO_CONTINUE:
- case VIDEO_COMMAND:
- case VIDEO_TRY_COMMAND:
- return ivtv_decoder_ioctls(filp, cmd, (void *)arg);
-
default:
break;
}
diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c
index 01cc9543f..9db045cf5 100644
--- a/linux/drivers/media/video/saa7134/saa7134-cards.c
+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c
@@ -4362,13 +4362,13 @@ struct saa7134_board saa7134_boards[] = {
.amux = TV,
.tv = 1,
}, {
- .name = name_comp,
- .vmux = 0,
+ .name = name_comp1,
+ .vmux = 3,
.amux = LINE1,
}, {
.name = name_svideo,
.vmux = 8,
- .amux = LINE1,
+ .amux = LINE2,
} },
.radio = {
.name = name_radio,
@@ -6120,6 +6120,11 @@ int saa7134_board_init1(struct saa7134_dev *dev)
msleep(10);
break;
case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+ saa7134_set_gpio(dev, 23, 0);
+ msleep(10);
+ saa7134_set_gpio(dev, 23, 1);
+ dev->has_remote = SAA7134_REMOTE_I2C;
+ break;
case SAA7134_BOARD_AVERMEDIA_M103:
saa7134_set_gpio(dev, 23, 0);
msleep(10);
diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c
index 4b4d5ef76..b77ccb5a0 100644
--- a/linux/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c
@@ -260,7 +260,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
addr = msgs[i].addr << 1;
if (msgs[i].flags & I2C_M_RD)
addr |= 1;
- if (i > 0 && msgs[i].flags & I2C_M_RD) {
+ if (i > 0 && msgs[i].flags & I2C_M_RD && msgs[i].addr != 0x40) {
/* workaround for a saa7134 i2c bug
* needed to talk to the mt352 demux
* thanks to pinnacle for the hint */
diff --git a/linux/drivers/media/video/tcm825x.c b/linux/drivers/media/video/tcm825x.c
index 2f823f27a..559ade821 100644
--- a/linux/drivers/media/video/tcm825x.c
+++ b/linux/drivers/media/video/tcm825x.c
@@ -50,7 +50,7 @@ struct tcm825x_sensor {
};
/* list of image formats supported by TCM825X sensor */
-const static struct v4l2_fmtdesc tcm825x_formats[] = {
+static const struct v4l2_fmtdesc tcm825x_formats[] = {
{
.description = "YUYV (YUV 4:2:2), packed",
.pixelformat = V4L2_PIX_FMT_UYVY,
@@ -76,15 +76,15 @@ const static struct v4l2_fmtdesc tcm825x_formats[] = {
* TCM825X register configuration for all combinations of pixel format and
* image size
*/
-const static struct tcm825x_reg subqcif = { 0x20, TCM825X_PICSIZ };
-const static struct tcm825x_reg qcif = { 0x18, TCM825X_PICSIZ };
-const static struct tcm825x_reg cif = { 0x14, TCM825X_PICSIZ };
-const static struct tcm825x_reg qqvga = { 0x0c, TCM825X_PICSIZ };
-const static struct tcm825x_reg qvga = { 0x04, TCM825X_PICSIZ };
-const static struct tcm825x_reg vga = { 0x00, TCM825X_PICSIZ };
+static const struct tcm825x_reg subqcif = { 0x20, TCM825X_PICSIZ };
+static const struct tcm825x_reg qcif = { 0x18, TCM825X_PICSIZ };
+static const struct tcm825x_reg cif = { 0x14, TCM825X_PICSIZ };
+static const struct tcm825x_reg qqvga = { 0x0c, TCM825X_PICSIZ };
+static const struct tcm825x_reg qvga = { 0x04, TCM825X_PICSIZ };
+static const struct tcm825x_reg vga = { 0x00, TCM825X_PICSIZ };
-const static struct tcm825x_reg yuv422 = { 0x00, TCM825X_PICFMT };
-const static struct tcm825x_reg rgb565 = { 0x02, TCM825X_PICFMT };
+static const struct tcm825x_reg yuv422 = { 0x00, TCM825X_PICFMT };
+static const struct tcm825x_reg rgb565 = { 0x02, TCM825X_PICFMT };
/* Our own specific controls */
#define V4L2_CID_ALC V4L2_CID_PRIVATE_BASE
@@ -248,10 +248,10 @@ static struct vcontrol {
};
-const static struct tcm825x_reg *tcm825x_siz_reg[NUM_IMAGE_SIZES] =
+static const struct tcm825x_reg *tcm825x_siz_reg[NUM_IMAGE_SIZES] =
{ &subqcif, &qqvga, &qcif, &qvga, &cif, &vga };
-const static struct tcm825x_reg *tcm825x_fmt_reg[NUM_PIXEL_FORMATS] =
+static const struct tcm825x_reg *tcm825x_fmt_reg[NUM_PIXEL_FORMATS] =
{ &yuv422, &rgb565 };
/*
diff --git a/linux/drivers/media/video/tcm825x.h b/linux/drivers/media/video/tcm825x.h
index 770ebacfa..5b7e69682 100644
--- a/linux/drivers/media/video/tcm825x.h
+++ b/linux/drivers/media/video/tcm825x.h
@@ -188,7 +188,7 @@ struct tcm825x_platform_data {
/* Array of image sizes supported by TCM825X. These must be ordered from
* smallest image size to largest.
*/
-const static struct capture_size tcm825x_sizes[] = {
+static const struct capture_size tcm825x_sizes[] = {
{ 128, 96 }, /* subQCIF */
{ 160, 120 }, /* QQVGA */
{ 176, 144 }, /* QCIF */
diff --git a/linux/drivers/media/video/tvp514x.c b/linux/drivers/media/video/tvp514x.c
index 8e23aa53c..5f4cbc2b2 100644
--- a/linux/drivers/media/video/tvp514x.c
+++ b/linux/drivers/media/video/tvp514x.c
@@ -686,7 +686,7 @@ static int ioctl_s_routing(struct v4l2_int_device *s,
break; /* Input detected */
}
- if ((current_std == STD_INVALID) || (try_count < 0))
+ if ((current_std == STD_INVALID) || (try_count <= 0))
return -EINVAL;
decoder->current_std = current_std;
diff --git a/linux/drivers/media/video/tw9910.c b/linux/drivers/media/video/tw9910.c
index c670b23a1..4593cdea7 100644
--- a/linux/drivers/media/video/tw9910.c
+++ b/linux/drivers/media/video/tw9910.c
@@ -645,6 +645,19 @@ static int tw9910_set_fmt(struct soc_camera_device *icd, __u32 pixfmt,
struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
int ret = -EINVAL;
u8 val;
+ int i;
+
+ /*
+ * check color format
+ */
+ for (i = 0 ; i < ARRAY_SIZE(tw9910_color_fmt) ; i++) {
+ if (pixfmt == tw9910_color_fmt[i].fourcc) {
+ ret = 0;
+ break;
+ }
+ }
+ if (ret < 0)
+ goto tw9910_set_fmt_error;
/*
* select suitable norm
diff --git a/linux/drivers/media/video/zoran/zoran_driver.c b/linux/drivers/media/video/zoran/zoran_driver.c
index 2609f54d7..798745c0a 100644
--- a/linux/drivers/media/video/zoran/zoran_driver.c
+++ b/linux/drivers/media/video/zoran/zoran_driver.c
@@ -356,9 +356,9 @@ v4l_fbuffer_alloc (struct file *file)
SetPageReserved(MAP_NR(mem + off));
dprintk(4,
KERN_INFO
- "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%lx)\n",
+ "%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%llx)\n",
ZR_DEVNAME(zr), i, (unsigned long) mem,
- virt_to_bus(mem));
+ (unsigned long long)virt_to_bus(mem));
} else {
#if defined(CONFIG_BIGPHYS_AREA)
/* Use bigphysarea_alloc_pages */