aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/indycam.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/indycam.c')
-rw-r--r--drivers/media/video/indycam.c128
1 files changed, 71 insertions, 57 deletions
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c
index 54099e303c8d..eb5078c07a33 100644
--- a/drivers/media/video/indycam.c
+++ b/drivers/media/video/indycam.c
@@ -22,7 +22,8 @@
22/* IndyCam decodes stream of photons into digital image representation ;-) */ 22/* IndyCam decodes stream of photons into digital image representation ;-) */
23#include <linux/videodev2.h> 23#include <linux/videodev2.h>
24#include <linux/i2c.h> 24#include <linux/i2c.h>
25#include <media/v4l2-common.h> 25#include <media/v4l2-device.h>
26#include <media/v4l2-chip-ident.h>
26#include <media/v4l2-i2c-drv-legacy.h> 27#include <media/v4l2-i2c-drv-legacy.h>
27 28
28#include "indycam.h" 29#include "indycam.h"
@@ -49,10 +50,15 @@ I2C_CLIENT_INSMOD;
49#endif 50#endif
50 51
51struct indycam { 52struct indycam {
52 struct i2c_client *client; 53 struct v4l2_subdev sd;
53 u8 version; 54 u8 version;
54}; 55};
55 56
57static inline struct indycam *to_indycam(struct v4l2_subdev *sd)
58{
59 return container_of(sd, struct indycam, sd);
60}
61
56static const u8 initseq[] = { 62static const u8 initseq[] = {
57 INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ 63 INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */
58 INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */ 64 INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */
@@ -66,8 +72,9 @@ static const u8 initseq[] = {
66 72
67/* IndyCam register handling */ 73/* IndyCam register handling */
68 74
69static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value) 75static int indycam_read_reg(struct v4l2_subdev *sd, u8 reg, u8 *value)
70{ 76{
77 struct i2c_client *client = v4l2_get_subdevdata(sd);
71 int ret; 78 int ret;
72 79
73 if (reg == INDYCAM_REG_RESET) { 80 if (reg == INDYCAM_REG_RESET) {
@@ -90,12 +97,12 @@ static int indycam_read_reg(struct i2c_client *client, u8 reg, u8 *value)
90 return 0; 97 return 0;
91} 98}
92 99
93static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value) 100static int indycam_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
94{ 101{
102 struct i2c_client *client = v4l2_get_subdevdata(sd);
95 int err; 103 int err;
96 104
97 if ((reg == INDYCAM_REG_BRIGHTNESS) 105 if (reg == INDYCAM_REG_BRIGHTNESS || reg == INDYCAM_REG_VERSION) {
98 || (reg == INDYCAM_REG_VERSION)) {
99 dprintk("indycam_write_reg(): " 106 dprintk("indycam_write_reg(): "
100 "skipping read-only register %d\n", reg); 107 "skipping read-only register %d\n", reg);
101 return 0; 108 return 0;
@@ -111,13 +118,13 @@ static int indycam_write_reg(struct i2c_client *client, u8 reg, u8 value)
111 return err; 118 return err;
112} 119}
113 120
114static int indycam_write_block(struct i2c_client *client, u8 reg, 121static int indycam_write_block(struct v4l2_subdev *sd, u8 reg,
115 u8 length, u8 *data) 122 u8 length, u8 *data)
116{ 123{
117 int i, err; 124 int i, err;
118 125
119 for (i = 0; i < length; i++) { 126 for (i = 0; i < length; i++) {
120 err = indycam_write_reg(client, reg + i, data[i]); 127 err = indycam_write_reg(sd, reg + i, data[i]);
121 if (err) 128 if (err)
122 return err; 129 return err;
123 } 130 }
@@ -128,29 +135,28 @@ static int indycam_write_block(struct i2c_client *client, u8 reg,
128/* Helper functions */ 135/* Helper functions */
129 136
130#ifdef INDYCAM_DEBUG 137#ifdef INDYCAM_DEBUG
131static void indycam_regdump_debug(struct i2c_client *client) 138static void indycam_regdump_debug(struct v4l2_subdev *sd)
132{ 139{
133 int i; 140 int i;
134 u8 val; 141 u8 val;
135 142
136 for (i = 0; i < 9; i++) { 143 for (i = 0; i < 9; i++) {
137 indycam_read_reg(client, i, &val); 144 indycam_read_reg(sd, i, &val);
138 dprintk("Reg %d = 0x%02x\n", i, val); 145 dprintk("Reg %d = 0x%02x\n", i, val);
139 } 146 }
140} 147}
141#endif 148#endif
142 149
143static int indycam_get_control(struct i2c_client *client, 150static int indycam_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
144 struct v4l2_control *ctrl)
145{ 151{
146 struct indycam *camera = i2c_get_clientdata(client); 152 struct indycam *camera = to_indycam(sd);
147 u8 reg; 153 u8 reg;
148 int ret = 0; 154 int ret = 0;
149 155
150 switch (ctrl->id) { 156 switch (ctrl->id) {
151 case V4L2_CID_AUTOGAIN: 157 case V4L2_CID_AUTOGAIN:
152 case V4L2_CID_AUTO_WHITE_BALANCE: 158 case V4L2_CID_AUTO_WHITE_BALANCE:
153 ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, &reg); 159 ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, &reg);
154 if (ret) 160 if (ret)
155 return -EIO; 161 return -EIO;
156 if (ctrl->id == V4L2_CID_AUTOGAIN) 162 if (ctrl->id == V4L2_CID_AUTOGAIN)
@@ -161,38 +167,38 @@ static int indycam_get_control(struct i2c_client *client,
161 ? 1 : 0; 167 ? 1 : 0;
162 break; 168 break;
163 case V4L2_CID_EXPOSURE: 169 case V4L2_CID_EXPOSURE:
164 ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, &reg); 170 ret = indycam_read_reg(sd, INDYCAM_REG_SHUTTER, &reg);
165 if (ret) 171 if (ret)
166 return -EIO; 172 return -EIO;
167 ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1); 173 ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1);
168 break; 174 break;
169 case V4L2_CID_GAIN: 175 case V4L2_CID_GAIN:
170 ret = indycam_read_reg(client, INDYCAM_REG_GAIN, &reg); 176 ret = indycam_read_reg(sd, INDYCAM_REG_GAIN, &reg);
171 if (ret) 177 if (ret)
172 return -EIO; 178 return -EIO;
173 ctrl->value = (s32)reg; 179 ctrl->value = (s32)reg;
174 break; 180 break;
175 case V4L2_CID_RED_BALANCE: 181 case V4L2_CID_RED_BALANCE:
176 ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, &reg); 182 ret = indycam_read_reg(sd, INDYCAM_REG_RED_BALANCE, &reg);
177 if (ret) 183 if (ret)
178 return -EIO; 184 return -EIO;
179 ctrl->value = (s32)reg; 185 ctrl->value = (s32)reg;
180 break; 186 break;
181 case V4L2_CID_BLUE_BALANCE: 187 case V4L2_CID_BLUE_BALANCE:
182 ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, &reg); 188 ret = indycam_read_reg(sd, INDYCAM_REG_BLUE_BALANCE, &reg);
183 if (ret) 189 if (ret)
184 return -EIO; 190 return -EIO;
185 ctrl->value = (s32)reg; 191 ctrl->value = (s32)reg;
186 break; 192 break;
187 case INDYCAM_CONTROL_RED_SATURATION: 193 case INDYCAM_CONTROL_RED_SATURATION:
188 ret = indycam_read_reg(client, 194 ret = indycam_read_reg(sd,
189 INDYCAM_REG_RED_SATURATION, &reg); 195 INDYCAM_REG_RED_SATURATION, &reg);
190 if (ret) 196 if (ret)
191 return -EIO; 197 return -EIO;
192 ctrl->value = (s32)reg; 198 ctrl->value = (s32)reg;
193 break; 199 break;
194 case INDYCAM_CONTROL_BLUE_SATURATION: 200 case INDYCAM_CONTROL_BLUE_SATURATION:
195 ret = indycam_read_reg(client, 201 ret = indycam_read_reg(sd,
196 INDYCAM_REG_BLUE_SATURATION, &reg); 202 INDYCAM_REG_BLUE_SATURATION, &reg);
197 if (ret) 203 if (ret)
198 return -EIO; 204 return -EIO;
@@ -200,7 +206,7 @@ static int indycam_get_control(struct i2c_client *client,
200 break; 206 break;
201 case V4L2_CID_GAMMA: 207 case V4L2_CID_GAMMA:
202 if (camera->version == CAMERA_VERSION_MOOSE) { 208 if (camera->version == CAMERA_VERSION_MOOSE) {
203 ret = indycam_read_reg(client, 209 ret = indycam_read_reg(sd,
204 INDYCAM_REG_GAMMA, &reg); 210 INDYCAM_REG_GAMMA, &reg);
205 if (ret) 211 if (ret)
206 return -EIO; 212 return -EIO;
@@ -216,17 +222,16 @@ static int indycam_get_control(struct i2c_client *client,
216 return ret; 222 return ret;
217} 223}
218 224
219static int indycam_set_control(struct i2c_client *client, 225static int indycam_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
220 struct v4l2_control *ctrl)
221{ 226{
222 struct indycam *camera = i2c_get_clientdata(client); 227 struct indycam *camera = to_indycam(sd);
223 u8 reg; 228 u8 reg;
224 int ret = 0; 229 int ret = 0;
225 230
226 switch (ctrl->id) { 231 switch (ctrl->id) {
227 case V4L2_CID_AUTOGAIN: 232 case V4L2_CID_AUTOGAIN:
228 case V4L2_CID_AUTO_WHITE_BALANCE: 233 case V4L2_CID_AUTO_WHITE_BALANCE:
229 ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, &reg); 234 ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, &reg);
230 if (ret) 235 if (ret)
231 break; 236 break;
232 237
@@ -242,34 +247,34 @@ static int indycam_set_control(struct i2c_client *client,
242 reg &= ~INDYCAM_CONTROL_AWBCTL; 247 reg &= ~INDYCAM_CONTROL_AWBCTL;
243 } 248 }
244 249
245 ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg); 250 ret = indycam_write_reg(sd, INDYCAM_REG_CONTROL, reg);
246 break; 251 break;
247 case V4L2_CID_EXPOSURE: 252 case V4L2_CID_EXPOSURE:
248 reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1); 253 reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1);
249 ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg); 254 ret = indycam_write_reg(sd, INDYCAM_REG_SHUTTER, reg);
250 break; 255 break;
251 case V4L2_CID_GAIN: 256 case V4L2_CID_GAIN:
252 ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value); 257 ret = indycam_write_reg(sd, INDYCAM_REG_GAIN, ctrl->value);
253 break; 258 break;
254 case V4L2_CID_RED_BALANCE: 259 case V4L2_CID_RED_BALANCE:
255 ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE, 260 ret = indycam_write_reg(sd, INDYCAM_REG_RED_BALANCE,
256 ctrl->value); 261 ctrl->value);
257 break; 262 break;
258 case V4L2_CID_BLUE_BALANCE: 263 case V4L2_CID_BLUE_BALANCE:
259 ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE, 264 ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_BALANCE,
260 ctrl->value); 265 ctrl->value);
261 break; 266 break;
262 case INDYCAM_CONTROL_RED_SATURATION: 267 case INDYCAM_CONTROL_RED_SATURATION:
263 ret = indycam_write_reg(client, INDYCAM_REG_RED_SATURATION, 268 ret = indycam_write_reg(sd, INDYCAM_REG_RED_SATURATION,
264 ctrl->value); 269 ctrl->value);
265 break; 270 break;
266 case INDYCAM_CONTROL_BLUE_SATURATION: 271 case INDYCAM_CONTROL_BLUE_SATURATION:
267 ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION, 272 ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_SATURATION,
268 ctrl->value); 273 ctrl->value);
269 break; 274 break;
270 case V4L2_CID_GAMMA: 275 case V4L2_CID_GAMMA:
271 if (camera->version == CAMERA_VERSION_MOOSE) { 276 if (camera->version == CAMERA_VERSION_MOOSE) {
272 ret = indycam_write_reg(client, INDYCAM_REG_GAMMA, 277 ret = indycam_write_reg(sd, INDYCAM_REG_GAMMA,
273 ctrl->value); 278 ctrl->value);
274 } 279 }
275 break; 280 break;
@@ -282,30 +287,39 @@ static int indycam_set_control(struct i2c_client *client,
282 287
283/* I2C-interface */ 288/* I2C-interface */
284 289
285static int indycam_command(struct i2c_client *client, unsigned int cmd, 290static int indycam_g_chip_ident(struct v4l2_subdev *sd,
286 void *arg) 291 struct v4l2_dbg_chip_ident *chip)
287{ 292{
288 /* The old video_decoder interface just isn't enough, 293 struct i2c_client *client = v4l2_get_subdevdata(sd);
289 * so we'll use some custom commands. */ 294 struct indycam *camera = to_indycam(sd);
290 switch (cmd) {
291 case VIDIOC_G_CTRL:
292 return indycam_get_control(client, arg);
293
294 case VIDIOC_S_CTRL:
295 return indycam_set_control(client, arg);
296 295
297 default: 296 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_INDYCAM,
298 return -EINVAL; 297 camera->version);
299 } 298}
300 299
301 return 0; 300static int indycam_command(struct i2c_client *client, unsigned cmd, void *arg)
301{
302 return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
302} 303}
303 304
305/* ----------------------------------------------------------------------- */
306
307static const struct v4l2_subdev_core_ops indycam_core_ops = {
308 .g_chip_ident = indycam_g_chip_ident,
309 .g_ctrl = indycam_g_ctrl,
310 .s_ctrl = indycam_s_ctrl,
311};
312
313static const struct v4l2_subdev_ops indycam_ops = {
314 .core = &indycam_core_ops,
315};
316
304static int indycam_probe(struct i2c_client *client, 317static int indycam_probe(struct i2c_client *client,
305 const struct i2c_device_id *id) 318 const struct i2c_device_id *id)
306{ 319{
307 int err = 0; 320 int err = 0;
308 struct indycam *camera; 321 struct indycam *camera;
322 struct v4l2_subdev *sd;
309 323
310 v4l_info(client, "chip found @ 0x%x (%s)\n", 324 v4l_info(client, "chip found @ 0x%x (%s)\n",
311 client->addr << 1, client->adapter->name); 325 client->addr << 1, client->adapter->name);
@@ -314,9 +328,8 @@ static int indycam_probe(struct i2c_client *client,
314 if (!camera) 328 if (!camera)
315 return -ENOMEM; 329 return -ENOMEM;
316 330
317 i2c_set_clientdata(client, camera); 331 sd = &camera->sd;
318 332 v4l2_i2c_subdev_init(sd, client, &indycam_ops);
319 camera->client = client;
320 333
321 camera->version = i2c_smbus_read_byte_data(client, 334 camera->version = i2c_smbus_read_byte_data(client,
322 INDYCAM_REG_VERSION); 335 INDYCAM_REG_VERSION);
@@ -330,20 +343,20 @@ static int indycam_probe(struct i2c_client *client,
330 INDYCAM_VERSION_MAJOR(camera->version), 343 INDYCAM_VERSION_MAJOR(camera->version),
331 INDYCAM_VERSION_MINOR(camera->version)); 344 INDYCAM_VERSION_MINOR(camera->version));
332 345
333 indycam_regdump(client); 346 indycam_regdump(sd);
334 347
335 // initialize 348 // initialize
336 err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq); 349 err = indycam_write_block(sd, 0, sizeof(initseq), (u8 *)&initseq);
337 if (err) { 350 if (err) {
338 printk(KERN_ERR "IndyCam initialization failed\n"); 351 printk(KERN_ERR "IndyCam initialization failed\n");
339 kfree(camera); 352 kfree(camera);
340 return -EIO; 353 return -EIO;
341 } 354 }
342 355
343 indycam_regdump(client); 356 indycam_regdump(sd);
344 357
345 // white balance 358 // white balance
346 err = indycam_write_reg(client, INDYCAM_REG_CONTROL, 359 err = indycam_write_reg(sd, INDYCAM_REG_CONTROL,
347 INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); 360 INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL);
348 if (err) { 361 if (err) {
349 printk(KERN_ERR "IndyCam: White balancing camera failed\n"); 362 printk(KERN_ERR "IndyCam: White balancing camera failed\n");
@@ -351,7 +364,7 @@ static int indycam_probe(struct i2c_client *client,
351 return -EIO; 364 return -EIO;
352 } 365 }
353 366
354 indycam_regdump(client); 367 indycam_regdump(sd);
355 368
356 printk(KERN_INFO "IndyCam initialized\n"); 369 printk(KERN_INFO "IndyCam initialized\n");
357 370
@@ -360,9 +373,10 @@ static int indycam_probe(struct i2c_client *client,
360 373
361static int indycam_remove(struct i2c_client *client) 374static int indycam_remove(struct i2c_client *client)
362{ 375{
363 struct indycam *camera = i2c_get_clientdata(client); 376 struct v4l2_subdev *sd = i2c_get_clientdata(client);
364 377
365 kfree(camera); 378 v4l2_device_unregister_subdev(sd);
379 kfree(to_indycam(sd));
366 return 0; 380 return 0;
367} 381}
368 382