diff options
author | Jean-François Moine <moinejf@free.fr> | 2010-11-13 03:10:27 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-12-29 05:16:44 -0500 |
commit | 42e142f6b72493b5daec9950c4c83d20ccf56a0d (patch) | |
tree | 34ac08f662b5513ee91a7ef157d0d6f9fdfd4aca /drivers | |
parent | 7491f785dd02bc35551e0463d798959b15644c1d (diff) |
[media] gspca - ov519: New sensor ov7660 with bridge ov530 (ov519)
[mchehab@redhat.com: Some CodingStyle fixes]
Tested-by: Anca Emanuel <anca.emanuel@gmail.com>
Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/gspca/ov519.c | 394 |
1 files changed, 386 insertions, 8 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 08f07c3488d8..0ed21dbb46cd 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -82,7 +82,7 @@ struct sd { | |||
82 | #define BRIDGE_OV511PLUS 1 | 82 | #define BRIDGE_OV511PLUS 1 |
83 | #define BRIDGE_OV518 2 | 83 | #define BRIDGE_OV518 2 |
84 | #define BRIDGE_OV518PLUS 3 | 84 | #define BRIDGE_OV518PLUS 3 |
85 | #define BRIDGE_OV519 4 | 85 | #define BRIDGE_OV519 4 /* = ov530 */ |
86 | #define BRIDGE_OVFX2 5 | 86 | #define BRIDGE_OVFX2 5 |
87 | #define BRIDGE_W9968CF 6 | 87 | #define BRIDGE_W9968CF 6 |
88 | #define BRIDGE_MASK 7 | 88 | #define BRIDGE_MASK 7 |
@@ -127,6 +127,7 @@ enum sensors { | |||
127 | SEN_OV7620AE, | 127 | SEN_OV7620AE, |
128 | SEN_OV7640, | 128 | SEN_OV7640, |
129 | SEN_OV7648, | 129 | SEN_OV7648, |
130 | SEN_OV7660, | ||
130 | SEN_OV7670, | 131 | SEN_OV7670, |
131 | SEN_OV76BE, | 132 | SEN_OV76BE, |
132 | SEN_OV8610, | 133 | SEN_OV8610, |
@@ -183,7 +184,7 @@ static const struct ctrl sd_ctrls[] = { | |||
183 | }, | 184 | }, |
184 | .set_control = setcolors, | 185 | .set_control = setcolors, |
185 | }, | 186 | }, |
186 | /* The flip controls work with ov7670 only */ | 187 | /* The flip controls work for sensors ov7660 and ov7670 only */ |
187 | [HFLIP] = { | 188 | [HFLIP] = { |
188 | { | 189 | { |
189 | .id = V4L2_CID_HFLIP, | 190 | .id = V4L2_CID_HFLIP, |
@@ -268,6 +269,8 @@ static const unsigned ctrl_dis[] = { | |||
268 | (1 << AUTOBRIGHT) | | 269 | (1 << AUTOBRIGHT) | |
269 | (1 << CONTRAST), | 270 | (1 << CONTRAST), |
270 | 271 | ||
272 | [SEN_OV7660] = (1 << AUTOBRIGHT), | ||
273 | |||
271 | [SEN_OV7670] = (1 << COLORS) | | 274 | [SEN_OV7670] = (1 << COLORS) | |
272 | (1 << AUTOBRIGHT), | 275 | (1 << AUTOBRIGHT), |
273 | 276 | ||
@@ -572,7 +575,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { | |||
572 | #define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */ | 575 | #define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */ |
573 | #define OV7610_REG_COM_I 0x29 /* misc settings */ | 576 | #define OV7610_REG_COM_I 0x29 /* misc settings */ |
574 | 577 | ||
575 | /* OV7670 registers */ | 578 | /* OV7660 and OV7670 registers */ |
576 | #define OV7670_R00_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ | 579 | #define OV7670_R00_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */ |
577 | #define OV7670_R01_BLUE 0x01 /* blue gain */ | 580 | #define OV7670_R01_BLUE 0x01 /* blue gain */ |
578 | #define OV7670_R02_RED 0x02 /* red gain */ | 581 | #define OV7670_R02_RED 0x02 /* red gain */ |
@@ -625,6 +628,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = { | |||
625 | /*#define OV7670_COM15_R00FF 0xc0 * 00 to FF */ | 628 | /*#define OV7670_COM15_R00FF 0xc0 * 00 to FF */ |
626 | #define OV7670_R41_COM16 0x41 /* Control 16 */ | 629 | #define OV7670_R41_COM16 0x41 /* Control 16 */ |
627 | #define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */ | 630 | #define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */ |
631 | /* end of ov7660 common registers */ | ||
628 | #define OV7670_R55_BRIGHT 0x55 /* Brightness */ | 632 | #define OV7670_R55_BRIGHT 0x55 /* Brightness */ |
629 | #define OV7670_R56_CONTRAS 0x56 /* Contrast control */ | 633 | #define OV7670_R56_CONTRAS 0x56 /* Contrast control */ |
630 | #define OV7670_R69_GFIX 0x69 /* Fix gain control */ | 634 | #define OV7670_R69_GFIX 0x69 /* Fix gain control */ |
@@ -1577,6 +1581,150 @@ static const struct ov_i2c_regvals norm_7640[] = { | |||
1577 | { 0x12, 0x14 }, | 1581 | { 0x12, 0x14 }, |
1578 | }; | 1582 | }; |
1579 | 1583 | ||
1584 | static const struct ov_regvals init_519_ov7660[] = { | ||
1585 | { 0x5d, 0x03 }, /* Turn off suspend mode */ | ||
1586 | { 0x53, 0x9b }, /* 0x9f enables the (unused) microcontroller */ | ||
1587 | { 0x54, 0x0f }, /* bit2 (jpeg enable) */ | ||
1588 | { 0xa2, 0x20 }, /* a2-a5 are undocumented */ | ||
1589 | { 0xa3, 0x18 }, | ||
1590 | { 0xa4, 0x04 }, | ||
1591 | { 0xa5, 0x28 }, | ||
1592 | { 0x37, 0x00 }, /* SetUsbInit */ | ||
1593 | { 0x55, 0x02 }, /* 4.096 Mhz audio clock */ | ||
1594 | /* Enable both fields, YUV Input, disable defect comp (why?) */ | ||
1595 | { 0x20, 0x0c }, /* 0x0d does U <-> V swap */ | ||
1596 | { 0x21, 0x38 }, | ||
1597 | { 0x22, 0x1d }, | ||
1598 | { 0x17, 0x50 }, /* undocumented */ | ||
1599 | { 0x37, 0x00 }, /* undocumented */ | ||
1600 | { 0x40, 0xff }, /* I2C timeout counter */ | ||
1601 | { 0x46, 0x00 }, /* I2C clock prescaler */ | ||
1602 | }; | ||
1603 | static const struct ov_i2c_regvals norm_7660[] = { | ||
1604 | {OV7670_R12_COM7, OV7670_COM7_RESET}, | ||
1605 | {OV7670_R11_CLKRC, 0x81}, | ||
1606 | {0x92, 0x00}, /* DM_LNL */ | ||
1607 | {0x93, 0x00}, /* DM_LNH */ | ||
1608 | {0x9d, 0x4c}, /* BD50ST */ | ||
1609 | {0x9e, 0x3f}, /* BD60ST */ | ||
1610 | {OV7670_R3B_COM11, 0x02}, | ||
1611 | {OV7670_R13_COM8, 0xf5}, | ||
1612 | {OV7670_R10_AECH, 0x00}, | ||
1613 | {OV7670_R00_GAIN, 0x00}, | ||
1614 | {OV7670_R01_BLUE, 0x7c}, | ||
1615 | {OV7670_R02_RED, 0x9d}, | ||
1616 | {OV7670_R12_COM7, 0x00}, | ||
1617 | {OV7670_R04_COM1, 00}, | ||
1618 | {OV7670_R18_HSTOP, 0x01}, | ||
1619 | {OV7670_R17_HSTART, 0x13}, | ||
1620 | {OV7670_R32_HREF, 0x92}, | ||
1621 | {OV7670_R19_VSTART, 0x02}, | ||
1622 | {OV7670_R1A_VSTOP, 0x7a}, | ||
1623 | {OV7670_R03_VREF, 0x00}, | ||
1624 | {OV7670_R0E_COM5, 0x04}, | ||
1625 | {OV7670_R0F_COM6, 0x62}, | ||
1626 | {OV7670_R15_COM10, 0x00}, | ||
1627 | {0x16, 0x02}, /* RSVD */ | ||
1628 | {0x1b, 0x00}, /* PSHFT */ | ||
1629 | {OV7670_R1E_MVFP, 0x01}, | ||
1630 | {0x29, 0x3c}, /* RSVD */ | ||
1631 | {0x33, 0x00}, /* CHLF */ | ||
1632 | {0x34, 0x07}, /* ARBLM */ | ||
1633 | {0x35, 0x84}, /* RSVD */ | ||
1634 | {0x36, 0x00}, /* RSVD */ | ||
1635 | {0x37, 0x04}, /* ADC */ | ||
1636 | {0x39, 0x43}, /* OFON */ | ||
1637 | {OV7670_R3A_TSLB, 0x00}, | ||
1638 | {OV7670_R3C_COM12, 0x6c}, | ||
1639 | {OV7670_R3D_COM13, 0x98}, | ||
1640 | {OV7670_R3F_EDGE, 0x23}, | ||
1641 | {OV7670_R40_COM15, 0xc1}, | ||
1642 | {OV7670_R41_COM16, 0x22}, | ||
1643 | {0x6b, 0x0a}, /* DBLV */ | ||
1644 | {0xa1, 0x08}, /* RSVD */ | ||
1645 | {0x69, 0x80}, /* HV */ | ||
1646 | {0x43, 0xf0}, /* RSVD.. */ | ||
1647 | {0x44, 0x10}, | ||
1648 | {0x45, 0x78}, | ||
1649 | {0x46, 0xa8}, | ||
1650 | {0x47, 0x60}, | ||
1651 | {0x48, 0x80}, | ||
1652 | {0x59, 0xba}, | ||
1653 | {0x5a, 0x9a}, | ||
1654 | {0x5b, 0x22}, | ||
1655 | {0x5c, 0xb9}, | ||
1656 | {0x5d, 0x9b}, | ||
1657 | {0x5e, 0x10}, | ||
1658 | {0x5f, 0xe0}, | ||
1659 | {0x60, 0x85}, | ||
1660 | {0x61, 0x60}, | ||
1661 | {0x9f, 0x9d}, /* RSVD */ | ||
1662 | {0xa0, 0xa0}, /* DSPC2 */ | ||
1663 | {0x4f, 0x60}, /* matrix */ | ||
1664 | {0x50, 0x64}, | ||
1665 | {0x51, 0x04}, | ||
1666 | {0x52, 0x18}, | ||
1667 | {0x53, 0x3c}, | ||
1668 | {0x54, 0x54}, | ||
1669 | {0x55, 0x40}, | ||
1670 | {0x56, 0x40}, | ||
1671 | {0x57, 0x40}, | ||
1672 | {0x58, 0x0d}, /* matrix sign */ | ||
1673 | {0x8b, 0xcc}, /* RSVD */ | ||
1674 | {0x8c, 0xcc}, | ||
1675 | {0x8d, 0xcf}, | ||
1676 | {0x6c, 0x40}, /* gamma curve */ | ||
1677 | {0x6d, 0xe0}, | ||
1678 | {0x6e, 0xa0}, | ||
1679 | {0x6f, 0x80}, | ||
1680 | {0x70, 0x70}, | ||
1681 | {0x71, 0x80}, | ||
1682 | {0x72, 0x60}, | ||
1683 | {0x73, 0x60}, | ||
1684 | {0x74, 0x50}, | ||
1685 | {0x75, 0x40}, | ||
1686 | {0x76, 0x38}, | ||
1687 | {0x77, 0x3c}, | ||
1688 | {0x78, 0x32}, | ||
1689 | {0x79, 0x1a}, | ||
1690 | {0x7a, 0x28}, | ||
1691 | {0x7b, 0x24}, | ||
1692 | {0x7c, 0x04}, /* gamma curve */ | ||
1693 | {0x7d, 0x12}, | ||
1694 | {0x7e, 0x26}, | ||
1695 | {0x7f, 0x46}, | ||
1696 | {0x80, 0x54}, | ||
1697 | {0x81, 0x64}, | ||
1698 | {0x82, 0x70}, | ||
1699 | {0x83, 0x7c}, | ||
1700 | {0x84, 0x86}, | ||
1701 | {0x85, 0x8e}, | ||
1702 | {0x86, 0x9c}, | ||
1703 | {0x87, 0xab}, | ||
1704 | {0x88, 0xc4}, | ||
1705 | {0x89, 0xd1}, | ||
1706 | {0x8a, 0xe5}, | ||
1707 | {OV7670_R14_COM9, 0x1e}, | ||
1708 | {OV7670_R24_AEW, 0x80}, | ||
1709 | {OV7670_R25_AEB, 0x72}, | ||
1710 | {OV7670_R26_VPT, 0xb3}, | ||
1711 | {0x62, 0x80}, /* LCC1 */ | ||
1712 | {0x63, 0x80}, /* LCC2 */ | ||
1713 | {0x64, 0x06}, /* LCC3 */ | ||
1714 | {0x65, 0x00}, /* LCC4 */ | ||
1715 | {0x66, 0x01}, /* LCC5 */ | ||
1716 | {0x94, 0x0e}, /* RSVD.. */ | ||
1717 | {0x95, 0x14}, | ||
1718 | {OV7670_R13_COM8, OV7670_COM8_FASTAEC | ||
1719 | | OV7670_COM8_AECSTEP | ||
1720 | | OV7670_COM8_BFILT | ||
1721 | | 0x10 | ||
1722 | | OV7670_COM8_AGC | ||
1723 | | OV7670_COM8_AWB | ||
1724 | | OV7670_COM8_AEC}, | ||
1725 | {0xa1, 0xc8} | ||
1726 | }; | ||
1727 | |||
1580 | /* 7670. Defaults taken from OmniVision provided data, | 1728 | /* 7670. Defaults taken from OmniVision provided data, |
1581 | * as provided by Jonathan Corbet of OLPC */ | 1729 | * as provided by Jonathan Corbet of OLPC */ |
1582 | static const struct ov_i2c_regvals norm_7670[] = { | 1730 | static const struct ov_i2c_regvals norm_7670[] = { |
@@ -2574,6 +2722,11 @@ static void ov7xx0_configure(struct sd *sd) | |||
2574 | PDEBUG(D_PROBE, "Sensor is an OV7648"); | 2722 | PDEBUG(D_PROBE, "Sensor is an OV7648"); |
2575 | sd->sensor = SEN_OV7648; | 2723 | sd->sensor = SEN_OV7648; |
2576 | break; | 2724 | break; |
2725 | case 0x60: | ||
2726 | PDEBUG(D_PROBE, "Sensor is a OV7660"); | ||
2727 | sd->sensor = SEN_OV7660; | ||
2728 | sd->invert_led = 0; | ||
2729 | break; | ||
2577 | default: | 2730 | default: |
2578 | PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); | 2731 | PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); |
2579 | return; | 2732 | return; |
@@ -2935,6 +3088,91 @@ static void ovfx2_configure(struct sd *sd) | |||
2935 | write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); | 3088 | write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2)); |
2936 | } | 3089 | } |
2937 | 3090 | ||
3091 | /* set the mode */ | ||
3092 | /* This function works for ov7660 only */ | ||
3093 | static void ov519_set_mode(struct sd *sd) | ||
3094 | { | ||
3095 | static const struct ov_regvals bridge_ov7660[2][10] = { | ||
3096 | {{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00}, | ||
3097 | {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, | ||
3098 | {0x25, 0x01}, {0x26, 0x00}}, | ||
3099 | {{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00}, | ||
3100 | {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c}, | ||
3101 | {0x25, 0x03}, {0x26, 0x00}} | ||
3102 | }; | ||
3103 | static const struct ov_i2c_regvals sensor_ov7660[2][3] = { | ||
3104 | {{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}}, | ||
3105 | {{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}} | ||
3106 | }; | ||
3107 | static const struct ov_i2c_regvals sensor_ov7660_2[] = { | ||
3108 | {OV7670_R17_HSTART, 0x13}, | ||
3109 | {OV7670_R18_HSTOP, 0x01}, | ||
3110 | {OV7670_R32_HREF, 0x92}, | ||
3111 | {OV7670_R19_VSTART, 0x02}, | ||
3112 | {OV7670_R1A_VSTOP, 0x7a}, | ||
3113 | {OV7670_R03_VREF, 0x00}, | ||
3114 | /* {0x33, 0x00}, */ | ||
3115 | /* {0x34, 0x07}, */ | ||
3116 | /* {0x36, 0x00}, */ | ||
3117 | /* {0x6b, 0x0a}, */ | ||
3118 | }; | ||
3119 | |||
3120 | write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode], | ||
3121 | ARRAY_SIZE(bridge_ov7660[0])); | ||
3122 | write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode], | ||
3123 | ARRAY_SIZE(sensor_ov7660[0])); | ||
3124 | write_i2c_regvals(sd, sensor_ov7660_2, | ||
3125 | ARRAY_SIZE(sensor_ov7660_2)); | ||
3126 | } | ||
3127 | |||
3128 | /* set the frame rate */ | ||
3129 | /* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */ | ||
3130 | static void ov519_set_fr(struct sd *sd) | ||
3131 | { | ||
3132 | int fr; | ||
3133 | u8 clock; | ||
3134 | /* frame rate table with indices: | ||
3135 | * - mode = 0: 320x240, 1: 640x480 | ||
3136 | * - fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5 | ||
3137 | * - reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock) | ||
3138 | */ | ||
3139 | static const u8 fr_tb[2][6][3] = { | ||
3140 | {{0x04, 0xff, 0x00}, | ||
3141 | {0x04, 0x1f, 0x00}, | ||
3142 | {0x04, 0x1b, 0x00}, | ||
3143 | {0x04, 0x15, 0x00}, | ||
3144 | {0x04, 0x09, 0x00}, | ||
3145 | {0x04, 0x01, 0x00}}, | ||
3146 | {{0x0c, 0xff, 0x00}, | ||
3147 | {0x0c, 0x1f, 0x00}, | ||
3148 | {0x0c, 0x1b, 0x00}, | ||
3149 | {0x04, 0xff, 0x01}, | ||
3150 | {0x04, 0x1f, 0x01}, | ||
3151 | {0x04, 0x1b, 0x01}}, | ||
3152 | }; | ||
3153 | |||
3154 | if (frame_rate > 0) | ||
3155 | sd->frame_rate = frame_rate; | ||
3156 | if (sd->frame_rate >= 30) | ||
3157 | fr = 0; | ||
3158 | else if (sd->frame_rate >= 25) | ||
3159 | fr = 1; | ||
3160 | else if (sd->frame_rate >= 20) | ||
3161 | fr = 2; | ||
3162 | else if (sd->frame_rate >= 15) | ||
3163 | fr = 3; | ||
3164 | else if (sd->frame_rate >= 10) | ||
3165 | fr = 4; | ||
3166 | else | ||
3167 | fr = 5; | ||
3168 | reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]); | ||
3169 | reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]); | ||
3170 | clock = fr_tb[sd->gspca_dev.curr_mode][fr][2]; | ||
3171 | if (sd->sensor == SEN_OV7660) | ||
3172 | clock |= 0x80; /* enable double clock */ | ||
3173 | ov518_i2c_w(sd, OV7670_R11_CLKRC, clock); | ||
3174 | } | ||
3175 | |||
2938 | /* this function is called at probe time */ | 3176 | /* this function is called at probe time */ |
2939 | static int sd_config(struct gspca_dev *gspca_dev, | 3177 | static int sd_config(struct gspca_dev *gspca_dev, |
2940 | const struct usb_device_id *id) | 3178 | const struct usb_device_id *id) |
@@ -3118,6 +3356,34 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
3118 | case SEN_OV7648: | 3356 | case SEN_OV7648: |
3119 | write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)); | 3357 | write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)); |
3120 | break; | 3358 | break; |
3359 | case SEN_OV7660: | ||
3360 | i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET); | ||
3361 | msleep(14); | ||
3362 | reg_w(sd, OV519_R57_SNAPSHOT, 0x23); | ||
3363 | write_regvals(sd, init_519_ov7660, | ||
3364 | ARRAY_SIZE(init_519_ov7660)); | ||
3365 | write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660)); | ||
3366 | sd->gspca_dev.curr_mode = 1; /* 640x480 */ | ||
3367 | sd->frame_rate = 15; | ||
3368 | ov519_set_mode(sd); | ||
3369 | ov519_set_fr(sd); | ||
3370 | sd->ctrls[COLORS].max = 4; /* 0..4 */ | ||
3371 | sd->ctrls[COLORS].val = | ||
3372 | sd->ctrls[COLORS].def = 2; | ||
3373 | setcolors(gspca_dev); | ||
3374 | sd->ctrls[CONTRAST].max = 6; /* 0..6 */ | ||
3375 | sd->ctrls[CONTRAST].val = | ||
3376 | sd->ctrls[CONTRAST].def = 3; | ||
3377 | setcontrast(gspca_dev); | ||
3378 | sd->ctrls[BRIGHTNESS].max = 6; /* 0..6 */ | ||
3379 | sd->ctrls[BRIGHTNESS].val = | ||
3380 | sd->ctrls[BRIGHTNESS].def = 3; | ||
3381 | setbrightness(gspca_dev); | ||
3382 | sd_reset_snapshot(gspca_dev); | ||
3383 | ov51x_restart(sd); | ||
3384 | ov51x_stop(sd); /* not in win traces */ | ||
3385 | ov51x_led_control(sd, 0); | ||
3386 | break; | ||
3121 | case SEN_OV7670: | 3387 | case SEN_OV7670: |
3122 | sd->ctrls[FREQ].max = 3; /* auto */ | 3388 | sd->ctrls[FREQ].max = 3; /* auto */ |
3123 | sd->ctrls[FREQ].def = 3; | 3389 | sd->ctrls[FREQ].def = 3; |
@@ -3431,16 +3697,21 @@ static void ov519_mode_init_regs(struct sd *sd) | |||
3431 | }; | 3697 | }; |
3432 | 3698 | ||
3433 | /******** Set the mode ********/ | 3699 | /******** Set the mode ********/ |
3434 | if (sd->sensor != SEN_OV7670) { | 3700 | switch (sd->sensor) { |
3701 | default: | ||
3435 | write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519)); | 3702 | write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519)); |
3436 | if (sd->sensor == SEN_OV7640 || | 3703 | if (sd->sensor == SEN_OV7640 || |
3437 | sd->sensor == SEN_OV7648) { | 3704 | sd->sensor == SEN_OV7648) { |
3438 | /* Select 8-bit input mode */ | 3705 | /* Select 8-bit input mode */ |
3439 | reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); | 3706 | reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); |
3440 | } | 3707 | } |
3441 | } else { | 3708 | break; |
3709 | case SEN_OV7660: | ||
3710 | return; /* done by ov519_set_mode/fr() */ | ||
3711 | case SEN_OV7670: | ||
3442 | write_regvals(sd, mode_init_519_ov7670, | 3712 | write_regvals(sd, mode_init_519_ov7670, |
3443 | ARRAY_SIZE(mode_init_519_ov7670)); | 3713 | ARRAY_SIZE(mode_init_519_ov7670)); |
3714 | break; | ||
3444 | } | 3715 | } |
3445 | 3716 | ||
3446 | reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4); | 3717 | reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4); |
@@ -3682,6 +3953,7 @@ static void mode_init_ov_sensor_regs(struct sd *sd) | |||
3682 | i2c_w(sd, 0x11, sd->clockdiv); | 3953 | i2c_w(sd, 0x11, sd->clockdiv); |
3683 | } | 3954 | } |
3684 | 3955 | ||
3956 | /* this function works for bridge ov519 and sensors ov7660 and ov7670 only */ | ||
3685 | static void sethvflip(struct gspca_dev *gspca_dev) | 3957 | static void sethvflip(struct gspca_dev *gspca_dev) |
3686 | { | 3958 | { |
3687 | struct sd *sd = (struct sd *) gspca_dev; | 3959 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -3703,11 +3975,18 @@ static void set_ov_sensor_window(struct sd *sd) | |||
3703 | int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; | 3975 | int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; |
3704 | 3976 | ||
3705 | /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ | 3977 | /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ |
3706 | if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610 || | 3978 | switch (sd->sensor) { |
3707 | sd->sensor == SEN_OV7670) { | 3979 | case SEN_OV2610: |
3980 | case SEN_OV3610: | ||
3981 | case SEN_OV7670: | ||
3708 | mode_init_ov_sensor_regs(sd); | 3982 | mode_init_ov_sensor_regs(sd); |
3709 | return; | 3983 | return; |
3984 | case SEN_OV7660: | ||
3985 | ov519_set_mode(sd); | ||
3986 | ov519_set_fr(sd); | ||
3987 | return; | ||
3710 | } | 3988 | } |
3989 | |||
3711 | gspca_dev = &sd->gspca_dev; | 3990 | gspca_dev = &sd->gspca_dev; |
3712 | qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; | 3991 | qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1; |
3713 | crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2; | 3992 | crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2; |
@@ -4101,6 +4380,22 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
4101 | { | 4380 | { |
4102 | struct sd *sd = (struct sd *) gspca_dev; | 4381 | struct sd *sd = (struct sd *) gspca_dev; |
4103 | int val; | 4382 | int val; |
4383 | static const struct ov_i2c_regvals brit_7660[][7] = { | ||
4384 | {{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90}, | ||
4385 | {0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}}, | ||
4386 | {{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1}, | ||
4387 | {0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}}, | ||
4388 | {{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2}, | ||
4389 | {0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}}, | ||
4390 | {{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3}, | ||
4391 | {0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}}, | ||
4392 | {{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3}, | ||
4393 | {0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}}, | ||
4394 | {{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3}, | ||
4395 | {0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}}, | ||
4396 | {{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4}, | ||
4397 | {0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}} | ||
4398 | }; | ||
4104 | 4399 | ||
4105 | val = sd->ctrls[BRIGHTNESS].val; | 4400 | val = sd->ctrls[BRIGHTNESS].val; |
4106 | switch (sd->sensor) { | 4401 | switch (sd->sensor) { |
@@ -4120,6 +4415,10 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
4120 | if (!sd->ctrls[AUTOBRIGHT].val) | 4415 | if (!sd->ctrls[AUTOBRIGHT].val) |
4121 | i2c_w(sd, OV7610_REG_BRT, val); | 4416 | i2c_w(sd, OV7610_REG_BRT, val); |
4122 | break; | 4417 | break; |
4418 | case SEN_OV7660: | ||
4419 | write_i2c_regvals(sd, brit_7660[val], | ||
4420 | ARRAY_SIZE(brit_7660[0])); | ||
4421 | break; | ||
4123 | case SEN_OV7670: | 4422 | case SEN_OV7670: |
4124 | /*win trace | 4423 | /*win trace |
4125 | * i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */ | 4424 | * i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */ |
@@ -4132,6 +4431,64 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
4132 | { | 4431 | { |
4133 | struct sd *sd = (struct sd *) gspca_dev; | 4432 | struct sd *sd = (struct sd *) gspca_dev; |
4134 | int val; | 4433 | int val; |
4434 | static const struct ov_i2c_regvals contrast_7660[][31] = { | ||
4435 | {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0}, | ||
4436 | {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30}, | ||
4437 | {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24}, | ||
4438 | {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34}, | ||
4439 | {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65}, | ||
4440 | {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83}, | ||
4441 | {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f}, | ||
4442 | {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}}, | ||
4443 | {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94}, | ||
4444 | {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30}, | ||
4445 | {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24}, | ||
4446 | {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31}, | ||
4447 | {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62}, | ||
4448 | {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81}, | ||
4449 | {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1}, | ||
4450 | {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}}, | ||
4451 | {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84}, | ||
4452 | {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40}, | ||
4453 | {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24}, | ||
4454 | {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34}, | ||
4455 | {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d}, | ||
4456 | {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81}, | ||
4457 | {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e}, | ||
4458 | {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}}, | ||
4459 | {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70}, | ||
4460 | {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48}, | ||
4461 | {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34}, | ||
4462 | {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22}, | ||
4463 | {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58}, | ||
4464 | {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80}, | ||
4465 | {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9}, | ||
4466 | {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}}, | ||
4467 | {{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80}, | ||
4468 | {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60}, | ||
4469 | {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38}, | ||
4470 | {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e}, | ||
4471 | {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46}, | ||
4472 | {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c}, | ||
4473 | {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4}, | ||
4474 | {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}}, | ||
4475 | {{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80}, | ||
4476 | {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30}, | ||
4477 | {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50}, | ||
4478 | {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08}, | ||
4479 | {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a}, | ||
4480 | {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b}, | ||
4481 | {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3}, | ||
4482 | {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}}, | ||
4483 | {{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60}, | ||
4484 | {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8}, | ||
4485 | {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c}, | ||
4486 | {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04}, | ||
4487 | {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22}, | ||
4488 | {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b}, | ||
4489 | {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde}, | ||
4490 | {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}}, | ||
4491 | }; | ||
4135 | 4492 | ||
4136 | val = sd->ctrls[CONTRAST].val; | 4493 | val = sd->ctrls[CONTRAST].val; |
4137 | switch (sd->sensor) { | 4494 | switch (sd->sensor) { |
@@ -4163,6 +4520,10 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
4163 | i2c_w(sd, 0x64, ctab[val >> 4]); | 4520 | i2c_w(sd, 0x64, ctab[val >> 4]); |
4164 | break; | 4521 | break; |
4165 | } | 4522 | } |
4523 | case SEN_OV7660: | ||
4524 | write_i2c_regvals(sd, contrast_7660[val], | ||
4525 | ARRAY_SIZE(contrast_7660[0])); | ||
4526 | break; | ||
4166 | case SEN_OV7670: | 4527 | case SEN_OV7670: |
4167 | /* check that this isn't just the same as ov7610 */ | 4528 | /* check that this isn't just the same as ov7610 */ |
4168 | i2c_w(sd, OV7670_R56_CONTRAS, val >> 1); | 4529 | i2c_w(sd, OV7670_R56_CONTRAS, val >> 1); |
@@ -4174,6 +4535,18 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
4174 | { | 4535 | { |
4175 | struct sd *sd = (struct sd *) gspca_dev; | 4536 | struct sd *sd = (struct sd *) gspca_dev; |
4176 | int val; | 4537 | int val; |
4538 | static const struct ov_i2c_regvals colors_7660[][6] = { | ||
4539 | {{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a}, | ||
4540 | {0x53, 0x19}, {0x54, 0x23}}, | ||
4541 | {{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11}, | ||
4542 | {0x53, 0x2c}, {0x54, 0x3e}}, | ||
4543 | {{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19}, | ||
4544 | {0x53, 0x40}, {0x54, 0x59}}, | ||
4545 | {{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20}, | ||
4546 | {0x53, 0x53}, {0x54, 0x73}}, | ||
4547 | {{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28}, | ||
4548 | {0x53, 0x66}, {0x54, 0x8e}}, | ||
4549 | }; | ||
4177 | 4550 | ||
4178 | val = sd->ctrls[COLORS].val; | 4551 | val = sd->ctrls[COLORS].val; |
4179 | switch (sd->sensor) { | 4552 | switch (sd->sensor) { |
@@ -4197,6 +4570,10 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
4197 | case SEN_OV7648: | 4570 | case SEN_OV7648: |
4198 | i2c_w(sd, OV7610_REG_SAT, val & 0xf0); | 4571 | i2c_w(sd, OV7610_REG_SAT, val & 0xf0); |
4199 | break; | 4572 | break; |
4573 | case SEN_OV7660: | ||
4574 | write_i2c_regvals(sd, colors_7660[val], | ||
4575 | ARRAY_SIZE(colors_7660[0])); | ||
4576 | break; | ||
4200 | case SEN_OV7670: | 4577 | case SEN_OV7670: |
4201 | /* supported later once I work out how to do it | 4578 | /* supported later once I work out how to do it |
4202 | * transparently fail now! */ | 4579 | * transparently fail now! */ |
@@ -4214,7 +4591,8 @@ static void setautobright(struct gspca_dev *gspca_dev) | |||
4214 | 4591 | ||
4215 | static void setfreq_i(struct sd *sd) | 4592 | static void setfreq_i(struct sd *sd) |
4216 | { | 4593 | { |
4217 | if (sd->sensor == SEN_OV7670) { | 4594 | if (sd->sensor == SEN_OV7660 |
4595 | || sd->sensor == SEN_OV7670) { | ||
4218 | switch (sd->ctrls[FREQ].val) { | 4596 | switch (sd->ctrls[FREQ].val) { |
4219 | case 0: /* Banding filter disabled */ | 4597 | case 0: /* Banding filter disabled */ |
4220 | i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT); | 4598 | i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT); |