aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-av-audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx18/cx18-av-audio.c')
-rw-r--r--drivers/media/video/cx18/cx18-av-audio.c231
1 files changed, 169 insertions, 62 deletions
diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/video/cx18/cx18-av-audio.c
index 0b55837880a7..a2f0ad570434 100644
--- a/drivers/media/video/cx18/cx18-av-audio.c
+++ b/drivers/media/video/cx18/cx18-av-audio.c
@@ -4,6 +4,7 @@
4 * Derived from cx25840-audio.c 4 * Derived from cx25840-audio.c
5 * 5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 * Copyright (C) 2008 Andy Walls <awalls@radix.net>
7 * 8 *
8 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
@@ -30,98 +31,165 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
30 if (freq != 32000 && freq != 44100 && freq != 48000) 31 if (freq != 32000 && freq != 44100 && freq != 48000)
31 return -EINVAL; 32 return -EINVAL;
32 33
33 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ 34 /*
34 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 */
35 69
36 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { 70 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
37 switch (freq) { 71 switch (freq) {
38 case 32000: 72 case 32000:
39 /* VID_PLL and AUX_PLL */ 73 /*
40 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);
41 78
42 /* AUX_PLL_FRAC */ 79 /* VID_PLL Fraction = 0x2be2fe */
43 /* 0x8.9504318a * 28,636,363.636 / 0x14 = 32000 * 384 */ 80 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
44 cx18_av_write4(cx, 0x110, 0x012a0863); 81 cx18_av_write4(cx, 0x10c, 0x002be2fe);
82
83 /* AUX_PLL Fraction = 0x176740c */
84 /* xtal * 0xd.bb3a060/0x20 = 32000 * 384: 393 MHz p-pd*/
85 cx18_av_write4(cx, 0x110, 0x0176740c);
45 86
46 /* src3/4/6_ctl */ 87 /* src3/4/6_ctl */
47 /* 0x1.f77f = (4 * 15734.26) / 32000 */ 88 /* 0x1.f77f = (4 * xtal/8*2/455) / 32000 */
48 cx18_av_write4(cx, 0x900, 0x0801f77f); 89 cx18_av_write4(cx, 0x900, 0x0801f77f);
49 cx18_av_write4(cx, 0x904, 0x0801f77f); 90 cx18_av_write4(cx, 0x904, 0x0801f77f);
50 cx18_av_write4(cx, 0x90c, 0x0801f77f); 91 cx18_av_write4(cx, 0x90c, 0x0801f77f);
51 92
52 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */ 93 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */
53 cx18_av_write(cx, 0x127, 0x54); 94 cx18_av_write(cx, 0x127, 0x60);
54 95
55 /* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */ 96 /* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */
56 cx18_av_write4(cx, 0x12c, 0x11202fff); 97 cx18_av_write4(cx, 0x12c, 0x11202fff);
57 98
58 /* 99 /*
59 * EN_AV_LOCK = 1 100 * EN_AV_LOCK = 0
60 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 = 101 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
61 * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8 102 * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
62 */ 103 */
63 cx18_av_write4(cx, 0x128, 0xa10d2ef8); 104 cx18_av_write4(cx, 0x128, 0xa00d2ef8);
64 break; 105 break;
65 106
66 case 44100: 107 case 44100:
67 /* VID_PLL and AUX_PLL */ 108 /*
68 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);
69 117
70 /* AUX_PLL_FRAC */ 118 /* AUX_PLL Fraction = 0x062a1f2 */
71 /* 0x9.7635e7 * 28,636,363.63 / 0x10 = 44100 * 384 */ 119 /* xtal * 0xe.3150f90/0x18 = 44100 * 384: 406 MHz p-pd*/
72 cx18_av_write4(cx, 0x110, 0x00ec6bce); 120 cx18_av_write4(cx, 0x110, 0x0062a1f2);
73 121
74 /* src3/4/6_ctl */ 122 /* src3/4/6_ctl */
75 /* 0x1.6d59 = (4 * 15734.26) / 44100 */ 123 /* 0x1.6d59 = (4 * xtal/8*2/455) / 44100 */
76 cx18_av_write4(cx, 0x900, 0x08016d59); 124 cx18_av_write4(cx, 0x900, 0x08016d59);
77 cx18_av_write4(cx, 0x904, 0x08016d59); 125 cx18_av_write4(cx, 0x904, 0x08016d59);
78 cx18_av_write4(cx, 0x90c, 0x08016d59); 126 cx18_av_write4(cx, 0x90c, 0x08016d59);
79 127
128 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x18 */
129 cx18_av_write(cx, 0x127, 0x58);
130
80 /* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */ 131 /* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */
81 cx18_av_write4(cx, 0x12c, 0x112092ff); 132 cx18_av_write4(cx, 0x12c, 0x112092ff);
82 133
83 /* 134 /*
84 * EN_AV_LOCK = 1 135 * EN_AV_LOCK = 0
85 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 = 136 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
86 * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8 137 * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
87 */ 138 */
88 cx18_av_write4(cx, 0x128, 0xa11d4bf8); 139 cx18_av_write4(cx, 0x128, 0xa01d4bf8);
89 break; 140 break;
90 141
91 case 48000: 142 case 48000:
92 /* VID_PLL and AUX_PLL */ 143 /*
93 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);
94 148
95 /* AUX_PLL_FRAC */ 149 /* VID_PLL Fraction = 0x2be2fe */
96 /* 0xa.4c6b6ea * 28,636,363.63 / 0x10 = 48000 * 384 */ 150 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
97 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);
98 156
99 /* src3/4/6_ctl */ 157 /* src3/4/6_ctl */
100 /* 0x1.4faa = (4 * 15734.26) / 48000 */ 158 /* 0x1.4faa = (4 * xtal/8*2/455) / 48000 */
101 cx18_av_write4(cx, 0x900, 0x08014faa); 159 cx18_av_write4(cx, 0x900, 0x08014faa);
102 cx18_av_write4(cx, 0x904, 0x08014faa); 160 cx18_av_write4(cx, 0x904, 0x08014faa);
103 cx18_av_write4(cx, 0x90c, 0x08014faa); 161 cx18_av_write4(cx, 0x90c, 0x08014faa);
104 162
163 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
164 cx18_av_write(cx, 0x127, 0x56);
165
105 /* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */ 166 /* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */
106 cx18_av_write4(cx, 0x12c, 0x11205fff); 167 cx18_av_write4(cx, 0x12c, 0x11205fff);
107 168
108 /* 169 /*
109 * EN_AV_LOCK = 1 170 * EN_AV_LOCK = 0
110 * VID_COUNT = 0x1193f8 = 143999.000 * 8 = 171 * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
111 * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8 172 * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
112 */ 173 */
113 cx18_av_write4(cx, 0x128, 0xa11193f8); 174 cx18_av_write4(cx, 0x128, 0xa01193f8);
114 break; 175 break;
115 } 176 }
116 } else { 177 } else {
117 switch (freq) { 178 switch (freq) {
118 case 32000: 179 case 32000:
119 /* VID_PLL and AUX_PLL */ 180 /*
120 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);
121 189
122 /* AUX_PLL_FRAC */ 190 /* AUX_PLL Fraction = 0x176740c */
123 /* 0x8.9504318 * 28,636,363.63 / 0x1e = 32000 * 256 */ 191 /* xtal * 0xd.bb3a060/0x30 = 32000 * 256: 393 MHz p-pd*/
124 cx18_av_write4(cx, 0x110, 0x012a0863); 192 cx18_av_write4(cx, 0x110, 0x0176740c);
125 193
126 /* src1_ctl */ 194 /* src1_ctl */
127 /* 0x1.0000 = 32000/32000 */ 195 /* 0x1.0000 = 32000/32000 */
@@ -133,27 +201,34 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
133 cx18_av_write4(cx, 0x904, 0x08020000); 201 cx18_av_write4(cx, 0x904, 0x08020000);
134 cx18_av_write4(cx, 0x90c, 0x08020000); 202 cx18_av_write4(cx, 0x90c, 0x08020000);
135 203
136 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */ 204 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x30 */
137 cx18_av_write(cx, 0x127, 0x54); 205 cx18_av_write(cx, 0x127, 0x70);
138 206
139 /* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */ 207 /* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */
140 cx18_av_write4(cx, 0x12c, 0x11201fff); 208 cx18_av_write4(cx, 0x12c, 0x11201fff);
141 209
142 /* 210 /*
143 * EN_AV_LOCK = 1 211 * EN_AV_LOCK = 0
144 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 = 212 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
145 * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8 213 * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
146 */ 214 */
147 cx18_av_write4(cx, 0x128, 0xa10d2ef8); 215 cx18_av_write4(cx, 0x128, 0xa00d2ef8);
148 break; 216 break;
149 217
150 case 44100: 218 case 44100:
151 /* VID_PLL and AUX_PLL */ 219 /*
152 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);
153 224
154 /* AUX_PLL_FRAC */ 225 /* VID_PLL Fraction = 0x2be2fe */
155 /* 0x9.7635e74 * 28,636,363.63 / 0x18 = 44100 * 256 */ 226 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
156 cx18_av_write4(cx, 0x110, 0x00ec6bce); 227 cx18_av_write4(cx, 0x10c, 0x002be2fe);
228
229 /* AUX_PLL Fraction = 0x062a1f2 */
230 /* xtal * 0xe.3150f90/0x24 = 44100 * 256: 406 MHz p-pd*/
231 cx18_av_write4(cx, 0x110, 0x0062a1f2);
157 232
158 /* src1_ctl */ 233 /* src1_ctl */
159 /* 0x1.60cd = 44100/32000 */ 234 /* 0x1.60cd = 44100/32000 */
@@ -165,24 +240,34 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
165 cx18_av_write4(cx, 0x904, 0x08017385); 240 cx18_av_write4(cx, 0x904, 0x08017385);
166 cx18_av_write4(cx, 0x90c, 0x08017385); 241 cx18_av_write4(cx, 0x90c, 0x08017385);
167 242
243 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x24 */
244 cx18_av_write(cx, 0x127, 0x64);
245
168 /* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */ 246 /* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */
169 cx18_av_write4(cx, 0x12c, 0x112061ff); 247 cx18_av_write4(cx, 0x12c, 0x112061ff);
170 248
171 /* 249 /*
172 * EN_AV_LOCK = 1 250 * EN_AV_LOCK = 0
173 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 = 251 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
174 * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8 252 * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
175 */ 253 */
176 cx18_av_write4(cx, 0x128, 0xa11d4bf8); 254 cx18_av_write4(cx, 0x128, 0xa01d4bf8);
177 break; 255 break;
178 256
179 case 48000: 257 case 48000:
180 /* VID_PLL and AUX_PLL */ 258 /*
181 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);
263
264 /* VID_PLL Fraction = 0x2be2fe */
265 /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
266 cx18_av_write4(cx, 0x10c, 0x002be2fe);
182 267
183 /* AUX_PLL_FRAC */ 268 /* AUX_PLL Fraction = 0x176740c */
184 /* 0xa.4c6b6ea * 28,636,363.63 / 0x18 = 48000 * 256 */ 269 /* xtal * 0xd.bb3a060/0x20 = 48000 * 256: 393 MHz p-pd*/
185 cx18_av_write4(cx, 0x110, 0x0098d6dd); 270 cx18_av_write4(cx, 0x110, 0x0176740c);
186 271
187 /* src1_ctl */ 272 /* src1_ctl */
188 /* 0x1.8000 = 48000/32000 */ 273 /* 0x1.8000 = 48000/32000 */
@@ -194,15 +279,18 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
194 cx18_av_write4(cx, 0x904, 0x08015555); 279 cx18_av_write4(cx, 0x904, 0x08015555);
195 cx18_av_write4(cx, 0x90c, 0x08015555); 280 cx18_av_write4(cx, 0x90c, 0x08015555);
196 281
282 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */
283 cx18_av_write(cx, 0x127, 0x60);
284
197 /* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */ 285 /* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */
198 cx18_av_write4(cx, 0x12c, 0x11203fff); 286 cx18_av_write4(cx, 0x12c, 0x11203fff);
199 287
200 /* 288 /*
201 * EN_AV_LOCK = 1 289 * EN_AV_LOCK = 0
202 * VID_COUNT = 0x1193f8 = 143999.000 * 8 = 290 * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
203 * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8 291 * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
204 */ 292 */
205 cx18_av_write4(cx, 0x128, 0xa11193f8); 293 cx18_av_write4(cx, 0x128, 0xa01193f8);
206 break; 294 break;
207 } 295 }
208 } 296 }
@@ -215,12 +303,15 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
215void cx18_av_audio_set_path(struct cx18 *cx) 303void cx18_av_audio_set_path(struct cx18 *cx)
216{ 304{
217 struct cx18_av_state *state = &cx->av_state; 305 struct cx18_av_state *state = &cx->av_state;
306 u8 v;
218 307
219 /* stop microcontroller */ 308 /* stop microcontroller */
220 cx18_av_and_or(cx, 0x803, ~0x10, 0); 309 v = cx18_av_read(cx, 0x803) & ~0x10;
310 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
221 311
222 /* assert soft reset */ 312 /* assert soft reset */
223 cx18_av_and_or(cx, 0x810, ~0x1, 0x01); 313 v = cx18_av_read(cx, 0x810) | 0x01;
314 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
224 315
225 /* Mute everything to prevent the PFFT! */ 316 /* Mute everything to prevent the PFFT! */
226 cx18_av_write(cx, 0x8d3, 0x1f); 317 cx18_av_write(cx, 0x8d3, 0x1f);
@@ -240,12 +331,14 @@ void cx18_av_audio_set_path(struct cx18 *cx)
240 set_audclk_freq(cx, state->audclk_freq); 331 set_audclk_freq(cx, state->audclk_freq);
241 332
242 /* deassert soft reset */ 333 /* deassert soft reset */
243 cx18_av_and_or(cx, 0x810, ~0x1, 0x00); 334 v = cx18_av_read(cx, 0x810) & ~0x01;
335 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
244 336
245 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { 337 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
246 /* When the microcontroller detects the 338 /* When the microcontroller detects the
247 * audio format, it will unmute the lines */ 339 * audio format, it will unmute the lines */
248 cx18_av_and_or(cx, 0x803, ~0x10, 0x10); 340 v = cx18_av_read(cx, 0x803) | 0x10;
341 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
249 } 342 }
250} 343}
251 344
@@ -347,19 +440,23 @@ static int get_mute(struct cx18 *cx)
347static void set_mute(struct cx18 *cx, int mute) 440static void set_mute(struct cx18 *cx, int mute)
348{ 441{
349 struct cx18_av_state *state = &cx->av_state; 442 struct cx18_av_state *state = &cx->av_state;
443 u8 v;
350 444
351 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { 445 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
352 /* Must turn off microcontroller in order to mute sound. 446 /* Must turn off microcontroller in order to mute sound.
353 * Not sure if this is the best method, but it does work. 447 * Not sure if this is the best method, but it does work.
354 * If the microcontroller is running, then it will undo any 448 * If the microcontroller is running, then it will undo any
355 * changes to the mute register. */ 449 * changes to the mute register. */
450 v = cx18_av_read(cx, 0x803);
356 if (mute) { 451 if (mute) {
357 /* disable microcontroller */ 452 /* disable microcontroller */
358 cx18_av_and_or(cx, 0x803, ~0x10, 0x00); 453 v &= ~0x10;
454 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
359 cx18_av_write(cx, 0x8d3, 0x1f); 455 cx18_av_write(cx, 0x8d3, 0x1f);
360 } else { 456 } else {
361 /* enable microcontroller */ 457 /* enable microcontroller */
362 cx18_av_and_or(cx, 0x803, ~0x10, 0x10); 458 v |= 0x10;
459 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
363 } 460 }
364 } else { 461 } else {
365 /* SRC1_MUTE_EN */ 462 /* SRC1_MUTE_EN */
@@ -375,16 +472,26 @@ int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)
375 472
376 switch (cmd) { 473 switch (cmd) {
377 case VIDIOC_INT_AUDIO_CLOCK_FREQ: 474 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
475 {
476 u8 v;
378 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { 477 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
379 cx18_av_and_or(cx, 0x803, ~0x10, 0); 478 v = cx18_av_read(cx, 0x803) & ~0x10;
479 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
380 cx18_av_write(cx, 0x8d3, 0x1f); 480 cx18_av_write(cx, 0x8d3, 0x1f);
381 } 481 }
382 cx18_av_and_or(cx, 0x810, ~0x1, 1); 482 v = cx18_av_read(cx, 0x810) | 0x1;
483 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
484
383 retval = set_audclk_freq(cx, *(u32 *)arg); 485 retval = set_audclk_freq(cx, *(u32 *)arg);
384 cx18_av_and_or(cx, 0x810, ~0x1, 0); 486
385 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) 487 v = cx18_av_read(cx, 0x810) & ~0x1;
386 cx18_av_and_or(cx, 0x803, ~0x10, 0x10); 488 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
489 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
490 v = cx18_av_read(cx, 0x803) | 0x10;
491 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
492 }
387 return retval; 493 return retval;
494 }
388 495
389 case VIDIOC_G_CTRL: 496 case VIDIOC_G_CTRL:
390 switch (ctrl->id) { 497 switch (ctrl->id) {