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