aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/ks0127.c646
-rw-r--r--include/media/v4l2-chip-ident.h5
2 files changed, 315 insertions, 336 deletions
diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c
index c97d55a43c07..9ae94484da64 100644
--- a/drivers/media/video/ks0127.c
+++ b/drivers/media/video/ks0127.c
@@ -39,8 +39,9 @@
39#include <linux/errno.h> 39#include <linux/errno.h>
40#include <linux/kernel.h> 40#include <linux/kernel.h>
41#include <linux/i2c.h> 41#include <linux/i2c.h>
42#include <linux/video_decoder.h> 42#include <linux/videodev2.h>
43#include <media/v4l2-common.h> 43#include <media/v4l2-device.h>
44#include <media/v4l2-chip-ident.h>
44#include <media/v4l2-i2c-drv-legacy.h> 45#include <media/v4l2-i2c-drv-legacy.h>
45#include "ks0127.h" 46#include "ks0127.h"
46 47
@@ -48,10 +49,17 @@ MODULE_DESCRIPTION("KS0127 video decoder driver");
48MODULE_AUTHOR("Ryan Drake"); 49MODULE_AUTHOR("Ryan Drake");
49MODULE_LICENSE("GPL"); 50MODULE_LICENSE("GPL");
50 51
51#define KS_TYPE_UNKNOWN 0 52/* Addresses to scan */
52#define KS_TYPE_0122S 1 53#define I2C_KS0127_ADDON 0xD8
53#define KS_TYPE_0127 2 54#define I2C_KS0127_ONBOARD 0xDA
54#define KS_TYPE_0127B 3 55
56static unsigned short normal_i2c[] = {
57 I2C_KS0127_ADDON >> 1,
58 I2C_KS0127_ONBOARD >> 1,
59 I2C_CLIENT_END
60};
61
62I2C_CLIENT_INSMOD;
55 63
56/* ks0127 control registers */ 64/* ks0127 control registers */
57#define KS_STAT 0x00 65#define KS_STAT 0x00
@@ -197,15 +205,17 @@ struct adjust {
197}; 205};
198 206
199struct ks0127 { 207struct ks0127 {
200 int format_width; 208 struct v4l2_subdev sd;
201 int format_height;
202 int cap_width;
203 int cap_height;
204 v4l2_std_id norm; 209 v4l2_std_id norm;
205 int ks_type; 210 int ident;
206 u8 regs[256]; 211 u8 regs[256];
207}; 212};
208 213
214static inline struct ks0127 *to_ks0127(struct v4l2_subdev *sd)
215{
216 return container_of(sd, struct ks0127, sd);
217}
218
209 219
210static int debug; /* insmod parameter */ 220static int debug; /* insmod parameter */
211 221
@@ -311,43 +321,45 @@ static void init_reg_defaults(void)
311 */ 321 */
312 322
313 323
314static u8 ks0127_read(struct i2c_client *c, u8 reg) 324static u8 ks0127_read(struct v4l2_subdev *sd, u8 reg)
315{ 325{
326 struct i2c_client *client = v4l2_get_subdevdata(sd);
316 char val = 0; 327 char val = 0;
317 struct i2c_msg msgs[] = { 328 struct i2c_msg msgs[] = {
318 { c->addr, 0, sizeof(reg), &reg }, 329 { client->addr, 0, sizeof(reg), &reg },
319 { c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val } 330 { client->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val }
320 }; 331 };
321 int ret; 332 int ret;
322 333
323 ret = i2c_transfer(c->adapter, msgs, ARRAY_SIZE(msgs)); 334 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
324 if (ret != ARRAY_SIZE(msgs)) 335 if (ret != ARRAY_SIZE(msgs))
325 v4l_dbg(1, debug, c, "read error\n"); 336 v4l2_dbg(1, debug, sd, "read error\n");
326 337
327 return val; 338 return val;
328} 339}
329 340
330 341
331static void ks0127_write(struct i2c_client *c, u8 reg, u8 val) 342static void ks0127_write(struct v4l2_subdev *sd, u8 reg, u8 val)
332{ 343{
333 struct ks0127 *ks = i2c_get_clientdata(c); 344 struct i2c_client *client = v4l2_get_subdevdata(sd);
345 struct ks0127 *ks = to_ks0127(sd);
334 char msg[] = { reg, val }; 346 char msg[] = { reg, val };
335 347
336 if (i2c_master_send(c, msg, sizeof(msg)) != sizeof(msg)) 348 if (i2c_master_send(client, msg, sizeof(msg)) != sizeof(msg))
337 v4l_dbg(1, debug, c, "write error\n"); 349 v4l2_dbg(1, debug, sd, "write error\n");
338 350
339 ks->regs[reg] = val; 351 ks->regs[reg] = val;
340} 352}
341 353
342 354
343/* generic bit-twiddling */ 355/* generic bit-twiddling */
344static void ks0127_and_or(struct i2c_client *client, u8 reg, u8 and_v, u8 or_v) 356static void ks0127_and_or(struct v4l2_subdev *sd, u8 reg, u8 and_v, u8 or_v)
345{ 357{
346 struct ks0127 *ks = i2c_get_clientdata(client); 358 struct ks0127 *ks = to_ks0127(sd);
347 359
348 u8 val = ks->regs[reg]; 360 u8 val = ks->regs[reg];
349 val = (val & and_v) | or_v; 361 val = (val & and_v) | or_v;
350 ks0127_write(client, reg, val); 362 ks0127_write(sd, reg, val);
351} 363}
352 364
353 365
@@ -355,391 +367,353 @@ static void ks0127_and_or(struct i2c_client *client, u8 reg, u8 and_v, u8 or_v)
355/**************************************************************************** 367/****************************************************************************
356* ks0127 private api 368* ks0127 private api
357****************************************************************************/ 369****************************************************************************/
358static void ks0127_reset(struct i2c_client *c) 370static void ks0127_init(struct v4l2_subdev *sd)
359{ 371{
360 struct ks0127 *ks = i2c_get_clientdata(c); 372 struct ks0127 *ks = to_ks0127(sd);
361 u8 *table = reg_defaults; 373 u8 *table = reg_defaults;
362 int i; 374 int i;
363 375
364 ks->ks_type = KS_TYPE_UNKNOWN; 376 ks->ident = V4L2_IDENT_KS0127;
365 377
366 v4l_dbg(1, debug, c, "reset\n"); 378 v4l2_dbg(1, debug, sd, "reset\n");
367 msleep(1); 379 msleep(1);
368 380
369 /* initialize all registers to known values */ 381 /* initialize all registers to known values */
370 /* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */ 382 /* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */
371 383
372 for (i = 1; i < 33; i++) 384 for (i = 1; i < 33; i++)
373 ks0127_write(c, i, table[i]); 385 ks0127_write(sd, i, table[i]);
374 386
375 for (i = 35; i < 40; i++) 387 for (i = 35; i < 40; i++)
376 ks0127_write(c, i, table[i]); 388 ks0127_write(sd, i, table[i]);
377 389
378 for (i = 41; i < 56; i++) 390 for (i = 41; i < 56; i++)
379 ks0127_write(c, i, table[i]); 391 ks0127_write(sd, i, table[i]);
380 392
381 for (i = 58; i < 64; i++) 393 for (i = 58; i < 64; i++)
382 ks0127_write(c, i, table[i]); 394 ks0127_write(sd, i, table[i]);
383 395
384 396
385 if ((ks0127_read(c, KS_STAT) & 0x80) == 0) { 397 if ((ks0127_read(sd, KS_STAT) & 0x80) == 0) {
386 ks->ks_type = KS_TYPE_0122S; 398 ks->ident = V4L2_IDENT_KS0122S;
387 v4l_dbg(1, debug, c, "ks0122s found\n"); 399 v4l2_dbg(1, debug, sd, "ks0122s found\n");
388 return; 400 return;
389 } 401 }
390 402
391 switch (ks0127_read(c, KS_CMDE) & 0x0f) { 403 switch (ks0127_read(sd, KS_CMDE) & 0x0f) {
392 case 0: 404 case 0:
393 ks->ks_type = KS_TYPE_0127; 405 v4l2_dbg(1, debug, sd, "ks0127 found\n");
394 v4l_dbg(1, debug, c, "ks0127 found\n");
395 break; 406 break;
396 407
397 case 9: 408 case 9:
398 ks->ks_type = KS_TYPE_0127B; 409 ks->ident = V4L2_IDENT_KS0127B;
399 v4l_dbg(1, debug, c, "ks0127B Revision A found\n"); 410 v4l2_dbg(1, debug, sd, "ks0127B Revision A found\n");
400 break; 411 break;
401 412
402 default: 413 default:
403 v4l_dbg(1, debug, c, "unknown revision\n"); 414 v4l2_dbg(1, debug, sd, "unknown revision\n");
404 break; 415 break;
405 } 416 }
406} 417}
407 418
408static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg) 419static int ks0127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
409{ 420{
410 struct ks0127 *ks = i2c_get_clientdata(c); 421 struct ks0127 *ks = to_ks0127(sd);
411 struct v4l2_routing *route = arg; 422
412 int *iarg = (int *)arg; 423 switch (route->input) {
413 v4l2_std_id *istd = arg; 424 case KS_INPUT_COMPOSITE_1:
414 int status; 425 case KS_INPUT_COMPOSITE_2:
415 426 case KS_INPUT_COMPOSITE_3:
416 if (!ks) 427 case KS_INPUT_COMPOSITE_4:
417 return -ENODEV; 428 case KS_INPUT_COMPOSITE_5:
418 429 case KS_INPUT_COMPOSITE_6:
419 switch (cmd) { 430 v4l2_dbg(1, debug, sd,
420 case VIDIOC_INT_INIT: 431 "VIDIOC_S_INPUT %d: Composite\n", route->input);
421 v4l_dbg(1, debug, c, "VIDIOC_INT_INIT\n"); 432 /* autodetect 50/60 Hz */
422 ks0127_reset(c); 433 ks0127_and_or(sd, KS_CMDA, 0xfc, 0x00);
434 /* VSE=0 */
435 ks0127_and_or(sd, KS_CMDA, ~0x40, 0x00);
436 /* set input line */
437 ks0127_and_or(sd, KS_CMDB, 0xb0, route->input);
438 /* non-freerunning mode */
439 ks0127_and_or(sd, KS_CMDC, 0x70, 0x0a);
440 /* analog input */
441 ks0127_and_or(sd, KS_CMDD, 0x03, 0x00);
442 /* enable chroma demodulation */
443 ks0127_and_or(sd, KS_CTRACK, 0xcf, 0x00);
444 /* chroma trap, HYBWR=1 */
445 ks0127_and_or(sd, KS_LUMA, 0x00,
446 (reg_defaults[KS_LUMA])|0x0c);
447 /* scaler fullbw, luma comb off */
448 ks0127_and_or(sd, KS_VERTIA, 0x08, 0x81);
449 /* manual chroma comb .25 .5 .25 */
450 ks0127_and_or(sd, KS_VERTIC, 0x0f, 0x90);
451
452 /* chroma path delay */
453 ks0127_and_or(sd, KS_CHROMB, 0x0f, 0x90);
454
455 ks0127_write(sd, KS_UGAIN, reg_defaults[KS_UGAIN]);
456 ks0127_write(sd, KS_VGAIN, reg_defaults[KS_VGAIN]);
457 ks0127_write(sd, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
458 ks0127_write(sd, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
423 break; 459 break;
424 460
425 case VIDIOC_INT_S_VIDEO_ROUTING: 461 case KS_INPUT_SVIDEO_1:
426 switch (route->input) { 462 case KS_INPUT_SVIDEO_2:
427 case KS_INPUT_COMPOSITE_1: 463 case KS_INPUT_SVIDEO_3:
428 case KS_INPUT_COMPOSITE_2: 464 v4l2_dbg(1, debug, sd,
429 case KS_INPUT_COMPOSITE_3: 465 "VIDIOC_S_INPUT %d: S-Video\n", route->input);
430 case KS_INPUT_COMPOSITE_4: 466 /* autodetect 50/60 Hz */
431 case KS_INPUT_COMPOSITE_5: 467 ks0127_and_or(sd, KS_CMDA, 0xfc, 0x00);
432 case KS_INPUT_COMPOSITE_6: 468 /* VSE=0 */
433 v4l_dbg(1, debug, c, 469 ks0127_and_or(sd, KS_CMDA, ~0x40, 0x00);
434 "VIDIOC_S_INPUT %d: Composite\n", *iarg); 470 /* set input line */
435 /* autodetect 50/60 Hz */ 471 ks0127_and_or(sd, KS_CMDB, 0xb0, route->input);
436 ks0127_and_or(c, KS_CMDA, 0xfc, 0x00); 472 /* non-freerunning mode */
437 /* VSE=0 */ 473 ks0127_and_or(sd, KS_CMDC, 0x70, 0x0a);
438 ks0127_and_or(c, KS_CMDA, ~0x40, 0x00); 474 /* analog input */
439 /* set input line */ 475 ks0127_and_or(sd, KS_CMDD, 0x03, 0x00);
440 ks0127_and_or(c, KS_CMDB, 0xb0, *iarg); 476 /* enable chroma demodulation */
441 /* non-freerunning mode */ 477 ks0127_and_or(sd, KS_CTRACK, 0xcf, 0x00);
442 ks0127_and_or(c, KS_CMDC, 0x70, 0x0a); 478 ks0127_and_or(sd, KS_LUMA, 0x00,
443 /* analog input */ 479 reg_defaults[KS_LUMA]);
444 ks0127_and_or(c, KS_CMDD, 0x03, 0x00); 480 /* disable luma comb */
445 /* enable chroma demodulation */ 481 ks0127_and_or(sd, KS_VERTIA, 0x08,
446 ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00); 482 (reg_defaults[KS_VERTIA]&0xf0)|0x01);
447 /* chroma trap, HYBWR=1 */ 483 ks0127_and_or(sd, KS_VERTIC, 0x0f,
448 ks0127_and_or(c, KS_LUMA, 0x00, 484 reg_defaults[KS_VERTIC]&0xf0);
449 (reg_defaults[KS_LUMA])|0x0c); 485
450 /* scaler fullbw, luma comb off */ 486 ks0127_and_or(sd, KS_CHROMB, 0x0f,
451 ks0127_and_or(c, KS_VERTIA, 0x08, 0x81); 487 reg_defaults[KS_CHROMB]&0xf0);
452 /* manual chroma comb .25 .5 .25 */ 488
453 ks0127_and_or(c, KS_VERTIC, 0x0f, 0x90); 489 ks0127_write(sd, KS_UGAIN, reg_defaults[KS_UGAIN]);
454 490 ks0127_write(sd, KS_VGAIN, reg_defaults[KS_VGAIN]);
455 /* chroma path delay */ 491 ks0127_write(sd, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
456 ks0127_and_or(c, KS_CHROMB, 0x0f, 0x90); 492 ks0127_write(sd, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
457
458 ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]);
459 ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]);
460 ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
461 ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
462 break;
463
464 case KS_INPUT_SVIDEO_1:
465 case KS_INPUT_SVIDEO_2:
466 case KS_INPUT_SVIDEO_3:
467 v4l_dbg(1, debug, c,
468 "VIDIOC_S_INPUT %d: S-Video\n", *iarg);
469 /* autodetect 50/60 Hz */
470 ks0127_and_or(c, KS_CMDA, 0xfc, 0x00);
471 /* VSE=0 */
472 ks0127_and_or(c, KS_CMDA, ~0x40, 0x00);
473 /* set input line */
474 ks0127_and_or(c, KS_CMDB, 0xb0, *iarg);
475 /* non-freerunning mode */
476 ks0127_and_or(c, KS_CMDC, 0x70, 0x0a);
477 /* analog input */
478 ks0127_and_or(c, KS_CMDD, 0x03, 0x00);
479 /* enable chroma demodulation */
480 ks0127_and_or(c, KS_CTRACK, 0xcf, 0x00);
481 ks0127_and_or(c, KS_LUMA, 0x00,
482 reg_defaults[KS_LUMA]);
483 /* disable luma comb */
484 ks0127_and_or(c, KS_VERTIA, 0x08,
485 (reg_defaults[KS_VERTIA]&0xf0)|0x01);
486 ks0127_and_or(c, KS_VERTIC, 0x0f,
487 reg_defaults[KS_VERTIC]&0xf0);
488
489 ks0127_and_or(c, KS_CHROMB, 0x0f,
490 reg_defaults[KS_CHROMB]&0xf0);
491
492 ks0127_write(c, KS_UGAIN, reg_defaults[KS_UGAIN]);
493 ks0127_write(c, KS_VGAIN, reg_defaults[KS_VGAIN]);
494 ks0127_write(c, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
495 ks0127_write(c, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
496 break;
497
498 case KS_INPUT_YUV656:
499 v4l_dbg(1, debug, c,
500 "VIDIOC_S_INPUT 15: YUV656\n");
501 if (ks->norm & V4L2_STD_525_60)
502 /* force 60 Hz */
503 ks0127_and_or(c, KS_CMDA, 0xfc, 0x03);
504 else
505 /* force 50 Hz */
506 ks0127_and_or(c, KS_CMDA, 0xfc, 0x02);
507
508 ks0127_and_or(c, KS_CMDA, 0xff, 0x40); /* VSE=1 */
509 /* set input line and VALIGN */
510 ks0127_and_or(c, KS_CMDB, 0xb0, (*iarg | 0x40));
511 /* freerunning mode, */
512 /* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0 VMEM=1*/
513 ks0127_and_or(c, KS_CMDC, 0x70, 0x87);
514 /* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */
515 ks0127_and_or(c, KS_CMDD, 0x03, 0x08);
516 /* disable chroma demodulation */
517 ks0127_and_or(c, KS_CTRACK, 0xcf, 0x30);
518 /* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */
519 ks0127_and_or(c, KS_LUMA, 0x00, 0x71);
520 ks0127_and_or(c, KS_VERTIC, 0x0f,
521 reg_defaults[KS_VERTIC]&0xf0);
522
523 /* scaler fullbw, luma comb off */
524 ks0127_and_or(c, KS_VERTIA, 0x08, 0x81);
525
526 ks0127_and_or(c, KS_CHROMB, 0x0f,
527 reg_defaults[KS_CHROMB]&0xf0);
528
529 ks0127_and_or(c, KS_CON, 0x00, 0x00);
530 ks0127_and_or(c, KS_BRT, 0x00, 32); /* spec: 34 */
531 /* spec: 229 (e5) */
532 ks0127_and_or(c, KS_SAT, 0x00, 0xe8);
533 ks0127_and_or(c, KS_HUE, 0x00, 0);
534
535 ks0127_and_or(c, KS_UGAIN, 0x00, 238);
536 ks0127_and_or(c, KS_VGAIN, 0x00, 0x00);
537
538 /*UOFF:0x30, VOFF:0x30, TSTCGN=1 */
539 ks0127_and_or(c, KS_UVOFFH, 0x00, 0x4f);
540 ks0127_and_or(c, KS_UVOFFL, 0x00, 0x00);
541 break;
542
543 default:
544 v4l_dbg(1, debug, c,
545 "VIDIOC_INT_S_VIDEO_ROUTING: Unknown input %d\n", route->input);
546 break;
547 }
548
549 /* hack: CDMLPF sometimes spontaneously switches on; */
550 /* force back off */
551 ks0127_write(c, KS_DEMOD, reg_defaults[KS_DEMOD]);
552 break; 493 break;
553 494
554 case VIDIOC_S_STD: /* sam This block mixes old and new norm names... */ 495 case KS_INPUT_YUV656:
555 /* Set to automatic SECAM/Fsc mode */ 496 v4l2_dbg(1, debug, sd, "VIDIOC_S_INPUT 15: YUV656\n");
556 ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00); 497 if (ks->norm & V4L2_STD_525_60)
557 498 /* force 60 Hz */
558 ks->norm = *istd; 499 ks0127_and_or(sd, KS_CMDA, 0xfc, 0x03);
559 500 else
560 if (*istd & V4L2_STD_NTSC) { 501 /* force 50 Hz */
561 v4l_dbg(1, debug, c, 502 ks0127_and_or(sd, KS_CMDA, 0xfc, 0x02);
562 "VIDIOC_S_STD: NTSC_M\n"); 503
563 ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); 504 ks0127_and_or(sd, KS_CMDA, 0xff, 0x40); /* VSE=1 */
564 ks->format_height = 240; 505 /* set input line and VALIGN */
565 ks->format_width = 704; 506 ks0127_and_or(sd, KS_CMDB, 0xb0, (route->input | 0x40));
566 } else if (*istd & V4L2_STD_PAL_N) { 507 /* freerunning mode, */
567 v4l_dbg(1, debug, c, 508 /* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0 VMEM=1*/
568 "KS0127_SET_NORM: NTSC_N (fixme)\n"); 509 ks0127_and_or(sd, KS_CMDC, 0x70, 0x87);
569 ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40); 510 /* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */
570 ks->format_height = 240; 511 ks0127_and_or(sd, KS_CMDD, 0x03, 0x08);
571 ks->format_width = 704; 512 /* disable chroma demodulation */
572 } else if (*istd & V4L2_STD_PAL) { 513 ks0127_and_or(sd, KS_CTRACK, 0xcf, 0x30);
573 v4l_dbg(1, debug, c, 514 /* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */
574 "VIDIOC_S_STD: PAL_N\n"); 515 ks0127_and_or(sd, KS_LUMA, 0x00, 0x71);
575 ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20); 516 ks0127_and_or(sd, KS_VERTIC, 0x0f,
576 ks->format_height = 290; 517 reg_defaults[KS_VERTIC]&0xf0);
577 ks->format_width = 704; 518
578 } else if (*istd & V4L2_STD_PAL_M) { 519 /* scaler fullbw, luma comb off */
579 v4l_dbg(1, debug, c, 520 ks0127_and_or(sd, KS_VERTIA, 0x08, 0x81);
580 "KS0127_SET_NORM: PAL_M (fixme)\n"); 521
581 ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40); 522 ks0127_and_or(sd, KS_CHROMB, 0x0f,
582 ks->format_height = 290; 523 reg_defaults[KS_CHROMB]&0xf0);
583 ks->format_width = 704; 524
584 } else if (*istd & V4L2_STD_SECAM) { 525 ks0127_and_or(sd, KS_CON, 0x00, 0x00);
585 v4l_dbg(1, debug, c, 526 ks0127_and_or(sd, KS_BRT, 0x00, 32); /* spec: 34 */
586 "KS0127_SET_NORM: SECAM\n"); 527 /* spec: 229 (e5) */
587 ks->format_height = 290; 528 ks0127_and_or(sd, KS_SAT, 0x00, 0xe8);
588 ks->format_width = 704; 529 ks0127_and_or(sd, KS_HUE, 0x00, 0);
589 530
590 /* set to secam autodetection */ 531 ks0127_and_or(sd, KS_UGAIN, 0x00, 238);
591 ks0127_and_or(c, KS_CHROMA, 0xdf, 0x20); 532 ks0127_and_or(sd, KS_VGAIN, 0x00, 0x00);
592 ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00); 533
593 schedule_timeout_interruptible(HZ/10+1); 534 /*UOFF:0x30, VOFF:0x30, TSTCGN=1 */
594 535 ks0127_and_or(sd, KS_UVOFFH, 0x00, 0x4f);
595 /* did it autodetect? */ 536 ks0127_and_or(sd, KS_UVOFFL, 0x00, 0x00);
596 if (!(ks0127_read(c, KS_DEMOD) & 0x40))
597 /* force to secam mode */
598 ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f);
599 } else {
600 v4l_dbg(1, debug, c,
601 "VIDIOC_S_STD: Unknown norm %llx\n", *istd);
602 }
603 break; 537 break;
604 538
605 case VIDIOC_QUERYCTRL: 539 default:
606 { 540 v4l2_dbg(1, debug, sd,
607 return -EINVAL; 541 "VIDIOC_INT_S_VIDEO_ROUTING: Unknown input %d\n", route->input);
608 }
609
610 case VIDIOC_S_CTRL:
611 v4l_dbg(1, debug, c,
612 "VIDIOC_S_CTRL: not yet supported\n");
613 return -EINVAL;
614
615 case VIDIOC_G_CTRL:
616 v4l_dbg(1, debug, c,
617 "VIDIOC_G_CTRL: not yet supported\n");
618 return -EINVAL;
619
620 /* sam todo: KS0127_SET_BRIGHTNESS: Merge into VIDIOC_S_CTRL */
621 /* sam todo: KS0127_SET_CONTRAST: Merge into VIDIOC_S_CTRL */
622 /* sam todo: KS0127_SET_HUE: Merge into VIDIOC_S_CTRL? */
623 /* sam todo: KS0127_SET_SATURATION: Merge into VIDIOC_S_CTRL */
624 /* sam todo: KS0127_SET_AGC_MODE: */
625 /* sam todo: KS0127_SET_AGC: */
626 /* sam todo: KS0127_SET_CHROMA_MODE: */
627 /* sam todo: KS0127_SET_PIXCLK_MODE: */
628 /* sam todo: KS0127_SET_GAMMA_MODE: */
629 /* sam todo: KS0127_SET_UGAIN: */
630 /* sam todo: KS0127_SET_VGAIN: */
631 /* sam todo: KS0127_SET_INVALY: */
632 /* sam todo: KS0127_SET_INVALU: */
633 /* sam todo: KS0127_SET_INVALV: */
634 /* sam todo: KS0127_SET_UNUSEY: */
635 /* sam todo: KS0127_SET_UNUSEU: */
636 /* sam todo: KS0127_SET_UNUSEV: */
637 /* sam todo: KS0127_SET_VSALIGN_MODE: */
638
639 case VIDIOC_STREAMON:
640 case VIDIOC_STREAMOFF:
641 {
642 int enable = cmd == VIDIOC_STREAMON;
643
644 if (enable) {
645 v4l_dbg(1, debug, c,
646 "VIDIOC_STREAMON\n");
647 /* All output pins on */
648 ks0127_and_or(c, KS_OFMTA, 0xcf, 0x30);
649 /* Obey the OEN pin */
650 ks0127_and_or(c, KS_CDEM, 0x7f, 0x00);
651 } else {
652 v4l_dbg(1, debug, c,
653 "VIDIOC_STREAMOFF\n");
654 /* Video output pins off */
655 ks0127_and_or(c, KS_OFMTA, 0xcf, 0x00);
656 /* Ignore the OEN pin */
657 ks0127_and_or(c, KS_CDEM, 0x7f, 0x80);
658 }
659 break; 542 break;
660 } 543 }
661 544
662 /* sam todo: KS0127_SET_OUTPUT_MODE: */ 545 /* hack: CDMLPF sometimes spontaneously switches on; */
663 /* sam todo: KS0127_SET_WIDTH: */ 546 /* force back off */
664 /* sam todo: KS0127_SET_HEIGHT: */ 547 ks0127_write(sd, KS_DEMOD, reg_defaults[KS_DEMOD]);
665 /* sam todo: KS0127_SET_HSCALE: */ 548 return 0;
666 549}
667 case VIDIOC_QUERYSTD: 550
668 case VIDIOC_INT_G_INPUT_STATUS: { 551static int ks0127_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
669 int stat = V4L2_IN_ST_NO_SIGNAL; 552{
670 v4l2_std_id std = V4L2_STD_ALL; 553 struct ks0127 *ks = to_ks0127(sd);
671 v4l_dbg(1, debug, c, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n"); 554
672 status = ks0127_read(c, KS_STAT); 555 /* Set to automatic SECAM/Fsc mode */
673 if (!(status & 0x20)) /* NOVID not set */ 556 ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x00);
674 stat = 0; 557
675 if (!(status & 0x01)) /* CLOCK set */ 558 ks->norm = std;
676 stat |= V4L2_IN_ST_NO_COLOR; 559 if (std & V4L2_STD_NTSC) {
677 if ((status & 0x08)) /* PALDET set */ 560 v4l2_dbg(1, debug, sd,
678 std = V4L2_STD_PAL; 561 "VIDIOC_S_STD: NTSC_M\n");
679 else 562 ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x20);
680 std = V4L2_STD_NTSC; 563 } else if (std & V4L2_STD_PAL_N) {
681 if (cmd == VIDIOC_QUERYSTD) 564 v4l2_dbg(1, debug, sd,
682 *istd = std; 565 "KS0127_SET_NORM: NTSC_N (fixme)\n");
683 else 566 ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x40);
684 *iarg = stat; 567 } else if (std & V4L2_STD_PAL) {
685 break; 568 v4l2_dbg(1, debug, sd,
569 "VIDIOC_S_STD: PAL_N\n");
570 ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x20);
571 } else if (std & V4L2_STD_PAL_M) {
572 v4l2_dbg(1, debug, sd,
573 "KS0127_SET_NORM: PAL_M (fixme)\n");
574 ks0127_and_or(sd, KS_CHROMA, 0x9f, 0x40);
575 } else if (std & V4L2_STD_SECAM) {
576 v4l2_dbg(1, debug, sd,
577 "KS0127_SET_NORM: SECAM\n");
578
579 /* set to secam autodetection */
580 ks0127_and_or(sd, KS_CHROMA, 0xdf, 0x20);
581 ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x00);
582 schedule_timeout_interruptible(HZ/10+1);
583
584 /* did it autodetect? */
585 if (!(ks0127_read(sd, KS_DEMOD) & 0x40))
586 /* force to secam mode */
587 ks0127_and_or(sd, KS_DEMOD, 0xf0, 0x0f);
588 } else {
589 v4l2_dbg(1, debug, sd,
590 "VIDIOC_S_STD: Unknown norm %llx\n", std);
686 } 591 }
592 return 0;
593}
687 594
688 /* Catch any unknown command */ 595static int ks0127_s_stream(struct v4l2_subdev *sd, int enable)
689 default: 596{
690 v4l_dbg(1, debug, c, "unknown: 0x%08x\n", cmd); 597 v4l2_dbg(1, debug, sd, "s_stream(%d)\n", enable);
691 return -EINVAL; 598 if (enable) {
599 /* All output pins on */
600 ks0127_and_or(sd, KS_OFMTA, 0xcf, 0x30);
601 /* Obey the OEN pin */
602 ks0127_and_or(sd, KS_CDEM, 0x7f, 0x00);
603 } else {
604 /* Video output pins off */
605 ks0127_and_or(sd, KS_OFMTA, 0xcf, 0x00);
606 /* Ignore the OEN pin */
607 ks0127_and_or(sd, KS_CDEM, 0x7f, 0x80);
692 } 608 }
693 return 0; 609 return 0;
694} 610}
695 611
612static int ks0127_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
613{
614 int stat = V4L2_IN_ST_NO_SIGNAL;
615 u8 status;
616 v4l2_std_id std = V4L2_STD_ALL;
617
618 v4l2_dbg(1, debug, sd, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n");
619 status = ks0127_read(sd, KS_STAT);
620 if (!(status & 0x20)) /* NOVID not set */
621 stat = 0;
622 if (!(status & 0x01)) /* CLOCK set */
623 stat |= V4L2_IN_ST_NO_COLOR;
624 if ((status & 0x08)) /* PALDET set */
625 std = V4L2_STD_PAL;
626 else
627 std = V4L2_STD_NTSC;
628 if (pstd)
629 *pstd = std;
630 if (pstatus)
631 *pstatus = stat;
632 return 0;
633}
696 634
697/* Addresses to scan */ 635static int ks0127_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
698#define I2C_KS0127_ADDON 0xD8 636{
699#define I2C_KS0127_ONBOARD 0xDA 637 return ks0127_status(sd, NULL, std);
638}
700 639
701static unsigned short normal_i2c[] = { 640static int ks0127_g_input_status(struct v4l2_subdev *sd, u32 *status)
702 I2C_KS0127_ADDON >> 1, 641{
703 I2C_KS0127_ONBOARD >> 1, 642 return ks0127_status(sd, status, NULL);
704 I2C_CLIENT_END 643}
644
645static int ks0127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
646{
647 struct i2c_client *client = v4l2_get_subdevdata(sd);
648 struct ks0127 *ks = to_ks0127(sd);
649
650 return v4l2_chip_ident_i2c_client(client, chip, ks->ident, 0);
651}
652
653static int ks0127_command(struct i2c_client *client, unsigned cmd, void *arg)
654{
655 return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
656}
657
658/* ----------------------------------------------------------------------- */
659
660static const struct v4l2_subdev_core_ops ks0127_core_ops = {
661 .g_chip_ident = ks0127_g_chip_ident,
705}; 662};
706 663
707I2C_CLIENT_INSMOD; 664static const struct v4l2_subdev_tuner_ops ks0127_tuner_ops = {
665 .s_std = ks0127_s_std,
666};
667
668static const struct v4l2_subdev_video_ops ks0127_video_ops = {
669 .s_routing = ks0127_s_routing,
670 .s_stream = ks0127_s_stream,
671 .querystd = ks0127_querystd,
672 .g_input_status = ks0127_g_input_status,
673};
708 674
709static int ks0127_probe(struct i2c_client *c, const struct i2c_device_id *id) 675static const struct v4l2_subdev_ops ks0127_ops = {
676 .core = &ks0127_core_ops,
677 .tuner = &ks0127_tuner_ops,
678 .video = &ks0127_video_ops,
679};
680
681/* ----------------------------------------------------------------------- */
682
683
684static int ks0127_probe(struct i2c_client *client, const struct i2c_device_id *id)
710{ 685{
711 struct ks0127 *ks; 686 struct ks0127 *ks;
687 struct v4l2_subdev *sd;
712 688
713 v4l_info(c, "%s chip found @ 0x%x (%s)\n", 689 v4l_info(client, "%s chip found @ 0x%x (%s)\n",
714 c->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board", 690 client->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board",
715 c->addr << 1, c->adapter->name); 691 client->addr << 1, client->adapter->name);
716 692
717 ks = kzalloc(sizeof(*ks), GFP_KERNEL); 693 ks = kzalloc(sizeof(*ks), GFP_KERNEL);
718 if (ks == NULL) 694 if (ks == NULL)
719 return -ENOMEM; 695 return -ENOMEM;
720 696 sd = &ks->sd;
721 i2c_set_clientdata(c, ks); 697 v4l2_i2c_subdev_init(sd, client, &ks0127_ops);
722
723 ks->ks_type = KS_TYPE_UNKNOWN;
724 698
725 /* power up */ 699 /* power up */
726 init_reg_defaults(); 700 init_reg_defaults();
727 ks0127_write(c, KS_CMDA, 0x2c); 701 ks0127_write(sd, KS_CMDA, 0x2c);
728 mdelay(10); 702 mdelay(10);
729 703
730 /* reset the device */ 704 /* reset the device */
731 ks0127_reset(c); 705 ks0127_init(sd);
732 return 0; 706 return 0;
733} 707}
734 708
735static int ks0127_remove(struct i2c_client *c) 709static int ks0127_remove(struct i2c_client *client)
736{ 710{
737 struct ks0127 *ks = i2c_get_clientdata(c); 711 struct v4l2_subdev *sd = i2c_get_clientdata(client);
738
739 ks0127_write(c, KS_OFMTA, 0x20); /* tristate */
740 ks0127_write(c, KS_CMDA, 0x2c | 0x80); /* power down */
741 712
742 kfree(ks); 713 v4l2_device_unregister_subdev(sd);
714 ks0127_write(sd, KS_OFMTA, 0x20); /* tristate */
715 ks0127_write(sd, KS_CMDA, 0x2c | 0x80); /* power down */
716 kfree(to_ks0127(sd));
743 return 0; 717 return 0;
744} 718}
745 719
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
index 69e3092fd288..b5ed91a4ce92 100644
--- a/include/media/v4l2-chip-ident.h
+++ b/include/media/v4l2-chip-ident.h
@@ -82,6 +82,11 @@ enum {
82 /* module bt866: just ident 866 */ 82 /* module bt866: just ident 866 */
83 V4L2_IDENT_BT866 = 866, 83 V4L2_IDENT_BT866 = 866,
84 84
85 /* module ks0127: reserved range 1120-1129 */
86 V4L2_IDENT_KS0122S = 1122,
87 V4L2_IDENT_KS0127 = 1127,
88 V4L2_IDENT_KS0127B = 1128,
89
85 /* module vp27smpx: just ident 2700 */ 90 /* module vp27smpx: just ident 2700 */
86 V4L2_IDENT_VP27SMPX = 2700, 91 V4L2_IDENT_VP27SMPX = 2700,
87 92