aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/indycam.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2009-02-27 07:05:10 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:43:10 -0400
commitcf4e9484f402c799fa25c9ffb7e9a3b620a3702d (patch)
tree5f7839009c8a66f4c1b5eaaf2c3c7365b515564d /drivers/media/video/indycam.c
parentbabb7dc7776dd6ded4e1e6cb7acc34c25c0eb521 (diff)
V4L/DVB (10861): vino/indycam/saa7191: convert to i2c modules to V4L2.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/indycam.c')
-rw-r--r--drivers/media/video/indycam.c234
1 files changed, 76 insertions, 158 deletions
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c
index 84b9e4f2b3b3..54099e303c8d 100644
--- a/drivers/media/video/indycam.c
+++ b/drivers/media/video/indycam.c
@@ -19,10 +19,11 @@
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21 21
22#include <linux/videodev.h>
23/* IndyCam decodes stream of photons into digital image representation ;-) */ 22/* IndyCam decodes stream of photons into digital image representation ;-) */
24#include <linux/video_decoder.h> 23#include <linux/videodev2.h>
25#include <linux/i2c.h> 24#include <linux/i2c.h>
25#include <media/v4l2-common.h>
26#include <media/v4l2-i2c-drv-legacy.h>
26 27
27#include "indycam.h" 28#include "indycam.h"
28 29
@@ -33,6 +34,10 @@ MODULE_VERSION(INDYCAM_MODULE_VERSION);
33MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); 34MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
34MODULE_LICENSE("GPL"); 35MODULE_LICENSE("GPL");
35 36
37static unsigned short normal_i2c[] = { 0x56 >> 1, I2C_CLIENT_END };
38
39I2C_CLIENT_INSMOD;
40
36// #define INDYCAM_DEBUG 41// #define INDYCAM_DEBUG
37 42
38#ifdef INDYCAM_DEBUG 43#ifdef INDYCAM_DEBUG
@@ -48,8 +53,6 @@ struct indycam {
48 u8 version; 53 u8 version;
49}; 54};
50 55
51static struct i2c_driver i2c_driver_indycam;
52
53static const u8 initseq[] = { 56static const u8 initseq[] = {
54 INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ 57 INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */
55 INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */ 58 INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */
@@ -138,44 +141,44 @@ static void indycam_regdump_debug(struct i2c_client *client)
138#endif 141#endif
139 142
140static int indycam_get_control(struct i2c_client *client, 143static int indycam_get_control(struct i2c_client *client,
141 struct indycam_control *ctrl) 144 struct v4l2_control *ctrl)
142{ 145{
143 struct indycam *camera = i2c_get_clientdata(client); 146 struct indycam *camera = i2c_get_clientdata(client);
144 u8 reg; 147 u8 reg;
145 int ret = 0; 148 int ret = 0;
146 149
147 switch (ctrl->type) { 150 switch (ctrl->id) {
148 case INDYCAM_CONTROL_AGC: 151 case V4L2_CID_AUTOGAIN:
149 case INDYCAM_CONTROL_AWB: 152 case V4L2_CID_AUTO_WHITE_BALANCE:
150 ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, &reg); 153 ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, &reg);
151 if (ret) 154 if (ret)
152 return -EIO; 155 return -EIO;
153 if (ctrl->type == INDYCAM_CONTROL_AGC) 156 if (ctrl->id == V4L2_CID_AUTOGAIN)
154 ctrl->value = (reg & INDYCAM_CONTROL_AGCENA) 157 ctrl->value = (reg & INDYCAM_CONTROL_AGCENA)
155 ? 1 : 0; 158 ? 1 : 0;
156 else 159 else
157 ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL) 160 ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL)
158 ? 1 : 0; 161 ? 1 : 0;
159 break; 162 break;
160 case INDYCAM_CONTROL_SHUTTER: 163 case V4L2_CID_EXPOSURE:
161 ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, &reg); 164 ret = indycam_read_reg(client, INDYCAM_REG_SHUTTER, &reg);
162 if (ret) 165 if (ret)
163 return -EIO; 166 return -EIO;
164 ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1); 167 ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1);
165 break; 168 break;
166 case INDYCAM_CONTROL_GAIN: 169 case V4L2_CID_GAIN:
167 ret = indycam_read_reg(client, INDYCAM_REG_GAIN, &reg); 170 ret = indycam_read_reg(client, INDYCAM_REG_GAIN, &reg);
168 if (ret) 171 if (ret)
169 return -EIO; 172 return -EIO;
170 ctrl->value = (s32)reg; 173 ctrl->value = (s32)reg;
171 break; 174 break;
172 case INDYCAM_CONTROL_RED_BALANCE: 175 case V4L2_CID_RED_BALANCE:
173 ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, &reg); 176 ret = indycam_read_reg(client, INDYCAM_REG_RED_BALANCE, &reg);
174 if (ret) 177 if (ret)
175 return -EIO; 178 return -EIO;
176 ctrl->value = (s32)reg; 179 ctrl->value = (s32)reg;
177 break; 180 break;
178 case INDYCAM_CONTROL_BLUE_BALANCE: 181 case V4L2_CID_BLUE_BALANCE:
179 ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, &reg); 182 ret = indycam_read_reg(client, INDYCAM_REG_BLUE_BALANCE, &reg);
180 if (ret) 183 if (ret)
181 return -EIO; 184 return -EIO;
@@ -195,7 +198,7 @@ static int indycam_get_control(struct i2c_client *client,
195 return -EIO; 198 return -EIO;
196 ctrl->value = (s32)reg; 199 ctrl->value = (s32)reg;
197 break; 200 break;
198 case INDYCAM_CONTROL_GAMMA: 201 case V4L2_CID_GAMMA:
199 if (camera->version == CAMERA_VERSION_MOOSE) { 202 if (camera->version == CAMERA_VERSION_MOOSE) {
200 ret = indycam_read_reg(client, 203 ret = indycam_read_reg(client,
201 INDYCAM_REG_GAMMA, &reg); 204 INDYCAM_REG_GAMMA, &reg);
@@ -214,20 +217,20 @@ static int indycam_get_control(struct i2c_client *client,
214} 217}
215 218
216static int indycam_set_control(struct i2c_client *client, 219static int indycam_set_control(struct i2c_client *client,
217 struct indycam_control *ctrl) 220 struct v4l2_control *ctrl)
218{ 221{
219 struct indycam *camera = i2c_get_clientdata(client); 222 struct indycam *camera = i2c_get_clientdata(client);
220 u8 reg; 223 u8 reg;
221 int ret = 0; 224 int ret = 0;
222 225
223 switch (ctrl->type) { 226 switch (ctrl->id) {
224 case INDYCAM_CONTROL_AGC: 227 case V4L2_CID_AUTOGAIN:
225 case INDYCAM_CONTROL_AWB: 228 case V4L2_CID_AUTO_WHITE_BALANCE:
226 ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, &reg); 229 ret = indycam_read_reg(client, INDYCAM_REG_CONTROL, &reg);
227 if (ret) 230 if (ret)
228 break; 231 break;
229 232
230 if (ctrl->type == INDYCAM_CONTROL_AGC) { 233 if (ctrl->id == V4L2_CID_AUTOGAIN) {
231 if (ctrl->value) 234 if (ctrl->value)
232 reg |= INDYCAM_CONTROL_AGCENA; 235 reg |= INDYCAM_CONTROL_AGCENA;
233 else 236 else
@@ -241,18 +244,18 @@ static int indycam_set_control(struct i2c_client *client,
241 244
242 ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg); 245 ret = indycam_write_reg(client, INDYCAM_REG_CONTROL, reg);
243 break; 246 break;
244 case INDYCAM_CONTROL_SHUTTER: 247 case V4L2_CID_EXPOSURE:
245 reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1); 248 reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1);
246 ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg); 249 ret = indycam_write_reg(client, INDYCAM_REG_SHUTTER, reg);
247 break; 250 break;
248 case INDYCAM_CONTROL_GAIN: 251 case V4L2_CID_GAIN:
249 ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value); 252 ret = indycam_write_reg(client, INDYCAM_REG_GAIN, ctrl->value);
250 break; 253 break;
251 case INDYCAM_CONTROL_RED_BALANCE: 254 case V4L2_CID_RED_BALANCE:
252 ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE, 255 ret = indycam_write_reg(client, INDYCAM_REG_RED_BALANCE,
253 ctrl->value); 256 ctrl->value);
254 break; 257 break;
255 case INDYCAM_CONTROL_BLUE_BALANCE: 258 case V4L2_CID_BLUE_BALANCE:
256 ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE, 259 ret = indycam_write_reg(client, INDYCAM_REG_BLUE_BALANCE,
257 ctrl->value); 260 ctrl->value);
258 break; 261 break;
@@ -264,7 +267,7 @@ static int indycam_set_control(struct i2c_client *client,
264 ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION, 267 ret = indycam_write_reg(client, INDYCAM_REG_BLUE_SATURATION,
265 ctrl->value); 268 ctrl->value);
266 break; 269 break;
267 case INDYCAM_CONTROL_GAMMA: 270 case V4L2_CID_GAMMA:
268 if (camera->version == CAMERA_VERSION_MOOSE) { 271 if (camera->version == CAMERA_VERSION_MOOSE) {
269 ret = indycam_write_reg(client, INDYCAM_REG_GAMMA, 272 ret = indycam_write_reg(client, INDYCAM_REG_GAMMA,
270 ctrl->value); 273 ctrl->value);
@@ -279,44 +282,50 @@ static int indycam_set_control(struct i2c_client *client,
279 282
280/* I2C-interface */ 283/* I2C-interface */
281 284
282static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) 285static int indycam_command(struct i2c_client *client, unsigned int cmd,
286 void *arg)
287{
288 /* The old video_decoder interface just isn't enough,
289 * so we'll use some custom commands. */
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
297 default:
298 return -EINVAL;
299 }
300
301 return 0;
302}
303
304static int indycam_probe(struct i2c_client *client,
305 const struct i2c_device_id *id)
283{ 306{
284 int err = 0; 307 int err = 0;
285 struct indycam *camera; 308 struct indycam *camera;
286 struct i2c_client *client;
287 309
288 printk(KERN_INFO "SGI IndyCam driver version %s\n", 310 v4l_info(client, "chip found @ 0x%x (%s)\n",
289 INDYCAM_MODULE_VERSION); 311 client->addr << 1, client->adapter->name);
290 312
291 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
292 if (!client)
293 return -ENOMEM;
294 camera = kzalloc(sizeof(struct indycam), GFP_KERNEL); 313 camera = kzalloc(sizeof(struct indycam), GFP_KERNEL);
295 if (!camera) { 314 if (!camera)
296 err = -ENOMEM; 315 return -ENOMEM;
297 goto out_free_client;
298 }
299 316
300 client->addr = addr;
301 client->adapter = adap;
302 client->driver = &i2c_driver_indycam;
303 client->flags = 0;
304 strcpy(client->name, "IndyCam client");
305 i2c_set_clientdata(client, camera); 317 i2c_set_clientdata(client, camera);
306 318
307 camera->client = client; 319 camera->client = client;
308 320
309 err = i2c_attach_client(client);
310 if (err)
311 goto out_free_camera;
312
313 camera->version = i2c_smbus_read_byte_data(client, 321 camera->version = i2c_smbus_read_byte_data(client,
314 INDYCAM_REG_VERSION); 322 INDYCAM_REG_VERSION);
315 if (camera->version != CAMERA_VERSION_INDY && 323 if (camera->version != CAMERA_VERSION_INDY &&
316 camera->version != CAMERA_VERSION_MOOSE) { 324 camera->version != CAMERA_VERSION_MOOSE) {
317 err = -ENODEV; 325 kfree(camera);
318 goto out_detach_client; 326 return -ENODEV;
319 } 327 }
328
320 printk(KERN_INFO "IndyCam v%d.%d detected\n", 329 printk(KERN_INFO "IndyCam v%d.%d detected\n",
321 INDYCAM_VERSION_MAJOR(camera->version), 330 INDYCAM_VERSION_MAJOR(camera->version),
322 INDYCAM_VERSION_MINOR(camera->version)); 331 INDYCAM_VERSION_MINOR(camera->version));
@@ -327,8 +336,8 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
327 err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq); 336 err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq);
328 if (err) { 337 if (err) {
329 printk(KERN_ERR "IndyCam initialization failed\n"); 338 printk(KERN_ERR "IndyCam initialization failed\n");
330 err = -EIO; 339 kfree(camera);
331 goto out_detach_client; 340 return -EIO;
332 } 341 }
333 342
334 indycam_regdump(client); 343 indycam_regdump(client);
@@ -338,8 +347,8 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
338 INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); 347 INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL);
339 if (err) { 348 if (err) {
340 printk(KERN_ERR "IndyCam: White balancing camera failed\n"); 349 printk(KERN_ERR "IndyCam: White balancing camera failed\n");
341 err = -EIO; 350 kfree(camera);
342 goto out_detach_client; 351 return -EIO;
343 } 352 }
344 353
345 indycam_regdump(client); 354 indycam_regdump(client);
@@ -347,124 +356,33 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
347 printk(KERN_INFO "IndyCam initialized\n"); 356 printk(KERN_INFO "IndyCam initialized\n");
348 357
349 return 0; 358 return 0;
350
351out_detach_client:
352 i2c_detach_client(client);
353out_free_camera:
354 kfree(camera);
355out_free_client:
356 kfree(client);
357 return err;
358} 359}
359 360
360static int indycam_probe(struct i2c_adapter *adap) 361static int indycam_remove(struct i2c_client *client)
361{
362 /* Indy specific crap */
363 if (adap->id == I2C_HW_SGI_VINO)
364 return indycam_attach(adap, INDYCAM_ADDR, 0);
365 /* Feel free to add probe here :-) */
366 return -ENODEV;
367}
368
369static int indycam_detach(struct i2c_client *client)
370{ 362{
371 struct indycam *camera = i2c_get_clientdata(client); 363 struct indycam *camera = i2c_get_clientdata(client);
372 364
373 i2c_detach_client(client);
374 kfree(camera); 365 kfree(camera);
375 kfree(client);
376 return 0; 366 return 0;
377} 367}
378 368
379static int indycam_command(struct i2c_client *client, unsigned int cmd, 369static int indycam_legacy_probe(struct i2c_adapter *adapter)
380 void *arg)
381{ 370{
382 // struct indycam *camera = i2c_get_clientdata(client); 371 return adapter->id == I2C_HW_SGI_VINO;
383
384 /* The old video_decoder interface just isn't enough,
385 * so we'll use some custom commands. */
386 switch (cmd) {
387 case DECODER_GET_CAPABILITIES: {
388 struct video_decoder_capability *cap = arg;
389
390 cap->flags = VIDEO_DECODER_NTSC;
391 cap->inputs = 1;
392 cap->outputs = 1;
393 break;
394 }
395 case DECODER_GET_STATUS: {
396 int *iarg = arg;
397
398 *iarg = DECODER_STATUS_GOOD | DECODER_STATUS_NTSC |
399 DECODER_STATUS_COLOR;
400 break;
401 }
402 case DECODER_SET_NORM: {
403 int *iarg = arg;
404
405 switch (*iarg) {
406 case VIDEO_MODE_NTSC:
407 break;
408 default:
409 return -EINVAL;
410 }
411 break;
412 }
413 case DECODER_SET_INPUT: {
414 int *iarg = arg;
415
416 if (*iarg != 0)
417 return -EINVAL;
418 break;
419 }
420 case DECODER_SET_OUTPUT: {
421 int *iarg = arg;
422
423 if (*iarg != 0)
424 return -EINVAL;
425 break;
426 }
427 case DECODER_ENABLE_OUTPUT: {
428 /* Always enabled */
429 break;
430 }
431 case DECODER_SET_PICTURE: {
432 // struct video_picture *pic = arg;
433 /* TODO: convert values for indycam_set_controls() */
434 break;
435 }
436 case DECODER_INDYCAM_GET_CONTROL: {
437 return indycam_get_control(client, arg);
438 }
439 case DECODER_INDYCAM_SET_CONTROL: {
440 return indycam_set_control(client, arg);
441 }
442 default:
443 return -EINVAL;
444 }
445
446 return 0;
447} 372}
448 373
449static struct i2c_driver i2c_driver_indycam = { 374static const struct i2c_device_id indycam_id[] = {
450 .driver = { 375 { "indycam", 0 },
451 .name = "indycam", 376 { }
452 }, 377};
453 .id = I2C_DRIVERID_INDYCAM, 378MODULE_DEVICE_TABLE(i2c, indycam_id);
454 .attach_adapter = indycam_probe, 379
455 .detach_client = indycam_detach, 380static struct v4l2_i2c_driver_data v4l2_i2c_data = {
456 .command = indycam_command, 381 .name = "indycam",
382 .driverid = I2C_DRIVERID_INDYCAM,
383 .command = indycam_command,
384 .probe = indycam_probe,
385 .remove = indycam_remove,
386 .legacy_probe = indycam_legacy_probe,
387 .id_table = indycam_id,
457}; 388};
458
459static int __init indycam_init(void)
460{
461 return i2c_add_driver(&i2c_driver_indycam);
462}
463
464static void __exit indycam_exit(void)
465{
466 i2c_del_driver(&i2c_driver_indycam);
467}
468
469module_init(indycam_init);
470module_exit(indycam_exit);