2 * cx18 ADEC audio functions
4 * Derived from cx25840-audio.c
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
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.
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.
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
24 #include "cx18-driver.h"
26 static int set_audclk_freq(struct cx18 *cx, u32 freq)
28 struct cx18_av_state *state = &cx->av_state;
30 if (freq != 32000 && freq != 44100 && freq != 48000)
33 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
34 cx18_av_write(cx, 0x127, 0x50);
36 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
39 /* VID_PLL and AUX_PLL */
40 cx18_av_write4(cx, 0x108, 0x1408040f);
43 /* 0x8.9504318a * 28,636,363.636 / 0x14 = 32000 * 384 */
44 cx18_av_write4(cx, 0x110, 0x012a0863);
47 /* 0x1.f77f = (4 * 15734.26) / 32000 */
48 cx18_av_write4(cx, 0x900, 0x0801f77f);
49 cx18_av_write4(cx, 0x904, 0x0801f77f);
50 cx18_av_write4(cx, 0x90c, 0x0801f77f);
52 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
53 cx18_av_write(cx, 0x127, 0x54);
55 /* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */
56 cx18_av_write4(cx, 0x12c, 0x11202fff);
60 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
61 * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
63 cx18_av_write4(cx, 0x128, 0xa10d2ef8);
67 /* VID_PLL and AUX_PLL */
68 cx18_av_write4(cx, 0x108, 0x1009040f);
71 /* 0x9.7635e7 * 28,636,363.63 / 0x10 = 44100 * 384 */
72 cx18_av_write4(cx, 0x110, 0x00ec6bce);
75 /* 0x1.6d59 = (4 * 15734.26) / 44100 */
76 cx18_av_write4(cx, 0x900, 0x08016d59);
77 cx18_av_write4(cx, 0x904, 0x08016d59);
78 cx18_av_write4(cx, 0x90c, 0x08016d59);
80 /* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */
81 cx18_av_write4(cx, 0x12c, 0x112092ff);
85 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
86 * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
88 cx18_av_write4(cx, 0x128, 0xa11d4bf8);
92 /* VID_PLL and AUX_PLL */
93 cx18_av_write4(cx, 0x108, 0x100a040f);
96 /* 0xa.4c6b6ea * 28,636,363.63 / 0x10 = 48000 * 384 */
97 cx18_av_write4(cx, 0x110, 0x0098d6dd);
100 /* 0x1.4faa = (4 * 15734.26) / 48000 */
101 cx18_av_write4(cx, 0x900, 0x08014faa);
102 cx18_av_write4(cx, 0x904, 0x08014faa);
103 cx18_av_write4(cx, 0x90c, 0x08014faa);
105 /* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */
106 cx18_av_write4(cx, 0x12c, 0x11205fff);
110 * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
111 * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
113 cx18_av_write4(cx, 0x128, 0xa11193f8);
119 /* VID_PLL and AUX_PLL */
120 cx18_av_write4(cx, 0x108, 0x1e08040f);
123 /* 0x8.9504318 * 28,636,363.63 / 0x1e = 32000 * 256 */
124 cx18_av_write4(cx, 0x110, 0x012a0863);
127 /* 0x1.0000 = 32000/32000 */
128 cx18_av_write4(cx, 0x8f8, 0x08010000);
131 /* 0x2.0000 = 2 * (32000/32000) */
132 cx18_av_write4(cx, 0x900, 0x08020000);
133 cx18_av_write4(cx, 0x904, 0x08020000);
134 cx18_av_write4(cx, 0x90c, 0x08020000);
136 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
137 cx18_av_write(cx, 0x127, 0x54);
139 /* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */
140 cx18_av_write4(cx, 0x12c, 0x11201fff);
144 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
145 * ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
147 cx18_av_write4(cx, 0x128, 0xa10d2ef8);
151 /* VID_PLL and AUX_PLL */
152 cx18_av_write4(cx, 0x108, 0x1809040f);
155 /* 0x9.7635e74 * 28,636,363.63 / 0x18 = 44100 * 256 */
156 cx18_av_write4(cx, 0x110, 0x00ec6bce);
159 /* 0x1.60cd = 44100/32000 */
160 cx18_av_write4(cx, 0x8f8, 0x080160cd);
163 /* 0x1.7385 = 2 * (32000/44100) */
164 cx18_av_write4(cx, 0x900, 0x08017385);
165 cx18_av_write4(cx, 0x904, 0x08017385);
166 cx18_av_write4(cx, 0x90c, 0x08017385);
168 /* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */
169 cx18_av_write4(cx, 0x12c, 0x112061ff);
173 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
174 * ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
176 cx18_av_write4(cx, 0x128, 0xa11d4bf8);
180 /* VID_PLL and AUX_PLL */
181 cx18_av_write4(cx, 0x108, 0x180a040f);
184 /* 0xa.4c6b6ea * 28,636,363.63 / 0x18 = 48000 * 256 */
185 cx18_av_write4(cx, 0x110, 0x0098d6dd);
188 /* 0x1.8000 = 48000/32000 */
189 cx18_av_write4(cx, 0x8f8, 0x08018000);
192 /* 0x1.5555 = 2 * (32000/48000) */
193 cx18_av_write4(cx, 0x900, 0x08015555);
194 cx18_av_write4(cx, 0x904, 0x08015555);
195 cx18_av_write4(cx, 0x90c, 0x08015555);
197 /* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */
198 cx18_av_write4(cx, 0x12c, 0x11203fff);
202 * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
203 * ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
205 cx18_av_write4(cx, 0x128, 0xa11193f8);
210 state->audclk_freq = freq;
215 void cx18_av_audio_set_path(struct cx18 *cx)
217 struct cx18_av_state *state = &cx->av_state;
219 /* stop microcontroller */
220 cx18_av_and_or(cx, 0x803, ~0x10, 0);
222 /* assert soft reset */
223 cx18_av_and_or(cx, 0x810, ~0x1, 0x01);
225 /* Mute everything to prevent the PFFT! */
226 cx18_av_write(cx, 0x8d3, 0x1f);
228 if (state->aud_input <= CX18_AV_AUDIO_SERIAL2) {
229 /* Set Path1 to Serial Audio Input */
230 cx18_av_write4(cx, 0x8d0, 0x01011012);
232 /* The microcontroller should not be started for the
233 * non-tuner inputs: autodetection is specific for
236 /* Set Path1 to Analog Demod Main Channel */
237 cx18_av_write4(cx, 0x8d0, 0x1f063870);
240 set_audclk_freq(cx, state->audclk_freq);
242 /* deassert soft reset */
243 cx18_av_and_or(cx, 0x810, ~0x1, 0x00);
245 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
246 /* When the microcontroller detects the
247 * audio format, it will unmute the lines */
248 cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
252 static int get_volume(struct cx18 *cx)
254 /* Volume runs +18dB to -96dB in 1/2dB steps
255 * change to fit the msp3400 -114dB to +12dB range */
257 /* check PATH1_VOLUME */
258 int vol = 228 - cx18_av_read(cx, 0x8d4);
259 vol = (vol / 2) + 23;
263 static void set_volume(struct cx18 *cx, int volume)
265 /* First convert the volume to msp3400 values (0-127) */
266 int vol = volume >> 9;
267 /* now scale it up to cx18_av values
268 * -114dB to -96dB maps to 0
269 * this should be 19, but in my testing that was 4dB too loud */
276 cx18_av_write(cx, 0x8d4, 228 - (vol * 2));
279 static int get_bass(struct cx18 *cx)
281 /* bass is 49 steps +12dB to -12dB */
283 /* check PATH1_EQ_BASS_VOL */
284 int bass = cx18_av_read(cx, 0x8d9) & 0x3f;
285 bass = (((48 - bass) * 0xffff) + 47) / 48;
289 static void set_bass(struct cx18 *cx, int bass)
291 /* PATH1_EQ_BASS_VOL */
292 cx18_av_and_or(cx, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
295 static int get_treble(struct cx18 *cx)
297 /* treble is 49 steps +12dB to -12dB */
299 /* check PATH1_EQ_TREBLE_VOL */
300 int treble = cx18_av_read(cx, 0x8db) & 0x3f;
301 treble = (((48 - treble) * 0xffff) + 47) / 48;
305 static void set_treble(struct cx18 *cx, int treble)
307 /* PATH1_EQ_TREBLE_VOL */
308 cx18_av_and_or(cx, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
311 static int get_balance(struct cx18 *cx)
313 /* balance is 7 bit, 0 to -96dB */
315 /* check PATH1_BAL_LEVEL */
316 int balance = cx18_av_read(cx, 0x8d5) & 0x7f;
317 /* check PATH1_BAL_LEFT */
318 if ((cx18_av_read(cx, 0x8d5) & 0x80) == 0)
319 balance = 0x80 - balance;
321 balance = 0x80 + balance;
325 static void set_balance(struct cx18 *cx, int balance)
327 int bal = balance >> 8;
330 cx18_av_and_or(cx, 0x8d5, 0x7f, 0x80);
331 /* PATH1_BAL_LEVEL */
332 cx18_av_and_or(cx, 0x8d5, ~0x7f, bal & 0x7f);
335 cx18_av_and_or(cx, 0x8d5, 0x7f, 0x00);
336 /* PATH1_BAL_LEVEL */
337 cx18_av_and_or(cx, 0x8d5, ~0x7f, 0x80 - bal);
341 static int get_mute(struct cx18 *cx)
343 /* check SRC1_MUTE_EN */
344 return cx18_av_read(cx, 0x8d3) & 0x2 ? 1 : 0;
347 static void set_mute(struct cx18 *cx, int mute)
349 struct cx18_av_state *state = &cx->av_state;
351 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
352 /* Must turn off microcontroller in order to mute sound.
353 * Not sure if this is the best method, but it does work.
354 * If the microcontroller is running, then it will undo any
355 * changes to the mute register. */
357 /* disable microcontroller */
358 cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
359 cx18_av_write(cx, 0x8d3, 0x1f);
361 /* enable microcontroller */
362 cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
366 cx18_av_and_or(cx, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
370 int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)
372 struct cx18_av_state *state = &cx->av_state;
373 struct v4l2_control *ctrl = arg;
377 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
378 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
379 cx18_av_and_or(cx, 0x803, ~0x10, 0);
380 cx18_av_write(cx, 0x8d3, 0x1f);
382 cx18_av_and_or(cx, 0x810, ~0x1, 1);
383 retval = set_audclk_freq(cx, *(u32 *)arg);
384 cx18_av_and_or(cx, 0x810, ~0x1, 0);
385 if (state->aud_input > CX18_AV_AUDIO_SERIAL2)
386 cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
391 case V4L2_CID_AUDIO_VOLUME:
392 ctrl->value = get_volume(cx);
394 case V4L2_CID_AUDIO_BASS:
395 ctrl->value = get_bass(cx);
397 case V4L2_CID_AUDIO_TREBLE:
398 ctrl->value = get_treble(cx);
400 case V4L2_CID_AUDIO_BALANCE:
401 ctrl->value = get_balance(cx);
403 case V4L2_CID_AUDIO_MUTE:
404 ctrl->value = get_mute(cx);
413 case V4L2_CID_AUDIO_VOLUME:
414 set_volume(cx, ctrl->value);
416 case V4L2_CID_AUDIO_BASS:
417 set_bass(cx, ctrl->value);
419 case V4L2_CID_AUDIO_TREBLE:
420 set_treble(cx, ctrl->value);
422 case V4L2_CID_AUDIO_BALANCE:
423 set_balance(cx, ctrl->value);
425 case V4L2_CID_AUDIO_MUTE:
426 set_mute(cx, ctrl->value);