diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-02-17 23:44:45 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-02-17 23:44:45 -0300 |
commit | b6705f84947f09dd3858f839267c9662fdbd667b (patch) | |
tree | c6a5dea386c7c837b17cbb4b44a158b78ca4c65e /linux/drivers | |
parent | 9446aad394fc912dc47f17e7638357edfd470ded (diff) | |
parent | aedda303081b327f1be76710db7032c675509d40 (diff) | |
download | mediapointer-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')
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 */ |