aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2008-04-22 13:45:51 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-24 13:07:49 -0400
commit081b496a75fec134657f036f585738a1ca869047 (patch)
tree41069e310a3d2ba54abc1767663f04b902255abe
parent2fd3c14cf53c379602d1a8a1a0aed7737a48c5c6 (diff)
V4L/DVB (7344): cx25840: better PAL-M and NTSC-KR handling
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c91
-rw-r--r--drivers/media/video/cx25840/cx25840-core.h2
-rw-r--r--drivers/media/video/cx25840/cx25840-vbi.c6
3 files changed, 38 insertions, 61 deletions
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 756a1eeb274e..ae395f8cf292 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -352,7 +352,7 @@ static void cx23885_initialize(struct i2c_client *client)
352static void input_change(struct i2c_client *client) 352static void input_change(struct i2c_client *client)
353{ 353{
354 struct cx25840_state *state = i2c_get_clientdata(client); 354 struct cx25840_state *state = i2c_get_clientdata(client);
355 v4l2_std_id std = cx25840_get_v4lstd(client); 355 v4l2_std_id std = state->std;
356 356
357 /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */ 357 /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */
358 if (std & V4L2_STD_SECAM) { 358 if (std & V4L2_STD_SECAM) {
@@ -523,32 +523,34 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
523 523
524/* ----------------------------------------------------------------------- */ 524/* ----------------------------------------------------------------------- */
525 525
526static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) 526static int set_v4lstd(struct i2c_client *client)
527{ 527{
528 u8 fmt=0; /* zero is autodetect */ 528 struct cx25840_state *state = i2c_get_clientdata(client);
529 u8 fmt = 0; /* zero is autodetect */
530 u8 pal_m = 0;
529 531
530 /* First tests should be against specific std */ 532 /* First tests should be against specific std */
531 if (std == V4L2_STD_NTSC_M_JP) { 533 if (state->std == V4L2_STD_NTSC_M_JP) {
532 fmt=0x2; 534 fmt = 0x2;
533 } else if (std == V4L2_STD_NTSC_443) { 535 } else if (state->std == V4L2_STD_NTSC_443) {
534 fmt=0x3; 536 fmt = 0x3;
535 } else if (std == V4L2_STD_PAL_M) { 537 } else if (state->std == V4L2_STD_PAL_M) {
536 fmt=0x5; 538 pal_m = 1;
537 } else if (std == V4L2_STD_PAL_N) { 539 fmt = 0x5;
538 fmt=0x6; 540 } else if (state->std == V4L2_STD_PAL_N) {
539 } else if (std == V4L2_STD_PAL_Nc) { 541 fmt = 0x6;
540 fmt=0x7; 542 } else if (state->std == V4L2_STD_PAL_Nc) {
541 } else if (std == V4L2_STD_PAL_60) { 543 fmt = 0x7;
542 fmt=0x8; 544 } else if (state->std == V4L2_STD_PAL_60) {
545 fmt = 0x8;
543 } else { 546 } else {
544 /* Then, test against generic ones */ 547 /* Then, test against generic ones */
545 if (std & V4L2_STD_NTSC) { 548 if (state->std & V4L2_STD_NTSC)
546 fmt=0x1; 549 fmt = 0x1;
547 } else if (std & V4L2_STD_PAL) { 550 else if (state->std & V4L2_STD_PAL)
548 fmt=0x4; 551 fmt = 0x4;
549 } else if (std & V4L2_STD_SECAM) { 552 else if (state->std & V4L2_STD_SECAM)
550 fmt=0xc; 553 fmt = 0xc;
551 }
552 } 554 }
553 555
554 v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt); 556 v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt);
@@ -563,42 +565,13 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
563 cx25840_and_or(client, 0x47b, ~6, 0); 565 cx25840_and_or(client, 0x47b, ~6, 0);
564 } 566 }
565 cx25840_and_or(client, 0x400, ~0xf, fmt); 567 cx25840_and_or(client, 0x400, ~0xf, fmt);
568 cx25840_and_or(client, 0x403, ~0x3, pal_m);
566 cx25840_vbi_setup(client); 569 cx25840_vbi_setup(client);
570 if (!state->is_cx25836)
571 input_change(client);
567 return 0; 572 return 0;
568} 573}
569 574
570v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
571{
572 struct cx25840_state *state = i2c_get_clientdata(client);
573 /* check VID_FMT_SEL first */
574 u8 fmt = cx25840_read(client, 0x400) & 0xf;
575
576 if (!fmt) {
577 /* check AFD_FMT_STAT if set to autodetect */
578 fmt = cx25840_read(client, 0x40d) & 0xf;
579 }
580
581 switch (fmt) {
582 case 0x1:
583 {
584 /* if the audio std is A2-M, then this is the South Korean
585 NTSC standard */
586 if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2)
587 return V4L2_STD_NTSC_M_KR;
588 return V4L2_STD_NTSC_M;
589 }
590 case 0x2: return V4L2_STD_NTSC_M_JP;
591 case 0x3: return V4L2_STD_NTSC_443;
592 case 0x4: return V4L2_STD_PAL;
593 case 0x5: return V4L2_STD_PAL_M;
594 case 0x6: return V4L2_STD_PAL_N;
595 case 0x7: return V4L2_STD_PAL_Nc;
596 case 0x8: return V4L2_STD_PAL_60;
597 case 0xc: return V4L2_STD_SECAM;
598 default: return V4L2_STD_UNKNOWN;
599 }
600}
601
602/* ----------------------------------------------------------------------- */ 575/* ----------------------------------------------------------------------- */
603 576
604static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) 577static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
@@ -718,9 +691,10 @@ static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
718 691
719static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) 692static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
720{ 693{
694 struct cx25840_state *state = i2c_get_clientdata(client);
721 struct v4l2_pix_format *pix; 695 struct v4l2_pix_format *pix;
722 int HSC, VSC, Vsrc, Hsrc, filter, Vlines; 696 int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
723 int is_50Hz = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); 697 int is_50Hz = !(state->std & V4L2_STD_525_60);
724 698
725 switch (fmt->type) { 699 switch (fmt->type) {
726 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 700 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -1096,12 +1070,15 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
1096 } 1070 }
1097 1071
1098 case VIDIOC_G_STD: 1072 case VIDIOC_G_STD:
1099 *(v4l2_std_id *)arg = cx25840_get_v4lstd(client); 1073 *(v4l2_std_id *)arg = state->std;
1100 break; 1074 break;
1101 1075
1102 case VIDIOC_S_STD: 1076 case VIDIOC_S_STD:
1077 if (state->radio == 0 && state->std == *(v4l2_std_id *)arg)
1078 return 0;
1103 state->radio = 0; 1079 state->radio = 0;
1104 return set_v4lstd(client, *(v4l2_std_id *)arg); 1080 state->std = *(v4l2_std_id *)arg;
1081 return set_v4lstd(client);
1105 1082
1106 case AUDC_SET_RADIO: 1083 case AUDC_SET_RADIO:
1107 state->radio = 1; 1084 state->radio = 1;
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h
index 95093edc9186..8bf797f48b09 100644
--- a/drivers/media/video/cx25840/cx25840-core.h
+++ b/drivers/media/video/cx25840/cx25840-core.h
@@ -38,6 +38,7 @@ struct cx25840_state {
38 struct i2c_client *c; 38 struct i2c_client *c;
39 int pvr150_workaround; 39 int pvr150_workaround;
40 int radio; 40 int radio;
41 v4l2_std_id std;
41 enum cx25840_video_input vid_input; 42 enum cx25840_video_input vid_input;
42 enum cx25840_audio_input aud_input; 43 enum cx25840_audio_input aud_input;
43 u32 audclk_freq; 44 u32 audclk_freq;
@@ -60,7 +61,6 @@ int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
60u8 cx25840_read(struct i2c_client *client, u16 addr); 61u8 cx25840_read(struct i2c_client *client, u16 addr);
61u32 cx25840_read4(struct i2c_client *client, u16 addr); 62u32 cx25840_read4(struct i2c_client *client, u16 addr);
62int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value); 63int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value);
63v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client);
64 64
65/* ----------------------------------------------------------------------- */ 65/* ----------------------------------------------------------------------- */
66/* cx25850-firmware.c */ 66/* cx25850-firmware.c */
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
index 6828f59b9d83..c754b9d13369 100644
--- a/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/drivers/media/video/cx25840/cx25840-vbi.c
@@ -85,7 +85,7 @@ static int decode_vps(u8 * dst, u8 * p)
85void cx25840_vbi_setup(struct i2c_client *client) 85void cx25840_vbi_setup(struct i2c_client *client)
86{ 86{
87 struct cx25840_state *state = i2c_get_clientdata(client); 87 struct cx25840_state *state = i2c_get_clientdata(client);
88 v4l2_std_id std = cx25840_get_v4lstd(client); 88 v4l2_std_id std = state->std;
89 int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation; 89 int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation;
90 int luma_lpf,uv_lpf, comb; 90 int luma_lpf,uv_lpf, comb;
91 u32 pll_int,pll_frac,pll_post; 91 u32 pll_int,pll_frac,pll_post;
@@ -242,7 +242,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
242 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ 242 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */
243 0, 0, 0, 0 243 0, 0, 0, 0
244 }; 244 };
245 int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); 245 int is_pal = !(state->std & V4L2_STD_525_60);
246 int i; 246 int i;
247 247
248 fmt = arg; 248 fmt = arg;
@@ -279,7 +279,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
279 279
280 case VIDIOC_S_FMT: 280 case VIDIOC_S_FMT:
281 { 281 {
282 int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); 282 int is_pal = !(state->std & V4L2_STD_525_60);
283 int vbi_offset = is_pal ? 1 : 0; 283 int vbi_offset = is_pal ? 1 : 0;
284 int i, x; 284 int i, x;
285 u8 lcr[24]; 285 u8 lcr[24];