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: Hans de Goede <j.w.r.degoede@hhs.nl> Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
5d8538c1c6
commit
9362773624
@ -20,6 +20,26 @@
|
||||
* 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"
|
||||
|
||||
#include "gspca.h"
|
||||
@ -74,10 +94,10 @@ struct sensor_data {
|
||||
/* sensor_data flags */
|
||||
#define F_GAIN 0x01 /* has gain */
|
||||
#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!) */
|
||||
#define MODE_RAW 0x10 /* raw bayer mode */
|
||||
#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
|
||||
|
||||
/* ctrl_dis helper macros */
|
||||
#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
|
||||
@ -211,7 +231,7 @@ static struct ctrl sd_ctrls[] = {
|
||||
static struct v4l2_pix_format vga_mode[] = {
|
||||
{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
|
||||
.bytesperline = 160,
|
||||
.sizeimage = 160 * 120,
|
||||
.sizeimage = 160 * 120 * 5 / 4,
|
||||
.colorspace = V4L2_COLORSPACE_SRGB,
|
||||
.priv = 2 | MODE_RAW},
|
||||
{160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
|
||||
@ -231,9 +251,19 @@ static struct v4l2_pix_format vga_mode[] = {
|
||||
.priv = 0},
|
||||
};
|
||||
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,
|
||||
.bytesperline = 176,
|
||||
.sizeimage = 176 * 144,
|
||||
.sizeimage = 176 * 144 * 5 / 4,
|
||||
.colorspace = V4L2_COLORSPACE_SRGB,
|
||||
.priv = 1 | MODE_RAW},
|
||||
{176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
|
||||
@ -241,6 +271,11 @@ static struct v4l2_pix_format sif_mode[] = {
|
||||
.sizeimage = 176 * 144 * 5 / 4,
|
||||
.colorspace = V4L2_COLORSPACE_SRGB,
|
||||
.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,
|
||||
.bytesperline = 352,
|
||||
.sizeimage = 352 * 288 * 5 / 4,
|
||||
@ -266,7 +301,7 @@ static const __u8 initOv6650[] = {
|
||||
0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
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] =
|
||||
{
|
||||
@ -350,7 +385,7 @@ static const __u8 initPas106[] = {
|
||||
0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
|
||||
0x16, 0x12, 0x24, COMP1, MCK_INIT1,
|
||||
0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
|
||||
0x18, 0x10, 0x02, 0x02, 0x09, 0x07
|
||||
};
|
||||
/* compression 0x86 mckinit1 0x2b */
|
||||
static const __u8 pas106_sensor_init[][8] = {
|
||||
@ -456,15 +491,14 @@ static const __u8 tas5130_sensor_init[][8] = {
|
||||
|
||||
struct sensor_data sensor_data[] = {
|
||||
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,
|
||||
0x60),
|
||||
SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
|
||||
SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
|
||||
F_GAIN, 0, 0x21),
|
||||
SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ,
|
||||
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),
|
||||
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),
|
||||
SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
|
||||
0),
|
||||
@ -834,10 +868,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
|
||||
cam->cam_mode = 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->gain = GAIN_DEF;
|
||||
sd->exposure = EXPOSURE_DEF;
|
||||
@ -864,31 +894,39 @@ static int sd_init(struct gspca_dev *gspca_dev)
|
||||
static void sd_start(struct gspca_dev *gspca_dev)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
struct cam *cam = &gspca_dev->cam;
|
||||
int mode, l;
|
||||
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];
|
||||
l = sensor_data[sd->sensor].bridge_init_size[sd->bridge];
|
||||
reg17_19[0] = sn9c10x[0x17 - 1];
|
||||
reg17_19[1] = sn9c10x[0x18 - 1] | (mode << 4);
|
||||
reg17_19[2] = sn9c10x[0x19 - 1];
|
||||
memcpy(reg12_19, &sn9c10x[0x12 - 1], 8);
|
||||
reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
|
||||
/* Special cases where reg 17 and or 19 value depends on mode */
|
||||
switch (sd->sensor) {
|
||||
case SENSOR_PAS202:
|
||||
reg17_19[0] = mode ? 0x24 : 0x20;
|
||||
reg12_19[5] = mode ? 0x24 : 0x20;
|
||||
break;
|
||||
case SENSOR_TAS5130CXX:
|
||||
/* probably not mode specific at all most likely the upper
|
||||
nibble of 0x19 is exposure (clock divider) just as with
|
||||
the tas5110, we need someone to test this. */
|
||||
reg17_19[2] = mode ? 0x23 : 0x43;
|
||||
reg12_19[7] = mode ? 0x23 : 0x43;
|
||||
break;
|
||||
}
|
||||
/* Disable compression when the raw bayer format has been selected */
|
||||
if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
|
||||
reg17_19[1] &= ~0x80;
|
||||
if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
|
||||
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_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
|
||||
@ -907,24 +945,24 @@ static void sd_start(struct gspca_dev *gspca_dev)
|
||||
sd->bridge]);
|
||||
|
||||
/* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
|
||||
reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
|
||||
reg_w(gspca_dev, 0x15, ®12_19[3], 2);
|
||||
/* compression register */
|
||||
reg_w(gspca_dev, 0x18, ®17_19[1], 1);
|
||||
reg_w(gspca_dev, 0x18, ®12_19[6], 1);
|
||||
/* H_start */
|
||||
reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
|
||||
reg_w(gspca_dev, 0x12, ®12_19[0], 1);
|
||||
/* V_START */
|
||||
reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
|
||||
reg_w(gspca_dev, 0x13, ®12_19[1], 1);
|
||||
/* reset 0x17 SensorClk enable inv Clk 0x60 */
|
||||
/*fixme: ov7630 [17]=68 8f (+20 if 102)*/
|
||||
reg_w(gspca_dev, 0x17, ®17_19[0], 1);
|
||||
reg_w(gspca_dev, 0x17, ®12_19[5], 1);
|
||||
/*MCKSIZE ->3 */ /*fixme: not ov7630*/
|
||||
reg_w(gspca_dev, 0x19, ®17_19[2], 1);
|
||||
reg_w(gspca_dev, 0x19, ®12_19[7], 1);
|
||||
/* AE_STRX AE_STRY AE_ENDX AE_ENDY */
|
||||
reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
|
||||
/* Enable video transfert */
|
||||
reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
|
||||
/* Compression */
|
||||
reg_w(gspca_dev, 0x18, ®17_19[1], 2);
|
||||
reg_w(gspca_dev, 0x18, ®12_19[6], 2);
|
||||
msleep(20);
|
||||
|
||||
sd->reg11 = -1;
|
||||
|
Loading…
Reference in New Issue
Block a user