aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2006-01-09 12:25:41 -0500
committerMauro Carvalho Chehab <mchehab@brturbo.com.br>2006-01-09 12:25:41 -0500
commit3578d3dd0b1e468a44a76a83efe90476a854625d (patch)
tree2cd544f2aae9844821afdf90308048a800e961a1
parent21fa715e67fe57e404d7f5f39b7f18016db9e4b6 (diff)
V4L/DVB (3214): Calculate the saa7115 AMCLK regs instead of using fixed values
- Calculate the audio master clock registers from the actual frequencies. This simplifies the code and it also prepares for adding CGC2 support. - VIDIOC_INT_AUDIO_CLOCK_FREQ now receives an u32 instead of an enum. It is more generic and actually easier to implement. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c20
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c10
-rw-r--r--drivers/media/video/cx25840/cx25840.h2
-rw-r--r--drivers/media/video/saa7115.c155
-rw-r--r--include/media/v4l2-common.h15
5 files changed, 55 insertions, 147 deletions
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index 740908f8027d..6c44bd9c1704 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -23,11 +23,13 @@
23 23
24#include "cx25840.h" 24#include "cx25840.h"
25 25
26inline static int set_audclk_freq(struct i2c_client *client, 26static int set_audclk_freq(struct i2c_client *client, u32 freq)
27 enum v4l2_audio_clock_freq freq)
28{ 27{
29 struct cx25840_state *state = i2c_get_clientdata(client); 28 struct cx25840_state *state = i2c_get_clientdata(client);
30 29
30 if (freq != 32000 && freq != 44100 && freq != 48000)
31 return -EINVAL;
32
31 /* assert soft reset */ 33 /* assert soft reset */
32 cx25840_and_or(client, 0x810, ~0x1, 0x01); 34 cx25840_and_or(client, 0x810, ~0x1, 0x01);
33 35
@@ -38,7 +40,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
38 switch (state->audio_input) { 40 switch (state->audio_input) {
39 case AUDIO_TUNER: 41 case AUDIO_TUNER:
40 switch (freq) { 42 switch (freq) {
41 case V4L2_AUDCLK_32_KHZ: 43 case 32000:
42 /* VID_PLL and AUX_PLL */ 44 /* VID_PLL and AUX_PLL */
43 cx25840_write4(client, 0x108, 0x0f040610); 45 cx25840_write4(client, 0x108, 0x0f040610);
44 46
@@ -51,7 +53,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
51 cx25840_write4(client, 0x90c, 0x7ff70108); 53 cx25840_write4(client, 0x90c, 0x7ff70108);
52 break; 54 break;
53 55
54 case V4L2_AUDCLK_441_KHZ: 56 case 44100:
55 /* VID_PLL and AUX_PLL */ 57 /* VID_PLL and AUX_PLL */
56 cx25840_write4(client, 0x108, 0x0f040910); 58 cx25840_write4(client, 0x108, 0x0f040910);
57 59
@@ -64,7 +66,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
64 cx25840_write4(client, 0x90c, 0x596d0108); 66 cx25840_write4(client, 0x90c, 0x596d0108);
65 break; 67 break;
66 68
67 case V4L2_AUDCLK_48_KHZ: 69 case 48000:
68 /* VID_PLL and AUX_PLL */ 70 /* VID_PLL and AUX_PLL */
69 cx25840_write4(client, 0x108, 0x0f040a10); 71 cx25840_write4(client, 0x108, 0x0f040a10);
70 72
@@ -84,7 +86,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
84 case AUDIO_INTERN: 86 case AUDIO_INTERN:
85 case AUDIO_RADIO: 87 case AUDIO_RADIO:
86 switch (freq) { 88 switch (freq) {
87 case V4L2_AUDCLK_32_KHZ: 89 case 32000:
88 /* VID_PLL and AUX_PLL */ 90 /* VID_PLL and AUX_PLL */
89 cx25840_write4(client, 0x108, 0x0f04081e); 91 cx25840_write4(client, 0x108, 0x0f04081e);
90 92
@@ -103,7 +105,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
103 cx25840_write(client, 0x127, 0x54); 105 cx25840_write(client, 0x127, 0x54);
104 break; 106 break;
105 107
106 case V4L2_AUDCLK_441_KHZ: 108 case 44100:
107 /* VID_PLL and AUX_PLL */ 109 /* VID_PLL and AUX_PLL */
108 cx25840_write4(client, 0x108, 0x0f040918); 110 cx25840_write4(client, 0x108, 0x0f040918);
109 111
@@ -119,7 +121,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
119 cx25840_write4(client, 0x90c, 0x85730108); 121 cx25840_write4(client, 0x90c, 0x85730108);
120 break; 122 break;
121 123
122 case V4L2_AUDCLK_48_KHZ: 124 case 48000:
123 /* VID_PLL and AUX_PLL */ 125 /* VID_PLL and AUX_PLL */
124 cx25840_write4(client, 0x108, 0x0f040a18); 126 cx25840_write4(client, 0x108, 0x0f040a18);
125 127
@@ -317,7 +319,7 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
317 case AUDC_SET_INPUT: 319 case AUDC_SET_INPUT:
318 return set_input(client, *(int *)arg); 320 return set_input(client, *(int *)arg);
319 case VIDIOC_INT_AUDIO_CLOCK_FREQ: 321 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
320 return set_audclk_freq(client, *(enum v4l2_audio_clock_freq *)arg); 322 return set_audclk_freq(client, *(u32 *)arg);
321 case VIDIOC_G_CTRL: 323 case VIDIOC_G_CTRL:
322 switch (ctrl->id) { 324 switch (ctrl->id) {
323 case V4L2_CID_AUDIO_VOLUME: 325 case V4L2_CID_AUDIO_VOLUME:
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 54ffae686dc9..c2c1e856aa60 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -802,7 +802,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
802 i2c_set_clientdata(client, state); 802 i2c_set_clientdata(client, state);
803 memset(state, 0, sizeof(struct cx25840_state)); 803 memset(state, 0, sizeof(struct cx25840_state));
804 state->input = CX25840_TUNER; 804 state->input = CX25840_TUNER;
805 state->audclk_freq = V4L2_AUDCLK_48_KHZ; 805 state->audclk_freq = 48000;
806 state->audio_input = AUDIO_TUNER; 806 state->audio_input = AUDIO_TUNER;
807 state->cardtype = CARDTYPE_PVR150; 807 state->cardtype = CARDTYPE_PVR150;
808 808
@@ -1008,13 +1008,7 @@ static void log_status(struct i2c_client *client)
1008 cx25840_info("Specified audio input: %s\n", 1008 cx25840_info("Specified audio input: %s\n",
1009 state->audio_input == 0 ? "Tuner" : "External"); 1009 state->audio_input == 0 ? "Tuner" : "External");
1010 1010
1011 switch (state->audclk_freq) { 1011 cx25840_info("Specified audioclock freq: %d Hz\n", state->audclk_freq);
1012 case V4L2_AUDCLK_441_KHZ: p = "44.1 kHz"; break;
1013 case V4L2_AUDCLK_48_KHZ: p = "48 kHz"; break;
1014 case V4L2_AUDCLK_32_KHZ: p = "32 kHz"; break;
1015 default: p = "undefined";
1016 }
1017 cx25840_info("Specified audioclock freq: %s\n", p);
1018 1012
1019 switch (pref_mode & 0xf) { 1013 switch (pref_mode & 0xf) {
1020 case 0: p = "mono/language A"; break; 1014 case 0: p = "mono/language A"; break;
diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840.h
index 40aa59f9c525..4731a19092a6 100644
--- a/drivers/media/video/cx25840/cx25840.h
+++ b/drivers/media/video/cx25840/cx25840.h
@@ -65,7 +65,7 @@ struct cx25840_state {
65 enum cx25840_cardtype cardtype; 65 enum cx25840_cardtype cardtype;
66 enum cx25840_input input; 66 enum cx25840_input input;
67 int audio_input; 67 int audio_input;
68 enum v4l2_audio_clock_freq audclk_freq; 68 u32 audclk_freq;
69}; 69};
70 70
71/* ----------------------------------------------------------------------- */ 71/* ----------------------------------------------------------------------- */
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index b175389d9f43..3e4e5584c5d0 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -39,6 +39,7 @@
39#include <linux/i2c.h> 39#include <linux/i2c.h>
40#include <linux/videodev2.h> 40#include <linux/videodev2.h>
41#include <media/v4l2-common.h> 41#include <media/v4l2-common.h>
42#include <asm/div64.h>
42 43
43MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver"); 44MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver");
44MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil"); 45MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil");
@@ -78,7 +79,7 @@ struct saa7115_state {
78 int hue; 79 int hue;
79 int sat; 80 int sat;
80 enum v4l2_chip_ident ident; 81 enum v4l2_chip_ident ident;
81 enum v4l2_audio_clock_freq audclk_freq; 82 u32 audclk_freq;
82}; 83};
83 84
84/* ----------------------------------------------------------------------- */ 85/* ----------------------------------------------------------------------- */
@@ -469,80 +470,6 @@ static const unsigned char saa7115_init_misc[] = {
469 0x00, 0x00 470 0x00, 0x00
470}; 471};
471 472
472/* ============== SAA7715 AUDIO settings ============= */
473
474/* 48.0 kHz */
475static const unsigned char saa7115_cfg_48_audio[] = {
476 0x34, 0xce,
477 0x35, 0xfb,
478 0x36, 0x30,
479 0x00, 0x00
480};
481
482/* 44.1 kHz */
483static const unsigned char saa7115_cfg_441_audio[] = {
484 0x34, 0xf2,
485 0x35, 0x00,
486 0x36, 0x2d,
487 0x00, 0x00
488};
489
490/* 32.0 kHz */
491static const unsigned char saa7115_cfg_32_audio[] = {
492 0x34, 0xdf,
493 0x35, 0xa7,
494 0x36, 0x20,
495 0x00, 0x00
496};
497
498/* 48.0 kHz 60hz */
499static const unsigned char saa7115_cfg_60hz_48_audio[] = {
500 0x30, 0xcd,
501 0x31, 0x20,
502 0x32, 0x03,
503 0x00, 0x00
504};
505
506/* 48.0 kHz 50hz */
507static const unsigned char saa7115_cfg_50hz_48_audio[] = {
508 0x30, 0x00,
509 0x31, 0xc0,
510 0x32, 0x03,
511 0x00, 0x00
512};
513
514/* 44.1 kHz 60hz */
515static const unsigned char saa7115_cfg_60hz_441_audio[] = {
516 0x30, 0xbc,
517 0x31, 0xdf,
518 0x32, 0x02,
519 0x00, 0x00
520};
521
522/* 44.1 kHz 50hz */
523static const unsigned char saa7115_cfg_50hz_441_audio[] = {
524 0x30, 0x00,
525 0x31, 0x72,
526 0x32, 0x03,
527 0x00, 0x00
528};
529
530/* 32.0 kHz 60hz */
531static const unsigned char saa7115_cfg_60hz_32_audio[] = {
532 0x30, 0xde,
533 0x31, 0x15,
534 0x32, 0x02,
535 0x00, 0x00
536};
537
538/* 32.0 kHz 50hz */
539static const unsigned char saa7115_cfg_50hz_32_audio[] = {
540 0x30, 0x00,
541 0x31, 0x80,
542 0x32, 0x02,
543 0x00, 0x00
544};
545
546static int saa7115_odd_parity(u8 c) 473static int saa7115_odd_parity(u8 c)
547{ 474{
548 c ^= (c >> 4); 475 c ^= (c >> 4);
@@ -627,40 +554,38 @@ static int saa7115_decode_wss(u8 * p)
627} 554}
628 555
629 556
630static int saa7115_set_audio_clock_freq(struct i2c_client *client, enum v4l2_audio_clock_freq freq) 557static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
631{ 558{
632 struct saa7115_state *state = i2c_get_clientdata(client); 559 struct saa7115_state *state = i2c_get_clientdata(client);
560 u32 acpf;
561 u32 acni;
562 u32 hz;
563 u64 f;
633 564
634 saa7115_dbg("set audio clock freq: %d\n", freq); 565 saa7115_dbg("set audio clock freq: %d\n", freq);
635 switch (freq) { 566
636 case V4L2_AUDCLK_32_KHZ: 567 /* sanity check */
637 saa7115_writeregs(client, saa7115_cfg_32_audio); 568 if (freq < 32000 || freq > 48000)
638 if (state->std & V4L2_STD_525_60) { 569 return -EINVAL;
639 saa7115_writeregs(client, saa7115_cfg_60hz_32_audio); 570
640 } else { 571 /* hz is the refresh rate times 100 */
641 saa7115_writeregs(client, saa7115_cfg_50hz_32_audio); 572 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
642 } 573 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
643 break; 574 acpf = (25600 * freq) / hz;
644 case V4L2_AUDCLK_441_KHZ: 575 /* acni = (256 * freq * 2^23) / crystal_frequency =
645 saa7115_writeregs(client, saa7115_cfg_441_audio); 576 (freq * 2^(8+23)) / crystal_frequency =
646 if (state->std & V4L2_STD_525_60) { 577 (freq << 31) / 32.11 MHz */
647 saa7115_writeregs(client, saa7115_cfg_60hz_441_audio); 578 f = freq;
648 } else { 579 f = f << 31;
649 saa7115_writeregs(client, saa7115_cfg_50hz_441_audio); 580 do_div(f, 32110000);
650 } 581 acni = f;
651 break; 582
652 case V4L2_AUDCLK_48_KHZ: 583 saa7115_write(client, 0x30, acpf & 0xff);
653 saa7115_writeregs(client, saa7115_cfg_48_audio); 584 saa7115_write(client, 0x31, (acpf >> 8) & 0xff);
654 if (state->std & V4L2_STD_525_60) { 585 saa7115_write(client, 0x32, (acpf >> 16) & 0x03);
655 saa7115_writeregs(client, saa7115_cfg_60hz_48_audio); 586 saa7115_write(client, 0x34, acni & 0xff);
656 } else { 587 saa7115_write(client, 0x35, (acni >> 8) & 0xff);
657 saa7115_writeregs(client, saa7115_cfg_50hz_48_audio); 588 saa7115_write(client, 0x36, (acni >> 16) & 0x3f);
658 }
659 break;
660 default:
661 saa7115_dbg("invalid audio setting %d\n", freq);
662 return -EINVAL;
663 }
664 state->audclk_freq = freq; 589 state->audclk_freq = freq;
665 return 0; 590 return 0;
666} 591}
@@ -773,24 +698,17 @@ static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client)
773static void saa7115_log_status(struct i2c_client *client) 698static void saa7115_log_status(struct i2c_client *client)
774{ 699{
775 struct saa7115_state *state = i2c_get_clientdata(client); 700 struct saa7115_state *state = i2c_get_clientdata(client);
776 char *audfreq = "undefined";
777 int reg1e, reg1f; 701 int reg1e, reg1f;
778 int signalOk; 702 int signalOk;
779 int vcr; 703 int vcr;
780 704
781 switch (state->audclk_freq) { 705 saa7115_info("Audio frequency: %d Hz\n", state->audclk_freq);
782 case V4L2_AUDCLK_32_KHZ: audfreq = "32 kHz"; break;
783 case V4L2_AUDCLK_441_KHZ: audfreq = "44.1 kHz"; break;
784 case V4L2_AUDCLK_48_KHZ: audfreq = "48 kHz"; break;
785 }
786
787 saa7115_info("Audio frequency: %s\n", audfreq);
788 if (client->name[6] == '4') { 706 if (client->name[6] == '4') {
789 /* status for the saa7114 */ 707 /* status for the saa7114 */
790 reg1f = saa7115_read(client, 0x1f); 708 reg1f = saa7115_read(client, 0x1f);
791 signalOk = (reg1f & 0xc1) == 0x81; 709 signalOk = (reg1f & 0xc1) == 0x81;
792 saa7115_info("Video signal: %s\n", signalOk ? "ok" : "bad"); 710 saa7115_info("Video signal: %s\n", signalOk ? "ok" : "bad");
793 saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); 711 saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
794 return; 712 return;
795 } 713 }
796 714
@@ -807,7 +725,7 @@ static void saa7115_log_status(struct i2c_client *client)
807 saa7115_info("Input: Composite %d\n", state->input); 725 saa7115_info("Input: Composite %d\n", state->input);
808 } 726 }
809 saa7115_info("Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad"); 727 saa7115_info("Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
810 saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz"); 728 saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
811 729
812 switch (reg1e & 0x03) { 730 switch (reg1e & 0x03) {
813 case 1: 731 case 1:
@@ -1108,7 +1026,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
1108 return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg); 1026 return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg);
1109 1027
1110 case VIDIOC_INT_AUDIO_CLOCK_FREQ: 1028 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
1111 return saa7115_set_audio_clock_freq(client, *(enum v4l2_audio_clock_freq *)arg); 1029 return saa7115_set_audio_clock_freq(client, *(u32 *)arg);
1112 1030
1113 case VIDIOC_G_TUNER: 1031 case VIDIOC_G_TUNER:
1114 { 1032 {
@@ -1307,7 +1225,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
1307 state->hue = 0; 1225 state->hue = 0;
1308 state->sat = 64; 1226 state->sat = 64;
1309 state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115; 1227 state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115;
1310 state->audclk_freq = V4L2_AUDCLK_48_KHZ; 1228 state->audclk_freq = 48000;
1311 1229
1312 saa7115_dbg("writing init values\n"); 1230 saa7115_dbg("writing init values\n");
1313 1231
@@ -1317,8 +1235,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
1317 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x); 1235 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
1318 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y); 1236 saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
1319 saa7115_writeregs(client, saa7115_cfg_60hz_video); 1237 saa7115_writeregs(client, saa7115_cfg_60hz_video);
1320 saa7115_writeregs(client, saa7115_cfg_48_audio); 1238 saa7115_set_audio_clock_freq(client, state->audclk_freq);
1321 saa7115_writeregs(client, saa7115_cfg_60hz_48_audio);
1322 saa7115_writeregs(client, saa7115_cfg_reset_scaler); 1239 saa7115_writeregs(client, saa7115_cfg_reset_scaler);
1323 1240
1324 i2c_attach_client(client); 1241 i2c_attach_client(client);
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 2f2402996409..90248d29ed0a 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -26,13 +26,6 @@
26#ifndef V4L2_COMMON_H_ 26#ifndef V4L2_COMMON_H_
27#define V4L2_COMMON_H_ 27#define V4L2_COMMON_H_
28 28
29/* VIDIOC_INT_AUDIO_CLOCK_FREQ */
30enum v4l2_audio_clock_freq {
31 V4L2_AUDCLK_32_KHZ = 32000,
32 V4L2_AUDCLK_441_KHZ = 44100,
33 V4L2_AUDCLK_48_KHZ = 48000,
34};
35
36/* VIDIOC_INT_G_REGISTER and VIDIOC_INT_S_REGISTER */ 29/* VIDIOC_INT_G_REGISTER and VIDIOC_INT_S_REGISTER */
37struct v4l2_register { 30struct v4l2_register {
38 u32 i2c_id; /* I2C driver ID of the I2C chip. 0 for the I2C adapter. */ 31 u32 i2c_id; /* I2C driver ID of the I2C chip. 0 for the I2C adapter. */
@@ -77,10 +70,12 @@ enum v4l2_chip_ident {
77/* Reset the I2C chip */ 70/* Reset the I2C chip */
78#define VIDIOC_INT_RESET _IO ('d', 102) 71#define VIDIOC_INT_RESET _IO ('d', 102)
79 72
80/* Set the frequency of the audio clock output. 73/* Set the frequency (in Hz) of the audio clock output.
81 Used to slave an audio processor to the video decoder, ensuring that audio 74 Used to slave an audio processor to the video decoder, ensuring that audio
82 and video remain synchronized. */ 75 and video remain synchronized.
83#define VIDIOC_INT_AUDIO_CLOCK_FREQ _IOR ('d', 103, enum v4l2_audio_clock_freq) 76 Usual values for the frequency are 48000, 44100 or 32000 Hz.
77 If the frequency is not supported, then -EINVAL is returned. */
78#define VIDIOC_INT_AUDIO_CLOCK_FREQ _IOW ('d', 103, u32)
84 79
85/* Video decoders that support sliced VBI need to implement this ioctl. 80/* Video decoders that support sliced VBI need to implement this ioctl.
86 Field p of the v4l2_sliced_vbi_line struct is set to the start of the VBI 81 Field p of the v4l2_sliced_vbi_line struct is set to the start of the VBI