aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-av-audio.c
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2008-12-20 21:48:57 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-30 06:39:24 -0500
commit55d81aa5c11f9da510a72cc48fd59689b3e91e3a (patch)
tree346221769914f99581eff5cdb5afe068acacd77b /drivers/media/video/cx18/cx18-av-audio.c
parent57e24b629a5282bee24aaff44977270a3e462041 (diff)
V4L/DVB (9937): cx18: Use a consistent crystal value for computing all PLL parameters
Use a consistent crystal value of 28.636360 MHz for computing all PLL parameters so clocks don't have relative error due to assumed crystal value mismatches. Also aimed to have all PLLs run their VOCs at close to 400 MHz to minimze the error of these PLLs as frequency synthesizers. Also set the VDCLK and AIMCLK PLLs to sane values before the APU and CPU firmware are loaded. Also fixed I2S Master clock dividers. Many thanks to Mike Bradley and Jeff Campbell for reporting this problem and suggesting the solution, researching and experimenting, and performing extensive testing to support their suggested solution. Reported-by: Jeff Campbell <jac1dlists@gmail.com> Reported-by: Mike Bradley <mike.bradley@incanetworks.com> Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18/cx18-av-audio.c')
-rw-r--r--drivers/media/video/cx18/cx18-av-audio.c165
1 files changed, 126 insertions, 39 deletions
diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/video/cx18/cx18-av-audio.c
index 148f710974d5..a2f0ad570434 100644
--- a/drivers/media/video/cx18/cx18-av-audio.c
+++ b/drivers/media/video/cx18/cx18-av-audio.c
@@ -31,27 +31,67 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
31 if (freq != 32000 && freq != 44100 && freq != 48000) 31 if (freq != 32000 && freq != 44100 && freq != 48000)
32 return -EINVAL; 32 return -EINVAL;
33 33
34 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ 34 /*
35 cx18_av_write(cx, 0x127, 0x50); 35 * The PLL parameters are based on the external crystal frequency that
36 * would ideally be:
37 *
38 * NTSC Color subcarrier freq * 8 =
39 * 4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz
40 *
41 * The accidents of history and rationale that explain from where this
42 * combination of magic numbers originate can be found in:
43 *
44 * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in
45 * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-80
46 *
47 * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the
48 * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-83
49 *
50 * As Mike Bradley has rightly pointed out, it's not the exact crystal
51 * frequency that matters, only that all parts of the driver and
52 * firmware are using the same value (close to the ideal value).
53 *
54 * Since I have a strong suspicion that, if the firmware ever assumes a
55 * crystal value at all, it will assume 28.636360 MHz, the crystal
56 * freq used in calculations in this driver will be:
57 *
58 * xtal_freq = 28.636360 MHz
59 *
60 * an error of less than 0.13 ppm which is way, way better than any off
61 * the shelf crystal will have for accuracy anyway.
62 *
63 * Below I aim to run the PLLs' VCOs near 400 MHz to minimze error.
64 *
65 * Many thanks to Jeff Campbell and Mike Bradley for their extensive
66 * investigation, experimentation, testing, and suggested solutions of
67 * of audio/video sync problems with SVideo and CVBS captures.
68 */
36 69
37 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { 70 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
38 switch (freq) { 71 switch (freq) {
39 case 32000: 72 case 32000:
40 /* VID_PLL and AUX_PLL */ 73 /*
41 cx18_av_write4(cx, 0x108, 0x1408040f); 74 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
75 * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x20
76 */
77 cx18_av_write4(cx, 0x108, 0x200d040f);
78
79 /* VID_PLL Fraction = 0x2be2fe */
80 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
81 cx18_av_write4(cx, 0x10c, 0x002be2fe);
42 82
43 /* AUX_PLL_FRAC */ 83 /* AUX_PLL Fraction = 0x176740c */
44 /* 0x8.9504318a * 28,636,363.636 / 0x14 = 32000 * 384 */ 84 /* xtal * 0xd.bb3a060/0x20 = 32000 * 384: 393 MHz p-pd*/
45 cx18_av_write4(cx, 0x110, 0x012a0863); 85 cx18_av_write4(cx, 0x110, 0x0176740c);
46 86
47 /* src3/4/6_ctl */ 87 /* src3/4/6_ctl */
48 /* 0x1.f77f = (4 * 15734.26) / 32000 */ 88 /* 0x1.f77f = (4 * xtal/8*2/455) / 32000 */
49 cx18_av_write4(cx, 0x900, 0x0801f77f); 89 cx18_av_write4(cx, 0x900, 0x0801f77f);
50 cx18_av_write4(cx, 0x904, 0x0801f77f); 90 cx18_av_write4(cx, 0x904, 0x0801f77f);
51 cx18_av_write4(cx, 0x90c, 0x0801f77f); 91 cx18_av_write4(cx, 0x90c, 0x0801f77f);
52 92
53 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */ 93 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */
54 cx18_av_write(cx, 0x127, 0x54); 94 cx18_av_write(cx, 0x127, 0x60);
55 95
56 /* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */ 96 /* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */
57 cx18_av_write4(cx, 0x12c, 0x11202fff); 97 cx18_av_write4(cx, 0x12c, 0x11202fff);
@@ -65,19 +105,29 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
65 break; 105 break;
66 106
67 case 44100: 107 case 44100:
68 /* VID_PLL and AUX_PLL */ 108 /*
69 cx18_av_write4(cx, 0x108, 0x1009040f); 109 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
110 * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x18
111 */
112 cx18_av_write4(cx, 0x108, 0x180e040f);
113
114 /* VID_PLL Fraction = 0x2be2fe */
115 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
116 cx18_av_write4(cx, 0x10c, 0x002be2fe);
70 117
71 /* AUX_PLL_FRAC */ 118 /* AUX_PLL Fraction = 0x062a1f2 */
72 /* 0x9.7635e7 * 28,636,363.63 / 0x10 = 44100 * 384 */ 119 /* xtal * 0xe.3150f90/0x18 = 44100 * 384: 406 MHz p-pd*/
73 cx18_av_write4(cx, 0x110, 0x00ec6bce); 120 cx18_av_write4(cx, 0x110, 0x0062a1f2);
74 121
75 /* src3/4/6_ctl */ 122 /* src3/4/6_ctl */
76 /* 0x1.6d59 = (4 * 15734.26) / 44100 */ 123 /* 0x1.6d59 = (4 * xtal/8*2/455) / 44100 */
77 cx18_av_write4(cx, 0x900, 0x08016d59); 124 cx18_av_write4(cx, 0x900, 0x08016d59);
78 cx18_av_write4(cx, 0x904, 0x08016d59); 125 cx18_av_write4(cx, 0x904, 0x08016d59);
79 cx18_av_write4(cx, 0x90c, 0x08016d59); 126 cx18_av_write4(cx, 0x90c, 0x08016d59);
80 127
128 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x18 */
129 cx18_av_write(cx, 0x127, 0x58);
130
81 /* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */ 131 /* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */
82 cx18_av_write4(cx, 0x12c, 0x112092ff); 132 cx18_av_write4(cx, 0x12c, 0x112092ff);
83 133
@@ -90,19 +140,29 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
90 break; 140 break;
91 141
92 case 48000: 142 case 48000:
93 /* VID_PLL and AUX_PLL */ 143 /*
94 cx18_av_write4(cx, 0x108, 0x100a040f); 144 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
145 * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x16
146 */
147 cx18_av_write4(cx, 0x108, 0x160e040f);
95 148
96 /* AUX_PLL_FRAC */ 149 /* VID_PLL Fraction = 0x2be2fe */
97 /* 0xa.4c6b6ea * 28,636,363.63 / 0x10 = 48000 * 384 */ 150 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
98 cx18_av_write4(cx, 0x110, 0x0098d6dd); 151 cx18_av_write4(cx, 0x10c, 0x002be2fe);
152
153 /* AUX_PLL Fraction = 0x05227ad */
154 /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz p-pd*/
155 cx18_av_write4(cx, 0x110, 0x005227ad);
99 156
100 /* src3/4/6_ctl */ 157 /* src3/4/6_ctl */
101 /* 0x1.4faa = (4 * 15734.26) / 48000 */ 158 /* 0x1.4faa = (4 * xtal/8*2/455) / 48000 */
102 cx18_av_write4(cx, 0x900, 0x08014faa); 159 cx18_av_write4(cx, 0x900, 0x08014faa);
103 cx18_av_write4(cx, 0x904, 0x08014faa); 160 cx18_av_write4(cx, 0x904, 0x08014faa);
104 cx18_av_write4(cx, 0x90c, 0x08014faa); 161 cx18_av_write4(cx, 0x90c, 0x08014faa);
105 162
163 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
164 cx18_av_write(cx, 0x127, 0x56);
165
106 /* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */ 166 /* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */
107 cx18_av_write4(cx, 0x12c, 0x11205fff); 167 cx18_av_write4(cx, 0x12c, 0x11205fff);
108 168
@@ -117,12 +177,19 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
117 } else { 177 } else {
118 switch (freq) { 178 switch (freq) {
119 case 32000: 179 case 32000:
120 /* VID_PLL and AUX_PLL */ 180 /*
121 cx18_av_write4(cx, 0x108, 0x1e08040f); 181 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
182 * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x30
183 */
184 cx18_av_write4(cx, 0x108, 0x300d040f);
185
186 /* VID_PLL Fraction = 0x2be2fe */
187 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
188 cx18_av_write4(cx, 0x10c, 0x002be2fe);
122 189
123 /* AUX_PLL_FRAC */ 190 /* AUX_PLL Fraction = 0x176740c */
124 /* 0x8.9504318 * 28,636,363.63 / 0x1e = 32000 * 256 */ 191 /* xtal * 0xd.bb3a060/0x30 = 32000 * 256: 393 MHz p-pd*/
125 cx18_av_write4(cx, 0x110, 0x012a0863); 192 cx18_av_write4(cx, 0x110, 0x0176740c);
126 193
127 /* src1_ctl */ 194 /* src1_ctl */
128 /* 0x1.0000 = 32000/32000 */ 195 /* 0x1.0000 = 32000/32000 */
@@ -134,8 +201,8 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
134 cx18_av_write4(cx, 0x904, 0x08020000); 201 cx18_av_write4(cx, 0x904, 0x08020000);
135 cx18_av_write4(cx, 0x90c, 0x08020000); 202 cx18_av_write4(cx, 0x90c, 0x08020000);
136 203
137 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */ 204 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x30 */
138 cx18_av_write(cx, 0x127, 0x54); 205 cx18_av_write(cx, 0x127, 0x70);
139 206
140 /* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */ 207 /* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */
141 cx18_av_write4(cx, 0x12c, 0x11201fff); 208 cx18_av_write4(cx, 0x12c, 0x11201fff);
@@ -149,12 +216,19 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
149 break; 216 break;
150 217
151 case 44100: 218 case 44100:
152 /* VID_PLL and AUX_PLL */ 219 /*
153 cx18_av_write4(cx, 0x108, 0x1809040f); 220 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
221 * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x24
222 */
223 cx18_av_write4(cx, 0x108, 0x240e040f);
224
225 /* VID_PLL Fraction = 0x2be2fe */
226 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
227 cx18_av_write4(cx, 0x10c, 0x002be2fe);
154 228
155 /* AUX_PLL_FRAC */ 229 /* AUX_PLL Fraction = 0x062a1f2 */
156 /* 0x9.7635e74 * 28,636,363.63 / 0x18 = 44100 * 256 */ 230 /* xtal * 0xe.3150f90/0x24 = 44100 * 256: 406 MHz p-pd*/
157 cx18_av_write4(cx, 0x110, 0x00ec6bce); 231 cx18_av_write4(cx, 0x110, 0x0062a1f2);
158 232
159 /* src1_ctl */ 233 /* src1_ctl */
160 /* 0x1.60cd = 44100/32000 */ 234 /* 0x1.60cd = 44100/32000 */
@@ -166,6 +240,9 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
166 cx18_av_write4(cx, 0x904, 0x08017385); 240 cx18_av_write4(cx, 0x904, 0x08017385);
167 cx18_av_write4(cx, 0x90c, 0x08017385); 241 cx18_av_write4(cx, 0x90c, 0x08017385);
168 242
243 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x24 */
244 cx18_av_write(cx, 0x127, 0x64);
245
169 /* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */ 246 /* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */
170 cx18_av_write4(cx, 0x12c, 0x112061ff); 247 cx18_av_write4(cx, 0x12c, 0x112061ff);
171 248
@@ -178,12 +255,19 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
178 break; 255 break;
179 256
180 case 48000: 257 case 48000:
181 /* VID_PLL and AUX_PLL */ 258 /*
182 cx18_av_write4(cx, 0x108, 0x180a040f); 259 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
260 * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x20
261 */
262 cx18_av_write4(cx, 0x108, 0x200d040f);
183 263
184 /* AUX_PLL_FRAC */ 264 /* VID_PLL Fraction = 0x2be2fe */
185 /* 0xa.4c6b6ea * 28,636,363.63 / 0x18 = 48000 * 256 */ 265 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
186 cx18_av_write4(cx, 0x110, 0x0098d6dd); 266 cx18_av_write4(cx, 0x10c, 0x002be2fe);
267
268 /* AUX_PLL Fraction = 0x176740c */
269 /* xtal * 0xd.bb3a060/0x20 = 48000 * 256: 393 MHz p-pd*/
270 cx18_av_write4(cx, 0x110, 0x0176740c);
187 271
188 /* src1_ctl */ 272 /* src1_ctl */
189 /* 0x1.8000 = 48000/32000 */ 273 /* 0x1.8000 = 48000/32000 */
@@ -195,6 +279,9 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
195 cx18_av_write4(cx, 0x904, 0x08015555); 279 cx18_av_write4(cx, 0x904, 0x08015555);
196 cx18_av_write4(cx, 0x90c, 0x08015555); 280 cx18_av_write4(cx, 0x90c, 0x08015555);
197 281
282 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */
283 cx18_av_write(cx, 0x127, 0x60);
284
198 /* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */ 285 /* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */
199 cx18_av_write4(cx, 0x12c, 0x11203fff); 286 cx18_av_write4(cx, 0x12c, 0x11203fff);
200 287