1 /* OmniVision OV76BE Camera Chip Support Code
3 * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org>
4 * http://alpha.dyndns.org/ov511/
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
14 #include <linux/slab.h>
15 #include "ovcamchip_priv.h"
17 /* OV7610 registers: Since the OV76BE is undocumented, we'll settle for these
19 #define REG_GAIN 0x00 /* gain [5:0] */
20 #define REG_BLUE 0x01 /* blue channel balance */
21 #define REG_RED 0x02 /* red channel balance */
22 #define REG_SAT 0x03 /* saturation */
23 #define REG_CNT 0x05 /* Y contrast */
24 #define REG_BRT 0x06 /* Y brightness */
25 #define REG_BLUE_BIAS 0x0C /* blue channel bias [5:0] */
26 #define REG_RED_BIAS 0x0D /* red channel bias [5:0] */
27 #define REG_GAMMA_COEFF 0x0E /* gamma settings */
28 #define REG_WB_RANGE 0x0F /* AEC/ALC/S-AWB settings */
29 #define REG_EXP 0x10 /* manual exposure setting */
30 #define REG_CLOCK 0x11 /* polarity/clock prescaler */
31 #define REG_FIELD_DIVIDE 0x16 /* field interval/mode settings */
32 #define REG_HWIN_START 0x17 /* horizontal window start */
33 #define REG_HWIN_END 0x18 /* horizontal window end */
34 #define REG_VWIN_START 0x19 /* vertical window start */
35 #define REG_VWIN_END 0x1A /* vertical window end */
36 #define REG_PIXEL_SHIFT 0x1B /* pixel shift */
37 #define REG_YOFFSET 0x21 /* Y channel offset */
38 #define REG_UOFFSET 0x22 /* U channel offset */
39 #define REG_ECW 0x24 /* exposure white level for AEC */
40 #define REG_ECB 0x25 /* exposure black level for AEC */
41 #define REG_FRAMERATE_H 0x2A /* frame rate MSB + misc */
42 #define REG_FRAMERATE_L 0x2B /* frame rate LSB */
43 #define REG_ALC 0x2C /* Auto Level Control settings */
44 #define REG_VOFFSET 0x2E /* V channel offset adjustment */
45 #define REG_ARRAY_BIAS 0x2F /* array bias -- don't change */
46 #define REG_YGAMMA 0x33 /* misc gamma settings [7:6] */
47 #define REG_BIAS_ADJUST 0x34 /* misc bias settings */
49 /* Window parameters */
62 /* NOTE: These are the same as the 7x10 settings, but should eventually be
63 * optimized for the OV76BE */
64 static struct ovcamchip_regvals regvals_init_76be[] = {
71 { 0x28, 0x24 }, /* 0c */
72 { 0x0f, 0x85 }, /* lg's setting */
92 { 0xff, 0xff }, /* END MARKER */
95 /* This initializes the OV76be camera chip and relevant variables. */
96 static int ov76be_init(struct i2c_client *c)
98 struct ovcamchip *ov = i2c_get_clientdata(c);
102 DDEBUG(4, &c->dev, "entered");
104 rc = ov_write_regvals(c, regvals_init_76be);
108 ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL);
118 static int ov76be_free(struct i2c_client *c)
120 struct ovcamchip *ov = i2c_get_clientdata(c);
126 static int ov76be_set_control(struct i2c_client *c,
127 struct ovcamchip_control *ctl)
129 struct ovcamchip *ov = i2c_get_clientdata(c);
130 struct ov76be *s = ov->spriv;
135 case OVCAMCHIP_CID_BRIGHT:
136 rc = ov_write(c, REG_BRT, v >> 8);
138 case OVCAMCHIP_CID_SAT:
139 rc = ov_write(c, REG_SAT, v >> 8);
141 case OVCAMCHIP_CID_EXP:
142 rc = ov_write(c, REG_EXP, v);
144 case OVCAMCHIP_CID_FREQ:
146 int sixty = (v == 60);
148 rc = ov_write_mask(c, 0x2a, sixty?0x00:0x80, 0x80);
152 rc = ov_write(c, 0x2b, sixty?0x00:0xac);
156 rc = ov_write_mask(c, 0x76, 0x01, 0x01);
159 case OVCAMCHIP_CID_BANDFILT:
160 rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04);
163 case OVCAMCHIP_CID_AUTOBRIGHT:
164 rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10);
167 case OVCAMCHIP_CID_AUTOEXP:
168 rc = ov_write_mask(c, 0x13, v?0x01:0x00, 0x01);
171 case OVCAMCHIP_CID_MIRROR:
172 rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40);
176 DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
181 DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc);
185 static int ov76be_get_control(struct i2c_client *c,
186 struct ovcamchip_control *ctl)
188 struct ovcamchip *ov = i2c_get_clientdata(c);
189 struct ov76be *s = ov->spriv;
191 unsigned char val = 0;
194 case OVCAMCHIP_CID_BRIGHT:
195 rc = ov_read(c, REG_BRT, &val);
196 ctl->value = val << 8;
198 case OVCAMCHIP_CID_SAT:
199 rc = ov_read(c, REG_SAT, &val);
200 ctl->value = val << 8;
202 case OVCAMCHIP_CID_EXP:
203 rc = ov_read(c, REG_EXP, &val);
206 case OVCAMCHIP_CID_BANDFILT:
207 ctl->value = s->bandfilt;
209 case OVCAMCHIP_CID_AUTOBRIGHT:
210 ctl->value = s->auto_brt;
212 case OVCAMCHIP_CID_AUTOEXP:
213 ctl->value = s->auto_exp;
215 case OVCAMCHIP_CID_MIRROR:
216 ctl->value = s->mirror;
219 DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
223 DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc);
227 static int ov76be_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
229 int qvga = win->quarter;
231 /******** QVGA-specific regs ********/
233 ov_write(c, 0x14, qvga?0xa4:0x84);
235 /******** Palette-specific regs ********/
237 if (win->format == VIDEO_PALETTE_GREY) {
238 ov_write_mask(c, 0x0e, 0x40, 0x40);
239 ov_write_mask(c, 0x13, 0x20, 0x20);
241 ov_write_mask(c, 0x0e, 0x00, 0x40);
242 ov_write_mask(c, 0x13, 0x00, 0x20);
245 /******** Clock programming ********/
247 ov_write(c, 0x11, win->clockdiv);
249 /******** Resolution-specific ********/
251 if (win->width == 640 && win->height == 480)
252 ov_write(c, 0x35, 0x9e);
254 ov_write(c, 0x35, 0x1e);
259 static int ov76be_set_window(struct i2c_client *c, struct ovcamchip_window *win)
261 int ret, hwscale, vwscale;
263 ret = ov76be_mode_init(c, win);
275 ov_write(c, 0x17, HWSBASE + (win->x >> hwscale));
276 ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale));
277 ov_write(c, 0x19, VWSBASE + (win->y >> vwscale));
278 ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale));
283 static int ov76be_command(struct i2c_client *c, unsigned int cmd, void *arg)
286 case OVCAMCHIP_CMD_S_CTRL:
287 return ov76be_set_control(c, arg);
288 case OVCAMCHIP_CMD_G_CTRL:
289 return ov76be_get_control(c, arg);
290 case OVCAMCHIP_CMD_S_MODE:
291 return ov76be_set_window(c, arg);
293 DDEBUG(2, &c->dev, "command not supported: %d", cmd);
298 struct ovcamchip_ops ov76be_ops = {
301 .command = ov76be_command,