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 /* common for all inputs and rates */
34 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
35 cx18_av_write(cx, 0x127, 0x50);
37 if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
40 /* VID_PLL and AUX_PLL */
41 cx18_av_write4(cx, 0x108, 0x1006040f);
44 cx18_av_write4(cx, 0x110, 0x01bb39ee);
46 /* src3/4/6_ctl = 0x0801f77f */
47 cx18_av_write4(cx, 0x900, 0x0801f77f);
48 cx18_av_write4(cx, 0x904, 0x0801f77f);
49 cx18_av_write4(cx, 0x90c, 0x0801f77f);
53 /* VID_PLL and AUX_PLL */
54 cx18_av_write4(cx, 0x108, 0x1009040f);
57 cx18_av_write4(cx, 0x110, 0x00ec6bd6);
59 /* src3/4/6_ctl = 0x08016d59 */
60 cx18_av_write4(cx, 0x900, 0x08016d59);
61 cx18_av_write4(cx, 0x904, 0x08016d59);
62 cx18_av_write4(cx, 0x90c, 0x08016d59);
66 /* VID_PLL and AUX_PLL */
67 cx18_av_write4(cx, 0x108, 0x100a040f);
70 cx18_av_write4(cx, 0x110, 0x0098d6e5);
72 /* src3/4/6_ctl = 0x08014faa */
73 cx18_av_write4(cx, 0x900, 0x08014faa);
74 cx18_av_write4(cx, 0x904, 0x08014faa);
75 cx18_av_write4(cx, 0x90c, 0x08014faa);
81 /* VID_PLL and AUX_PLL */
82 cx18_av_write4(cx, 0x108, 0x1e08040f);
85 cx18_av_write4(cx, 0x110, 0x012a0869);
87 /* src1_ctl = 0x08010000 */
88 cx18_av_write4(cx, 0x8f8, 0x08010000);
90 /* src3/4/6_ctl = 0x08020000 */
91 cx18_av_write4(cx, 0x900, 0x08020000);
92 cx18_av_write4(cx, 0x904, 0x08020000);
93 cx18_av_write4(cx, 0x90c, 0x08020000);
95 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
96 cx18_av_write(cx, 0x127, 0x54);
100 /* VID_PLL and AUX_PLL */
101 cx18_av_write4(cx, 0x108, 0x1809040f);
104 cx18_av_write4(cx, 0x110, 0x00ec6bd6);
106 /* src1_ctl = 0x08010000 */
107 cx18_av_write4(cx, 0x8f8, 0x080160cd);
109 /* src3/4/6_ctl = 0x08020000 */
110 cx18_av_write4(cx, 0x900, 0x08017385);
111 cx18_av_write4(cx, 0x904, 0x08017385);
112 cx18_av_write4(cx, 0x90c, 0x08017385);
116 /* VID_PLL and AUX_PLL */
117 cx18_av_write4(cx, 0x108, 0x180a040f);
120 cx18_av_write4(cx, 0x110, 0x0098d6e5);
122 /* src1_ctl = 0x08010000 */
123 cx18_av_write4(cx, 0x8f8, 0x08018000);
125 /* src3/4/6_ctl = 0x08020000 */
126 cx18_av_write4(cx, 0x900, 0x08015555);
127 cx18_av_write4(cx, 0x904, 0x08015555);
128 cx18_av_write4(cx, 0x90c, 0x08015555);
133 state->audclk_freq = freq;
138 void cx18_av_audio_set_path(struct cx18 *cx)
140 struct cx18_av_state *state = &cx->av_state;
142 /* stop microcontroller */
143 cx18_av_and_or(cx, 0x803, ~0x10, 0);
145 /* assert soft reset */
146 cx18_av_and_or(cx, 0x810, ~0x1, 0x01);
148 /* Mute everything to prevent the PFFT! */
149 cx18_av_write(cx, 0x8d3, 0x1f);
151 if (state->aud_input == CX18_AV_AUDIO_SERIAL) {
152 /* Set Path1 to Serial Audio Input */
153 cx18_av_write4(cx, 0x8d0, 0x01011012);
155 /* The microcontroller should not be started for the
156 * non-tuner inputs: autodetection is specific for
159 /* Set Path1 to Analog Demod Main Channel */
160 cx18_av_write4(cx, 0x8d0, 0x1f063870);
163 set_audclk_freq(cx, state->audclk_freq);
165 /* deassert soft reset */
166 cx18_av_and_or(cx, 0x810, ~0x1, 0x00);
168 if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
169 /* When the microcontroller detects the
170 * audio format, it will unmute the lines */
171 cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
175 static int get_volume(struct cx18 *cx)
177 /* Volume runs +18dB to -96dB in 1/2dB steps
178 * change to fit the msp3400 -114dB to +12dB range */
180 /* check PATH1_VOLUME */
181 int vol = 228 - cx18_av_read(cx, 0x8d4);
182 vol = (vol / 2) + 23;
186 static void set_volume(struct cx18 *cx, int volume)
188 /* First convert the volume to msp3400 values (0-127) */
189 int vol = volume >> 9;
190 /* now scale it up to cx18_av values
191 * -114dB to -96dB maps to 0
192 * this should be 19, but in my testing that was 4dB too loud */
199 cx18_av_write(cx, 0x8d4, 228 - (vol * 2));
202 static int get_bass(struct cx18 *cx)
204 /* bass is 49 steps +12dB to -12dB */
206 /* check PATH1_EQ_BASS_VOL */
207 int bass = cx18_av_read(cx, 0x8d9) & 0x3f;
208 bass = (((48 - bass) * 0xffff) + 47) / 48;
212 static void set_bass(struct cx18 *cx, int bass)
214 /* PATH1_EQ_BASS_VOL */
215 cx18_av_and_or(cx, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
218 static int get_treble(struct cx18 *cx)
220 /* treble is 49 steps +12dB to -12dB */
222 /* check PATH1_EQ_TREBLE_VOL */
223 int treble = cx18_av_read(cx, 0x8db) & 0x3f;
224 treble = (((48 - treble) * 0xffff) + 47) / 48;
228 static void set_treble(struct cx18 *cx, int treble)
230 /* PATH1_EQ_TREBLE_VOL */
231 cx18_av_and_or(cx, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
234 static int get_balance(struct cx18 *cx)
236 /* balance is 7 bit, 0 to -96dB */
238 /* check PATH1_BAL_LEVEL */
239 int balance = cx18_av_read(cx, 0x8d5) & 0x7f;
240 /* check PATH1_BAL_LEFT */
241 if ((cx18_av_read(cx, 0x8d5) & 0x80) == 0)
242 balance = 0x80 - balance;
244 balance = 0x80 + balance;
248 static void set_balance(struct cx18 *cx, int balance)
250 int bal = balance >> 8;
253 cx18_av_and_or(cx, 0x8d5, 0x7f, 0x80);
254 /* PATH1_BAL_LEVEL */
255 cx18_av_and_or(cx, 0x8d5, ~0x7f, bal & 0x7f);
258 cx18_av_and_or(cx, 0x8d5, 0x7f, 0x00);
259 /* PATH1_BAL_LEVEL */
260 cx18_av_and_or(cx, 0x8d5, ~0x7f, 0x80 - bal);
264 static int get_mute(struct cx18 *cx)
266 /* check SRC1_MUTE_EN */
267 return cx18_av_read(cx, 0x8d3) & 0x2 ? 1 : 0;
270 static void set_mute(struct cx18 *cx, int mute)
272 struct cx18_av_state *state = &cx->av_state;
274 if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
275 /* Must turn off microcontroller in order to mute sound.
276 * Not sure if this is the best method, but it does work.
277 * If the microcontroller is running, then it will undo any
278 * changes to the mute register. */
280 /* disable microcontroller */
281 cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
282 cx18_av_write(cx, 0x8d3, 0x1f);
284 /* enable microcontroller */
285 cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
289 cx18_av_and_or(cx, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
293 int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)
295 struct cx18_av_state *state = &cx->av_state;
296 struct v4l2_control *ctrl = arg;
300 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
301 if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
302 cx18_av_and_or(cx, 0x803, ~0x10, 0);
303 cx18_av_write(cx, 0x8d3, 0x1f);
305 cx18_av_and_or(cx, 0x810, ~0x1, 1);
306 retval = set_audclk_freq(cx, *(u32 *)arg);
307 cx18_av_and_or(cx, 0x810, ~0x1, 0);
308 if (state->aud_input != CX18_AV_AUDIO_SERIAL)
309 cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
314 case V4L2_CID_AUDIO_VOLUME:
315 ctrl->value = get_volume(cx);
317 case V4L2_CID_AUDIO_BASS:
318 ctrl->value = get_bass(cx);
320 case V4L2_CID_AUDIO_TREBLE:
321 ctrl->value = get_treble(cx);
323 case V4L2_CID_AUDIO_BALANCE:
324 ctrl->value = get_balance(cx);
326 case V4L2_CID_AUDIO_MUTE:
327 ctrl->value = get_mute(cx);
336 case V4L2_CID_AUDIO_VOLUME:
337 set_volume(cx, ctrl->value);
339 case V4L2_CID_AUDIO_BASS:
340 set_bass(cx, ctrl->value);
342 case V4L2_CID_AUDIO_TREBLE:
343 set_treble(cx, ctrl->value);
345 case V4L2_CID_AUDIO_BALANCE:
346 set_balance(cx, ctrl->value);
348 case V4L2_CID_AUDIO_MUTE:
349 set_mute(cx, ctrl->value);