OMAP3 SRF: Generic shared resource f/w
[linux-ginger.git] / drivers / media / video / cx25840 / cx25840-audio.c
blob2f846f5e0f9fe1f3a60246cdcf8b960129bc7c46
1 /* cx25840 audio functions
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.
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.
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.
19 #include <linux/videodev2.h>
20 #include <linux/i2c.h>
21 #include <media/v4l2-common.h>
22 #include <media/cx25840.h>
24 #include "cx25840-core.h"
26 static int set_audclk_freq(struct i2c_client *client, u32 freq)
28 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
30 if (freq != 32000 && freq != 44100 && freq != 48000)
31 return -EINVAL;
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);
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;
47 if (!state->is_cx231xx) {
48 /* VID_PLL and AUX_PLL */
49 cx25840_write4(client, 0x108, 0x1006040f);
51 /* AUX_PLL_FRAC */
52 cx25840_write4(client, 0x110, 0x01bb39ee);
55 if (state->is_cx25836)
56 break;
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;
64 case 44100:
65 if (state->is_cx23885) {
66 /* We don't have register values
67 * so avoid destroying registers. */
68 break;
71 if (!state->is_cx231xx) {
72 /* VID_PLL and AUX_PLL */
73 cx25840_write4(client, 0x108, 0x1009040f);
75 /* AUX_PLL_FRAC */
76 cx25840_write4(client, 0x110, 0x00ec6bd6);
79 if (state->is_cx25836)
80 break;
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;
88 case 48000:
89 if (state->is_cx23885) {
90 /* We don't have register values
91 * so avoid destroying registers. */
92 break;
95 if (!state->is_cx231xx) {
96 /* VID_PLL and AUX_PLL */
97 cx25840_write4(client, 0x108, 0x100a040f);
99 /* AUX_PLL_FRAC */
100 cx25840_write4(client, 0x110, 0x0098d6e5);
103 if (state->is_cx25836)
104 break;
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;
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;
121 if (!state->is_cx231xx) {
122 /* VID_PLL and AUX_PLL */
123 cx25840_write4(client, 0x108, 0x1e08040f);
125 /* AUX_PLL_FRAC */
126 cx25840_write4(client, 0x110, 0x012a0869);
129 if (state->is_cx25836)
130 break;
132 /* src1_ctl = 0x08010000 */
133 cx25840_write4(client, 0x8f8, 0x08010000);
135 /* src3/4/6_ctl = 0x08020000 */
136 cx25840_write4(client, 0x900, 0x08020000);
137 cx25840_write4(client, 0x904, 0x08020000);
138 cx25840_write4(client, 0x90c, 0x08020000);
140 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
141 cx25840_write(client, 0x127, 0x54);
142 break;
144 case 44100:
145 if (state->is_cx23885) {
146 /* We don't have register values
147 * so avoid destroying registers. */
148 break;
152 if (!state->is_cx231xx) {
153 /* VID_PLL and AUX_PLL */
154 cx25840_write4(client, 0x108, 0x1809040f);
156 /* AUX_PLL_FRAC */
157 cx25840_write4(client, 0x110, 0x00ec6bd6);
160 if (state->is_cx25836)
161 break;
163 /* src1_ctl = 0x08010000 */
164 cx25840_write4(client, 0x8f8, 0x080160cd);
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;
172 case 48000:
173 if (!state->is_cx23885 && !state->is_cx231xx) {
174 /* VID_PLL and AUX_PLL */
175 cx25840_write4(client, 0x108, 0x180a040f);
177 /* AUX_PLL_FRAC */
178 cx25840_write4(client, 0x110, 0x0098d6e5);
181 if (state->is_cx25836)
182 break;
184 if (!state->is_cx23885 && !state->is_cx231xx) {
185 /* src1_ctl */
186 cx25840_write4(client, 0x8f8, 0x08018000);
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 {
194 cx25840_write4(client, 0x8f8, 0x0801867c);
196 cx25840_write4(client, 0x900, 0x08014faa);
197 cx25840_write4(client, 0x904, 0x08014faa);
198 cx25840_write4(client, 0x90c, 0x08014faa);
200 break;
204 state->audclk_freq = freq;
206 return 0;
209 void cx25840_audio_set_path(struct i2c_client *client)
211 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
213 /* assert soft reset */
214 cx25840_and_or(client, 0x810, ~0x1, 0x01);
216 /* stop microcontroller */
217 cx25840_and_or(client, 0x803, ~0x10, 0);
219 /* Mute everything to prevent the PFFT! */
220 cx25840_write(client, 0x8d3, 0x1f);
222 if (state->aud_input == CX25840_AUDIO_SERIAL) {
223 /* Set Path1 to Serial Audio Input */
224 cx25840_write4(client, 0x8d0, 0x01011012);
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);
234 set_audclk_freq(client, state->audclk_freq);
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);
242 /* deassert soft reset */
243 cx25840_and_or(client, 0x810, ~0x1, 0x00);
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);
250 static int get_volume(struct i2c_client *client)
252 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
253 int vol;
255 if (state->unmute_volume >= 0)
256 return state->unmute_volume;
258 /* Volume runs +18dB to -96dB in 1/2dB steps
259 * change to fit the msp3400 -114dB to +12dB range */
261 /* check PATH1_VOLUME */
262 vol = 228 - cx25840_read(client, 0x8d4);
263 vol = (vol / 2) + 23;
264 return vol << 9;
267 static void set_volume(struct i2c_client *client, int volume)
269 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
270 int vol;
272 if (state->unmute_volume >= 0) {
273 state->unmute_volume = volume;
274 return;
277 /* Convert the volume to msp3400 values (0-127) */
278 vol = volume >> 9;
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;
289 /* PATH1_VOLUME */
290 cx25840_write(client, 0x8d4, 228 - (vol * 2));
293 static int get_bass(struct i2c_client *client)
295 /* bass is 49 steps +12dB to -12dB */
297 /* check PATH1_EQ_BASS_VOL */
298 int bass = cx25840_read(client, 0x8d9) & 0x3f;
299 bass = (((48 - bass) * 0xffff) + 47) / 48;
300 return bass;
303 static void set_bass(struct i2c_client *client, int bass)
305 /* PATH1_EQ_BASS_VOL */
306 cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
309 static int get_treble(struct i2c_client *client)
311 /* treble is 49 steps +12dB to -12dB */
313 /* check PATH1_EQ_TREBLE_VOL */
314 int treble = cx25840_read(client, 0x8db) & 0x3f;
315 treble = (((48 - treble) * 0xffff) + 47) / 48;
316 return treble;
319 static void set_treble(struct i2c_client *client, int treble)
321 /* PATH1_EQ_TREBLE_VOL */
322 cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
325 static int get_balance(struct i2c_client *client)
327 /* balance is 7 bit, 0 to -96dB */
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;
339 static void set_balance(struct i2c_client *client, int balance)
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);
355 static int get_mute(struct i2c_client *client)
357 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
359 return state->unmute_volume >= 0;
362 static void set_mute(struct i2c_client *client, int mute)
364 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
366 if (mute && state->unmute_volume == -1) {
367 int vol = get_volume(client);
369 set_volume(client, 0);
370 state->unmute_volume = vol;
372 else if (!mute && state->unmute_volume != -1) {
373 int vol = state->unmute_volume;
375 state->unmute_volume = -1;
376 set_volume(client, vol);
380 int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
382 struct i2c_client *client = v4l2_get_subdevdata(sd);
383 struct cx25840_state *state = to_state(sd);
384 int retval;
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);
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;
400 int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
402 struct i2c_client *client = v4l2_get_subdevdata(sd);
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;
423 return 0;
426 int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
428 struct i2c_client *client = v4l2_get_subdevdata(sd);
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;
449 return 0;