Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 174102
b: refs/heads/master
c: b1784b3
h: refs/heads/master
v: v3
  • Loading branch information
Márton Németh authored and Mauro Carvalho Chehab committed Dec 5, 2009
1 parent 4229bb8 commit 1f32c98
Show file tree
Hide file tree
Showing 3 changed files with 208 additions and 110 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 67c98f72e132e191ff4db0ac7bd81ea94fa5c667
refs/heads/master: b1784b3377bdeaeb6b9d01e651ff07bd44fec0f4
155 changes: 102 additions & 53 deletions trunk/drivers/media/video/gspca/pac7302.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ static const __u8 page3_7302[] = {
0x00
};

static void reg_w_buf(struct gspca_dev *gspca_dev,
static int reg_w_buf(struct gspca_dev *gspca_dev,
__u8 index,
const char *buffer, int len)
{
Expand All @@ -349,10 +349,11 @@ static void reg_w_buf(struct gspca_dev *gspca_dev,
PDEBUG(D_ERR, "reg_w_buf(): "
"Failed to write registers to index 0x%x, error %i",
index, ret);
return ret;
}


static void reg_w(struct gspca_dev *gspca_dev,
static int reg_w(struct gspca_dev *gspca_dev,
__u8 index,
__u8 value)
{
Expand All @@ -369,23 +370,27 @@ static void reg_w(struct gspca_dev *gspca_dev,
PDEBUG(D_ERR, "reg_w(): "
"Failed to write register to index 0x%x, value 0x%x, error %i",
index, value, ret);
return ret;
}

static void reg_w_seq(struct gspca_dev *gspca_dev,
static int reg_w_seq(struct gspca_dev *gspca_dev,
const __u8 *seq, int len)
{
int ret = 0;
while (--len >= 0) {
reg_w(gspca_dev, seq[0], seq[1]);
if (0 <= ret)
ret = reg_w(gspca_dev, seq[0], seq[1]);
seq += 2;
}
return ret;
}

/* load the beginning of a page */
static void reg_w_page(struct gspca_dev *gspca_dev,
static int reg_w_page(struct gspca_dev *gspca_dev,
const __u8 *page, int len)
{
int index;
int ret;
int ret = 0;

for (index = 0; index < len; index++) {
if (page[index] == SKIP) /* skip this index */
Expand All @@ -397,52 +402,61 @@ static void reg_w_page(struct gspca_dev *gspca_dev,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, index, gspca_dev->usb_buf, 1,
500);
if (ret < 0)
if (ret < 0) {
PDEBUG(D_ERR, "reg_w_page(): "
"Failed to write register to index 0x%x, "
"value 0x%x, error %i",
index, page[index], ret);
break;
}
}
return ret;
}

/* output a variable sequence */
static void reg_w_var(struct gspca_dev *gspca_dev,
static int reg_w_var(struct gspca_dev *gspca_dev,
const __u8 *seq,
const __u8 *page3, unsigned int page3_len,
const __u8 *page4, unsigned int page4_len)
{
int index, len;
int ret = 0;

for (;;) {
index = *seq++;
len = *seq++;
switch (len) {
case END_OF_SEQUENCE:
return;
return ret;
case LOAD_PAGE4:
reg_w_page(gspca_dev, page4, page4_len);
ret = reg_w_page(gspca_dev, page4, page4_len);
break;
case LOAD_PAGE3:
reg_w_page(gspca_dev, page3, page3_len);
ret = reg_w_page(gspca_dev, page3, page3_len);
break;
default:
if (len > USB_BUF_SZ) {
PDEBUG(D_ERR|D_STREAM,
"Incorrect variable sequence");
return;
return -EINVAL;
}
while (len > 0) {
if (len < 8) {
reg_w_buf(gspca_dev, index, seq, len);
ret = reg_w_buf(gspca_dev,
index, seq, len);
if (ret < 0)
return ret;
seq += len;
break;
}
reg_w_buf(gspca_dev, index, seq, 8);
ret = reg_w_buf(gspca_dev, index, seq, 8);
seq += 8;
index += 8;
len -= 8;
}
}
if (ret < 0)
return ret;
}
/* not reached */
}
Expand Down Expand Up @@ -472,18 +486,19 @@ static int sd_config(struct gspca_dev *gspca_dev,
}

/* This function is used by pac7302 only */
static void setbrightcont(struct gspca_dev *gspca_dev)
static int setbrightcont(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int i, v;
int ret;
static const __u8 max[10] =
{0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
0xd4, 0xec};
static const __u8 delta[10] =
{0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
0x11, 0x0b};

reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
for (i = 0; i < 10; i++) {
v = max[i];
v += (sd->brightness - BRIGHTNESS_MAX)
Expand All @@ -493,47 +508,62 @@ static void setbrightcont(struct gspca_dev *gspca_dev)
v = 0;
else if (v > 0xff)
v = 0xff;
reg_w(gspca_dev, 0xa2 + i, v);
if (0 <= ret)
ret = reg_w(gspca_dev, 0xa2 + i, v);
}
reg_w(gspca_dev, 0xdc, 0x01);
if (0 <= ret)
ret = reg_w(gspca_dev, 0xdc, 0x01);
return ret;
}

/* This function is used by pac7302 only */
static void setcolors(struct gspca_dev *gspca_dev)
static int setcolors(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int i, v;
int ret;
static const int a[9] =
{217, -212, 0, -101, 170, -67, -38, -315, 355};
static const int b[9] =
{19, 106, 0, 19, 106, 1, 19, 106, 1};

reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
reg_w(gspca_dev, 0x11, 0x01);
reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
if (0 <= ret)
ret = reg_w(gspca_dev, 0x11, 0x01);
if (0 <= ret)
ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
for (i = 0; i < 9; i++) {
v = a[i] * sd->colors / COLOR_MAX + b[i];
reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
}
reg_w(gspca_dev, 0xdc, 0x01);
if (0 <= ret)
ret = reg_w(gspca_dev, 0xdc, 0x01);
PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
return ret;
}

static void setgain(struct gspca_dev *gspca_dev)
static int setgain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int ret;

reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
reg_w(gspca_dev, 0x10, sd->gain >> 3);
ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
if (0 <= ret)
ret = reg_w(gspca_dev, 0x10, sd->gain >> 3);

/* load registers to sensor (Bit 0, auto clear) */
reg_w(gspca_dev, 0x11, 0x01);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x11, 0x01);
return ret;
}

static void setexposure(struct gspca_dev *gspca_dev)
static int setexposure(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int ret;
__u8 reg;

/* register 2 of frame 3/4 contains the clock divider configuring the
Expand All @@ -549,47 +579,58 @@ static void setexposure(struct gspca_dev *gspca_dev)
the nearest multiple of 3, except when between 6 and 12? */
if (reg < 6 || reg > 12)
reg = ((reg + 1) / 3) * 3;
reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
reg_w(gspca_dev, 0x02, reg);
ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
if (0 <= ret)
ret = reg_w(gspca_dev, 0x02, reg);

/* load registers to sensor (Bit 0, auto clear) */
reg_w(gspca_dev, 0x11, 0x01);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x11, 0x01);
return ret;
}

static void sethvflip(struct gspca_dev *gspca_dev)
static int sethvflip(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int ret;
__u8 data;

reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00);
reg_w(gspca_dev, 0x21, data);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x21, data);
/* load registers to sensor (Bit 0, auto clear) */
reg_w(gspca_dev, 0x11, 0x01);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x11, 0x01);
return ret;
}

/* this function is called at probe and resume time for pac7302 */
static int sd_init(struct gspca_dev *gspca_dev)
{
reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);

return 0;
return reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
}

