diff options
Diffstat (limited to 'drivers/media/video/cx18/cx18-av-audio.c')
-rw-r--r-- | drivers/media/video/cx18/cx18-av-audio.c | 231 |
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) | |||
215 | void cx18_av_audio_set_path(struct cx18 *cx) | 303 | void 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) | |||
347 | static void set_mute(struct cx18 *cx, int mute) | 440 | static 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) { |