1 /* cx25840 audio functions
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License
5 * as published by the Free Software Foundation; either version 2
6 * of the License, or (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 */
17
18
19 #include <linux/videodev2.h>
20 #include <linux/i2c.h>
21 #include <media/v4l2-common.h>
22 #include <media/cx25840.h>
23
24 #include "cx25840-core.h"
25
26 static int set_audclk_freq(struct i2c_client *client, u32 freq)
27 {
28 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
29
30 if (freq != 32000 && freq != 44100 && freq != 48000)
31 return -EINVAL;
32
33 /* common for all inputs and rates */
34 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
35 if (!state->is_cx23885 && !state->is_cx231xx)
36 cx25840_write(client, 0x127, 0x50);
37
38 if (state->aud_input != CX25840_AUDIO_SERIAL) {
39 switch (freq) {
40 case 32000:
41 if (state->is_cx23885) {
42 /* We don't have register values
43 * so avoid destroying registers. */
44 break;
45 }
46
47 if (!state->is_cx231xx) {
48 /* VID_PLL and AUX_PLL */
49 cx25840_write4(client, 0x108, 0x1006040f);
50
51 /* AUX_PLL_FRAC */
52 cx25840_write4(client, 0x110, 0x01bb39ee);
53 }
54
55 if (state->is_cx25836)
56 break;
57
58 /* src3/4/6_ctl = 0x0801f77f */
59 cx25840_write4(client, 0x900, 0x0801f77f);
60 cx25840_write4(client, 0x904, 0x0801f77f);
61 cx25840_write4(client, 0x90c, 0x0801f77f);
62 break;
63
64 case 44100:
65 if (state->is_cx23885) {
66 /* We don't have register values
67 * so avoid destroying registers. */
68 break;
69 }
70
71 if (!state->is_cx231xx) {
72 /* VID_PLL and AUX_PLL */
73 cx25840_write4(client, 0x108, 0x1009040f);
74
75 /* AUX_PLL_FRAC */
76 cx25840_write4(client, 0x110, 0x00ec6bd6);
77 }
78
79 if (state->is_cx25836)
80 break;
81
82 /* src3/4/6_ctl = 0x08016d59 */
83 cx25840_write4(client, 0x900, 0x08016d59);
84 cx25840_write4(client, 0x904, 0x08016d59);
85 cx25840_write4(client, 0x90c, 0x08016d59);
86 break;
87
88 case 48000:
89 if (state->is_cx23885) {
90 /* We don't have register values
91 * so avoid destroying registers. */
92 break;
93 }
94
95 if (!state->is_cx231xx) {
96 /* VID_PLL and AUX_PLL */
97 cx25840_write4(client, 0x108, 0x100a040f);
98
99 /* AUX_PLL_FRAC */
100 cx25840_write4(client, 0x110, 0x0098d6e5);
101 }
102
103 if (state->is_cx25836)
104 break;
105
106 /* src3/4/6_ctl = 0x08014faa */
107 cx25840_write4(client, 0x900, 0x08014faa);
108 cx25840_write4(client, 0x904, 0x08014faa);
109 cx25840_write4(client, 0x90c, 0x08014faa);
110 break;
111 }
112 } else {
113 switch (freq) {
114 case 32000:
115 if (state->is_cx23885) {
116 /* We don't have register values
117 * so avoid destroying registers. */
118 break;
119 }
120
121 if (!state->is_cx231xx) {
122 /* VID_PLL and AUX_PLL */
123 cx25840_write4(client, 0x108, 0x1e08040f);
124
125 /* AUX_PLL_FRAC */
126 cx25840_write4(client, 0x110, 0x012a0869);
127 }
128
129 if (state->is_cx25836)
130 break;
131
132 /* src1_ctl = 0x08010000 */
133 cx25840_write4(client, 0x8f8, 0x08010000);
134
135 /* src3/4/6_ctl = 0x08020000 */
136 cx25840_write4(client, 0x900, 0x08020000);
137 cx25840_write4(client, 0x904, 0x08020000);
138 cx25840_write4(client, 0x90c, 0x08020000);
139
140 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
141 cx25840_write(client, 0x127, 0x54);
142 break;
143
144 case 44100:
145 if (state->is_cx23885) {
146 /* We don't have register values
147 * so avoid destroying registers. */
148 break;
149 }
150
151
152 if (!state->is_cx231xx) {
153 /* VID_PLL and AUX_PLL */
154 cx25840_write4(client, 0x108, 0x1809040f);
155
156 /* AUX_PLL_FRAC */
157 cx25840_write4(client, 0x110, 0x00ec6bd6);
158 }
159
160 if (state->is_cx25836)
161 break;
162
163 /* src1_ctl = 0x08010000 */
164 cx25840_write4(client, 0x8f8, 0x080160cd);
165
166 /* src3/4/6_ctl = 0x08020000 */
167 cx25840_write4(client, 0x900, 0x08017385);
168 cx25840_write4(client, 0x904, 0x08017385);
169 cx25840_write4(client, 0x90c, 0x08017385);
170 break;
171
172 case 48000:
173 if (!state->is_cx23885 && !state->is_cx231xx) {
174 /* VID_PLL and AUX_PLL */
175 cx25840_write4(client, 0x108, 0x180a040f);
176
177 /* AUX_PLL_FRAC */
178 cx25840_write4(client, 0x110, 0x0098d6e5);
179 }
180
181 if (state->is_cx25836)
182 break;
183
184 if (!state->is_cx23885 && !state->is_cx231xx) {
185 /* src1_ctl */
186 cx25840_write4(client, 0x8f8, 0x08018000);
187
188 /* src3/4/6_ctl */
189 cx25840_write4(client, 0x900, 0x08015555);
190 cx25840_write4(client, 0x904, 0x08015555);
191 cx25840_write4(client, 0x90c, 0x08015555);
192 } else {
193
194 cx25840_write4(client, 0x8f8, 0x0801867c);
195
196 cx25840_write4(client, 0x900, 0x08014faa);
197 cx25840_write4(client, 0x904, 0x08014faa);
198 cx25840_write4(client, 0x90c, 0x08014faa);
199 }
200 break;
201 }
202 }
203
204 state->audclk_freq = freq;
205
206 return 0;
207 }
208
209 void cx25840_audio_set_path(struct i2c_client *client)
210 {
211 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
212
213 /* assert soft reset */
214 cx25840_and_or(client, 0x810, ~0x1, 0x01);
215
216 /* stop microcontroller */
217 cx25840_and_or(client, 0x803, ~0x10, 0);
218
219 /* Mute everything to prevent the PFFT! */
220 cx25840_write(client, 0x8d3, 0x1f);
221
222 if (state->aud_input == CX25840_AUDIO_SERIAL) {
223 /* Set Path1 to Serial Audio Input */
224 cx25840_write4(client, 0x8d0, 0x01011012);
225
226 /* The microcontroller should not be started for the
227 * non-tuner inputs: autodetection is specific for
228 * TV audio. */
229 } else {
230 /* Set Path1 to Analog Demod Main Channel */
231 cx25840_write4(client, 0x8d0, 0x1f063870);
232 }
233
234 set_audclk_freq(client, state->audclk_freq);
235
236 if (state->aud_input != CX25840_AUDIO_SERIAL) {
237 /* When the microcontroller detects the
238 * audio format, it will unmute the lines */
239 cx25840_and_or(client, 0x803, ~0x10, 0x10);
240 }
241
242 /* deassert soft reset */
243 cx25840_and_or(client, 0x810, ~0x1, 0x00);
244
245 /* Ensure the controller is running when we exit */
246 if (state->is_cx23885 || state->is_cx231xx)
247 cx25840_and_or(client, 0x803, ~0x10, 0x10);
248 }
249
250 static int get_volume(struct i2c_client *client)
251 {
252 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
253 int vol;
254
255 if (state->unmute_volume >= 0)
256 return state->unmute_volume;
257
258 /* Volume runs +18dB to -96dB in 1/2dB steps
259 * change to fit the msp3400 -114dB to +12dB range */
260
261 /* check PATH1_VOLUME */
262 vol = 228 - cx25840_read(client, 0x8d4);
263 vol = (vol / 2) + 23;
264 return vol << 9;
265 }
266
267 static void set_volume(struct i2c_client *client, int volume)
268 {
269 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
270 int vol;
271
272 if (state->unmute_volume >= 0) {
273 state->unmute_volume = volume;
274 return;
275 }
276
277 /* Convert the volume to msp3400 values (0-127) */
278 vol = volume >> 9;
279
280 /* now scale it up to cx25840 values
281 * -114dB to -96dB maps to 0
282 * this should be 19, but in my testing that was 4dB too loud */
283 if (vol <= 23) {
284 vol = 0;
285 } else {
286 vol -= 23;
287 }
288
289 /* PATH1_VOLUME */
290 cx25840_write(client, 0x8d4, 228 - (vol * 2));
291 }
292
293 static int get_bass(struct i2c_client *client)
294 {
295 /* bass is 49 steps +12dB to -12dB */
296
297 /* check PATH1_EQ_BASS_VOL */
298 int bass = cx25840_read(client, 0x8d9) & 0x3f;
299 bass = (((48 - bass) * 0xffff) + 47) / 48;
300 return bass;
301 }
302
303 static void set_bass(struct i2c_client *client, int bass)
304 {
305 /* PATH1_EQ_BASS_VOL */
306 cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
307 }
308
309 static int get_treble(struct i2c_client *client)
310 {
311 /* treble is 49 steps +12dB to -12dB */
312
313 /* check PATH1_EQ_TREBLE_VOL */
314 int treble = cx25840_read(client, 0x8db) & 0x3f;
315 treble = (((48 - treble) * 0xffff) + 47) / 48;
316 return treble;
317 }
318
319 static void set_treble(struct i2c_client *client, int treble)
320 {
321 /* PATH1_EQ_TREBLE_VOL */
322 cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
323 }
324
325 static int get_balance(struct i2c_client *client)
326 {
327 /* balance is 7 bit, 0 to -96dB */
328
329 /* check PATH1_BAL_LEVEL */
330 int balance = cx25840_read(client, 0x8d5) & 0x7f;
331 /* check PATH1_BAL_LEFT */
332 if ((cx25840_read(client, 0x8d5) & 0x80) == 0)
333 balance = 0x80 - balance;
334 else
335 balance = 0x80 + balance;
336 return balance << 8;
337 }
338
339 static void set_balance(struct i2c_client *client, int balance)
340 {
341 int bal = balance >> 8;
342 if (bal > 0x80) {
343 /* PATH1_BAL_LEFT */
344 cx25840_and_or(client, 0x8d5, 0x7f, 0x80);
345 /* PATH1_BAL_LEVEL */
346 cx25840_and_or(client, 0x8d5, ~0x7f, bal & 0x7f);
347 } else {
348 /* PATH1_BAL_LEFT */
349 cx25840_and_or(client, 0x8d5, 0x7f, 0x00);
350 /* PATH1_BAL_LEVEL */
351 cx25840_and_or(client, 0x8d5, ~0x7f, 0x80 - bal);
352 }
353 }
354
355 static int get_mute(struct i2c_client *client)
356 {
357 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
358
359 return state->unmute_volume >= 0;
360 }
361
362 static void set_mute(struct i2c_client *client, int mute)
363 {
364 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
365
366 if (mute && state->unmute_volume == -1) {
367 int vol = get_volume(client);
368
369 set_volume(client, 0);
370 state->unmute_volume = vol;
371 }
372 else if (!mute && state->unmute_volume != -1) {
373 int vol = state->unmute_volume;
374
375 state->unmute_volume = -1;
376 set_volume(client, vol);
377 }
378 }
379
380 int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
381 {
382 struct i2c_client *client = v4l2_get_subdevdata(sd);
383 struct cx25840_state *state = to_state(sd);
384 int retval;
385
386 if (!state->is_cx25836)
387 cx25840_and_or(client, 0x810, ~0x1, 1);
388 if (state->aud_input != CX25840_AUDIO_SERIAL) {
389 cx25840_and_or(client, 0x803, ~0x10, 0);
390 cx25840_write(client, 0x8d3, 0x1f);
391 }
392 retval = set_audclk_freq(client, freq);
393 if (state->aud_input != CX25840_AUDIO_SERIAL)
394 cx25840_and_or(client, 0x803, ~0x10, 0x10);
395 if (!state->is_cx25836)
396 cx25840_and_or(client, 0x810, ~0x1, 0);
397 return retval;
398 }
399
400 int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
401 {
402 struct i2c_client *client = v4l2_get_subdevdata(sd);
403
404 switch (ctrl->id) {
405 case V4L2_CID_AUDIO_VOLUME:
406 ctrl->value = get_volume(client);
407 break;
408 case V4L2_CID_AUDIO_BASS:
409 ctrl->value = get_bass(client);
410 break;
411 case V4L2_CID_AUDIO_TREBLE:
412 ctrl->value = get_treble(client);
413 break;
414 case V4L2_CID_AUDIO_BALANCE:
415 ctrl->value = get_balance(client);
416 break;
417 case V4L2_CID_AUDIO_MUTE:
418 ctrl->value = get_mute(client);
419 break;
420 default:
421 return -EINVAL;
422 }
423 return 0;
424 }
425
426 int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
427 {
428 struct i2c_client *client = v4l2_get_subdevdata(sd);
429
430 switch (ctrl->id) {
431 case V4L2_CID_AUDIO_VOLUME:
432 set_volume(client, ctrl->value);
433 break;
434 case V4L2_CID_AUDIO_BASS:
435 set_bass(client, ctrl->value);
436 break;
437 case V4L2_CID_AUDIO_TREBLE:
438 set_treble(client, ctrl->value);
439 break;
440 case V4L2_CID_AUDIO_BALANCE:
441 set_balance(client, ctrl->value);
442 break;
443 case V4L2_CID_AUDIO_MUTE:
444 set_mute(client, ctrl->value);
445 break;
446 default:
447 return -EINVAL;
448 }
449 return 0;
450 }
451
|
This page was automatically generated by the
LXR engine.
|