static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int ret = 0;

sd->sof_read = 0;

reg_w_var(gspca_dev, start_7302,
ret = reg_w_var(gspca_dev, start_7302,
page3_7302, sizeof(page3_7302),
NULL, 0);
setbrightcont(gspca_dev);
setcolors(gspca_dev);
setgain(gspca_dev);
setexposure(gspca_dev);
sethvflip(gspca_dev);
if (0 <= ret)
ret = setbrightcont(gspca_dev);
if (0 <= ret)
ret = setcolors(gspca_dev);
if (0 <= ret)
setgain(gspca_dev);
if (0 <= ret)
setexposure(gspca_dev);
if (0 <= ret)
sethvflip(gspca_dev);

/* only resolution 640x480 is supported for pac7302 */

Expand All @@ -598,26 +639,34 @@ static int sd_start(struct gspca_dev *gspca_dev)
atomic_set(&sd->avg_lum, -1);

/* start stream */
reg_w(gspca_dev, 0xff, 0x01);
reg_w(gspca_dev, 0x78, 0x01);
if (0 <= ret)
ret = reg_w(gspca_dev, 0xff, 0x01);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x78, 0x01);

return 0;
return ret;
}

static void sd_stopN(struct gspca_dev *gspca_dev)
{
int ret;

/* stop stream */
reg_w(gspca_dev, 0xff, 0x01);
reg_w(gspca_dev, 0x78, 0x00);
ret = reg_w(gspca_dev, 0xff, 0x01);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x78, 0x00);
}

/* called on streamoff with alt 0 and on disconnect for pac7302 */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
int ret;

if (!gspca_dev->present)
return;
reg_w(gspca_dev, 0xff, 0x01);
reg_w(gspca_dev, 0x78, 0x40);
ret = reg_w(gspca_dev, 0xff, 0x01);
if (0 <= ret)
ret = reg_w(gspca_dev, 0x78, 0x40);
}

/* Include pac common sof detection functions */
Expand Down
Loading

0 comments on commit 1f32c98

Please sign in to comment.