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)
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) {
41 if (state->is_cx23885) {
42 /* We don't have register values
43 * so avoid destroying registers. */
47 if (!state->is_cx231xx) {
49 /* VID_PLL and AUX_PLL */
50 cx25840_write4(client, 0x108, 0x1006040f);
53 cx25840_write4(client, 0x110, 0x01bb39ee);
56 if (state->is_cx25836)
59 /* src3/4/6_ctl = 0x0801f77f */
60 cx25840_write4(client, 0x900, 0x0801f77f);
61 cx25840_write4(client, 0x904, 0x0801f77f);
62 cx25840_write4(client, 0x90c, 0x0801f77f);
66 if (state->is_cx23885) {
67 /* We don't have register values
68 * so avoid destroying registers. */
72 if (!state->is_cx231xx) {
74 /* VID_PLL and AUX_PLL */
75 cx25840_write4(client, 0x108, 0x1009040f);
78 cx25840_write4(client, 0x110, 0x00ec6bd6);
81 if (state->is_cx25836)
84 /* src3/4/6_ctl = 0x08016d59 */
85 cx25840_write4(client, 0x900, 0x08016d59);
86 cx25840_write4(client, 0x904, 0x08016d59);
87 cx25840_write4(client, 0x90c, 0x08016d59);
91 if (state->is_cx23885) {
92 /* We don't have register values
93 * so avoid destroying registers. */
97 if (!state->is_cx231xx) {
99 /* VID_PLL and AUX_PLL */
100 cx25840_write4(client, 0x108, 0x100a040f);
103 cx25840_write4(client, 0x110, 0x0098d6e5);
106 if (state->is_cx25836)
109 /* src3/4/6_ctl = 0x08014faa */
110 cx25840_write4(client, 0x900, 0x08014faa);
111 cx25840_write4(client, 0x904, 0x08014faa);
112 cx25840_write4(client, 0x90c, 0x08014faa);
118 if (state->is_cx23885) {
119 /* We don't have register values
120 * so avoid destroying registers. */
124 if (!state->is_cx231xx) {
126 /* VID_PLL and AUX_PLL */
127 cx25840_write4(client, 0x108, 0x1e08040f);
130 cx25840_write4(client, 0x110, 0x012a0869);
133 if (state->is_cx25836)
136 /* src1_ctl = 0x08010000 */
137 cx25840_write4(client, 0x8f8, 0x08010000);
139 /* src3/4/6_ctl = 0x08020000 */
140 cx25840_write4(client, 0x900, 0x08020000);
141 cx25840_write4(client, 0x904, 0x08020000);
142 cx25840_write4(client, 0x90c, 0x08020000);
144 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
145 cx25840_write(client, 0x127, 0x54);
149 if (state->is_cx23885) {
150 /* We don't have register values
151 * so avoid destroying registers. */
156 if (!state->is_cx231xx) {
158 /* VID_PLL and AUX_PLL */
159 cx25840_write4(client, 0x108, 0x1809040f);
162 cx25840_write4(client, 0x110, 0x00ec6bd6);
165 if (state->is_cx25836)
168 /* src1_ctl = 0x08010000 */
169 cx25840_write4(client, 0x8f8, 0x080160cd);
171 /* src3/4/6_ctl = 0x08020000 */
172 cx25840_write4(client, 0x900, 0x08017385);
173 cx25840_write4(client, 0x904, 0x08017385);
174 cx25840_write4(client, 0x90c, 0x08017385);
178 if (!state->is_cx23885 && !state->is_cx231xx) {
179 /* VID_PLL and AUX_PLL */
180 cx25840_write4(client, 0x108, 0x180a040f);
183 cx25840_write4(client, 0x110, 0x0098d6e5);
186 if (state->is_cx25836)
189 if (!state->is_cx23885 && !state->is_cx231xx) {
191 cx25840_write4(client, 0x8f8, 0x08018000);
194 cx25840_write4(client, 0x900, 0x08015555);
195 cx25840_write4(client, 0x904, 0x08015555);
196 cx25840_write4(client, 0x90c, 0x08015555);
199 cx25840_write4(client, 0x8f8, 0x0801867c);
201 cx25840_write4(client, 0x900, 0x08014faa);
202 cx25840_write4(client, 0x904, 0x08014faa);
203 cx25840_write4(client, 0x90c, 0x08014faa);
209 state->audclk_freq = freq;
214 void cx25840_audio_set_path(struct i2c_client *client)
216 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
218 /* assert soft reset */
219 cx25840_and_or(client, 0x810, ~0x1, 0x01);
221 /* stop microcontroller */
222 cx25840_and_or(client, 0x803, ~0x10, 0);
224 /* Mute everything to prevent the PFFT! */
225 cx25840_write(client, 0x8d3, 0x1f);
227 if (state->aud_input == CX25840_AUDIO_SERIAL) {
228 /* Set Path1 to Serial Audio Input */
229 cx25840_write4(client, 0x8d0, 0x01011012);
231 /* The microcontroller should not be started for the
232 * non-tuner inputs: autodetection is specific for
235 /* Set Path1 to Analog Demod Main Channel */
236 cx25840_write4(client, 0x8d0, 0x1f063870);
239 set_audclk_freq(client, state->audclk_freq);
241 if (state->aud_input != CX25840_AUDIO_SERIAL) {
242 /* When the microcontroller detects the
243 * audio format, it will unmute the lines */
244 cx25840_and_or(client, 0x803, ~0x10, 0x10);
247 /* deassert soft reset */
248 cx25840_and_or(client, 0x810, ~0x1, 0x00);
250 if (state->is_cx23885 || state->is_cx231xx) {
251 /* Ensure the controller is running when we exit */
252 cx25840_and_or(client, 0x803, ~0x10, 0x10);
256 static int get_volume(struct i2c_client *client)
258 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
261 if (state->unmute_volume >= 0)
262 return state->unmute_volume;
264 /* Volume runs +18dB to -96dB in 1/2dB steps
265 * change to fit the msp3400 -114dB to +12dB range */
267 /* check PATH1_VOLUME */
268 vol = 228 - cx25840_read(client, 0x8d4);
269 vol = (vol / 2) + 23;
273 static void set_volume(struct i2c_client *client, int volume)
275 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
278 if (state->unmute_volume >= 0) {
279 state->unmute_volume = volume;
283 /* Convert the volume to msp3400 values (0-127) */
286 /* now scale it up to cx25840 values
287 * -114dB to -96dB maps to 0
288 * this should be 19, but in my testing that was 4dB too loud */
296 cx25840_write(client, 0x8d4, 228 - (vol * 2));
299 static int get_bass(struct i2c_client *client)
301 /* bass is 49 steps +12dB to -12dB */
303 /* check PATH1_EQ_BASS_VOL */
304 int bass = cx25840_read(client, 0x8d9) & 0x3f;
305 bass = (((48 - bass) * 0xffff) + 47) / 48;
309 static void set_bass(struct i2c_client *client, int bass)
311 /* PATH1_EQ_BASS_VOL */
312 cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
315 static int get_treble(struct i2c_client *client)
317 /* treble is 49 steps +12dB to -12dB */
319 /* check PATH1_EQ_TREBLE_VOL */
320 int treble = cx25840_read(client, 0x8db) & 0x3f;
321 treble = (((48 - treble) * 0xffff) + 47) / 48;
325 static void set_treble(struct i2c_client *client, int treble)
327 /* PATH1_EQ_TREBLE_VOL */
328 cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
331 static int get_balance(struct i2c_client *client)
333 /* balance is 7 bit, 0 to -96dB */
335 /* check PATH1_BAL_LEVEL */
336 int balance = cx25840_read(client, 0x8d5) & 0x7f;
337 /* check PATH1_BAL_LEFT */
338 if ((cx25840_read(client, 0x8d5) & 0x80) == 0)
339 balance = 0x80 - balance;
341 balance = 0x80 + balance;
345 static void set_balance(struct i2c_client *client, int balance)
347 int bal = balance >> 8;
350 cx25840_and_or(client, 0x8d5, 0x7f, 0x80);
351 /* PATH1_BAL_LEVEL */
352 cx25840_and_or(client, 0x8d5, ~0x7f, bal & 0x7f);
355 cx25840_and_or(client, 0x8d5, 0x7f, 0x00);
356 /* PATH1_BAL_LEVEL */
357 cx25840_and_or(client, 0x8d5, ~0x7f, 0x80 - bal);
361 static int get_mute(struct i2c_client *client)
363 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
365 return state->unmute_volume >= 0;
368 static void set_mute(struct i2c_client *client, int mute)
370 struct cx25840_state *state = to_state(i2c_get_clientdata(client));
372 if (mute && state->unmute_volume == -1) {
373 int vol = get_volume(client);
375 set_volume(client, 0);
376 state->unmute_volume = vol;
378 else if (!mute && state->unmute_volume != -1) {
379 int vol = state->unmute_volume;
381 state->unmute_volume = -1;
382 set_volume(client, vol);
386 int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
388 struct i2c_client *client = v4l2_get_subdevdata(sd);
389 struct cx25840_state *state = to_state(sd);
392 if (!state->is_cx25836)
393 cx25840_and_or(client, 0x810, ~0x1, 1);
394 if (state->aud_input != CX25840_AUDIO_SERIAL) {
395 cx25840_and_or(client, 0x803, ~0x10, 0);
396 cx25840_write(client, 0x8d3, 0x1f);
398 retval = set_audclk_freq(client, freq);
399 if (state->aud_input != CX25840_AUDIO_SERIAL)
400 cx25840_and_or(client, 0x803, ~0x10, 0x10);
401 if (!state->is_cx25836)
402 cx25840_and_or(client, 0x810, ~0x1, 0);
406 int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
408 struct i2c_client *client = v4l2_get_subdevdata(sd);
411 case V4L2_CID_AUDIO_VOLUME:
412 ctrl->value = get_volume(client);
414 case V4L2_CID_AUDIO_BASS:
415 ctrl->value = get_bass(client);
417 case V4L2_CID_AUDIO_TREBLE:
418 ctrl->value = get_treble(client);
420 case V4L2_CID_AUDIO_BALANCE:
421 ctrl->value = get_balance(client);
423 case V4L2_CID_AUDIO_MUTE:
424 ctrl->value = get_mute(client);
432 int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
434 struct i2c_client *client = v4l2_get_subdevdata(sd);
437 case V4L2_CID_AUDIO_VOLUME:
438 set_volume(client, ctrl->value);
440 case V4L2_CID_AUDIO_BASS:
441 set_bass(client, ctrl->value);
443 case V4L2_CID_AUDIO_TREBLE:
444 set_treble(client, ctrl->value);
446 case V4L2_CID_AUDIO_BALANCE:
447 set_balance(client, ctrl->value);
449 case V4L2_CID_AUDIO_MUTE:
450 set_mute(client, ctrl->value);