V4L/DVB (9512): cx18: Fix write retries for registers that always change - part 3.
[deliverable/linux.git] / drivers / media / video / cx18 / cx18-av-audio.c
CommitLineData
1c1e45d1
HV
1/*
2 * cx18 ADEC audio functions
3 *
4 * Derived from cx25840-audio.c
5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 */
23
24#include "cx18-driver.h"
25
26static int set_audclk_freq(struct cx18 *cx, u32 freq)
27{
28 struct cx18_av_state *state = &cx->av_state;
29
30 if (freq != 32000 && freq != 44100 && freq != 48000)
31 return -EINVAL;
32
1c1e45d1
HV
33 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
34 cx18_av_write(cx, 0x127, 0x50);
35
81cb727d 36 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
1c1e45d1
HV
37 switch (freq) {
38 case 32000:
39 /* VID_PLL and AUX_PLL */
f8f6296a 40 cx18_av_write4(cx, 0x108, 0x1408040f);
1c1e45d1
HV
41
42 /* AUX_PLL_FRAC */
f8f6296a
AW
43 /* 0x8.9504318a * 28,636,363.636 / 0x14 = 32000 * 384 */
44 cx18_av_write4(cx, 0x110, 0x012a0863);
1c1e45d1 45
f8f6296a
AW
46 /* src3/4/6_ctl */
47 /* 0x1.f77f = (4 * 15734.26) / 32000 */
1c1e45d1
HV
48 cx18_av_write4(cx, 0x900, 0x0801f77f);
49 cx18_av_write4(cx, 0x904, 0x0801f77f);
50 cx18_av_write4(cx, 0x90c, 0x0801f77f);
f8f6296a
AW
51
52 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
53 cx18_av_write(cx, 0x127, 0x54);
35f92b2a
AW
54
55 /* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */
56 cx18_av_write4(cx, 0x12c, 0x11202fff);
57
58 /*
59 * EN_AV_LOCK = 1
60 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
61 * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
62 */
63 cx18_av_write4(cx, 0x128, 0xa10d2ef8);
1c1e45d1
HV
64 break;
65
66 case 44100:
67 /* VID_PLL and AUX_PLL */
68 cx18_av_write4(cx, 0x108, 0x1009040f);
69
70 /* AUX_PLL_FRAC */
35f92b2a
AW
71 /* 0x9.7635e7 * 28,636,363.63 / 0x10 = 44100 * 384 */
72 cx18_av_write4(cx, 0x110, 0x00ec6bce);
1c1e45d1 73
f8f6296a
AW
74 /* src3/4/6_ctl */
75 /* 0x1.6d59 = (4 * 15734.26) / 44100 */
1c1e45d1
HV
76 cx18_av_write4(cx, 0x900, 0x08016d59);
77 cx18_av_write4(cx, 0x904, 0x08016d59);
78 cx18_av_write4(cx, 0x90c, 0x08016d59);
35f92b2a
AW
79
80 /* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */
81 cx18_av_write4(cx, 0x12c, 0x112092ff);
82
83 /*
84 * EN_AV_LOCK = 1
85 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
86 * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
87 */
88 cx18_av_write4(cx, 0x128, 0xa11d4bf8);
1c1e45d1
HV
89 break;
90
91 case 48000:
92 /* VID_PLL and AUX_PLL */
93 cx18_av_write4(cx, 0x108, 0x100a040f);
94
95 /* AUX_PLL_FRAC */
35f92b2a
AW
96 /* 0xa.4c6b6ea * 28,636,363.63 / 0x10 = 48000 * 384 */
97 cx18_av_write4(cx, 0x110, 0x0098d6dd);
1c1e45d1 98
f8f6296a
AW
99 /* src3/4/6_ctl */
100 /* 0x1.4faa = (4 * 15734.26) / 48000 */
1c1e45d1
HV
101 cx18_av_write4(cx, 0x900, 0x08014faa);
102 cx18_av_write4(cx, 0x904, 0x08014faa);
103 cx18_av_write4(cx, 0x90c, 0x08014faa);
35f92b2a
AW
104
105 /* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */
106 cx18_av_write4(cx, 0x12c, 0x11205fff);
107
108 /*
109 * EN_AV_LOCK = 1
110 * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
111 * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
112 */
113 cx18_av_write4(cx, 0x128, 0xa11193f8);
1c1e45d1
HV
114 break;
115 }
116 } else {
117 switch (freq) {
118 case 32000:
119 /* VID_PLL and AUX_PLL */
120 cx18_av_write4(cx, 0x108, 0x1e08040f);
121
122 /* AUX_PLL_FRAC */
35f92b2a
AW
123 /* 0x8.9504318 * 28,636,363.63 / 0x1e = 32000 * 256 */
124 cx18_av_write4(cx, 0x110, 0x012a0863);
1c1e45d1 125
f8f6296a
AW
126 /* src1_ctl */
127 /* 0x1.0000 = 32000/32000 */
1c1e45d1
HV
128 cx18_av_write4(cx, 0x8f8, 0x08010000);
129
f8f6296a
AW
130 /* src3/4/6_ctl */
131 /* 0x2.0000 = 2 * (32000/32000) */
1c1e45d1
HV
132 cx18_av_write4(cx, 0x900, 0x08020000);
133 cx18_av_write4(cx, 0x904, 0x08020000);
134 cx18_av_write4(cx, 0x90c, 0x08020000);
135
136 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
137 cx18_av_write(cx, 0x127, 0x54);
35f92b2a
AW
138
139 /* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */
140 cx18_av_write4(cx, 0x12c, 0x11201fff);
141
142 /*
143 * EN_AV_LOCK = 1
144 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
145 * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
146 */
147 cx18_av_write4(cx, 0x128, 0xa10d2ef8);
1c1e45d1
HV
148 break;
149
150 case 44100:
151 /* VID_PLL and AUX_PLL */
152 cx18_av_write4(cx, 0x108, 0x1809040f);
153
154 /* AUX_PLL_FRAC */
35f92b2a
AW
155 /* 0x9.7635e74 * 28,636,363.63 / 0x18 = 44100 * 256 */
156 cx18_av_write4(cx, 0x110, 0x00ec6bce);
1c1e45d1 157
f8f6296a
AW
158 /* src1_ctl */
159 /* 0x1.60cd = 44100/32000 */
1c1e45d1
HV
160 cx18_av_write4(cx, 0x8f8, 0x080160cd);
161
f8f6296a
AW
162 /* src3/4/6_ctl */
163 /* 0x1.7385 = 2 * (32000/44100) */
1c1e45d1
HV
164 cx18_av_write4(cx, 0x900, 0x08017385);
165 cx18_av_write4(cx, 0x904, 0x08017385);
166 cx18_av_write4(cx, 0x90c, 0x08017385);
35f92b2a
AW
167
168 /* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */
169 cx18_av_write4(cx, 0x12c, 0x112061ff);
170
171 /*
172 * EN_AV_LOCK = 1
173 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
174 * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
175 */
176 cx18_av_write4(cx, 0x128, 0xa11d4bf8);
1c1e45d1
HV
177 break;
178
179 case 48000:
180 /* VID_PLL and AUX_PLL */
181 cx18_av_write4(cx, 0x108, 0x180a040f);
182
183 /* AUX_PLL_FRAC */
35f92b2a
AW
184 /* 0xa.4c6b6ea * 28,636,363.63 / 0x18 = 48000 * 256 */
185 cx18_av_write4(cx, 0x110, 0x0098d6dd);
1c1e45d1 186
f8f6296a
AW
187 /* src1_ctl */
188 /* 0x1.8000 = 48000/32000 */
1c1e45d1
HV
189 cx18_av_write4(cx, 0x8f8, 0x08018000);
190
f8f6296a
AW
191 /* src3/4/6_ctl */
192 /* 0x1.5555 = 2 * (32000/48000) */
1c1e45d1
HV
193 cx18_av_write4(cx, 0x900, 0x08015555);
194 cx18_av_write4(cx, 0x904, 0x08015555);
195 cx18_av_write4(cx, 0x90c, 0x08015555);
35f92b2a
AW
196
197 /* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */
198 cx18_av_write4(cx, 0x12c, 0x11203fff);
199
200 /*
201 * EN_AV_LOCK = 1
202 * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
203 * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
204 */
205 cx18_av_write4(cx, 0x128, 0xa11193f8);
1c1e45d1
HV
206 break;
207 }
208 }
209
210 state->audclk_freq = freq;
211
212 return 0;
213}
214
215void cx18_av_audio_set_path(struct cx18 *cx)
216{
217 struct cx18_av_state *state = &cx->av_state;
ced07371 218 u8 v;
1c1e45d1
HV
219
220 /* stop microcontroller */
ced07371
AW
221 v = cx18_av_read(cx, 0x803) & ~0x10;
222 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
1c1e45d1
HV
223
224 /* assert soft reset */
ced07371
AW
225 v = cx18_av_read(cx, 0x810) | 0x01;
226 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
1c1e45d1
HV
227
228 /* Mute everything to prevent the PFFT! */
229 cx18_av_write(cx, 0x8d3, 0x1f);
230
81cb727d 231 if (state->aud_input <= CX18_AV_AUDIO_SERIAL2) {
1c1e45d1
HV
232 /* Set Path1 to Serial Audio Input */
233 cx18_av_write4(cx, 0x8d0, 0x01011012);
234
235 /* The microcontroller should not be started for the
236 * non-tuner inputs: autodetection is specific for
237 * TV audio. */
238 } else {
239 /* Set Path1 to Analog Demod Main Channel */
240 cx18_av_write4(cx, 0x8d0, 0x1f063870);
241 }
242
243 set_audclk_freq(cx, state->audclk_freq);
244
245 /* deassert soft reset */
ced07371
AW
246 v = cx18_av_read(cx, 0x810) & ~0x01;
247 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
1c1e45d1 248
81cb727d 249 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
1c1e45d1
HV
250 /* When the microcontroller detects the
251 * audio format, it will unmute the lines */
ced07371
AW
252 v = cx18_av_read(cx, 0x803) | 0x10;
253 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
1c1e45d1
HV
254 }
255}
256
257static int get_volume(struct cx18 *cx)
258{
259 /* Volume runs +18dB to -96dB in 1/2dB steps
260 * change to fit the msp3400 -114dB to +12dB range */
261
262 /* check PATH1_VOLUME */
263 int vol = 228 - cx18_av_read(cx, 0x8d4);
264 vol = (vol / 2) + 23;
265 return vol << 9;
266}
267
268static void set_volume(struct cx18 *cx, int volume)
269{
270 /* First convert the volume to msp3400 values (0-127) */
271 int vol = volume >> 9;
272 /* now scale it up to cx18_av values
273 * -114dB to -96dB maps to 0
274 * this should be 19, but in my testing that was 4dB too loud */
275 if (vol <= 23)
276 vol = 0;
277 else
278 vol -= 23;
279
280 /* PATH1_VOLUME */
281 cx18_av_write(cx, 0x8d4, 228 - (vol * 2));
282}
283
284static int get_bass(struct cx18 *cx)
285{
286 /* bass is 49 steps +12dB to -12dB */
287
288 /* check PATH1_EQ_BASS_VOL */
289 int bass = cx18_av_read(cx, 0x8d9) & 0x3f;
290 bass = (((48 - bass) * 0xffff) + 47) / 48;
291 return bass;
292}
293
294static void set_bass(struct cx18 *cx, int bass)
295{
296 /* PATH1_EQ_BASS_VOL */
297 cx18_av_and_or(cx, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
298}
299
300static int get_treble(struct cx18 *cx)
301{
302 /* treble is 49 steps +12dB to -12dB */
303
304 /* check PATH1_EQ_TREBLE_VOL */
305 int treble = cx18_av_read(cx, 0x8db) & 0x3f;
306 treble = (((48 - treble) * 0xffff) + 47) / 48;
307 return treble;
308}
309
310static void set_treble(struct cx18 *cx, int treble)
311{
312 /* PATH1_EQ_TREBLE_VOL */
313 cx18_av_and_or(cx, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
314}
315
316static int get_balance(struct cx18 *cx)
317{
318 /* balance is 7 bit, 0 to -96dB */
319
320 /* check PATH1_BAL_LEVEL */
321 int balance = cx18_av_read(cx, 0x8d5) & 0x7f;
322 /* check PATH1_BAL_LEFT */
323 if ((cx18_av_read(cx, 0x8d5) & 0x80) == 0)
324 balance = 0x80 - balance;
325 else
326 balance = 0x80 + balance;
327 return balance << 8;
328}
329
330static void set_balance(struct cx18 *cx, int balance)
331{
332 int bal = balance >> 8;
333 if (bal > 0x80) {
334 /* PATH1_BAL_LEFT */
335 cx18_av_and_or(cx, 0x8d5, 0x7f, 0x80);
336 /* PATH1_BAL_LEVEL */
337 cx18_av_and_or(cx, 0x8d5, ~0x7f, bal & 0x7f);
338 } else {
339 /* PATH1_BAL_LEFT */
340 cx18_av_and_or(cx, 0x8d5, 0x7f, 0x00);
341 /* PATH1_BAL_LEVEL */
342 cx18_av_and_or(cx, 0x8d5, ~0x7f, 0x80 - bal);
343 }
344}
345
346static int get_mute(struct cx18 *cx)
347{
348 /* check SRC1_MUTE_EN */
349 return cx18_av_read(cx, 0x8d3) & 0x2 ? 1 : 0;
350}
351
352static void set_mute(struct cx18 *cx, int mute)
353{
354 struct cx18_av_state *state = &cx->av_state;
ced07371 355 u8 v;
1c1e45d1 356
81cb727d 357 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
1c1e45d1
HV
358 /* Must turn off microcontroller in order to mute sound.
359 * Not sure if this is the best method, but it does work.
360 * If the microcontroller is running, then it will undo any
361 * changes to the mute register. */
ced07371 362 v = cx18_av_read(cx, 0x803);
1c1e45d1
HV
363 if (mute) {
364 /* disable microcontroller */
ced07371
AW
365 v &= ~0x10;
366 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
1c1e45d1
HV
367 cx18_av_write(cx, 0x8d3, 0x1f);
368 } else {
369 /* enable microcontroller */
ced07371
AW
370 v |= 0x10;
371 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
1c1e45d1
HV
372 }
373 } else {
374 /* SRC1_MUTE_EN */
375 cx18_av_and_or(cx, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
376 }
377}
378
379int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)
380{
381 struct cx18_av_state *state = &cx->av_state;
382 struct v4l2_control *ctrl = arg;
383 int retval;
384
385 switch (cmd) {
386 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
ced07371
AW
387 {
388 u8 v;
81cb727d 389 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
ced07371
AW
390 v = cx18_av_read(cx, 0x803) & ~0x10;
391 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
1c1e45d1
HV
392 cx18_av_write(cx, 0x8d3, 0x1f);
393 }
ced07371
AW
394 v = cx18_av_read(cx, 0x810) | 0x1;
395 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
396
1c1e45d1 397 retval = set_audclk_freq(cx, *(u32 *)arg);
ced07371
AW
398
399 v = cx18_av_read(cx, 0x810) & ~0x1;
400 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
401 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
402 v = cx18_av_read(cx, 0x803) | 0x10;
403 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
404 }
1c1e45d1 405 return retval;
ced07371 406 }
1c1e45d1
HV
407
408 case VIDIOC_G_CTRL:
409 switch (ctrl->id) {
410 case V4L2_CID_AUDIO_VOLUME:
411 ctrl->value = get_volume(cx);
412 break;
413 case V4L2_CID_AUDIO_BASS:
414 ctrl->value = get_bass(cx);
415 break;
416 case V4L2_CID_AUDIO_TREBLE:
417 ctrl->value = get_treble(cx);
418 break;
419 case V4L2_CID_AUDIO_BALANCE:
420 ctrl->value = get_balance(cx);
421 break;
422 case V4L2_CID_AUDIO_MUTE:
423 ctrl->value = get_mute(cx);
424 break;
425 default:
426 return -EINVAL;
427 }
428 break;
429
430 case VIDIOC_S_CTRL:
431 switch (ctrl->id) {
432 case V4L2_CID_AUDIO_VOLUME:
433 set_volume(cx, ctrl->value);
434 break;
435 case V4L2_CID_AUDIO_BASS:
436 set_bass(cx, ctrl->value);
437 break;
438 case V4L2_CID_AUDIO_TREBLE:
439 set_treble(cx, ctrl->value);
440 break;
441 case V4L2_CID_AUDIO_BALANCE:
442 set_balance(cx, ctrl->value);
443 break;
444 case V4L2_CID_AUDIO_MUTE:
445 set_mute(cx, ctrl->value);
446 break;
447 default:
448 return -EINVAL;
449 }
450 break;
451
452 default:
453 return -EINVAL;
454 }
455
456 return 0;
457}
This page took 0.1122 seconds and 5 git commands to generate.