aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/vpx3220.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/vpx3220.c')
-rw-r--r--drivers/media/video/vpx3220.c232
1 files changed, 115 insertions, 117 deletions
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 67aa0db4b81a..cd2064e7733b 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -27,6 +27,7 @@
27#include <media/v4l2-common.h> 27#include <media/v4l2-common.h>
28#include <media/v4l2-i2c-drv-legacy.h> 28#include <media/v4l2-i2c-drv-legacy.h>
29#include <linux/videodev.h> 29#include <linux/videodev.h>
30#include <linux/videodev2.h>
30#include <linux/video_decoder.h> 31#include <linux/video_decoder.h>
31 32
32MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver"); 33MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
@@ -44,7 +45,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
44struct vpx3220 { 45struct vpx3220 {
45 unsigned char reg[255]; 46 unsigned char reg[255];
46 47
47 int norm; 48 v4l2_std_id norm;
48 int input; 49 int input;
49 int enable; 50 int enable;
50 int bright; 51 int bright;
@@ -259,79 +260,41 @@ static const unsigned short init_fp[] = {
259 0x4b, 0x298, /* PLL gain */ 260 0x4b, 0x298, /* PLL gain */
260}; 261};
261 262
262static void vpx3220_dump_i2c(struct i2c_client *client)
263{
264 int len = sizeof(init_common);
265 const unsigned char *data = init_common;
266
267 while (len > 1) {
268 v4l_dbg(1, debug, client, "i2c reg 0x%02x data 0x%02x\n",
269 *data, vpx3220_read(client, *data));
270 data += 2;
271 len -= 2;
272 }
273}
274 263
275static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg) 264static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
276{ 265{
277 struct vpx3220 *decoder = i2c_get_clientdata(client); 266 struct vpx3220 *decoder = i2c_get_clientdata(client);
278 267
279 switch (cmd) { 268 switch (cmd) {
280 case 0: 269 case VIDIOC_INT_INIT:
281 { 270 {
282 vpx3220_write_block(client, init_common, 271 vpx3220_write_block(client, init_common,
283 sizeof(init_common)); 272 sizeof(init_common));
284 vpx3220_write_fp_block(client, init_fp, 273 vpx3220_write_fp_block(client, init_fp,
285 sizeof(init_fp) >> 1); 274 sizeof(init_fp) >> 1);
286 switch (decoder->norm) { 275 if (decoder->norm & V4L2_STD_NTSC) {
287 case VIDEO_MODE_NTSC:
288 vpx3220_write_fp_block(client, init_ntsc, 276 vpx3220_write_fp_block(client, init_ntsc,
289 sizeof(init_ntsc) >> 1); 277 sizeof(init_ntsc) >> 1);
290 break; 278 } else if (decoder->norm & V4L2_STD_PAL) {
291
292 case VIDEO_MODE_PAL:
293 vpx3220_write_fp_block(client, init_pal, 279 vpx3220_write_fp_block(client, init_pal,
294 sizeof(init_pal) >> 1); 280 sizeof(init_pal) >> 1);
295 break; 281 } else if (decoder->norm & V4L2_STD_SECAM) {
296 case VIDEO_MODE_SECAM:
297 vpx3220_write_fp_block(client, init_secam, 282 vpx3220_write_fp_block(client, init_secam,
298 sizeof(init_secam) >> 1); 283 sizeof(init_secam) >> 1);
299 break; 284 } else {
300 default:
301 vpx3220_write_fp_block(client, init_pal, 285 vpx3220_write_fp_block(client, init_pal,
302 sizeof(init_pal) >> 1); 286 sizeof(init_pal) >> 1);
303 break;
304 } 287 }
305 break; 288 break;
306 } 289 }
307 290
308 case DECODER_DUMP: 291 case VIDIOC_QUERYSTD:
309 { 292 case VIDIOC_INT_G_INPUT_STATUS:
310 vpx3220_dump_i2c(client);
311 break;
312 }
313
314 case DECODER_GET_CAPABILITIES:
315 {
316 struct video_decoder_capability *cap = arg;
317
318 v4l_dbg(1, debug, client, "DECODER_GET_CAPABILITIES\n");
319
320 cap->flags = VIDEO_DECODER_PAL |
321 VIDEO_DECODER_NTSC |
322 VIDEO_DECODER_SECAM |
323 VIDEO_DECODER_AUTO |
324 VIDEO_DECODER_CCIR;
325 cap->inputs = 3;
326 cap->outputs = 1;
327 break;
328 }
329
330 case DECODER_GET_STATUS:
331 { 293 {
332 int res = 0, status; 294 int res = V4L2_IN_ST_NO_SIGNAL, status;
295 v4l2_std_id std = 0;
333 296
334 v4l_dbg(1, debug, client, "DECODER_GET_STATUS\n"); 297 v4l_dbg(1, debug, client, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n");
335 298
336 status = vpx3220_fp_read(client, 0x0f3); 299 status = vpx3220_fp_read(client, 0x0f3);
337 300
@@ -341,35 +304,38 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
341 return status; 304 return status;
342 305
343 if ((status & 0x20) == 0) { 306 if ((status & 0x20) == 0) {
344 res |= DECODER_STATUS_GOOD | DECODER_STATUS_COLOR; 307 res = 0;
345 308
346 switch (status & 0x18) { 309 switch (status & 0x18) {
347 case 0x00: 310 case 0x00:
348 case 0x10: 311 case 0x10:
349 case 0x14: 312 case 0x14:
350 case 0x18: 313 case 0x18:
351 res |= DECODER_STATUS_PAL; 314 std = V4L2_STD_PAL;
352 break; 315 break;
353 316
354 case 0x08: 317 case 0x08:
355 res |= DECODER_STATUS_SECAM; 318 std = V4L2_STD_SECAM;
356 break; 319 break;
357 320
358 case 0x04: 321 case 0x04:
359 case 0x0c: 322 case 0x0c:
360 case 0x1c: 323 case 0x1c:
361 res |= DECODER_STATUS_NTSC; 324 std = V4L2_STD_NTSC;
362 break; 325 break;
363 } 326 }
364 } 327 }
365 328
366 *(int *) arg = res; 329 if (cmd == VIDIOC_QUERYSTD)
330 *(v4l2_std_id *)arg = std;
331 else
332 *(int *)arg = res;
367 break; 333 break;
368 } 334 }
369 335
370 case DECODER_SET_NORM: 336 case VIDIOC_S_STD:
371 { 337 {
372 int *iarg = arg, data; 338 v4l2_std_id *iarg = arg;
373 int temp_input; 339 int temp_input;
374 340
375 /* Here we back up the input selection because it gets 341 /* Here we back up the input selection because it gets
@@ -377,36 +343,23 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
377 choosen video norm */ 343 choosen video norm */
378 temp_input = vpx3220_fp_read(client, 0xf2); 344 temp_input = vpx3220_fp_read(client, 0xf2);
379 345
380 v4l_dbg(1, debug, client, "DECODER_SET_NORM %d\n", *iarg); 346 v4l_dbg(1, debug, client, "VIDIOC_S_STD %llx\n", *iarg);
381 switch (*iarg) { 347 if (*iarg & V4L2_STD_NTSC) {
382 case VIDEO_MODE_NTSC:
383 vpx3220_write_fp_block(client, init_ntsc, 348 vpx3220_write_fp_block(client, init_ntsc,
384 sizeof(init_ntsc) >> 1); 349 sizeof(init_ntsc) >> 1);
385 v4l_dbg(1, debug, client, "norm switched to NTSC\n"); 350 v4l_dbg(1, debug, client, "norm switched to NTSC\n");
386 break; 351 } else if (*iarg & V4L2_STD_PAL) {
387
388 case VIDEO_MODE_PAL:
389 vpx3220_write_fp_block(client, init_pal, 352 vpx3220_write_fp_block(client, init_pal,
390 sizeof(init_pal) >> 1); 353 sizeof(init_pal) >> 1);
391 v4l_dbg(1, debug, client, "norm switched to PAL\n"); 354 v4l_dbg(1, debug, client, "norm switched to PAL\n");
392 break; 355 } else if (*iarg & V4L2_STD_SECAM) {
393
394 case VIDEO_MODE_SECAM:
395 vpx3220_write_fp_block(client, init_secam, 356 vpx3220_write_fp_block(client, init_secam,
396 sizeof(init_secam) >> 1); 357 sizeof(init_secam) >> 1);
397 v4l_dbg(1, debug, client, "norm switched to SECAM\n"); 358 v4l_dbg(1, debug, client, "norm switched to SECAM\n");
398 break; 359 } else {
399
400 case VIDEO_MODE_AUTO:
401 /* FIXME This is only preliminary support */
402 data = vpx3220_fp_read(client, 0xf2) & 0x20;
403 vpx3220_fp_write(client, 0xf2, 0x00c0 | data);
404 v4l_dbg(1, debug, client, "norm switched to AUTO\n");
405 break;
406
407 default:
408 return -EINVAL; 360 return -EINVAL;
409 } 361 }
362
410 decoder->norm = *iarg; 363 decoder->norm = *iarg;
411 364
412 /* And here we set the backed up video input again */ 365 /* And here we set the backed up video input again */
@@ -415,9 +368,10 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
415 break; 368 break;
416 } 369 }
417 370
418 case DECODER_SET_INPUT: 371 case VIDIOC_INT_S_VIDEO_ROUTING:
419 { 372 {
420 int *iarg = arg, data; 373 struct v4l2_routing *route = arg;
374 int data;
421 375
422 /* RJ: *iarg = 0: ST8 (PCTV) input 376 /* RJ: *iarg = 0: ST8 (PCTV) input
423 *iarg = 1: COMPOSITE input 377 *iarg = 1: COMPOSITE input
@@ -429,73 +383,117 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
429 {0x0e, 1} 383 {0x0e, 1}
430 }; 384 };
431 385
432 if (*iarg < 0 || *iarg > 2) 386 if (route->input < 0 || route->input > 2)
433 return -EINVAL; 387 return -EINVAL;
434 388
435 v4l_dbg(1, debug, client, "input switched to %s\n", inputs[*iarg]); 389 v4l_dbg(1, debug, client, "input switched to %s\n", inputs[route->input]);
436 390
437 vpx3220_write(client, 0x33, input[*iarg][0]); 391 vpx3220_write(client, 0x33, input[route->input][0]);
438 392
439 data = vpx3220_fp_read(client, 0xf2) & ~(0x0020); 393 data = vpx3220_fp_read(client, 0xf2) & ~(0x0020);
440 if (data < 0) 394 if (data < 0)
441 return data; 395 return data;
442 /* 0x0010 is required to latch the setting */ 396 /* 0x0010 is required to latch the setting */
443 vpx3220_fp_write(client, 0xf2, 397 vpx3220_fp_write(client, 0xf2,
444 data | (input[*iarg][1] << 5) | 0x0010); 398 data | (input[route->input][1] << 5) | 0x0010);
445 399
446 udelay(10); 400 udelay(10);
447 break; 401 break;
448 } 402 }
449 403
450 case DECODER_SET_OUTPUT: 404 case VIDIOC_STREAMON:
405 case VIDIOC_STREAMOFF:
451 { 406 {
452 int *iarg = arg; 407 int on = cmd == VIDIOC_STREAMON;
408 v4l_dbg(1, debug, client, "VIDIOC_STREAM%s\n", on ? "ON" : "OFF");
453 409
454 /* not much choice of outputs */ 410 vpx3220_write(client, 0xf2, (on ? 0x1b : 0x00));
455 if (*iarg != 0) {
456 return -EINVAL;
457 }
458 break; 411 break;
459 } 412 }
460 413
461 case DECODER_ENABLE_OUTPUT: 414 case VIDIOC_QUERYCTRL:
462 { 415 {
463 int *iarg = arg; 416 struct v4l2_queryctrl *qc = arg;
464 417
465 v4l_dbg(1, debug, client, "DECODER_ENABLE_OUTPUT %d\n", *iarg); 418 switch (qc->id) {
419 case V4L2_CID_BRIGHTNESS:
420 v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
421 break;
422
423 case V4L2_CID_CONTRAST:
424 v4l2_ctrl_query_fill(qc, 0, 63, 1, 32);
425 break;
426
427 case V4L2_CID_SATURATION:
428 v4l2_ctrl_query_fill(qc, 0, 4095, 1, 2048);
429 break;
466 430
467 vpx3220_write(client, 0xf2, (*iarg ? 0x1b : 0x00)); 431 case V4L2_CID_HUE:
432 v4l2_ctrl_query_fill(qc, -512, 511, 1, 0);
433 break;
434
435 default:
436 return -EINVAL;
437 }
468 break; 438 break;
469 } 439 }
470 440
471 case DECODER_SET_PICTURE: 441 case VIDIOC_G_CTRL:
472 { 442 {
473 struct video_picture *pic = arg; 443 struct v4l2_control *ctrl = arg;
474 444
475 if (decoder->bright != pic->brightness) { 445 switch (ctrl->id) {
476 /* We want -128 to 128 we get 0-65535 */ 446 case V4L2_CID_BRIGHTNESS:
477 decoder->bright = pic->brightness; 447 ctrl->value = decoder->bright;
478 vpx3220_write(client, 0xe6, 448 break;
479 (decoder->bright - 32768) >> 8); 449 case V4L2_CID_CONTRAST:
480 } 450 ctrl->value = decoder->contrast;
481 if (decoder->contrast != pic->contrast) { 451 break;
482 /* We want 0 to 64 we get 0-65535 */ 452 case V4L2_CID_SATURATION:
483 /* Bit 7 and 8 is for noise shaping */ 453 ctrl->value = decoder->sat;
484 decoder->contrast = pic->contrast; 454 break;
485 vpx3220_write(client, 0xe7, 455 case V4L2_CID_HUE:
486 (decoder->contrast >> 10) + 192); 456 ctrl->value = decoder->hue;
487 } 457 break;
488 if (decoder->sat != pic->colour) { 458 default:
489 /* We want 0 to 4096 we get 0-65535 */ 459 return -EINVAL;
490 decoder->sat = pic->colour;
491 vpx3220_fp_write(client, 0xa0,
492 decoder->sat >> 4);
493 } 460 }
494 if (decoder->hue != pic->hue) { 461 break;
495 /* We want -512 to 512 we get 0-65535 */ 462 }
496 decoder->hue = pic->hue; 463
497 vpx3220_fp_write(client, 0x1c, 464 case VIDIOC_S_CTRL:
498 ((decoder->hue - 32768) >> 6) & 0xFFF); 465 {
466 struct v4l2_control *ctrl = arg;
467
468 switch (ctrl->id) {
469 case V4L2_CID_BRIGHTNESS:
470 if (decoder->bright != ctrl->value) {
471 decoder->bright = ctrl->value;
472 vpx3220_write(client, 0xe6, decoder->bright);
473 }
474 break;
475 case V4L2_CID_CONTRAST:
476 if (decoder->contrast != ctrl->value) {
477 /* Bit 7 and 8 is for noise shaping */
478 decoder->contrast = ctrl->value;
479 vpx3220_write(client, 0xe7,
480 decoder->contrast + 192);
481 }
482 break;
483 case V4L2_CID_SATURATION:
484 if (decoder->sat != ctrl->value) {
485 decoder->sat = ctrl->value;
486 vpx3220_fp_write(client, 0xa0, decoder->sat);
487 }
488 break;
489 case V4L2_CID_HUE:
490 if (decoder->hue != ctrl->value) {
491 decoder->hue = ctrl->value;
492 vpx3220_fp_write(client, 0x1c, decoder->hue);
493 }
494 break;
495 default:
496 return -EINVAL;
499 } 497 }
500 break; 498 break;
501 } 499 }
@@ -541,7 +539,7 @@ static int vpx3220_probe(struct i2c_client *client,
541 decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL); 539 decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL);
542 if (decoder == NULL) 540 if (decoder == NULL)
543 return -ENOMEM; 541 return -ENOMEM;
544 decoder->norm = VIDEO_MODE_PAL; 542 decoder->norm = V4L2_STD_PAL;
545 decoder->input = 0; 543 decoder->input = 0;
546 decoder->enable = 1; 544 decoder->enable = 1;
547 decoder->bright = 32768; 545 decoder->bright = 32768;