summaryrefslogtreecommitdiff
path: root/linux/drivers/media
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media')
-rw-r--r--linux/drivers/media/dvb/frontends/isl6421.c1
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-cards.c28
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-driver.c36
-rw-r--r--linux/drivers/media/video/bt8xx/bttv-i2c.c2
-rw-r--r--linux/drivers/media/video/bt8xx/bttvp.h3
-rw-r--r--linux/drivers/media/video/cafe_ccic.c66
-rw-r--r--linux/drivers/media/video/cpia_pp.c46
-rw-r--r--linux/drivers/media/video/cx88/cx88-alsa.c3
-rw-r--r--linux/drivers/media/video/cx88/cx88-cards.c19
-rw-r--r--linux/drivers/media/video/cx88/cx88-core.c8
-rw-r--r--linux/drivers/media/video/cx88/cx88-i2c.c3
-rw-r--r--linux/drivers/media/video/cx88/cx88-mpeg.c3
-rw-r--r--linux/drivers/media/video/cx88/cx88-video.c3
-rw-r--r--linux/drivers/media/video/cx88/cx88.h2
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-i2c.c2
-rw-r--r--linux/drivers/media/video/ir-kbd-i2c.c2
-rw-r--r--linux/drivers/media/video/ov7670.c32
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-cards.c4
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-i2c.c2
-rw-r--r--linux/drivers/media/video/sn9c102/Makefile17
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102.h17
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_core.c199
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_devtable.h14
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_hv7131d.c7
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_hv7131r.c458
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_mi0343.c111
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_mi0360.c353
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_ov7630.c63
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_ov7660.c3
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_pas106b.c5
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_pas202bcb.c15
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c6
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_tas5110d.c121
-rw-r--r--linux/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c5
34 files changed, 1357 insertions, 302 deletions
diff --git a/linux/drivers/media/dvb/frontends/isl6421.c b/linux/drivers/media/dvb/frontends/isl6421.c
index ef319369e..c967148a5 100644
--- a/linux/drivers/media/dvb/frontends/isl6421.c
+++ b/linux/drivers/media/dvb/frontends/isl6421.c
@@ -122,6 +122,7 @@ struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter
/* detect if it is present or not */
if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
kfree(isl6421);
+ fe->sec_priv = NULL;
return NULL;
}
diff --git a/linux/drivers/media/video/bt8xx/bttv-cards.c b/linux/drivers/media/video/bt8xx/bttv-cards.c
index b0e6c3e9c..d26dcf3d4 100644
--- a/linux/drivers/media/video/bt8xx/bttv-cards.c
+++ b/linux/drivers/media/video/bt8xx/bttv-cards.c
@@ -3015,20 +3015,20 @@ void __devinit bttv_idcard(struct bttv *btv)
if (UNSET != audiomux[0]) {
gpiobits = 0;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
bttv_tvcards[btv->c.type].gpiomux[i] = audiomux[i];
gpiobits |= audiomux[i];
}
} else {
gpiobits = audioall;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
bttv_tvcards[btv->c.type].gpiomux[i] = audioall;
}
}
bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits;
printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=",
btv->c.nr,bttv_tvcards[btv->c.type].gpiomask);
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]);
}
printk("\n");
@@ -3692,7 +3692,7 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen)
for (n = 0; n < microlen; n++) {
bits = micro[n];
- for ( i = 0 ; i < 8 ; i++ ) {
+ for (i = 0 ; i < 8 ; i++) {
gpio_bits(BTTV_ALT_DCLK,0);
if (bits & 0x01)
gpio_bits(BTTV_ALT_DATA,BTTV_ALT_DATA);
@@ -3749,7 +3749,7 @@ static void __devinit osprey_eeprom(struct bttv *btv)
/* this might be an antique... check for MMAC label in eeprom */
if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) {
unsigned char checksum = 0;
- for (i =0; i<21; i++)
+ for (i = 0; i < 21; i++)
checksum += ee[i];
if (checksum != ee[21])
return;
@@ -3761,12 +3761,13 @@ static void __devinit osprey_eeprom(struct bttv *btv)
unsigned short type;
int offset = 4*16;
- for(; offset < 8*16; offset += 16) {
+ for (; offset < 8*16; offset += 16) {
unsigned short checksum = 0;
/* verify the checksum */
- for(i = 0; i<14; i++) checksum += ee[i+offset];
- checksum = ~checksum; /* no idea why */
- if ((((checksum>>8)&0x0FF) == ee[offset+14]) &&
+ for (i = 0; i < 14; i++)
+ checksum += ee[i+offset];
+ checksum = ~checksum; /* no idea why */
+ if ((((checksum>>8)&0x0FF) == ee[offset+14]) &&
((checksum & 0x0FF) == ee[offset+15])) {
break;
}
@@ -3779,7 +3780,6 @@ static void __devinit osprey_eeprom(struct bttv *btv)
type = (ee[offset+4]<<8) | (ee[offset+5]);
switch(type) {
-
/* 848 based */
case 0x0004:
btv->c.type = BTTV_BOARD_OSPREY1x0_848;
@@ -4245,8 +4245,7 @@ static int tea5757_read(struct bttv *btv)
}
dprintk("bttv%d: tea5757:",btv->c.nr);
- for(i = 0; i < 24; i++)
- {
+ for (i = 0; i < 24; i++) {
udelay(5);
bus_high(btv,btv->mbox_clk);
udelay(5);
@@ -4278,8 +4277,7 @@ static int tea5757_write(struct bttv *btv, int value)
dprintk("bttv%d: tea5757: write 0x%X\n", btv->c.nr, value);
bus_low(btv,btv->mbox_clk);
bus_high(btv,btv->mbox_we);
- for(i = 0; i < 25; i++)
- {
+ for (i = 0; i < 25; i++) {
if (reg & 0x1000000)
bus_high(btv,btv->mbox_data);
else
@@ -4871,7 +4869,7 @@ static void kodicom4400r_init(struct bttv *btv)
gpio_write(1 << 9); /* reset MUX */
gpio_write(0);
/* Preset camera 0 to the 4 controllers */
- for (ix=0; ix<4; ix++) {
+ for (ix = 0; ix < 4; ix++) {
sw_status[ix] = ix;
kodicom4400r_write(btv, ix, ix, 1);
}
diff --git a/linux/drivers/media/video/bt8xx/bttv-driver.c b/linux/drivers/media/video/bt8xx/bttv-driver.c
index 25a61e379..2aad57b5a 100644
--- a/linux/drivers/media/video/bt8xx/bttv-driver.c
+++ b/linux/drivers/media/video/bt8xx/bttv-driver.c
@@ -177,6 +177,36 @@ static CLASS_DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
#endif
/* ----------------------------------------------------------------------- */
+/* dvb auto-load setup */
+#if defined(CONFIG_MODULES) && defined(MODULE)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static void request_module_async(void *ptr)
+#else
+static void request_module_async(struct work_struct *work)
+#endif
+{
+ request_module("dvb-bt8xx");
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#define request_modules(dev)
+#else
+static void request_modules(struct bttv *dev)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ INIT_WORK(&dev->request_module_wk, request_module_async, (void*)dev);
+#else
+ INIT_WORK(&dev->request_module_wk, request_module_async);
+#endif
+ schedule_work(&dev->request_module_wk);
+}
+#endif
+#else
+#define request_modules(dev)
+#endif /* CONFIG_MODULES */
+
+
+/* ----------------------------------------------------------------------- */
/* static data */
/* special timing tables from conexant... */
@@ -4811,9 +4841,11 @@ static int __devinit bttv_probe(struct pci_dev *dev,
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- /* add subdevices */
- if (bttv_tvcards[btv->c.type].has_dvb)
+ /* add subdevices and autoload dvb-bt8xx if needed */
+ if (bttv_tvcards[btv->c.type].has_dvb) {
bttv_sub_add_device(&btv->c, "dvb");
+ request_modules(btv);
+ }
#endif
bttv_input_init(btv);
diff --git a/linux/drivers/media/video/bt8xx/bttv-i2c.c b/linux/drivers/media/video/bt8xx/bttv-i2c.c
index 68522754a..3f545c610 100644
--- a/linux/drivers/media/video/bt8xx/bttv-i2c.c
+++ b/linux/drivers/media/video/bt8xx/bttv-i2c.c
@@ -426,7 +426,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
unsigned char buf;
int i,rc;
- for (i = 0; i < 128; i++) {
+ for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
c->addr = i;
rc = i2c_master_recv(c,&buf,0);
if (rc < 0)
diff --git a/linux/drivers/media/video/bt8xx/bttvp.h b/linux/drivers/media/video/bt8xx/bttvp.h
index a273c424b..eee6f5ae3 100644
--- a/linux/drivers/media/video/bt8xx/bttvp.h
+++ b/linux/drivers/media/video/bt8xx/bttvp.h
@@ -452,6 +452,9 @@ struct bttv {
unsigned int users;
struct bttv_fh init;
+ /* used to make dvb-bt8xx autoloadable */
+ struct work_struct request_module_wk;
+
/* Default (0) and current (1) video capturing and overlay
cropping parameters in bttv_tvnorm.cropcap units. Protected
by bttv.lock. */
diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c
index b96d45654..ea69590a1 100644
--- a/linux/drivers/media/video/cafe_ccic.c
+++ b/linux/drivers/media/video/cafe_ccic.c
@@ -38,7 +38,7 @@
#include "cafe_ccic-regs.h"
-#define CAFE_VERSION 0x000001
+#define CAFE_VERSION 0x000002
/*
@@ -712,7 +712,13 @@ static void cafe_ctlr_init(struct cafe_camera *cam)
cafe_reg_write(cam, REG_GL_CSR, GCSR_SRS|GCSR_MRS); /* Needed? */
cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRC);
cafe_reg_write(cam, REG_GL_CSR, GCSR_SRC|GCSR_MRS);
+ /*
+ * Here we must wait a bit for the controller to come around.
+ */
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
mdelay(5); /* FIXME revisit this */
+ spin_lock_irqsave(&cam->dev_lock, flags);
+
cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC);
cafe_reg_set_bit(cam, REG_GL_IMASK, GIMSK_CCIC_EN);
/*
@@ -780,9 +786,9 @@ static void cafe_ctlr_power_up(struct cafe_camera *cam)
* Control 1 is power down, set to 0 to operate.
*/
cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */
- mdelay(1); /* Marvell says 1ms will do it */
+// mdelay(1); /* Marvell says 1ms will do it */
cafe_reg_write(cam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0);
- mdelay(1); /* Enough? */
+// mdelay(1); /* Enough? */
spin_unlock_irqrestore(&cam->dev_lock, flags);
}
@@ -1803,18 +1809,19 @@ static void cafe_frame_tasklet(unsigned long data)
if (list_empty(&cam->sb_avail))
break; /* Leave it valid, hope for better later */
clear_bit(bufno, &cam->flags);
- /*
- * We could perhaps drop the spinlock during this
- * big copy. Something to consider.
- */
sbuf = list_entry(cam->sb_avail.next,
struct cafe_sio_buffer, list);
+ /*
+ * Drop the lock during the big copy. This *should* be safe...
+ */
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
memcpy(sbuf->buffer, cam->dma_bufs[bufno],
cam->pix_format.sizeimage);
sbuf->v4lbuf.bytesused = cam->pix_format.sizeimage;
sbuf->v4lbuf.sequence = cam->buf_seq[bufno];
sbuf->v4lbuf.flags &= ~V4L2_BUF_FLAG_QUEUED;
sbuf->v4lbuf.flags |= V4L2_BUF_FLAG_DONE;
+ spin_lock_irqsave(&cam->dev_lock, flags);
list_move_tail(&sbuf->list, &cam->sb_full);
}
if (! list_empty(&cam->sb_full))
@@ -2118,6 +2125,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
cam->v4ldev = cafe_v4l_template;
cam->v4ldev.debug = 0;
// cam->v4ldev.debug = V4L2_DEBUG_IOCTL_ARG;
+ cam->v4ldev.dev = &pdev->dev;
ret = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER, -1);
if (ret)
goto out_smbus;
@@ -2187,10 +2195,48 @@ static void cafe_pci_remove(struct pci_dev *pdev)
}
+#ifdef CONFIG_PM
+/*
+ * Basic power management.
+ */
+static int cafe_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct cafe_camera *cam = cafe_find_by_pdev(pdev);
+ int ret;
+
+ ret = pci_save_state(pdev);
+ if (ret)
+ return ret;
+ cafe_ctlr_stop_dma(cam);
+ cafe_ctlr_power_down(cam);
+ pci_disable_device(pdev);
+ return 0;
+}
+
+
+static int cafe_pci_resume(struct pci_dev *pdev)
+{
+ struct cafe_camera *cam = cafe_find_by_pdev(pdev);
+ int ret = 0;
+
+ ret = pci_restore_state(pdev);
+ if (ret)
+ return ret;
+ pci_enable_device(pdev);
+ cafe_ctlr_init(cam);
+ cafe_ctlr_power_up(cam);
+ set_bit(CF_CONFIG_NEEDED, &cam->flags);
+ if (cam->state == S_SPECREAD)
+ cam->state = S_IDLE; /* Don't bother restarting */
+ else if (cam->state == S_SINGLEREAD || cam->state == S_STREAMING)
+ ret = cafe_read_setup(cam, cam->state);
+ return ret;
+}
+
+#endif /* CONFIG_PM */
static struct pci_device_id cafe_ids[] = {
- { PCI_DEVICE(0x1148, 0x4340) }, /* Temporary ID on devel board */
{ PCI_DEVICE(0x11ab, 0x4100) }, /* Eventual real ID */
{ PCI_DEVICE(0x11ab, 0x4102) }, /* Really eventual real ID */
{ 0, }
@@ -2203,6 +2249,10 @@ static struct pci_driver cafe_pci_driver = {
.id_table = cafe_ids,
.probe = cafe_pci_probe,
.remove = cafe_pci_remove,
+#ifdef CONFIG_PM
+ .suspend = cafe_pci_suspend,
+ .resume = cafe_pci_resume,
+#endif
};
diff --git a/linux/drivers/media/video/cpia_pp.c b/linux/drivers/media/video/cpia_pp.c
index 337675e96..d2c34c156 100644
--- a/linux/drivers/media/video/cpia_pp.c
+++ b/linux/drivers/media/video/cpia_pp.c
@@ -62,7 +62,6 @@ static int cpia_pp_close(void *privdata);
#define PPCPIA_PARPORT_OFF -2
#define PPCPIA_PARPORT_NONE -1
-#ifdef MODULE
static int parport_nr[PARPORT_MAX] = {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC};
static char *parport[PARPORT_MAX] = {NULL,};
@@ -72,11 +71,6 @@ MODULE_LICENSE("GPL");
module_param_array(parport, charp, NULL, 0);
MODULE_PARM_DESC(parport, "'auto' or a list of parallel port numbers. Just like lp.");
-#else
-static int parport_nr[PARPORT_MAX] __initdata =
- {[0 ... PARPORT_MAX - 1] = PPCPIA_PARPORT_UNSPEC};
-static int parport_ptr = 0;
-#endif
struct pp_cam_entry {
struct pardevice *pdev;
@@ -827,7 +821,7 @@ static struct parport_driver cpia_pp_driver = {
.detach = cpia_pp_detach,
};
-static int cpia_pp_init(void)
+static int __init cpia_pp_init(void)
{
printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER);
@@ -846,8 +840,7 @@ static int cpia_pp_init(void)
return 0;
}
-#ifdef MODULE
-int init_module(void)
+static int __init cpia_init(void)
{
if (parport[0]) {
/* The user gave some parameters. Let's see what they were. */
@@ -874,38 +867,11 @@ int init_module(void)
return cpia_pp_init();
}
-void cleanup_module(void)
+static void __exit cpia_cleanup(void)
{
- parport_unregister_driver (&cpia_pp_driver);
+ parport_unregister_driver(&cpia_pp_driver);
return;
}
-#else /* !MODULE */
-
-static int __init cpia_pp_setup(char *str)
-{
- int err;
-
- if (!strncmp(str, "parport", 7)) {
- int n = simple_strtoul(str + 7, NULL, 10);
- if (parport_ptr < PARPORT_MAX) {
- parport_nr[parport_ptr++] = n;
- } else {
- LOG("too many ports, %s ignored.\n", str);
- }
- } else if (!strcmp(str, "auto")) {
- parport_nr[0] = PPCPIA_PARPORT_AUTO;
- } else if (!strcmp(str, "none")) {
- parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE;
- }
-
- err=cpia_pp_init();
- if (err)
- return err;
-
- return 1;
-}
-
-__setup("cpia_pp=", cpia_pp_setup);
-
-#endif /* !MODULE */
+module_init(cpia_init);
+module_exit(cpia_cleanup);
diff --git a/linux/drivers/media/video/cx88/cx88-alsa.c b/linux/drivers/media/video/cx88/cx88-alsa.c
index bf67ec27d..da5dc6817 100644
--- a/linux/drivers/media/video/cx88/cx88-alsa.c
+++ b/linux/drivers/media/video/cx88/cx88-alsa.c
@@ -257,7 +257,8 @@ static void cx8801_aud_irq(snd_cx88_card_t *chip)
cx_write(MO_AUD_INTSTAT, status);
if (debug > 1 || (status & mask & ~0xff))
cx88_print_irqbits(core->name, "irq aud",
- cx88_aud_irqs, status, mask);
+ cx88_aud_irqs, ARRAY_SIZE(cx88_aud_irqs),
+ status, mask);
/* risc op code error */
if (status & (1 << 16)) {
printk(KERN_WARNING "%s/0: audio risc op code error\n",core->name);
diff --git a/linux/drivers/media/video/cx88/cx88-cards.c b/linux/drivers/media/video/cx88/cx88-cards.c
index 774bcfed9..825334ef3 100644
--- a/linux/drivers/media/video/cx88/cx88-cards.c
+++ b/linux/drivers/media/video/cx88/cx88-cards.c
@@ -1823,7 +1823,7 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
{ 0x03, 0x0C },
};
- for (i = 0; i < 13; i++) {
+ for (i = 0; i < ARRAY_SIZE(init_bufs); i++) {
msg.buf = init_bufs[i];
msg.len = (i != 12 ? 5 : 2);
err = i2c_transfer(&core->i2c_adap, &msg, 1);
@@ -1950,12 +1950,21 @@ void cx88_card_setup(struct cx88_core *core)
if (0 == core->i2c_rc) {
/* enable tuner */
int i;
- static const u8 buffer [] = { 0x10,0x12,0x13,0x04,0x16,0x00,0x14,0x04,0x017,0x00 };
+ static const u8 buffer [][2] = {
+ {0x10,0x12},
+ {0x13,0x04},
+ {0x16,0x00},
+ {0x14,0x04},
+ {0x17,0x00}
+ };
core->i2c_client.addr = 0x0a;
- for (i = 0; i < 5; i++)
- if (2 != i2c_master_send(&core->i2c_client,&buffer[i*2],2))
- printk(KERN_WARNING "%s: Unable to enable tuner(%i).\n",
+ for (i = 0; i < ARRAY_SIZE(buffer); i++)
+ if (2 != i2c_master_send(&core->i2c_client,
+ buffer[i],2))
+ printk(KERN_WARNING
+ "%s: Unable to enable "
+ "tuner(%i).\n",
core->name, i);
}
break;
diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c
index 367dc3c7b..ba132d065 100644
--- a/linux/drivers/media/video/cx88/cx88-core.c
+++ b/linux/drivers/media/video/cx88/cx88-core.c
@@ -524,12 +524,12 @@ static char *cx88_pci_irqs[32] = {
};
void cx88_print_irqbits(char *name, char *tag, char **strings,
- u32 bits, u32 mask)
+ int len, u32 bits, u32 mask)
{
unsigned int i;
printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < len; i++) {
if (!(bits & (1 << i)))
continue;
if (strings[i])
@@ -555,8 +555,8 @@ int cx88_core_irq(struct cx88_core *core, u32 status)
}
if (!handled)
cx88_print_irqbits(core->name, "irq pci",
- cx88_pci_irqs, status,
- core->pci_irqmask);
+ cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs),
+ status, core->pci_irqmask);
return handled;
}
diff --git a/linux/drivers/media/video/cx88/cx88-i2c.c b/linux/drivers/media/video/cx88/cx88-i2c.c
index 2f60c957b..30fd0776a 100644
--- a/linux/drivers/media/video/cx88/cx88-i2c.c
+++ b/linux/drivers/media/video/cx88/cx88-i2c.c
@@ -1,3 +1,4 @@
+
/*
cx88-i2c.c -- all the i2c code is here
@@ -206,7 +207,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
unsigned char buf;
int i,rc;
- for (i = 0; i < 128; i++) {
+ for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
c->addr = i;
rc = i2c_master_recv(c,&buf,0);
if (rc < 0)
diff --git a/linux/drivers/media/video/cx88/cx88-mpeg.c b/linux/drivers/media/video/cx88/cx88-mpeg.c
index cb642ca03..ce4ab476b 100644
--- a/linux/drivers/media/video/cx88/cx88-mpeg.c
+++ b/linux/drivers/media/video/cx88/cx88-mpeg.c
@@ -405,7 +405,8 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
if (debug || (status & mask & ~0xff))
cx88_print_irqbits(core->name, "irq mpeg ",
- cx88_mpeg_irqs, status, mask);
+ cx88_mpeg_irqs, ARRAY_SIZE(cx88_mpeg_irqs),
+ status, mask);
/* risc op code error */
if (status & (1 << 16)) {
diff --git a/linux/drivers/media/video/cx88/cx88-video.c b/linux/drivers/media/video/cx88/cx88-video.c
index 2e6259ceb..6eb6c370b 100644
--- a/linux/drivers/media/video/cx88/cx88-video.c
+++ b/linux/drivers/media/video/cx88/cx88-video.c
@@ -1836,7 +1836,8 @@ static void cx8800_vid_irq(struct cx8800_dev *dev)
cx_write(MO_VID_INTSTAT, status);
if (irq_debug || (status & mask & ~0xff))
cx88_print_irqbits(core->name, "irq vid",
- cx88_vid_irqs, status, mask);
+ cx88_vid_irqs, ARRAY_SIZE(cx88_vid_irqs),
+ status, mask);
/* risc op code error */
if (status & (1 << 16)) {
diff --git a/linux/drivers/media/video/cx88/cx88.h b/linux/drivers/media/video/cx88/cx88.h
index 4719046e1..a35b46cab 100644
--- a/linux/drivers/media/video/cx88/cx88.h
+++ b/linux/drivers/media/video/cx88/cx88.h
@@ -545,7 +545,7 @@ struct cx8802_dev {
/* cx88-core.c */
extern void cx88_print_irqbits(char *name, char *tag, char **strings,
- u32 bits, u32 mask);
+ int len, u32 bits, u32 mask);
extern int cx88_core_irq(struct cx88_core *core, u32 status);
extern void cx88_wakeup(struct cx88_core *core,
diff --git a/linux/drivers/media/video/em28xx/em28xx-i2c.c b/linux/drivers/media/video/em28xx/em28xx-i2c.c
index 4ee4cea10..ceb71f67c 100644
--- a/linux/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/linux/drivers/media/video/em28xx/em28xx-i2c.c
@@ -544,7 +544,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
unsigned char buf;
int i, rc;
- for (i = 0; i < 128; i++) {
+ for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
c->addr = i;
rc = i2c_master_recv(c, &buf, 0);
if (rc < 0)
diff --git a/linux/drivers/media/video/ir-kbd-i2c.c b/linux/drivers/media/video/ir-kbd-i2c.c
index d20bad700..8d0c49782 100644
--- a/linux/drivers/media/video/ir-kbd-i2c.c
+++ b/linux/drivers/media/video/ir-kbd-i2c.c
@@ -174,7 +174,7 @@ static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
return -EIO;
}
- for (start = 0; start<4; start++) {
+ for (start = 0; start < ARRAY_SIZE(b); start++) {
if (b[start] == marker) {
code=b[(start+parity_offset+1)%4];
parity=b[(start+parity_offset)%4];
diff --git a/linux/drivers/media/video/ov7670.c b/linux/drivers/media/video/ov7670.c
index b033bf334..9ecf35fb1 100644
--- a/linux/drivers/media/video/ov7670.c
+++ b/linux/drivers/media/video/ov7670.c
@@ -164,6 +164,10 @@ MODULE_LICENSE("GPL");
#define REG_GFIX 0x69 /* Fix gain control */
+#define REG_REG76 0x76 /* OV's name */
+#define R76_BLKPCOR 0x80 /* Black pixel correction enable */
+#define R76_WHTPCOR 0x40 /* White pixel correction enable */
+
#define REG_RGB444 0x8c /* RGB 444 control */
#define R444_ENABLE 0x02 /* Turn on RGB444, overrides 5x5 */
#define R444_RGBX 0x01 /* Empty nibble at end */
@@ -257,7 +261,7 @@ static struct regval_list ov7670_default_regs[] = {
/* Almost all of these are magic "reserved" values. */
{ REG_COM5, 0x61 }, { REG_COM6, 0x4b },
- { 0x16, 0x02 }, { REG_MVFP, 0x07|MVFP_MIRROR },
+ { 0x16, 0x02 }, { REG_MVFP, 0x07 },
{ 0x21, 0x02 }, { 0x22, 0x91 },
{ 0x29, 0x07 }, { 0x33, 0x0b },
{ 0x35, 0x0b }, { 0x37, 0x1d },
@@ -382,6 +386,13 @@ static struct regval_list ov7670_fmt_rgb444[] = {
{ 0xff, 0xff },
};
+static struct regval_list ov7670_fmt_raw[] = {
+ { REG_COM7, COM7_BAYER },
+ { REG_COM13, 0x08 }, /* No gamma, magic rsvd bit */
+ { REG_COM16, 0x3d }, /* Edge enhancement, denoise */
+ { REG_REG76, 0xe1 }, /* Pix correction, magic rsvd */
+ { 0xff, 0xff },
+};
@@ -506,32 +517,39 @@ static struct ov7670_format_struct {
__u32 pixelformat;
struct regval_list *regs;
int cmatrix[CMATRIX_LEN];
+ int bpp; /* Bytes per pixel */
} ov7670_formats[] = {
{
.desc = "YUYV 4:2:2",
.pixelformat = V4L2_PIX_FMT_YUYV,
.regs = ov7670_fmt_yuv422,
.cmatrix = { 128, -128, 0, -34, -94, 128 },
+ .bpp = 2,
},
{
.desc = "RGB 444",
.pixelformat = V4L2_PIX_FMT_RGB444,
.regs = ov7670_fmt_rgb444,
.cmatrix = { 179, -179, 0, -61, -176, 228 },
+ .bpp = 2,
},
{
.desc = "RGB 565",
.pixelformat = V4L2_PIX_FMT_RGB565,
.regs = ov7670_fmt_rgb565,
.cmatrix = { 179, -179, 0, -61, -176, 228 },
+ .bpp = 2,
+ },
+ {
+ .desc = "Raw RGB Bayer",
+ .pixelformat = V4L2_PIX_FMT_SBGGR8,
+ .regs = ov7670_fmt_raw,
+ .cmatrix = { 0, 0, 0, 0, 0, 0 },
+ .bpp = 1
},
};
-#define N_OV7670_FMTS (sizeof(ov7670_formats)/sizeof(ov7670_formats[0]))
+#define N_OV7670_FMTS ARRAY_SIZE(ov7670_formats)
-/*
- * All formats we support are 2 bytes/pixel.
- */
-#define BYTES_PER_PIXEL 2
/*
* Then there is the issue of window sizes. Try to capture the info here.
@@ -708,7 +726,7 @@ static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt,
*/
pix->width = wsize->width;
pix->height = wsize->height;
- pix->bytesperline = pix->width*BYTES_PER_PIXEL;
+ pix->bytesperline = pix->width*ov7670_formats[index].bpp;
pix->sizeimage = pix->height*pix->bytesperline;
return 0;
}
diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c
index 5e8a2f498..31c74df34 100644
--- a/linux/drivers/media/video/saa7134/saa7134-cards.c
+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c
@@ -1544,12 +1544,12 @@ struct saa7134_board saa7134_boards[] = {
},{
.name = name_comp1,
.vmux = 0,
- .amux = LINE2,
+ .amux = LINE1,
.gpio = 0x02,
},{
.name = name_svideo,
.vmux = 6,
- .amux = LINE2,
+ .amux = LINE1,
.gpio = 0x02,
}},
.radio = {
diff --git a/linux/drivers/media/video/saa7134/saa7134-i2c.c b/linux/drivers/media/video/saa7134/saa7134-i2c.c
index 1d41abee5..f470c85e7 100644
--- a/linux/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/linux/drivers/media/video/saa7134/saa7134-i2c.c
@@ -465,7 +465,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
unsigned char buf;
int i,rc;
- for (i = 0; i < 128; i++) {
+ for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
c->addr = i;
rc = i2c_master_recv(c,&buf,0);
if (rc < 0)
diff --git a/linux/drivers/media/video/sn9c102/Makefile b/linux/drivers/media/video/sn9c102/Makefile
index 30e3dfe53..a56d16f69 100644
--- a/linux/drivers/media/video/sn9c102/Makefile
+++ b/linux/drivers/media/video/sn9c102/Makefile
@@ -1,7 +1,14 @@
-sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o \
- sn9c102_ov7630.o sn9c102_ov7660.o sn9c102_pas106b.o \
- sn9c102_pas202bcb.o sn9c102_tas5110c1b.o \
- sn9c102_tas5130d1b.o
+sn9c102-objs := sn9c102_core.o \
+ sn9c102_hv7131d.o \
+ sn9c102_hv7131r.o \
+ sn9c102_mi0343.o \
+ sn9c102_mi0360.o \
+ sn9c102_ov7630.o \
+ sn9c102_ov7660.o \
+ sn9c102_pas106b.o \
+ sn9c102_pas202bcb.o \
+ sn9c102_tas5110c1b.o \
+ sn9c102_tas5110d.o \
+ sn9c102_tas5130d1b.o
obj-$(CONFIG_USB_SN9C102) += sn9c102.o
-
diff --git a/linux/drivers/media/video/sn9c102/sn9c102.h b/linux/drivers/media/video/sn9c102/sn9c102.h
index d6af8fa87..dfb089b15 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102.h
+++ b/linux/drivers/media/video/sn9c102/sn9c102.h
@@ -81,8 +81,13 @@ enum sn9c102_stream_state {
typedef char sn9c102_sof_header_t[62];
+struct sn9c102_sof_t {
+ sn9c102_sof_header_t header;
+ u16 bytesread;
+};
+
struct sn9c102_sysfs_attr {
- u8 reg, i2c_reg;
+ u16 reg, i2c_reg;
sn9c102_sof_header_t frame_header;
};
@@ -115,7 +120,7 @@ struct sn9c102_device {
struct v4l2_jpegcompression compression;
struct sn9c102_sysfs_attr sysfs;
- sn9c102_sof_header_t sof_header;
+ struct sn9c102_sof_t sof;
u16 reg[384];
struct sn9c102_module_param module_param;
@@ -189,8 +194,8 @@ do { \
if ((level) == 1 || (level) == 2) \
pr_info("sn9c102: " fmt "\n", ## args); \
else if ((level) == 3) \
- pr_debug("sn9c102: [%s:%d] " fmt "\n", __FUNCTION__, \
- __LINE__ , ## args); \
+ pr_debug("sn9c102: [%s:%d] " fmt "\n", \
+ __FUNCTION__, __LINE__ , ## args); \
} \
} while (0)
#else
@@ -201,8 +206,8 @@ do { \
#undef PDBG
#define PDBG(fmt, args...) \
-dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __FUNCTION__, __LINE__ , ## args)
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __FUNCTION__, \
+ __LINE__ , ## args)
#undef PDBGG
#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_core.c b/linux/drivers/media/video/sn9c102/sn9c102_core.c
index a02d43ece..c8bcdc33f 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/linux/drivers/media/video/sn9c102/sn9c102_core.c
@@ -44,11 +44,12 @@
/*****************************************************************************/
#define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers"
-#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia"
+#define SN9C102_MODULE_ALIAS "sn9c1xx"
+#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia"
#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define SN9C102_MODULE_LICENSE "GPL"
-#define SN9C102_MODULE_VERSION "1:1.34"
-#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 34)
+#define SN9C102_MODULE_VERSION "1:1.39"
+#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 39)
/*****************************************************************************/
@@ -56,6 +57,7 @@ MODULE_DEVICE_TABLE(usb, sn9c102_id_table);
MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);
MODULE_DESCRIPTION(SN9C102_MODULE_NAME);
+MODULE_ALIAS(SN9C102_MODULE_ALIAS);
MODULE_VERSION(SN9C102_MODULE_VERSION);
MODULE_LICENSE(SN9C102_MODULE_LICENSE);
@@ -106,8 +108,7 @@ MODULE_PARM_DESC(debug,
"\n1 = critical errors"
"\n2 = significant informations"
"\n3 = more verbose messages"
- "\nLevel 3 is useful for testing only, when only "
- "one device is used."
+ "\nLevel 3 is useful for testing only."
"\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
"\n");
#endif
@@ -121,8 +122,8 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
struct v4l2_pix_format* p = &(cam->sensor.pix_format);
struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
size_t imagesize = cam->module_param.force_munmap || io == IO_READ ?
- (p->width * p->height * p->priv) / 8 :
- (r->width * r->height * p->priv) / 8;
+ (p->width * p->height * p->priv) / 8 :
+ (r->width * r->height * p->priv) / 8;
void* buff = NULL;
u32 i;
@@ -485,18 +486,43 @@ static size_t sn9c102_sof_length(struct sn9c102_device* cam)
static void*
sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
{
- char sof_header[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
- size_t soflen = 0, i;
+ const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
+ const char *m = mem;
+ size_t soflen = 0, i, j;
soflen = sn9c102_sof_length(cam);
- for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
- if (!memcmp(mem + i, sof_header, sizeof(sof_header))) {
- memcpy(cam->sof_header, mem + i,
- sizeof(sn9c102_sof_header_t));
- /* Skip the header */
- return mem + i + soflen;
+ for (i = 0; i < len; i++) {
+ size_t b;
+
+ /* Read the variable part of the header */
+ if (unlikely(cam->sof.bytesread >= sizeof(marker))) {
+ cam->sof.header[cam->sof.bytesread] = *(m+i);
+ if (++cam->sof.bytesread == soflen) {
+ cam->sof.bytesread = 0;
+ return mem + i;
+ }
+ continue;
+ }
+
+ /* Search for the SOF marker (fixed part) in the header */
+ for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) {
+ if (unlikely(i+j) == len)
+ return NULL;
+ if (*(m+i+j) == marker[cam->sof.bytesread]) {
+ cam->sof.header[cam->sof.bytesread] = *(m+i+j);
+ if (++cam->sof.bytesread == sizeof(marker)) {
+ PDBGG("Bytes to analyze: %zd. SOF "
+ "starts at byte #%zd", len, i);
+ i += j+1;
+ break;
+ }
+ } else {
+ cam->sof.bytesread = 0;
+ break;
}
+ }
+ }
return NULL;
}
@@ -513,10 +539,16 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
};
size_t i, j;
+ /* The EOF header does not exist in compressed data */
if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
- return NULL; /* EOF header does not exist in compressed data */
+ return NULL;
+ /*
+ The EOF header might cross the packet boundary, but this is not a
+ problem, since the end of a frame is determined by checking its size
+ in the first place.
+ */
for (i = 0; (len >= 4) && (i <= len - 4); i++)
for (j = 0; j < ARRAY_SIZE(eof_header); j++)
if (!memcmp(mem + i, eof_header[j], 4))
@@ -643,6 +675,7 @@ static void sn9c102_urb_complete(struct urb *urb)
cam->stream = STREAM_OFF;
if ((*f))
(*f)->state = F_QUEUED;
+ cam->sof.bytesread = 0;
DBG(3, "Stream interrupted by application");
wake_up(&cam->wait_stream);
}
@@ -680,6 +713,7 @@ static void sn9c102_urb_complete(struct urb *urb)
if (status) {
DBG(3, "Error in isochronous frame");
(*f)->state = F_ERROR;
+ cam->sof.bytesread = 0;
continue;
}
@@ -696,13 +730,13 @@ end_of_frame:
if (eof)
img = (eof > pos) ? eof - pos - 1 : 0;
- if ((*f)->buf.bytesused+img > imagesize) {
+ if ((*f)->buf.bytesused + img > imagesize) {
u32 b;
b = (*f)->buf.bytesused + img -
imagesize;
img = imagesize - (*f)->buf.bytesused;
- DBG(3, "Expected EOF not found: "
- "video frame cut");
+ PDBGG("Expected EOF not found: video "
+ "frame cut");
if (eof)
DBG(3, "Exceeded limit: +%u "
"bytes", (unsigned)(b));
@@ -723,11 +757,6 @@ end_of_frame:
V4L2_PIX_FMT_JPEG) && eof)) {
u32 b;
- if (cam->sensor.pix_format.pixelformat
- == V4L2_PIX_FMT_JPEG)
- sn9c102_write_eoimarker(cam,
- (*f));
-
b = (*f)->buf.bytesused;
(*f)->state = F_DONE;
(*f)->buf.sequence= ++cam->frame_count;
@@ -745,7 +774,7 @@ end_of_frame:
spin_unlock(&cam->queue_lock);
memcpy(cam->sysfs.frame_header,
- cam->sof_header, soflen);
+ cam->sof.header, soflen);
DBG(3, "Video frame captured: %lu "
"bytes", (unsigned long)(b));
@@ -795,7 +824,13 @@ start_of_frame:
V4L2_PIX_FMT_SN9C10X ||
cam->sensor.pix_format.pixelformat ==
V4L2_PIX_FMT_JPEG) {
- eof = sof - soflen;
+ if (sof - pos >= soflen) {
+ eof = sof - soflen;
+ } else { /* remove header */
+ eof = pos;
+ (*f)->buf.bytesused -=
+ (soflen - (sof - pos));
+ }
goto end_of_frame;
} else {
DBG(3, "SOF before expected EOF after "
@@ -882,6 +917,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
}
cam->frame_current = NULL;
+ cam->sof.bytesread = 0;
for (i = 0; i < SN9C102_URBS; i++) {
err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
@@ -963,9 +999,9 @@ static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count)
if (len < 6) {
strncpy(str, buff, len);
- str[len+1] = '\0';
+ str[len] = '\0';
} else {
- strncpy(str, buff, 4);
+ strncpy(str, buff, 6);
str[6] = '\0';
}
@@ -1066,7 +1102,7 @@ static ssize_t sn9c102_show_val(struct class_device* cd, char* buf)
count = sprintf(buf, "%d\n", val);
- DBG(3, "Read bytes: %zd", count);
+ DBG(3, "Read bytes: %zd, value: %d", count, val);
mutex_unlock(&sn9c102_sysfs_lock);
@@ -1201,7 +1237,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
count = sprintf(buf, "%d\n", val);
- DBG(3, "Read bytes: %zd", count);
+ DBG(3, "Read bytes: %zd, value: %d", count, val);
mutex_unlock(&sn9c102_sysfs_lock);
@@ -1481,10 +1517,10 @@ sn9c102_set_compression(struct sn9c102_device* cam,
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
case BRIDGE_SN9C103:
- if (compression->quality == 0)
+ if (compression->quality == 0)
err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01,
0x17);
- else if (compression->quality == 1)
+ else if (compression->quality == 1)
err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe,
0x17);
break;
@@ -1493,10 +1529,10 @@ sn9c102_set_compression(struct sn9c102_device* cam,
if (compression->quality == 0) {
for (i = 0; i <= 63; i++) {
err += sn9c102_write_reg(cam,
- SN9C102_Y_QTABLE0[i],
+ SN9C102_Y_QTABLE1[i],
0x100 + i);
err += sn9c102_write_reg(cam,
- SN9C102_UV_QTABLE0[i],
+ SN9C102_UV_QTABLE1[i],
0x140 + i);
}
err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
@@ -1601,9 +1637,13 @@ static int sn9c102_init(struct sn9c102_device* cam)
if (cam->bridge == BRIDGE_SN9C101 ||
cam->bridge == BRIDGE_SN9C102 ||
cam->bridge == BRIDGE_SN9C103) {
+ if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
+ s->pix_format.pixelformat= V4L2_PIX_FMT_SBGGR8;
cam->compression.quality = cam->reg[0x17] & 0x01 ?
0 : 1;
} else {
+ if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
+ s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG;
cam->compression.quality = cam->reg[0x18] & 0x40 ?
0 : 1;
err += sn9c102_set_compression(cam, &cam->compression);
@@ -1809,7 +1849,7 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
DBG(3, "Close and open the device again to choose "
"the read method");
mutex_unlock(&cam->fileop_mutex);
- return -EINVAL;
+ return -EBUSY;
}
if (cam->io == IO_NONE) {
@@ -1849,16 +1889,16 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
return err;
}
} else {
- timeout = wait_event_interruptible_timeout
- ( cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED),
- cam->module_param.frame_timeout *
- 1000 * msecs_to_jiffies(1) );
- if (timeout < 0) {
- mutex_unlock(&cam->fileop_mutex);
- return timeout;
+ timeout = wait_event_interruptible_timeout
+ ( cam->wait_frame,
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED),
+ cam->module_param.frame_timeout *
+ 1000 * msecs_to_jiffies(1) );
+ if (timeout < 0) {
+ mutex_unlock(&cam->fileop_mutex);
+ return timeout;
} else if (timeout == 0 &&
!(cam->state & DEV_DISCONNECTED)) {
DBG(1, "Video frame timeout elapsed");
@@ -2005,7 +2045,12 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
return -EIO;
}
- if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||
+ if (!(vma->vm_flags & (VM_WRITE | VM_READ))) {
+ mutex_unlock(&cam->fileop_mutex);
+ return -EACCES;
+ }
+
+ if (cam->io != IO_MMAP ||
size != PAGE_ALIGN(cam->frame[0].buf.length)) {
mutex_unlock(&cam->fileop_mutex);
return -EINVAL;
@@ -2271,7 +2316,7 @@ sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
if (cam->frame[i].vma_use_count) {
DBG(3, "VIDIOC_S_CROP failed. "
"Unmap the buffers first.");
- return -EINVAL;
+ return -EBUSY;
}
/* Preserve R,G or B origin */
@@ -2414,8 +2459,8 @@ sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
case BRIDGE_SN9C103:
- strcpy(fmtd.description, "compressed");
- fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
+ strcpy(fmtd.description, "compressed");
+ fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
break;
case BRIDGE_SN9C105:
case BRIDGE_SN9C120:
@@ -2449,8 +2494,10 @@ sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
- pfmt->bytesperline = (pfmt->pixelformat==V4L2_PIX_FMT_SN9C10X ||
- pfmt->pixelformat==V4L2_PIX_FMT_JPEG)
+ pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ?
+ V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
+ pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X ||
+ pfmt->pixelformat == V4L2_PIX_FMT_JPEG)
? 0 : (pfmt->width * pfmt->priv) / 8;
pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
pfmt->field = V4L2_FIELD_NONE;
@@ -2525,9 +2572,9 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
case BRIDGE_SN9C103:
- if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
- pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
- pix->pixelformat = pfmt->pixelformat;
+ if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
+ pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
+ pix->pixelformat = pfmt->pixelformat;
break;
case BRIDGE_SN9C105:
case BRIDGE_SN9C120:
@@ -2537,7 +2584,8 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
break;
}
pix->priv = pfmt->priv; /* bpp */
- pix->colorspace = pfmt->colorspace;
+ pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ?
+ V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
pix->pixelformat == V4L2_PIX_FMT_JPEG)
? 0 : (pix->width * pix->priv) / 8;
@@ -2555,7 +2603,7 @@ sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
if (cam->frame[i].vma_use_count) {
DBG(3, "VIDIOC_S_FMT failed. Unmap the "
"buffers first.");
- return -EINVAL;
+ return -EBUSY;
}
if (cam->stream == STREAM_ON)
@@ -2670,14 +2718,14 @@ sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg)
if (cam->io == IO_READ) {
DBG(3, "Close and open the device again to choose the mmap "
"I/O method");
- return -EINVAL;
+ return -EBUSY;
}
for (i = 0; i < cam->nbuffers; i++)
if (cam->frame[i].vma_use_count) {
DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
"still mapped.");
- return -EINVAL;
+ return -EBUSY;
}
if (cam->stream == STREAM_ON)
@@ -2789,15 +2837,15 @@ sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
if (err)
return err;
} else {
- timeout = wait_event_interruptible_timeout
- ( cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED),
- cam->module_param.frame_timeout *
- 1000 * msecs_to_jiffies(1) );
- if (timeout < 0)
- return timeout;
+ timeout = wait_event_interruptible_timeout
+ ( cam->wait_frame,
+ (!list_empty(&cam->outqueue)) ||
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED),
+ cam->module_param.frame_timeout *
+ 1000 * msecs_to_jiffies(1) );
+ if (timeout < 0)
+ return timeout;
else if (timeout == 0 &&
!(cam->state & DEV_DISCONNECTED)) {
DBG(1, "Video frame timeout elapsed");
@@ -2841,9 +2889,6 @@ sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg)
if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
return -EINVAL;
- if (list_empty(&cam->inqueue))
- return -EINVAL;
-
cam->stream = STREAM_ON;
DBG(3, "Stream on");
@@ -3170,8 +3215,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
r = sn9c102_read_reg(cam, 0x00);
if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
- DBG(1, "Sorry, this is not a SN9C1xx based camera "
- "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+ DBG(1, "Sorry, this is not a SN9C1xx-based camera "
+ "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
err = -ENODEV;
goto fail;
}
@@ -3181,19 +3226,19 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
DBG(2, "SN9C10[12] PC Camera Controller detected "
- "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+ "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
break;
case BRIDGE_SN9C103:
DBG(2, "SN9C103 PC Camera Controller detected "
- "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+ "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
break;
case BRIDGE_SN9C105:
DBG(2, "SN9C105 PC Camera Controller detected "
- "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+ "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
break;
case BRIDGE_SN9C120:
DBG(2, "SN9C120 PC Camera Controller detected "
- "(vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+ "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
break;
}
@@ -3264,6 +3309,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
"device controlling. Error #%d", err);
#else
DBG(2, "Optional device control through 'sysfs' interface disabled");
+ DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' "
+ "configuration option to enable it.");
#endif
usb_set_intfdata(intf, cam);
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h
index 3a682eca6..f49bd8c5b 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102_devtable.h
+++ b/linux/drivers/media/video/sn9c102/sn9c102_devtable.h
@@ -89,16 +89,22 @@ static const struct usb_device_id sn9c102_id_table[] = {
{ SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
+ { SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), },
+ { SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
{ SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
/* SN9C120 */
+ { SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), },
+ { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), },
+ { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
+ { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
{ SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
@@ -114,12 +120,15 @@ static const struct usb_device_id sn9c102_id_table[] = {
Functions must return 0 on success, the appropriate error otherwise.
*/
extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
+extern int sn9c102_probe_hv7131r(struct sn9c102_device* cam);
extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
+extern int sn9c102_probe_mi0360(struct sn9c102_device* cam);
extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
extern int sn9c102_probe_ov7660(struct sn9c102_device* cam);
extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
+extern int sn9c102_probe_tas5110d(struct sn9c102_device* cam);
extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
/*
@@ -128,13 +137,16 @@ extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
the order of the list below, from top to bottom.
*/
static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {
+ &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
+ &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
&sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
+ &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
&sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
&sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
- &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
&sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
&sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
&sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
+ &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
&sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
NULL,
};
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/linux/drivers/media/video/sn9c102/sn9c102_hv7131d.c
index 7ae368f60..9b2e2d68c 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102_hv7131d.c
+++ b/linux/drivers/media/video/sn9c102/sn9c102_hv7131d.c
@@ -22,9 +22,6 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor hv7131d;
-
-
static int hv7131d_init(struct sn9c102_device* cam)
{
int err = 0;
@@ -153,7 +150,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor hv7131d = {
.name = "HV7131D",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
+ .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES,
@@ -263,7 +260,7 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
if (r0 < 0 || r1 < 0)
return -EIO;
- if (r0 != 0x00 && r1 != 0x04)
+ if (r0 != 0x00 || r1 != 0x04)
return -ENODEV;
sn9c102_attach_sensor(cam, &hv7131d);
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_hv7131r.c b/linux/drivers/media/video/sn9c102/sn9c102_hv7131r.c
new file mode 100644
index 000000000..c4a3e3991
--- /dev/null
+++ b/linux/drivers/media/video/sn9c102/sn9c102_hv7131r.c
@@ -0,0 +1,458 @@
+/***************************************************************************
+ * Plug-in for HV7131R image sensor connected to the SN9C1xx PC Camera *
+ * Controllers *
+ * *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * *
+ * 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 *
+ * (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA. *
+ ***************************************************************************/
+
+#include "sn9c102_sensor.h"
+
+
+static int hv7131r_init(struct sn9c102_device* cam)
+{
+ int err = 0;
+
+ switch (sn9c102_get_bridge(cam)) {
+ case BRIDGE_SN9C103:
+ err += sn9c102_write_reg(cam, 0x00, 0x03);
+ err += sn9c102_write_reg(cam, 0x1a, 0x04);
+ err += sn9c102_write_reg(cam, 0x20, 0x05);
+ err += sn9c102_write_reg(cam, 0x20, 0x06);
+ err += sn9c102_write_reg(cam, 0x03, 0x10);
+ err += sn9c102_write_reg(cam, 0x00, 0x14);
+ err += sn9c102_write_reg(cam, 0x60, 0x17);
+ err += sn9c102_write_reg(cam, 0x0a, 0x18);
+ err += sn9c102_write_reg(cam, 0xf0, 0x19);
+ err += sn9c102_write_reg(cam, 0x1d, 0x1a);
+ err += sn9c102_write_reg(cam, 0x10, 0x1b);
+ err += sn9c102_write_reg(cam, 0x02, 0x1c);
+ err += sn9c102_write_reg(cam, 0x03, 0x1d);
+ err += sn9c102_write_reg(cam, 0x0f, 0x1e);
+ err += sn9c102_write_reg(cam, 0x0c, 0x1f);
+ err += sn9c102_write_reg(cam, 0x00, 0x20);
+ err += sn9c102_write_reg(cam, 0x10, 0x21);
+ err += sn9c102_write_reg(cam, 0x20, 0x22);
+ err += sn9c102_write_reg(cam, 0x30, 0x23);
+ err += sn9c102_write_reg(cam, 0x40, 0x24);
+ err += sn9c102_write_reg(cam, 0x50, 0x25);
+ err += sn9c102_write_reg(cam, 0x60, 0x26);
+ err += sn9c102_write_reg(cam, 0x70, 0x27);
+ err += sn9c102_write_reg(cam, 0x80, 0x28);
+ err += sn9c102_write_reg(cam, 0x90, 0x29);
+ err += sn9c102_write_reg(cam, 0xa0, 0x2a);
+ err += sn9c102_write_reg(cam, 0xb0, 0x2b);
+ err += sn9c102_write_reg(cam, 0xc0, 0x2c);
+ err += sn9c102_write_reg(cam, 0xd0, 0x2d);
+ err += sn9c102_write_reg(cam, 0xe0, 0x2e);
+ err += sn9c102_write_reg(cam, 0xf0, 0x2f);
+ err += sn9c102_write_reg(cam, 0xff, 0x30);
+ break;
+ case BRIDGE_SN9C105:
+ case BRIDGE_SN9C120:
+ err += sn9c102_write_reg(cam, 0x44, 0x01);
+ err += sn9c102_write_reg(cam, 0x40, 0x02);
+ err += sn9c102_write_reg(cam, 0x00, 0x03);
+ err += sn9c102_write_reg(cam, 0x1a, 0x04);
+ err += sn9c102_write_reg(cam, 0x44, 0x05);
+ err += sn9c102_write_reg(cam, 0x3e, 0x06);
+ err += sn9c102_write_reg(cam, 0x1a, 0x07);
+ err += sn9c102_write_reg(cam, 0x03, 0x10);
+ err += sn9c102_write_reg(cam, 0x08, 0x14);
+ err += sn9c102_write_reg(cam, 0xa3, 0x17);
+ err += sn9c102_write_reg(cam, 0x4b, 0x18);
+ err += sn9c102_write_reg(cam, 0x00, 0x19);
+ err += sn9c102_write_reg(cam, 0x1d, 0x1a);
+ err += sn9c102_write_reg(cam, 0x10, 0x1b);
+ err += sn9c102_write_reg(cam, 0x02, 0x1c);
+ err += sn9c102_write_reg(cam, 0x03, 0x1d);
+ err += sn9c102_write_reg(cam, 0x0f, 0x1e);
+ err += sn9c102_write_reg(cam, 0x0c, 0x1f);
+ err += sn9c102_write_reg(cam, 0x00, 0x20);
+ err += sn9c102_write_reg(cam, 0x29, 0x21);
+ err += sn9c102_write_reg(cam, 0x40, 0x22);
+ err += sn9c102_write_reg(cam, 0x54, 0x23);
+ err += sn9c102_write_reg(cam, 0x66, 0x24);
+ err += sn9c102_write_reg(cam, 0x76, 0x25);
+ err += sn9c102_write_reg(cam, 0x85, 0x26);
+ err += sn9c102_write_reg(cam, 0x94, 0x27);
+ err += sn9c102_write_reg(cam, 0xa1, 0x28);
+ err += sn9c102_write_reg(cam, 0xae, 0x29);
+ err += sn9c102_write_reg(cam, 0xbb, 0x2a);
+ err += sn9c102_write_reg(cam, 0xc7, 0x2b);
+ err += sn9c102_write_reg(cam, 0xd3, 0x2c);
+ err += sn9c102_write_reg(cam, 0xde, 0x2d);
+ err += sn9c102_write_reg(cam, 0xea, 0x2e);
+ err += sn9c102_write_reg(cam, 0xf4, 0x2f);
+ err += sn9c102_write_reg(cam, 0xff, 0x30);
+ err += sn9c102_write_reg(cam, 0x00, 0x3F);
+ err += sn9c102_write_reg(cam, 0xC7, 0x40);
+ err += sn9c102_write_reg(cam, 0x01, 0x41);
+ err += sn9c102_write_reg(cam, 0x44, 0x42);
+ err += sn9c102_write_reg(cam, 0x00, 0x43);
+ err += sn9c102_write_reg(cam, 0x44, 0x44);
+ err += sn9c102_write_reg(cam, 0x00, 0x45);
+ err += sn9c102_write_reg(cam, 0x44, 0x46);
+ err += sn9c102_write_reg(cam, 0x00, 0x47);
+ err += sn9c102_write_reg(cam, 0xC7, 0x48);
+ err += sn9c102_write_reg(cam, 0x01, 0x49);
+ err += sn9c102_write_reg(cam, 0xC7, 0x4A);
+ err += sn9c102_write_reg(cam, 0x01, 0x4B);
+ err += sn9c102_write_reg(cam, 0xC7, 0x4C);
+ err += sn9c102_write_reg(cam, 0x01, 0x4D);
+ err += sn9c102_write_reg(cam, 0x44, 0x4E);
+ err += sn9c102_write_reg(cam, 0x00, 0x4F);
+ err += sn9c102_write_reg(cam, 0x44, 0x50);
+ err += sn9c102_write_reg(cam, 0x00, 0x51);
+ err += sn9c102_write_reg(cam, 0x44, 0x52);
+ err += sn9c102_write_reg(cam, 0x00, 0x53);
+ err += sn9c102_write_reg(cam, 0xC7, 0x54);
+ err += sn9c102_write_reg(cam, 0x01, 0x55);
+ err += sn9c102_write_reg(cam, 0xC7, 0x56);
+ err += sn9c102_write_reg(cam, 0x01, 0x57);
+ err += sn9c102_write_reg(cam, 0xC7, 0x58);
+ err += sn9c102_write_reg(cam, 0x01, 0x59);
+ err += sn9c102_write_reg(cam, 0x44, 0x5A);
+ err += sn9c102_write_reg(cam, 0x00, 0x5B);
+ err += sn9c102_write_reg(cam, 0x44, 0x5C);
+ err += sn9c102_write_reg(cam, 0x00, 0x5D);
+ err += sn9c102_write_reg(cam, 0x44, 0x5E);
+ err += sn9c102_write_reg(cam, 0x00, 0x5F);
+ err += sn9c102_write_reg(cam, 0xC7, 0x60);
+ err += sn9c102_write_reg(cam, 0x01, 0x61);
+ err += sn9c102_write_reg(cam, 0xC7, 0x62);
+ err += sn9c102_write_reg(cam, 0x01, 0x63);
+ err += sn9c102_write_reg(cam, 0xC7, 0x64);
+ err += sn9c102_write_reg(cam, 0x01, 0x65);
+ err += sn9c102_write_reg(cam, 0x44, 0x66);
+ err += sn9c102_write_reg(cam, 0x00, 0x67);
+ err += sn9c102_write_reg(cam, 0x44, 0x68);
+ err += sn9c102_write_reg(cam, 0x00, 0x69);
+ err += sn9c102_write_reg(cam, 0x44, 0x6A);
+ err += sn9c102_write_reg(cam, 0x00, 0x6B);
+ err += sn9c102_write_reg(cam, 0xC7, 0x6C);
+ err += sn9c102_write_reg(cam, 0x01, 0x6D);
+ err += sn9c102_write_reg(cam, 0xC7, 0x6E);
+ err += sn9c102_write_reg(cam, 0x01, 0x6F);
+ err += sn9c102_write_reg(cam, 0xC7, 0x70);
+ err += sn9c102_write_reg(cam, 0x01, 0x71);
+ err += sn9c102_write_reg(cam, 0x44, 0x72);
+ err += sn9c102_write_reg(cam, 0x00, 0x73);
+ err += sn9c102_write_reg(cam, 0x44, 0x74);
+ err += sn9c102_write_reg(cam, 0x00, 0x75);
+ err += sn9c102_write_reg(cam, 0x44, 0x76);
+ err += sn9c102_write_reg(cam, 0x00, 0x77);
+ err += sn9c102_write_reg(cam, 0xC7, 0x78);
+ err += sn9c102_write_reg(cam, 0x01, 0x79);
+ err += sn9c102_write_reg(cam, 0xC7, 0x7A);
+ err += sn9c102_write_reg(cam, 0x01, 0x7B);
+ err += sn9c102_write_reg(cam, 0xC7, 0x7C);
+ err += sn9c102_write_reg(cam, 0x01, 0x7D);
+ err += sn9c102_write_reg(cam, 0x44, 0x7E);
+ err += sn9c102_write_reg(cam, 0x00, 0x7F);
+ err += sn9c102_write_reg(cam, 0x14, 0x84);
+ err += sn9c102_write_reg(cam, 0x00, 0x85);
+ err += sn9c102_write_reg(cam, 0x27, 0x86);
+ err += sn9c102_write_reg(cam, 0x00, 0x87);
+ err += sn9c102_write_reg(cam, 0x07, 0x88);
+ err += sn9c102_write_reg(cam, 0x00, 0x89);
+ err += sn9c102_write_reg(cam, 0xEC, 0x8A);
+ err += sn9c102_write_reg(cam, 0x0f, 0x8B);
+ err += sn9c102_write_reg(cam, 0xD8, 0x8C);
+ err += sn9c102_write_reg(cam, 0x0f, 0x8D);
+ err += sn9c102_write_reg(cam, 0x3D, 0x8E);
+ err += sn9c102_write_reg(cam, 0x00, 0x8F);
+ err += sn9c102_write_reg(cam, 0x3D, 0x90);
+ err += sn9c102_write_reg(cam, 0x00, 0x91);
+ err += sn9c102_write_reg(cam, 0xCD, 0x92);
+ err += sn9c102_write_reg(cam, 0x0f, 0x93);
+ err += sn9c102_write_reg(cam, 0xf7, 0x94);
+ err += sn9c102_write_reg(cam, 0x0f, 0x95);
+ err += sn9c102_write_reg(cam, 0x0C, 0x96);
+ err += sn9c102_write_reg(cam, 0x00, 0x97);
+ err += sn9c102_write_reg(cam, 0x00, 0x98);
+ err += sn9c102_write_reg(cam, 0x66, 0x99);
+ err += sn9c102_write_reg(cam, 0x05, 0x9A);
+ err += sn9c102_write_reg(cam, 0x00, 0x9B);
+ err += sn9c102_write_reg(cam, 0x04, 0x9C);
+ err += sn9c102_write_reg(cam, 0x00, 0x9D);
+ err += sn9c102_write_reg(cam, 0x08, 0x9E);
+ err += sn9c102_write_reg(cam, 0x00, 0x9F);
+ err += sn9c102_write_reg(cam, 0x2D, 0xC0);
+ err += sn9c102_write_reg(cam, 0x2D, 0xC1);
+ err += sn9c102_write_reg(cam, 0x3A, 0xC2);
+ err += sn9c102_write_reg(cam, 0x05, 0xC3);
+ err += sn9c102_write_reg(cam, 0x04, 0xC4);
+ err += sn9c102_write_reg(cam, 0x3F, 0xC5);
+ err += sn9c102_write_reg(cam, 0x00, 0xC6);
+ err += sn9c102_write_reg(cam, 0x00, 0xC7);
+ err += sn9c102_write_reg(cam, 0x50, 0xC8);
+ err += sn9c102_write_reg(cam, 0x3C, 0xC9);
+ err += sn9c102_write_reg(cam, 0x28, 0xCA);
+ err += sn9c102_write_reg(cam, 0xD8, 0xCB);
+ err += sn9c102_write_reg(cam, 0x14, 0xCC);
+ err += sn9c102_write_reg(cam, 0xEC, 0xCD);
+ err += sn9c102_write_reg(cam, 0x32, 0xCE);
+ err += sn9c102_write_reg(cam, 0xDD, 0xCF);
+ err += sn9c102_write_reg(cam, 0x32, 0xD0);
+ err += sn9c102_write_reg(cam, 0xDD, 0xD1);
+ err += sn9c102_write_reg(cam, 0x6A, 0xD2);
+ err += sn9c102_write_reg(cam, 0x50, 0xD3);
+ err += sn9c102_write_reg(cam, 0x00, 0xD4);
+ err += sn9c102_write_reg(cam, 0x00, 0xD5);
+ err += sn9c102_write_reg(cam, 0x00, 0xD6);
+ break;
+ default:
+ break;
+ }
+
+ err += sn9c102_i2c_write(cam, 0x20, 0x00);
+ err += sn9c102_i2c_write(cam, 0x21, 0xd6);
+ err += sn9c102_i2c_write(cam, 0x25, 0x06);
+
+ return err;
+}
+
+
+static int hv7131r_get_ctrl(struct sn9c102_device* cam,
+ struct v4l2_control* ctrl)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_GAIN:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0)
+ return -EIO;
+ return 0;
+ case V4L2_CID_RED_BALANCE:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0)
+ return -EIO;
+ ctrl->value = ctrl->value & 0x3f;
+ return 0;
+ case V4L2_CID_BLUE_BALANCE:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0)
+ return -EIO;
+ ctrl->value = ctrl->value & 0x3f;
+ return 0;
+ case SN9C102_V4L2_CID_GREEN_BALANCE:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0)
+ return -EIO;
+ ctrl->value = ctrl->value & 0x3f;
+ return 0;
+ case V4L2_CID_BLACK_LEVEL:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x01)) < 0)
+ return -EIO;
+ ctrl->value = (ctrl->value & 0x08) ? 1 : 0;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+
+static int hv7131r_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
+{
+ int err = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_GAIN:
+ err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
+ break;
+ case V4L2_CID_RED_BALANCE:
+ err += sn9c102_i2c_write(cam, 0x31, ctrl->value);
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ err += sn9c102_i2c_write(cam, 0x33, ctrl->value);
+ break;
+ case SN9C102_V4L2_CID_GREEN_BALANCE:
+ err += sn9c102_i2c_write(cam, 0x32, ctrl->value);
+ break;
+ case V4L2_CID_BLACK_LEVEL:
+ {
+ int r = sn9c102_i2c_read(cam, 0x01);
+ if (r < 0)
+ return -EIO;
+ err += sn9c102_i2c_write(cam, 0x01,
+ (ctrl->value<<3) | (r&0xf7));
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return err ? -EIO : 0;
+}
+
+
+static int hv7131r_set_crop(struct sn9c102_device* cam,
+ const struct v4l2_rect* rect)
+{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+ int err = 0;
+ u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
+ v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+
+ err += sn9c102_write_reg(cam, h_start, 0x12);
+ err += sn9c102_write_reg(cam, v_start, 0x13);
+
+ return err;
+}
+
+
+static int hv7131r_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
+{
+ int err = 0;
+
+ switch (sn9c102_get_bridge(cam)) {
+ case BRIDGE_SN9C103:
+ if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
+ err += sn9c102_write_reg(cam, 0xa0, 0x19);
+ err += sn9c102_i2c_write(cam, 0x01, 0x04);
+ } else {
+ err += sn9c102_write_reg(cam, 0x30, 0x19);
+ err += sn9c102_i2c_write(cam, 0x01, 0x04);
+ }
+ break;
+ case BRIDGE_SN9C105:
+ case BRIDGE_SN9C120:
+ if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
+ err += sn9c102_write_reg(cam, 0xa5, 0x17);
+ err += sn9c102_i2c_write(cam, 0x01, 0x24);
+ } else {
+ err += sn9c102_write_reg(cam, 0xa3, 0x17);
+ err += sn9c102_i2c_write(cam, 0x01, 0x04);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return err;
+}
+
+
+static struct sn9c102_sensor hv7131r = {
+ .name = "HV7131R",
+ .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+ .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
+ .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
+ .frequency = SN9C102_I2C_100KHZ,
+ .interface = SN9C102_I2C_2WIRES,
+ .i2c_slave_id = 0x11,
+ .init = &hv7131r_init,
+ .qctrl = {
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "global gain",
+ .minimum = 0x00,
+ .maximum = 0xff,
+ .step = 0x01,
+ .default_value = 0x40,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "red balance",
+ .minimum = 0x00,
+ .maximum = 0x3f,
+ .step = 0x01,
+ .default_value = 0x08,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "blue balance",
+ .minimum = 0x00,
+ .maximum = 0x3f,
+ .step = 0x01,
+ .default_value = 0x1a,
+ .flags = 0,
+ },
+ {
+ .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "green balance",
+ .minimum = 0x00,
+ .maximum = 0x3f,
+ .step = 0x01,
+ .default_value = 0x2f,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_BLACK_LEVEL,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "auto black level compensation",
+ .minimum = 0x00,
+ .maximum = 0x01,
+ .step = 0x01,
+ .default_value = 0x00,
+ .flags = 0,
+ },
+ },
+ .get_ctrl = &hv7131r_get_ctrl,
+ .set_ctrl = &hv7131r_set_ctrl,
+ .cropcap = {
+ .bounds = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ .defrect = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ },
+ .set_crop = &hv7131r_set_crop,
+ .pix_format = {
+ .width = 640,
+ .height = 480,
+ .pixelformat = V4L2_PIX_FMT_SBGGR8,
+ .priv = 8,
+ },
+ .set_pix_format = &hv7131r_set_pix_format
+};
+
+
+int sn9c102_probe_hv7131r(struct sn9c102_device* cam)
+{
+ int devid, err = 0;
+
+ err += sn9c102_write_reg(cam, 0x09, 0x01);
+ err += sn9c102_write_reg(cam, 0x44, 0x02);
+ err += sn9c102_write_reg(cam, 0x34, 0x01);
+ err += sn9c102_write_reg(cam, 0x20, 0x17);
+ err += sn9c102_write_reg(cam, 0x34, 0x01);
+ err += sn9c102_write_reg(cam, 0x46, 0x01);
+ if (err)
+ return -EIO;
+
+ devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00);
+ if (devid < 0)
+ return -EIO;
+
+ if (devid != 0x02)
+ return -ENODEV;
+
+ sn9c102_attach_sensor(cam, &hv7131r);
+
+ return 0;
+}
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_mi0343.c b/linux/drivers/media/video/sn9c102/sn9c102_mi0343.c
index a33d1bc10..441156d61 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102_mi0343.c
+++ b/linux/drivers/media/video/sn9c102/sn9c102_mi0343.c
@@ -22,12 +22,9 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor mi0343;
-static u8 mi0343_i2c_data[5+1];
-
-
static int mi0343_init(struct sn9c102_device* cam)
{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
int err = 0;
err += sn9c102_write_reg(cam, 0x00, 0x10);
@@ -38,20 +35,20 @@ static int mi0343_init(struct sn9c102_device* cam)
err += sn9c102_write_reg(cam, 0x07, 0x18);
err += sn9c102_write_reg(cam, 0xa0, 0x19);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x0d, 0x00, 0x01, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x0d, 0x00, 0x00, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x03, 0x01, 0xe1, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x04, 0x02, 0x81, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x05, 0x00, 0x17, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x06, 0x00, 0x11, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
- 0x62, 0x04, 0x9a, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+ 0x00, 0x01, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+ 0x00, 0x00, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
+ 0x01, 0xe1, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
+ 0x02, 0x81, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
+ 0x00, 0x17, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
+ 0x00, 0x11, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
+ 0x04, 0x9a, 0, 0);
return err;
}
@@ -60,43 +57,46 @@ static int mi0343_init(struct sn9c102_device* cam)
static int mi0343_get_ctrl(struct sn9c102_device* cam,
struct v4l2_control* ctrl)
{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+ u8 data[5+1];
+
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x09, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
+ 2+1, data) < 0)
return -EIO;
- ctrl->value = mi0343_i2c_data[2];
+ ctrl->value = data[2];
return 0;
case V4L2_CID_GAIN:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x35, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
+ 2+1, data) < 0)
return -EIO;
break;
case V4L2_CID_HFLIP:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x20, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
+ 2+1, data) < 0)
return -EIO;
- ctrl->value = mi0343_i2c_data[3] & 0x20 ? 1 : 0;
+ ctrl->value = data[3] & 0x20 ? 1 : 0;
return 0;
case V4L2_CID_VFLIP:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x20, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
+ 2+1, data) < 0)
return -EIO;
- ctrl->value = mi0343_i2c_data[3] & 0x80 ? 1 : 0;
+ ctrl->value = data[3] & 0x80 ? 1 : 0;
return 0;
case V4L2_CID_RED_BALANCE:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x2d, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
+ 2+1, data) < 0)
return -EIO;
break;
case V4L2_CID_BLUE_BALANCE:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x2c, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
+ 2+1, data) < 0)
return -EIO;
break;
case SN9C102_V4L2_CID_GREEN_BALANCE:
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
- 0x2e, 2+1, mi0343_i2c_data) < 0)
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
+ 2+1, data) < 0)
return -EIO;
break;
default:
@@ -108,7 +108,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
case V4L2_CID_RED_BALANCE:
case V4L2_CID_BLUE_BALANCE:
case SN9C102_V4L2_CID_GREEN_BALANCE:
- ctrl->value = mi0343_i2c_data[3] | (mi0343_i2c_data[2] << 8);
+ ctrl->value = data[3] | (data[2] << 8);
if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
ctrl->value -= 0x10;
else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
@@ -124,6 +124,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
static int mi0343_set_ctrl(struct sn9c102_device* cam,
const struct v4l2_control* ctrl)
{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
u16 reg = 0;
int err = 0;
@@ -143,50 +144,42 @@ static int mi0343_set_ctrl(struct sn9c102_device* cam,
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x09, ctrl->value, 0x00,
0, 0);
break;
case V4L2_CID_GAIN:
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x35, reg >> 8, reg & 0xff,
0, 0);
break;
case V4L2_CID_HFLIP:
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x20, ctrl->value ? 0x40:0x00,
ctrl->value ? 0x20:0x00,
0, 0);
break;
case V4L2_CID_VFLIP:
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x20, ctrl->value ? 0x80:0x00,
ctrl->value ? 0x80:0x00,
0, 0);
break;
case V4L2_CID_RED_BALANCE:
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x2d, reg >> 8, reg & 0xff,
0, 0);
break;
case V4L2_CID_BLUE_BALANCE:
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x2c, reg >> 8, reg & 0xff,
0, 0);
break;
case SN9C102_V4L2_CID_GREEN_BALANCE:
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x2b, reg >> 8, reg & 0xff,
0, 0);
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x2e, reg >> 8, reg & 0xff,
0, 0);
break;
@@ -216,16 +209,15 @@ static int mi0343_set_crop(struct sn9c102_device* cam,
static int mi0343_set_pix_format(struct sn9c102_device* cam,
const struct v4l2_pix_format* pix)
{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
int err = 0;
if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x0a, 0x00, 0x03, 0, 0);
err += sn9c102_write_reg(cam, 0x20, 0x19);
} else {
- err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
- mi0343.i2c_slave_id,
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
0x0a, 0x00, 0x05, 0, 0);
err += sn9c102_write_reg(cam, 0xa0, 0x19);
}
@@ -237,7 +229,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor mi0343 = {
.name = "MI-0343",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
+ .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES,
.i2c_slave_id = 0x5d,
@@ -343,6 +335,7 @@ static struct sn9c102_sensor mi0343 = {
int sn9c102_probe_mi0343(struct sn9c102_device* cam)
{
+ u8 data[5+1];
int err = 0;
err += sn9c102_write_reg(cam, 0x01, 0x01);
@@ -352,10 +345,10 @@ int sn9c102_probe_mi0343(struct sn9c102_device* cam)
return -EIO;
if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
- 2, mi0343_i2c_data) < 0)
+ 2, data) < 0)
return -EIO;
- if (mi0343_i2c_data[4] != 0x32 && mi0343_i2c_data[3] != 0xe3)
+ if (data[4] != 0x32 || data[3] != 0xe3)
return -ENODEV;
sn9c102_attach_sensor(cam, &mi0343);
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_mi0360.c b/linux/drivers/media/video/sn9c102/sn9c102_mi0360.c
new file mode 100644
index 000000000..7154dd053
--- /dev/null
+++ b/linux/drivers/media/video/sn9c102/sn9c102_mi0360.c
@@ -0,0 +1,353 @@
+/***************************************************************************
+ * Plug-in for MI-0360 image sensor connected to the SN9C1xx PC Camera *
+ * Controllers *
+ * *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * *
+ * 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 *
+ * (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA. *
+ ***************************************************************************/
+
+#include "sn9c102_sensor.h"
+
+
+static int mi0360_init(struct sn9c102_device* cam)
+{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+ int err = 0;
+
+ err += sn9c102_write_reg(cam, 0x00, 0x10);
+ err += sn9c102_write_reg(cam, 0x00, 0x11);
+ err += sn9c102_write_reg(cam, 0x0a, 0x14);
+ err += sn9c102_write_reg(cam, 0x40, 0x01);
+ err += sn9c102_write_reg(cam, 0x20, 0x17);
+ err += sn9c102_write_reg(cam, 0x07, 0x18);
+ err += sn9c102_write_reg(cam, 0xa0, 0x19);
+ err += sn9c102_write_reg(cam, 0x02, 0x1c);
+ err += sn9c102_write_reg(cam, 0x03, 0x1d);
+ err += sn9c102_write_reg(cam, 0x0f, 0x1e);
+ err += sn9c102_write_reg(cam, 0x0c, 0x1f);
+ err += sn9c102_write_reg(cam, 0x00, 0x20);
+ err += sn9c102_write_reg(cam, 0x10, 0x21);
+ err += sn9c102_write_reg(cam, 0x20, 0x22);
+ err += sn9c102_write_reg(cam, 0x30, 0x23);
+ err += sn9c102_write_reg(cam, 0x40, 0x24);
+ err += sn9c102_write_reg(cam, 0x50, 0x25);
+ err += sn9c102_write_reg(cam, 0x60, 0x26);
+ err += sn9c102_write_reg(cam, 0x70, 0x27);
+ err += sn9c102_write_reg(cam, 0x80, 0x28);
+ err += sn9c102_write_reg(cam, 0x90, 0x29);
+ err += sn9c102_write_reg(cam, 0xa0, 0x2a);
+ err += sn9c102_write_reg(cam, 0xb0, 0x2b);
+ err += sn9c102_write_reg(cam, 0xc0, 0x2c);
+ err += sn9c102_write_reg(cam, 0xd0, 0x2d);
+ err += sn9c102_write_reg(cam, 0xe0, 0x2e);
+ err += sn9c102_write_reg(cam, 0xf0, 0x2f);
+ err += sn9c102_write_reg(cam, 0xff, 0x30);
+
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+ 0x00, 0x01, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+ 0x00, 0x00, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
+ 0x01, 0xe1, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
+ 0x02, 0x81, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
+ 0x00, 0x17, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
+ 0x00, 0x11, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
+ 0x04, 0x9a, 0, 0);
+
+ return err;
+}
+
+
+static int mi0360_get_ctrl(struct sn9c102_device* cam,
+ struct v4l2_control* ctrl)
+{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+ u8 data[5+1];
+
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
+ 2+1, data) < 0)
+ return -EIO;
+ ctrl->value = data[2];
+ return 0;
+ case V4L2_CID_GAIN:
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
+ 2+1, data) < 0)
+ return -EIO;
+ ctrl->value = data[3];
+ return 0;
+ case V4L2_CID_RED_BALANCE:
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
+ 2+1, data) < 0)
+ return -EIO;
+ ctrl->value = data[3];
+ return 0;
+ case V4L2_CID_BLUE_BALANCE:
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
+ 2+1, data) < 0)
+ return -EIO;
+ ctrl->value = data[3];
+ return 0;
+ case SN9C102_V4L2_CID_GREEN_BALANCE:
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
+ 2+1, data) < 0)
+ return -EIO;
+ ctrl->value = data[3];
+ return 0;
+ case V4L2_CID_HFLIP:
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
+ 2+1, data) < 0)
+ return -EIO;
+ ctrl->value = data[3] & 0x20 ? 1 : 0;
+ return 0;
+ case V4L2_CID_VFLIP:
+ if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
+ 2+1, data) < 0)
+ return -EIO;
+ ctrl->value = data[3] & 0x80 ? 1 : 0;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+static int mi0360_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
+{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+ int err = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x09, ctrl->value, 0x00,
+ 0, 0);
+ break;
+ case V4L2_CID_GAIN:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x35, 0x03, ctrl->value,
+ 0, 0);
+ break;
+ case V4L2_CID_RED_BALANCE:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x2c, 0x03, ctrl->value,
+ 0, 0);
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x2d, 0x03, ctrl->value,
+ 0, 0);
+ break;
+ case SN9C102_V4L2_CID_GREEN_BALANCE:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x2b, 0x03, ctrl->value,
+ 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x2e, 0x03, ctrl->value,
+ 0, 0);
+ break;
+ case V4L2_CID_HFLIP:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x20, ctrl->value ? 0x40:0x00,
+ ctrl->value ? 0x20:0x00,
+ 0, 0);
+ break;
+ case V4L2_CID_VFLIP:
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x20, ctrl->value ? 0x80:0x00,
+ ctrl->value ? 0x80:0x00,
+ 0, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return err ? -EIO : 0;
+}
+
+
+static int mi0360_set_crop(struct sn9c102_device* cam,
+ const struct v4l2_rect* rect)
+{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+ int err = 0;
+ u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
+ v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+
+ err += sn9c102_write_reg(cam, h_start, 0x12);
+ err += sn9c102_write_reg(cam, v_start, 0x13);
+
+ return err;
+}
+
+
+static int mi0360_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
+{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+ int err = 0;
+
+ if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x0a, 0x00, 0x02, 0, 0);
+ err += sn9c102_write_reg(cam, 0x20, 0x19);
+ } else {
+ err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+ 0x0a, 0x00, 0x05, 0, 0);
+ err += sn9c102_write_reg(cam, 0x60, 0x19);
+ }
+
+ return err;
+}
+
+
+static struct sn9c102_sensor mi0360 = {
+ .name = "MI-0360",
+ .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+ .supported_bridge = BRIDGE_SN9C103,
+ .frequency = SN9C102_I2C_100KHZ,
+ .interface = SN9C102_I2C_2WIRES,
+ .i2c_slave_id = 0x5d,
+ .init = &mi0360_init,
+ .qctrl = {
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "exposure",
+ .minimum = 0x00,
+ .maximum = 0x0f,
+ .step = 0x01,
+ .default_value = 0x05,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "global gain",
+ .minimum = 0x00,
+ .maximum = 0x7f,
+ .step = 0x01,
+ .default_value = 0x25,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "horizontal mirror",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "vertical mirror",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "blue balance",
+ .minimum = 0x00,
+ .maximum = 0x7f,
+ .step = 0x01,
+ .default_value = 0x0f,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "red balance",
+ .minimum = 0x00,
+ .maximum = 0x7f,
+ .step = 0x01,
+ .default_value = 0x32,
+ .flags = 0,
+ },
+ {
+ .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "green balance",
+ .minimum = 0x00,
+ .maximum = 0x7f,
+ .step = 0x01,
+ .default_value = 0x25,
+ .flags = 0,
+ },
+ },
+ .get_ctrl = &mi0360_get_ctrl,
+ .set_ctrl = &mi0360_set_ctrl,
+ .cropcap = {
+ .bounds = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ .defrect = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ },
+ .set_crop = &mi0360_set_crop,
+ .pix_format = {
+ .width = 640,
+ .height = 480,
+ .pixelformat = V4L2_PIX_FMT_SBGGR8,
+ .priv = 8,
+ },
+ .set_pix_format = &mi0360_set_pix_format
+};
+
+
+int sn9c102_probe_mi0360(struct sn9c102_device* cam)
+{
+ u8 data[5+1];
+ int err = 0;
+
+ err += sn9c102_write_reg(cam, 0x01, 0x01);
+ err += sn9c102_write_reg(cam, 0x00, 0x01);
+ err += sn9c102_write_reg(cam, 0x28, 0x17);
+ if (err)
+ return -EIO;
+
+ if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00,
+ 2+1, data) < 0)
+ return -EIO;
+
+ if (data[2] != 0x82 || data[3] != 0x43)
+ return -ENODEV;
+
+ sn9c102_attach_sensor(cam, &mi0360);
+
+ return 0;
+}
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_ov7630.c b/linux/drivers/media/video/sn9c102/sn9c102_ov7630.c
index 7df09ff38..ad9fb2ca2 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102_ov7630.c
+++ b/linux/drivers/media/video/sn9c102/sn9c102_ov7630.c
@@ -22,9 +22,6 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor ov7630;
-
-
static int ov7630_init(struct sn9c102_device* cam)
{
int err = 0;
@@ -32,21 +29,21 @@ static int ov7630_init(struct sn9c102_device* cam)
switch (sn9c102_get_bridge(cam)) {
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
- err += sn9c102_write_reg(cam, 0x00, 0x14);
- err += sn9c102_write_reg(cam, 0x60, 0x17);
- err += sn9c102_write_reg(cam, 0x0f, 0x18);
- err += sn9c102_write_reg(cam, 0x50, 0x19);
+ err += sn9c102_write_reg(cam, 0x00, 0x14);
+ err += sn9c102_write_reg(cam, 0x60, 0x17);
+ err += sn9c102_write_reg(cam, 0x0f, 0x18);
+ err += sn9c102_write_reg(cam, 0x50, 0x19);
err += sn9c102_i2c_write(cam, 0x12, 0x8d);
err += sn9c102_i2c_write(cam, 0x12, 0x0d);
err += sn9c102_i2c_write(cam, 0x11, 0x00);
- err += sn9c102_i2c_write(cam, 0x15, 0x34);
- err += sn9c102_i2c_write(cam, 0x16, 0x03);
- err += sn9c102_i2c_write(cam, 0x17, 0x1c);
- err += sn9c102_i2c_write(cam, 0x18, 0xbd);
- err += sn9c102_i2c_write(cam, 0x19, 0x06);
- err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
- err += sn9c102_i2c_write(cam, 0x1b, 0x04);
+ err += sn9c102_i2c_write(cam, 0x15, 0x35);
+ err += sn9c102_i2c_write(cam, 0x16, 0x03);
+ err += sn9c102_i2c_write(cam, 0x17, 0x1c);
+ err += sn9c102_i2c_write(cam, 0x18, 0xbd);
+ err += sn9c102_i2c_write(cam, 0x19, 0x06);
+ err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
+ err += sn9c102_i2c_write(cam, 0x1b, 0x04);
err += sn9c102_i2c_write(cam, 0x20, 0x44);
err += sn9c102_i2c_write(cam, 0x23, 0xee);
err += sn9c102_i2c_write(cam, 0x26, 0xa0);
@@ -108,23 +105,23 @@ static int ov7630_init(struct sn9c102_device* cam)
err += sn9c102_i2c_write(cam, 0x11, 0x01);
err += sn9c102_i2c_write(cam, 0x1b, 0x04);
err += sn9c102_i2c_write(cam, 0x20, 0x44);
- err += sn9c102_i2c_write(cam, 0x23, 0xee);
- err += sn9c102_i2c_write(cam, 0x26, 0xa0);
- err += sn9c102_i2c_write(cam, 0x27, 0x9a);
+ err += sn9c102_i2c_write(cam, 0x23, 0xee);
+ err += sn9c102_i2c_write(cam, 0x26, 0xa0);
+ err += sn9c102_i2c_write(cam, 0x27, 0x9a);
err += sn9c102_i2c_write(cam, 0x28, 0x20);
- err += sn9c102_i2c_write(cam, 0x29, 0x30);
- err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
- err += sn9c102_i2c_write(cam, 0x30, 0x24);
- err += sn9c102_i2c_write(cam, 0x32, 0x86);
- err += sn9c102_i2c_write(cam, 0x60, 0xa9);
- err += sn9c102_i2c_write(cam, 0x61, 0x42);
- err += sn9c102_i2c_write(cam, 0x65, 0x00);
- err += sn9c102_i2c_write(cam, 0x69, 0x38);
- err += sn9c102_i2c_write(cam, 0x6f, 0x88);
- err += sn9c102_i2c_write(cam, 0x70, 0x0b);
- err += sn9c102_i2c_write(cam, 0x71, 0x00);
- err += sn9c102_i2c_write(cam, 0x74, 0x21);
- err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
+ err += sn9c102_i2c_write(cam, 0x29, 0x30);
+ err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
+ err += sn9c102_i2c_write(cam, 0x30, 0x24);
+ err += sn9c102_i2c_write(cam, 0x32, 0x86);
+ err += sn9c102_i2c_write(cam, 0x60, 0xa9);
+ err += sn9c102_i2c_write(cam, 0x61, 0x42);
+ err += sn9c102_i2c_write(cam, 0x65, 0x00);
+ err += sn9c102_i2c_write(cam, 0x69, 0x38);
+ err += sn9c102_i2c_write(cam, 0x6f, 0x88);
+ err += sn9c102_i2c_write(cam, 0x70, 0x0b);
+ err += sn9c102_i2c_write(cam, 0x71, 0x00);
+ err += sn9c102_i2c_write(cam, 0x74, 0x21);
+ err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
break;
default:
break;
@@ -428,9 +425,9 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam)
switch (sn9c102_get_bridge(cam)) {
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
- err += sn9c102_write_reg(cam, 0x01, 0x01);
- err += sn9c102_write_reg(cam, 0x00, 0x01);
- err += sn9c102_write_reg(cam, 0x28, 0x17);
+ err += sn9c102_write_reg(cam, 0x01, 0x01);
+ err += sn9c102_write_reg(cam, 0x00, 0x01);
+ err += sn9c102_write_reg(cam, 0x28, 0x17);
break;
case BRIDGE_SN9C103: /* do _not_ change anything! */
err += sn9c102_write_reg(cam, 0x09, 0x01);
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_ov7660.c b/linux/drivers/media/video/sn9c102/sn9c102_ov7660.c
index d670c24d4..eef90ff3d 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102_ov7660.c
+++ b/linux/drivers/media/video/sn9c102/sn9c102_ov7660.c
@@ -22,9 +22,6 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor ov7660;
-
-
static int ov7660_init(struct sn9c102_device* cam)
{
int err = 0;
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_pas106b.c b/linux/drivers/media/video/sn9c102/sn9c102_pas106b.c
index 8d79a5fae..a67057210 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102_pas106b.c
+++ b/linux/drivers/media/video/sn9c102/sn9c102_pas106b.c
@@ -23,9 +23,6 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor pas106b;
-
-
static int pas106b_init(struct sn9c102_device* cam)
{
int err = 0;
@@ -172,7 +169,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor pas106b = {
.name = "PAS106B",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
+ .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
.sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES,
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/linux/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
index 7894f01b5..4447d7cb1 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
+++ b/linux/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
@@ -28,9 +28,6 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor pas202bcb;
-
-
static int pas202bcb_init(struct sn9c102_device* cam)
{
int err = 0;
@@ -38,12 +35,12 @@ static int pas202bcb_init(struct sn9c102_device* cam)
switch (sn9c102_get_bridge(cam)) {
case BRIDGE_SN9C101:
case BRIDGE_SN9C102:
- err += sn9c102_write_reg(cam, 0x00, 0x10);
- err += sn9c102_write_reg(cam, 0x00, 0x11);
- err += sn9c102_write_reg(cam, 0x00, 0x14);
- err += sn9c102_write_reg(cam, 0x20, 0x17);
- err += sn9c102_write_reg(cam, 0x30, 0x19);
- err += sn9c102_write_reg(cam, 0x09, 0x18);
+ err += sn9c102_write_reg(cam, 0x00, 0x10);
+ err += sn9c102_write_reg(cam, 0x00, 0x11);
+ err += sn9c102_write_reg(cam, 0x00, 0x14);
+ err += sn9c102_write_reg(cam, 0x20, 0x17);
+ err += sn9c102_write_reg(cam, 0x30, 0x19);
+ err += sn9c102_write_reg(cam, 0x09, 0x18);
break;
case BRIDGE_SN9C103:
err += sn9c102_write_reg(cam, 0x00, 0x02);
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/linux/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
index 90023ad63..a265767e5 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
+++ b/linux/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
@@ -22,9 +22,6 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor tas5110c1b;
-
-
static int tas5110c1b_init(struct sn9c102_device* cam)
{
int err = 0;
@@ -98,7 +95,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor tas5110c1b = {
.name = "TAS5110C1B",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
+ .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
.sysfs_ops = SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_3WIRES,
@@ -146,7 +143,6 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
const struct usb_device_id tas5110c1b_id_table[] = {
{ USB_DEVICE(0x0c45, 0x6001), },
{ USB_DEVICE(0x0c45, 0x6005), },
- { USB_DEVICE(0x0c45, 0x6007), },
{ USB_DEVICE(0x0c45, 0x60ab), },
{ }
};
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/linux/drivers/media/video/sn9c102/sn9c102_tas5110d.c
new file mode 100644
index 000000000..4681cfa1b
--- /dev/null
+++ b/linux/drivers/media/video/sn9c102/sn9c102_tas5110d.c
@@ -0,0 +1,121 @@
+/***************************************************************************
+ * Plug-in for TAS5110D image sensor connected to the SN9C1xx PC Camera *
+ * Controllers *
+ * *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * *
+ * 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 *
+ * (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA. *
+ ***************************************************************************/
+
+#include "sn9c102_sensor.h"
+
+
+static int tas5110d_init(struct sn9c102_device* cam)
+{
+ int err = 0;
+
+ err += sn9c102_write_reg(cam, 0x01, 0x01);
+ err += sn9c102_write_reg(cam, 0x04, 0x01);
+ err += sn9c102_write_reg(cam, 0x0a, 0x14);
+ err += sn9c102_write_reg(cam, 0x60, 0x17);
+ err += sn9c102_write_reg(cam, 0x06, 0x18);
+ err += sn9c102_write_reg(cam, 0xfb, 0x19);
+
+ err += sn9c102_i2c_write(cam, 0x9a, 0xca);
+
+ return err;
+}
+
+
+static int tas5110d_set_crop(struct sn9c102_device* cam,
+ const struct v4l2_rect* rect)
+{
+ struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+ int err = 0;
+ u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
+ v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
+
+ err += sn9c102_write_reg(cam, h_start, 0x12);
+ err += sn9c102_write_reg(cam, v_start, 0x13);
+
+ err += sn9c102_write_reg(cam, 0x14, 0x1a);
+ err += sn9c102_write_reg(cam, 0x0a, 0x1b);
+
+ return err;
+}
+
+
+static int tas5110d_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
+{
+ int err = 0;
+
+ if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+ err += sn9c102_write_reg(cam, 0x3b, 0x19);
+ else
+ err += sn9c102_write_reg(cam, 0xfb, 0x19);
+
+ return err;
+}
+
+
+static struct sn9c102_sensor tas5110d = {
+ .name = "TAS5110D",
+ .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+ .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
+ .sysfs_ops = SN9C102_I2C_WRITE,
+ .frequency = SN9C102_I2C_100KHZ,
+ .interface = SN9C102_I2C_2WIRES,
+ .i2c_slave_id = 0x61,
+ .init = &tas5110d_init,
+ .cropcap = {
+ .bounds = {
+ .left = 0,
+ .top = 0,
+ .width = 352,
+ .height = 288,
+ },
+ .defrect = {
+ .left = 0,
+ .top = 0,
+ .width = 352,
+ .height = 288,
+ },
+ },
+ .set_crop = &tas5110d_set_crop,
+ .pix_format = {
+ .width = 352,
+ .height = 288,
+ .pixelformat = V4L2_PIX_FMT_SBGGR8,
+ .priv = 8,
+ },
+ .set_pix_format = &tas5110d_set_pix_format
+};
+
+
+int sn9c102_probe_tas5110d(struct sn9c102_device* cam)
+{
+ const struct usb_device_id tas5110d_id_table[] = {
+ { USB_DEVICE(0x0c45, 0x6007), },
+ { }
+ };
+
+ if (!sn9c102_match_id(cam, tas5110d_id_table))
+ return -ENODEV;
+
+ sn9c102_attach_sensor(cam, &tas5110d);
+
+ return 0;
+}
diff --git a/linux/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/linux/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
index cb1b318bc..a7f711396 100644
--- a/linux/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
+++ b/linux/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
@@ -22,9 +22,6 @@
#include "sn9c102_sensor.h"
-static struct sn9c102_sensor tas5130d1b;
-
-
static int tas5130d1b_init(struct sn9c102_device* cam)
{
int err = 0;
@@ -99,7 +96,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
static struct sn9c102_sensor tas5130d1b = {
.name = "TAS5130D1B",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
+ .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
.sysfs_ops = SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_3WIRES,