Commit 93627736 authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab

V4L/DVB (8868): gspca: Support for vga modes with sif sensors in sonixb.

- Add documentation for some known registers
- Add support for vga modes (320x240, 160x120) for sif sensors
- Remove F_RAW sensor flag raw mode should work on any sensor as its a bridge
   only thing and keeping the flag was becoming awkward.
- Fixup ov6650 and pas106 auto exposure window settings
Signed-off-by: default avatarHans de Goede <j.w.r.degoede@hhs.nl>
Signed-off-by: default avatarJean-Francois Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 5d8538c1
...@@ -20,6 +20,26 @@ ...@@ -20,6 +20,26 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
/* Some documentation on known sonixb registers:
Reg Use
0x10 high nibble red gain low nibble blue gain
0x11 low nibble green gain
0x12 hstart
0x13 vstart
0x15 hsize (hsize = register-value * 16)
0x16 vsize (vsize = register-value * 16)
0x17 bit 0 toggle compression quality (according to sn9c102 driver)
0x18 bit 7 enables compression, bit 4-5 set image down scaling:
00 scale 1, 01 scale 1/2, 10, scale 1/4
0x19 high-nibble is sensor clock divider, changes exposure on sensors which
use a clock generated by the bridge. Some sensors have their own clock.
0x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32)
0x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32)
0x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32)
0x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32)
*/
#define MODULE_NAME "sonixb" #define MODULE_NAME "sonixb"
#include "gspca.h" #include "gspca.h"
...@@ -74,10 +94,10 @@ struct sensor_data { ...@@ -74,10 +94,10 @@ struct sensor_data {
/* sensor_data flags */ /* sensor_data flags */
#define F_GAIN 0x01 /* has gain */ #define F_GAIN 0x01 /* has gain */
#define F_SIF 0x02 /* sif or vga */ #define F_SIF 0x02 /* sif or vga */
#define F_RAW 0x04 /* sensor tested ok with raw bayer mode */
/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
#define MODE_RAW 0x10 /* raw bayer mode */ #define MODE_RAW 0x10 /* raw bayer mode */
#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
/* ctrl_dis helper macros */ /* ctrl_dis helper macros */
#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)) #define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
...@@ -211,7 +231,7 @@ static struct ctrl sd_ctrls[] = { ...@@ -211,7 +231,7 @@ static struct ctrl sd_ctrls[] = {
static struct v4l2_pix_format vga_mode[] = { static struct v4l2_pix_format vga_mode[] = {
{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline = 160, .bytesperline = 160,
.sizeimage = 160 * 120, .sizeimage = 160 * 120 * 5 / 4,
.colorspace = V4L2_COLORSPACE_SRGB, .colorspace = V4L2_COLORSPACE_SRGB,
.priv = 2 | MODE_RAW}, .priv = 2 | MODE_RAW},
{160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
...@@ -231,9 +251,19 @@ static struct v4l2_pix_format vga_mode[] = { ...@@ -231,9 +251,19 @@ static struct v4l2_pix_format vga_mode[] = {
.priv = 0}, .priv = 0},
}; };
static struct v4l2_pix_format sif_mode[] = { static struct v4l2_pix_format sif_mode[] = {
{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline = 160,
.sizeimage = 160 * 120,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
{160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
.bytesperline = 160,
.sizeimage = 160 * 120 * 5 / 4,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1 | MODE_REDUCED_SIF},
{176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline = 176, .bytesperline = 176,
.sizeimage = 176 * 144, .sizeimage = 176 * 144 * 5 / 4,
.colorspace = V4L2_COLORSPACE_SRGB, .colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1 | MODE_RAW}, .priv = 1 | MODE_RAW},
{176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
...@@ -241,6 +271,11 @@ static struct v4l2_pix_format sif_mode[] = { ...@@ -241,6 +271,11 @@ static struct v4l2_pix_format sif_mode[] = {
.sizeimage = 176 * 144 * 5 / 4, .sizeimage = 176 * 144 * 5 / 4,
.colorspace = V4L2_COLORSPACE_SRGB, .colorspace = V4L2_COLORSPACE_SRGB,
.priv = 1}, .priv = 1},
{320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
.bytesperline = 320,
.sizeimage = 320 * 240 * 5 / 4,
.colorspace = V4L2_COLORSPACE_SRGB,
.priv = 0 | MODE_REDUCED_SIF},
{352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE, {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
.bytesperline = 352, .bytesperline = 352,
.sizeimage = 352 * 288 * 5 / 4, .sizeimage = 352 * 288 * 5 / 4,
...@@ -266,7 +301,7 @@ static const __u8 initOv6650[] = { ...@@ -266,7 +301,7 @@ static const __u8 initOv6650[] = {
0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b, 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
}; };
static const __u8 ov6650_sensor_init[][8] = static const __u8 ov6650_sensor_init[][8] =
{ {
...@@ -350,7 +385,7 @@ static const __u8 initPas106[] = { ...@@ -350,7 +385,7 @@ static const __u8 initPas106[] = {
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
0x16, 0x12, 0x24, COMP1, MCK_INIT1, 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
0x18, 0x10, 0x04, 0x03, 0x11, 0x0c 0x18, 0x10, 0x02, 0x02, 0x09, 0x07
}; };
/* compression 0x86 mckinit1 0x2b */ /* compression 0x86 mckinit1 0x2b */
static const __u8 pas106_sensor_init[][8] = { static const __u8 pas106_sensor_init[][8] = {
...@@ -456,15 +491,14 @@ static const __u8 tas5130_sensor_init[][8] = { ...@@ -456,15 +491,14 @@ static const __u8 tas5130_sensor_init[][8] = {
struct sensor_data sensor_data[] = { struct sensor_data sensor_data[] = {
SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF|F_RAW, 0, SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
0x60),
SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
F_GAIN, 0, 0x21), F_GAIN, 0, 0x21),
SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ, SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ,
0), 0),
SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_RAW, SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0,
NO_EXPO|NO_FREQ, 0), NO_EXPO|NO_FREQ, 0),
SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF|F_RAW, SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF,
NO_BRIGHTNESS|NO_FREQ, 0), NO_BRIGHTNESS|NO_FREQ, 0),
SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
0), 0),
...@@ -834,10 +868,6 @@ static int sd_config(struct gspca_dev *gspca_dev, ...@@ -834,10 +868,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->cam_mode = sif_mode; cam->cam_mode = sif_mode;
cam->nmodes = ARRAY_SIZE(sif_mode); cam->nmodes = ARRAY_SIZE(sif_mode);
} }
if (!(sensor_data[sd->sensor].flags & F_RAW)) {
cam->cam_mode++;
cam->nmodes--;
}
sd->brightness = BRIGHTNESS_DEF; sd->brightness = BRIGHTNESS_DEF;
sd->gain = GAIN_DEF; sd->gain = GAIN_DEF;
sd->exposure = EXPOSURE_DEF; sd->exposure = EXPOSURE_DEF;
...@@ -864,31 +894,39 @@ static int sd_init(struct gspca_dev *gspca_dev) ...@@ -864,31 +894,39 @@ static int sd_init(struct gspca_dev *gspca_dev)
static void sd_start(struct gspca_dev *gspca_dev) static void sd_start(struct gspca_dev *gspca_dev)
{ {
struct sd *sd = (struct sd *) gspca_dev; struct sd *sd = (struct sd *) gspca_dev;
struct cam *cam = &gspca_dev->cam;
int mode, l; int mode, l;
const __u8 *sn9c10x; const __u8 *sn9c10x;
__u8 reg17_19[3]; __u8 reg12_19[8];
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 0x07; mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge]; sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge];
l = sensor_data[sd->sensor].bridge_init_size[sd->bridge]; l = sensor_data[sd->sensor].bridge_init_size[sd->bridge];
reg17_19[0] = sn9c10x[0x17 - 1]; memcpy(reg12_19, &sn9c10x[0x12 - 1], 8);
reg17_19[1] = sn9c10x[0x18 - 1] | (mode << 4); reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
reg17_19[2] = sn9c10x[0x19 - 1];
/* Special cases where reg 17 and or 19 value depends on mode */ /* Special cases where reg 17 and or 19 value depends on mode */
switch (sd->sensor) { switch (sd->sensor) {
case SENSOR_PAS202: case SENSOR_PAS202:
reg17_19[0] = mode ? 0x24 : 0x20; reg12_19[5] = mode ? 0x24 : 0x20;
break; break;
case SENSOR_TAS5130CXX: case SENSOR_TAS5130CXX:
/* probably not mode specific at all most likely the upper /* probably not mode specific at all most likely the upper
nibble of 0x19 is exposure (clock divider) just as with nibble of 0x19 is exposure (clock divider) just as with
the tas5110, we need someone to test this. */ the tas5110, we need someone to test this. */
reg17_19[2] = mode ? 0x23 : 0x43; reg12_19[7] = mode ? 0x23 : 0x43;
break; break;
} }
/* Disable compression when the raw bayer format has been selected */ /* Disable compression when the raw bayer format has been selected */
if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
reg17_19[1] &= ~0x80; reg12_19[6] &= ~0x80;
/* Vga mode emulation on SIF sensor? */
if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
reg12_19[0] += 16; /* 0x12: hstart adjust */
reg12_19[1] += 24; /* 0x13: vstart adjust */
reg12_19[3] = 320 / 16; /* 0x15: hsize */
reg12_19[4] = 240 / 16; /* 0x16: vsize */
}
/* reg 0x01 bit 2 video transfert on */ /* reg 0x01 bit 2 video transfert on */
reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1); reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
...@@ -907,24 +945,24 @@ static void sd_start(struct gspca_dev *gspca_dev) ...@@ -907,24 +945,24 @@ static void sd_start(struct gspca_dev *gspca_dev)
sd->bridge]); sd->bridge]);
/* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2); reg_w(gspca_dev, 0x15, &reg12_19[3], 2);
/* compression register */ /* compression register */
reg_w(gspca_dev, 0x18, &reg17_19[1], 1); reg_w(gspca_dev, 0x18, &reg12_19[6], 1);
/* H_start */ /* H_start */
reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1); reg_w(gspca_dev, 0x12, &reg12_19[0], 1);
/* V_START */ /* V_START */
reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1); reg_w(gspca_dev, 0x13, &reg12_19[1], 1);
/* reset 0x17 SensorClk enable inv Clk 0x60 */ /* reset 0x17 SensorClk enable inv Clk 0x60 */
/*fixme: ov7630 [17]=68 8f (+20 if 102)*/ /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
reg_w(gspca_dev, 0x17, &reg17_19[0], 1); reg_w(gspca_dev, 0x17, &reg12_19[5], 1);
/*MCKSIZE ->3 */ /*fixme: not ov7630*/ /*MCKSIZE ->3 */ /*fixme: not ov7630*/
reg_w(gspca_dev, 0x19, &reg17_19[2], 1); reg_w(gspca_dev, 0x19, &reg12_19[7], 1);
/* AE_STRX AE_STRY AE_ENDX AE_ENDY */ /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4); reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
/* Enable video transfert */ /* Enable video transfert */
reg_w(gspca_dev, 0x01, &sn9c10x[0], 1); reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
/* Compression */ /* Compression */
reg_w(gspca_dev, 0x18, &reg17_19[1], 2); reg_w(gspca_dev, 0x18, &reg12_19[6], 2);
msleep(20); msleep(20);
sd->reg11 = -1; sd->reg11 = -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment