Merge branch 'dmapool' of git://git.kernel.org/pub/scm/linux/kernel/git/willy/misc
[linux-2.6] / drivers / media / video / cx25840 / cx25840-audio.c
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 = 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
194 void cx25840_audio_set_path(struct i2c_client *client)
195 {
196         struct cx25840_state *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
236 static int get_volume(struct i2c_client *client)
237 {
238         struct cx25840_state *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
253 static void set_volume(struct i2c_client *client, int volume)
254 {
255         struct cx25840_state *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
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
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
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
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
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
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
341 static int get_mute(struct i2c_client *client)
342 {
343         struct cx25840_state *state = i2c_get_clientdata(client);
344
345         return state->unmute_volume >= 0;
346 }
347
348 static void set_mute(struct i2c_client *client, int mute)
349 {
350         struct cx25840_state *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
366 int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
367 {
368         struct cx25840_state *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 }