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
) {
48 /* VID_PLL and AUX_PLL */
49 cx25840_write4(client
, 0x108, 0x1006040f);
52 cx25840_write4(client
, 0x110, 0x01bb39ee);
55 if (state
->is_cx25836
)
58 /* src3/4/6_ctl = 0x0801f77f */
59 cx25840_write4(client
, 0x900, 0x0801f77f);
60 cx25840_write4(client
, 0x904, 0x0801f77f);
61 cx25840_write4(client
, 0x90c, 0x0801f77f);
65 if (state
->is_cx23885
) {
66 /* We don't have register values
67 * so avoid destroying registers. */
71 if (!state
->is_cx231xx
) {
72 /* VID_PLL and AUX_PLL */
73 cx25840_write4(client
, 0x108, 0x1009040f);
76 cx25840_write4(client
, 0x110, 0x00ec6bd6);
79 if (state
->is_cx25836
)
82 /* src3/4/6_ctl = 0x08016d59 */
83 cx25840_write4(client
, 0x900, 0x08016d59);
84 cx25840_write4(client
, 0x904, 0x08016d59);
85 cx25840_write4(client
, 0x90c, 0x08016d59);
89 if (state
->is_cx23885
) {
90 /* We don't have register values
91 * so avoid destroying registers. */
95 if (!state
->is_cx231xx
) {
96 /* VID_PLL and AUX_PLL */
97 cx25840_write4(client
, 0x108, 0x100a040f);
100 cx25840_write4(client
, 0x110, 0x0098d6e5);
103 if (state
->is_cx25836
)
106 /* src3/4/6_ctl = 0x08014faa */
107 cx25840_write4(client
, 0x900, 0x08014faa);
108 cx25840_write4(client
, 0x904, 0x08014faa);
109 cx25840_write4(client
, 0x90c, 0x08014faa);
115 if (state
->is_cx23885
) {
116 /* We don't have register values
117 * so avoid destroying registers. */
121 if (!state
->is_cx231xx
) {
122 /* VID_PLL and AUX_PLL */
123 cx25840_write4(client
, 0x108, 0x1e08040f);
126 cx25840_write4(client
, 0x110, 0x012a0869);
129 if (state
->is_cx25836
)
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);
145 if (state
->is_cx23885
) {
146 /* We don't have register values
147 * so avoid destroying registers. */
152 if (!state
->is_cx231xx
) {
153 /* VID_PLL and AUX_PLL */
154 cx25840_write4(client
, 0x108, 0x1809040f);
157 cx25840_write4(client
, 0x110, 0x00ec6bd6);
160 if (state
->is_cx25836
)
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);
173 if (!state
->is_cx23885
&& !state
->is_cx231xx
) {
174 /* VID_PLL and AUX_PLL */
175 cx25840_write4(client
, 0x108, 0x180a040f);
178 cx25840_write4(client
, 0x110, 0x0098d6e5);
181 if (state
->is_cx25836
)
184 if (!state
->is_cx23885
&& !state
->is_cx231xx
) {
186 cx25840_write4(client
, 0x8f8, 0x08018000);
189 cx25840_write4(client
, 0x900, 0x08015555);
190 cx25840_write4(client
, 0x904, 0x08015555);
191 cx25840_write4(client
, 0x90c, 0x08015555);
194 cx25840_write4(client
, 0x8f8, 0x0801867c);
196 cx25840_write4(client
, 0x900, 0x08014faa);
197 cx25840_write4(client
, 0x904, 0x08014faa);
198 cx25840_write4(client
, 0x90c, 0x08014faa);
204 state
->audclk_freq
= freq
;
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
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
));
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;
267 static void set_volume(struct i2c_client
*client
, int volume
)
269 struct cx25840_state
*state
= to_state(i2c_get_clientdata(client
));
272 if (state
->unmute_volume
>= 0) {
273 state
->unmute_volume
= volume
;
277 /* Convert the volume to msp3400 values (0-127) */
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 */
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;
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;
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
;
335 balance
= 0x80 + balance
;
339 static void set_balance(struct i2c_client
*client
, int balance
)
341 int bal
= balance
>> 8;
344 cx25840_and_or(client
, 0x8d5, 0x7f, 0x80);
345 /* PATH1_BAL_LEVEL */
346 cx25840_and_or(client
, 0x8d5, ~0x7f, bal
& 0x7f);
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
);
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);
400 int cx25840_audio_g_ctrl(struct v4l2_subdev
*sd
, struct v4l2_control
*ctrl
)
402 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
405 case V4L2_CID_AUDIO_VOLUME
:
406 ctrl
->value
= get_volume(client
);
408 case V4L2_CID_AUDIO_BASS
:
409 ctrl
->value
= get_bass(client
);
411 case V4L2_CID_AUDIO_TREBLE
:
412 ctrl
->value
= get_treble(client
);
414 case V4L2_CID_AUDIO_BALANCE
:
415 ctrl
->value
= get_balance(client
);
417 case V4L2_CID_AUDIO_MUTE
:
418 ctrl
->value
= get_mute(client
);
426 int cx25840_audio_s_ctrl(struct v4l2_subdev
*sd
, struct v4l2_control
*ctrl
)
428 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
431 case V4L2_CID_AUDIO_VOLUME
:
432 set_volume(client
, ctrl
->value
);
434 case V4L2_CID_AUDIO_BASS
:
435 set_bass(client
, ctrl
->value
);
437 case V4L2_CID_AUDIO_TREBLE
:
438 set_treble(client
, ctrl
->value
);
440 case V4L2_CID_AUDIO_BALANCE
:
441 set_balance(client
, ctrl
->value
);
443 case V4L2_CID_AUDIO_MUTE
:
444 set_mute(client
, ctrl
->value
);