Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sn9c102_hv7131d.c
Go to the documentation of this file.
1 /***************************************************************************
2  * Plug-in for HV7131D image sensor connected to the SN9C1xx PC Camera *
3  * Controllers *
4  * *
5  * Copyright (C) 2004-2007 by Luca Risolia <[email protected]> *
6  * *
7  * This program is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program; if not, write to the Free Software *
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
20  ***************************************************************************/
21 
22 #include "sn9c102_sensor.h"
23 #include "sn9c102_devtable.h"
24 
25 
26 static int hv7131d_init(struct sn9c102_device* cam)
27 {
28  int err;
29 
30  err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
31  {0x00, 0x14}, {0x60, 0x17},
32  {0x0e, 0x18}, {0xf2, 0x19});
33 
34  err += sn9c102_i2c_write(cam, 0x01, 0x04);
35  err += sn9c102_i2c_write(cam, 0x02, 0x00);
36  err += sn9c102_i2c_write(cam, 0x28, 0x00);
37 
38  return err;
39 }
40 
41 
42 static int hv7131d_get_ctrl(struct sn9c102_device* cam,
43  struct v4l2_control* ctrl)
44 {
45  switch (ctrl->id) {
46  case V4L2_CID_EXPOSURE:
47  {
48  int r1 = sn9c102_i2c_read(cam, 0x26),
49  r2 = sn9c102_i2c_read(cam, 0x27);
50  if (r1 < 0 || r2 < 0)
51  return -EIO;
52  ctrl->value = (r1 << 8) | (r2 & 0xff);
53  }
54  return 0;
56  if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0)
57  return -EIO;
58  ctrl->value = 0x3f - (ctrl->value & 0x3f);
59  return 0;
61  if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0)
62  return -EIO;
63  ctrl->value = 0x3f - (ctrl->value & 0x3f);
64  return 0;
66  if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0)
67  return -EIO;
68  ctrl->value = 0x3f - (ctrl->value & 0x3f);
69  return 0;
71  if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0)
72  return -EIO;
73  ctrl->value &= 0x3f;
74  return 0;
76  if ((ctrl->value = sn9c102_i2c_read(cam, 0x34)) < 0)
77  return -EIO;
78  ctrl->value &= 0x07;
79  return 0;
80  default:
81  return -EINVAL;
82  }
83 }
84 
85 
86 static int hv7131d_set_ctrl(struct sn9c102_device* cam,
87  const struct v4l2_control* ctrl)
88 {
89  int err = 0;
90 
91  switch (ctrl->id) {
92  case V4L2_CID_EXPOSURE:
93  err += sn9c102_i2c_write(cam, 0x26, ctrl->value >> 8);
94  err += sn9c102_i2c_write(cam, 0x27, ctrl->value & 0xff);
95  break;
97  err += sn9c102_i2c_write(cam, 0x31, 0x3f - ctrl->value);
98  break;
100  err += sn9c102_i2c_write(cam, 0x33, 0x3f - ctrl->value);
101  break;
103  err += sn9c102_i2c_write(cam, 0x32, 0x3f - ctrl->value);
104  break;
106  err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
107  break;
109  err += sn9c102_i2c_write(cam, 0x34, ctrl->value);
110  break;
111  default:
112  return -EINVAL;
113  }
114 
115  return err ? -EIO : 0;
116 }
117 
118 
119 static int hv7131d_set_crop(struct sn9c102_device* cam,
120  const struct v4l2_rect* rect)
121 {
122  struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
123  int err = 0;
124  u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2,
125  v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
126 
127  err += sn9c102_write_reg(cam, h_start, 0x12);
128  err += sn9c102_write_reg(cam, v_start, 0x13);
129 
130  return err;
131 }
132 
133 
134 static int hv7131d_set_pix_format(struct sn9c102_device* cam,
135  const struct v4l2_pix_format* pix)
136 {
137  int err = 0;
138 
139  if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
140  err += sn9c102_write_reg(cam, 0x42, 0x19);
141  else
142  err += sn9c102_write_reg(cam, 0xf2, 0x19);
143 
144  return err;
145 }
146 
147 
148 static const struct sn9c102_sensor hv7131d = {
149  .name = "HV7131D",
150  .maintainer = "Luca Risolia <[email protected]>",
151  .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
152  .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
153  .frequency = SN9C102_I2C_100KHZ,
154  .interface = SN9C102_I2C_2WIRES,
155  .i2c_slave_id = 0x11,
156  .init = &hv7131d_init,
157  .qctrl = {
158  {
159  .id = V4L2_CID_EXPOSURE,
160  .type = V4L2_CTRL_TYPE_INTEGER,
161  .name = "exposure",
162  .minimum = 0x0250,
163  .maximum = 0xffff,
164  .step = 0x0001,
165  .default_value = 0x0250,
166  .flags = 0,
167  },
168  {
169  .id = V4L2_CID_RED_BALANCE,
170  .type = V4L2_CTRL_TYPE_INTEGER,
171  .name = "red balance",
172  .minimum = 0x00,
173  .maximum = 0x3f,
174  .step = 0x01,
175  .default_value = 0x00,
176  .flags = 0,
177  },
178  {
179  .id = V4L2_CID_BLUE_BALANCE,
180  .type = V4L2_CTRL_TYPE_INTEGER,
181  .name = "blue balance",
182  .minimum = 0x00,
183  .maximum = 0x3f,
184  .step = 0x01,
185  .default_value = 0x20,
186  .flags = 0,
187  },
188  {
190  .type = V4L2_CTRL_TYPE_INTEGER,
191  .name = "green balance",
192  .minimum = 0x00,
193  .maximum = 0x3f,
194  .step = 0x01,
195  .default_value = 0x1e,
196  .flags = 0,
197  },
198  {
200  .type = V4L2_CTRL_TYPE_INTEGER,
201  .name = "reset level",
202  .minimum = 0x19,
203  .maximum = 0x3f,
204  .step = 0x01,
205  .default_value = 0x30,
206  .flags = 0,
207  },
208  {
210  .type = V4L2_CTRL_TYPE_INTEGER,
211  .name = "pixel bias voltage",
212  .minimum = 0x00,
213  .maximum = 0x07,
214  .step = 0x01,
215  .default_value = 0x02,
216  .flags = 0,
217  },
218  },
219  .get_ctrl = &hv7131d_get_ctrl,
220  .set_ctrl = &hv7131d_set_ctrl,
221  .cropcap = {
222  .bounds = {
223  .left = 0,
224  .top = 0,
225  .width = 640,
226  .height = 480,
227  },
228  .defrect = {
229  .left = 0,
230  .top = 0,
231  .width = 640,
232  .height = 480,
233  },
234  },
235  .set_crop = &hv7131d_set_crop,
236  .pix_format = {
237  .width = 640,
238  .height = 480,
239  .pixelformat = V4L2_PIX_FMT_SBGGR8,
240  .priv = 8,
241  },
242  .set_pix_format = &hv7131d_set_pix_format
243 };
244 
245 
247 {
248  int r0 = 0, r1 = 0, err;
249 
250  err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
251  {0x28, 0x17});
252 
253  r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00);
254  r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01);
255  if (err || r0 < 0 || r1 < 0)
256  return -EIO;
257 
258  if ((r0 != 0x00 && r0 != 0x01) || r1 != 0x04)
259  return -ENODEV;
260 
261  sn9c102_attach_sensor(cam, &hv7131d);
262 
263  return 0;
264 }