tizen 2.4 release
[kernel/u-boot-tm1.git] / drivers / sound / cmd_sound_htc.c
1 /*
2  * Copyright 2000-2009
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <command.h>
26 #include <errno.h>
27 #include <ubi_uboot.h>
28 #include <asm/io.h>
29
30 #include "sound_common.h"
31
32 #define pr_fmt(fmt) "[sound: htc ]" fmt
33 #ifdef  CMD_SND_DEBUG
34 #define snd_dbg(fmt,args...)    pr_info(fmt ,##args)
35 #else
36 #define snd_dbg(fmt,args...)
37 #endif
38
39 enum {
40         SOUND_DIGITAL_LOOP = 0x01,
41         SOUND_ANALOG_LOOP = 0x02,
42 };
43
44 enum {
45         SOUND_MAIN_MIC = 0x01,
46         SOUND_AUX_MIC = 0x02,
47         SOUND_HEADSET_MIC = 0x04,
48         SOUND_AIL = 0x08,
49         SOUND_AIR = 0x10,
50 };
51
52 enum {
53         SOUND_SPEAKER = 0x01,
54         SOUND_EARPIECE = 0x02,
55         SOUND_HEADPHONE = 0x04,
56         SOUND_SPEAKER2 = 0x08,
57 };
58
59 static inline char *_2str(int enable)
60 {
61         return enable ? "enable" : "disable";
62 }
63
64 static inline int is_analog_loop(int loop)
65 {
66         return loop & SOUND_ANALOG_LOOP;
67 }
68
69 static int speaker_pa_enable(int on)
70 {
71         sprd_inter_speaker_pa(on);
72         return 0;
73 }
74
75 static int hp_pa_enable(int on)
76 {
77 #ifdef CONFIG_SOUND_CODEC_SPRD_V3
78         sprd_inter_headphone_pa(on);
79 #endif
80         return 0;
81 }
82
83 static int audio_codec(int enable, int loop, int drv_in, int drv_out)
84 {
85         static int s_loop = 0;
86         static int s_drv_in = 0;
87         static int s_drv_out = 0;
88         static int s_enable = 0;
89         static int s_adc_power = 0;
90         static int s_dac_power = 0;
91         int adc_need_power_on = 0;
92         int dac_need_power_on = 0;
93
94         if (enable == 0xA) {
95                 drv_in = s_drv_in;
96                 drv_out = s_drv_out;
97                 loop = s_loop;
98                 s_loop = 0;
99                 s_drv_in = 0;
100                 s_drv_out = 0;
101                 enable = 0;
102                 printf("force disable all\n");
103         } else {
104                 enable -= 0xD;
105                 if (enable) {
106                         s_loop |= loop;
107                         s_drv_in |= drv_in;
108                         s_drv_out |= drv_out;
109                         if (loop != s_loop) {
110                                 printf
111                                     ("warnning: had some other loop path enable\n");
112                         }
113                         if (drv_in != s_drv_in) {
114                                 printf
115                                     ("warnning: had some other driver in opened\n");
116                         }
117                         if (drv_out != s_drv_out) {
118                                 printf
119                                     ("warnning: had some other driver out opened\n");
120                         }
121                 } else {
122                         s_loop &= ~loop;
123                         s_drv_in &= ~drv_in;
124                         s_drv_out &= ~drv_out;
125                         if ((s_drv_in == 0) && (s_drv_out != 0)) {
126                                 printf
127                                     ("warnning: can't loop by driver in all disable\n");
128                                 drv_out |= s_drv_out;
129                                 s_drv_out = 0;
130                                 loop |= s_loop;
131                                 s_loop = 0;
132                         }
133                         if ((s_drv_out == 0) && (s_drv_in != 0)) {
134                                 printf
135                                     ("warnning: can't loop by driver out all disable\n");
136                                 drv_in |= s_drv_in;
137                                 s_drv_in = 0;
138                                 loop |= s_loop;
139                                 s_loop = 0;
140                         }
141                 }
142         }
143         if (s_drv_in) {
144                 adc_need_power_on = 1;
145         }
146         if (s_drv_out) {
147                 dac_need_power_on = 1;
148         }
149
150         if (enable) {
151                 if (adc_need_power_on != s_adc_power) {
152                         adcl_switch(enable);
153                         adcr_switch(enable);
154                         if (!is_analog_loop(loop)) {
155                                 adcl_digital_switch(enable);
156                                 adcr_digital_switch(enable);
157                         }
158                         s_adc_power = adc_need_power_on;
159                 }
160
161                 if (dac_need_power_on != s_dac_power) {
162                         if (!is_analog_loop(loop)) {
163                                 dacl_digital_switch(enable);
164                                 dacr_digital_switch(enable);
165                         }
166                         s_dac_power = dac_need_power_on;
167                 }
168         }
169
170         if (drv_in & SOUND_MAIN_MIC) {
171                 printf("main mic %s\n", _2str(enable));
172                 mic_bias_enable(SPRD_CODEC_MIC_BIAS, enable);
173                 mixer_set(ID_FUN(SPRD_CODEC_MAIN_MIC, SPRD_CODEC_LEFT), enable);
174                 mixer_set(ID_FUN(SPRD_CODEC_MAIN_MIC, SPRD_CODEC_RIGHT),
175                           enable);
176         }
177         if (drv_in & SOUND_AUX_MIC) {
178                 printf("aux mic %s\n", _2str(enable));
179                 mic_bias_enable(SPRD_CODEC_AUXMIC_BIAS, enable);
180                 mixer_set(ID_FUN(SPRD_CODEC_AUX_MIC, SPRD_CODEC_LEFT), enable);
181                 mixer_set(ID_FUN(SPRD_CODEC_AUX_MIC, SPRD_CODEC_RIGHT), enable);
182         }
183         if (drv_in & SOUND_HEADSET_MIC) {
184                 printf("headset mic %s\n", _2str(enable));
185                 mixer_set(ID_FUN(SPRD_CODEC_HP_MIC, SPRD_CODEC_LEFT), enable);
186                 mixer_set(ID_FUN(SPRD_CODEC_HP_MIC, SPRD_CODEC_RIGHT), enable);
187         }
188         if (drv_in & SOUND_AIL) {
189                 printf("analog left signal %s\n", _2str(enable));
190                 mixer_set(ID_FUN(SPRD_CODEC_AIL, SPRD_CODEC_LEFT), enable);
191                 mixer_set(ID_FUN(SPRD_CODEC_AIL, SPRD_CODEC_RIGHT), enable);
192         }
193         if (drv_in & SOUND_AIR) {
194                 printf("analog right signal %s\n", _2str(enable));
195                 mixer_set(ID_FUN(SPRD_CODEC_AIR, SPRD_CODEC_LEFT), enable);
196                 mixer_set(ID_FUN(SPRD_CODEC_AIR, SPRD_CODEC_RIGHT), enable);
197         }
198
199         if (s_drv_in) {
200                 pga_enable(SPRD_CODEC_PGA_ADCL, 0x0A, enable);
201                 pga_enable(SPRD_CODEC_PGA_ADCR, 0x0A, enable);
202         }
203
204         if (drv_out & SOUND_SPEAKER) {
205                 printf("speaker %s\n", _2str(enable));
206                 spkl_switch(enable);
207                 if (is_analog_loop(loop)) {
208                         mixer_set(ID_FUN(SPRD_CODEC_SPK_ADCL, SPRD_CODEC_LEFT),
209                                   enable);
210                         mixer_set(ID_FUN(SPRD_CODEC_SPK_ADCR, SPRD_CODEC_LEFT),
211                                   enable);
212                 } else {
213                         mixer_set(ID_FUN(SPRD_CODEC_SPK_DACL, SPRD_CODEC_LEFT),
214                                   enable);
215                         mixer_set(ID_FUN(SPRD_CODEC_SPK_DACR, SPRD_CODEC_LEFT),
216                                   enable);
217                 }
218                 pga_enable(SPRD_CODEC_PGA_SPKL, 0x03, enable);
219                 speaker_pa_enable(enable);
220         }
221         if (drv_out & SOUND_EARPIECE) {
222                 printf("earpiece %s\n", _2str(enable));
223                 ear_switch(enable);
224                 if (is_analog_loop(loop)) {
225                         printf("[err]earpiece can't support analog loop\n");
226                 } else {
227                         mixer_enable(ID_FUN
228                                      (SPRD_CODEC_EAR_DACL, SPRD_CODEC_LEFT),
229                                      enable);
230                 }
231                 pga_enable(SPRD_CODEC_PGA_EAR, 0x0F, enable);
232         }
233         if (drv_out & SOUND_HEADPHONE) {
234                 printf("headphone %s\n", _2str(enable));
235                 hp_switch(enable);
236                 if (is_analog_loop(loop)) {
237                         mixer_set(ID_FUN(SPRD_CODEC_HP_ADCL, SPRD_CODEC_LEFT),
238                                   enable);
239                         mixer_set(ID_FUN(SPRD_CODEC_HP_ADCR, SPRD_CODEC_RIGHT),
240                                   enable);
241                 } else {
242                         mixer_set(ID_FUN(SPRD_CODEC_HP_DACL, SPRD_CODEC_LEFT),
243                                   enable);
244                         mixer_set(ID_FUN(SPRD_CODEC_HP_DACR, SPRD_CODEC_RIGHT),
245                                   enable);
246                 }
247                 pga_enable(SPRD_CODEC_PGA_HPL, 0x0C, enable);
248                 pga_enable(SPRD_CODEC_PGA_HPR, 0x0C, enable);
249                 hp_pa_enable(enable);
250         }
251         if (drv_out & SOUND_SPEAKER2) {
252                 printf("speaker2 %s\n", _2str(enable));
253                 spkr_switch(enable);
254                 if (is_analog_loop(loop)) {
255                         mixer_set(ID_FUN(SPRD_CODEC_SPK_ADCL, SPRD_CODEC_RIGHT),
256                                   enable);
257                         mixer_set(ID_FUN(SPRD_CODEC_SPK_ADCR, SPRD_CODEC_RIGHT),
258                                   enable);
259                 } else {
260                         mixer_set(ID_FUN(SPRD_CODEC_SPK_DACL, SPRD_CODEC_RIGHT),
261                                   enable);
262                         mixer_set(ID_FUN(SPRD_CODEC_SPK_DACR, SPRD_CODEC_RIGHT),
263                                   enable);
264                 }
265                 pga_enable(SPRD_CODEC_PGA_SPKR, 0x03, enable);
266         }
267
268         if (s_drv_out) {
269         }
270
271         if (!enable) {
272                 if (adc_need_power_on != s_adc_power) {
273                         if (!is_analog_loop(loop)) {
274                                 adcl_digital_switch(enable);
275                                 adcr_digital_switch(enable);
276                         }
277                         adcl_switch(enable);
278                         adcr_switch(enable);
279                         s_adc_power = adc_need_power_on;
280                 }
281
282                 if (dac_need_power_on != s_dac_power) {
283                         if (!is_analog_loop(loop)) {
284                                 dacl_digital_switch(enable);
285                                 dacr_digital_switch(enable);
286                         }
287                         s_dac_power = dac_need_power_on;
288                 }
289         }
290
291         if (enable == s_enable) {
292                 return 0;
293         } else {
294                 if (enable && loop) {
295                         printf("%s audio loop\n", _2str(enable));
296                         if (!is_analog_loop(loop)) {
297                                 sprd_codec_digital_loop(enable);
298                         }
299                         s_enable = enable;
300                 } else {
301                         if ((s_drv_in == 0) && (s_drv_out == 0)) {
302                                 printf("%s audio loop\n", _2str(enable));
303                                 if (!is_analog_loop(loop)) {
304                                         sprd_codec_digital_loop(enable);
305                                 }
306                                 s_enable = enable;
307                         }
308                 }
309         }
310         return 0;
311 }
312
313 int do_audio_codec(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[])
314 {
315         int enable = 0;
316         int loop = SOUND_DIGITAL_LOOP;
317         int drv_in = SOUND_MAIN_MIC;
318         int drv_out = SOUND_SPEAKER;
319
320         if (argc < 2)
321                 return cmd_usage(cmdtp);
322
323         enable = simple_strtoul(argv[1], NULL, 16);
324
325         if (!((enable == 0xA) || (enable == 0xD) || (enable == 0xE))) {
326                 printf("enable or disable? please refer:\n");
327                 return cmd_usage(cmdtp);
328         }
329
330         if (argc > 2)
331                 drv_in = simple_strtoul(argv[2], NULL, 16);
332         if (argc > 3)
333                 drv_out = simple_strtoul(argv[3], NULL, 16);
334         if (argc > 4)
335                 loop = simple_strtoul(argv[4], NULL, 16);
336
337         printf("\n");
338         return audio_codec(enable, loop, drv_in, drv_out);
339 }
340
341 #ifdef CONFIG_SOUND_DAI_VBC_R2P0
342 /* audio pin mux function */
343
344 static int audio_iis_fm(int enable, int port, int drv_out)
345 {
346         int ret = 0;
347         if (ret = arch_audio_pin_func_i2s_port(port, 0)) {
348                 printf("error iis port %d\n", port);
349                 return ret;
350         }
351         printf("iis port %d\n", port);
352         arch_audio_i2s_port_sys_sel(port, I2S_PORT_SYS_SEL_VBC);
353         /* codec setting */
354         ret = audio_codec(enable, 0, 0, drv_out);
355         sprd_codec_pcm_set_sample_rate(1, 32000);
356         sprd_codec_pcm_set_sample_rate(0, 32000);
357
358         if (enable == 0xA) {
359                 enable = 0;
360         } else {
361                 enable -= 0xD;
362         }
363         /* vbc setting */
364         if (enable) {
365                 vbc_startup(SNDRV_PCM_STREAM_PLAYBACK);
366                 vbc_startup(SNDRV_PCM_STREAM_CAPTURE);
367                 vbc_adc_sel_iis(2);
368                 vbc_dac0_fm_mixer(1);
369                 vbc_dac1_fm_mixer(1);
370                 vbc_trigger(SNDRV_PCM_STREAM_PLAYBACK, enable);
371                 vbc_trigger(SNDRV_PCM_STREAM_CAPTURE, enable);
372         } else {
373                 vbc_trigger(SNDRV_PCM_STREAM_PLAYBACK, enable);
374                 vbc_trigger(SNDRV_PCM_STREAM_CAPTURE, enable);
375                 vbc_dac0_fm_mixer(0);
376                 vbc_dac1_fm_mixer(0);
377                 vbc_adc_sel_iis(0);
378                 vbc_shutdown(SNDRV_PCM_STREAM_PLAYBACK);
379                 vbc_shutdown(SNDRV_PCM_STREAM_CAPTURE);
380         }
381
382         return ret;
383 }
384
385
386 int do_audio_iis_fm(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[])
387 {
388         int enable = 0;
389         int port = 3;
390         int drv_out = SOUND_SPEAKER;
391
392         if (argc < 2)
393                 return cmd_usage(cmdtp);
394
395         enable = simple_strtoul(argv[1], NULL, 16);
396
397         if (!((enable == 0xA) || (enable == 0xD) || (enable == 0xE))) {
398                 printf("enable or disable? please refer:\n");
399                 return cmd_usage(cmdtp);
400         }
401
402         if (argc > 2)
403                 port = simple_strtoul(argv[2], NULL, 16);
404         if (argc > 3)
405                 drv_out = simple_strtoul(argv[3], NULL, 16);
406
407         printf("\n");
408         return audio_iis_fm(enable, port, drv_out);
409 }
410 #endif
411
412 int do_func(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[])
413 {
414         return 0;
415 }
416
417 /* command define */
418
419 U_BOOT_CMD(audio_codec, 5, 1, do_audio_codec,
420            "switch audio analog route",
421            "\n"
422            "    - switch audio analog route, switch many driver in/out\n"
423            "audio_codec enable [driver_in] [driver_out] [loop]\n"
424            "    enable    - enable or diable audio loop\n"
425            "        d     - disable\n"
426            "        e     - enable\n"
427            "        a     - force all disable\n"
428            "    driver_in - select driver in\n"
429            "        0x01  - main mic(d)\n"
430            "        0x02  - aux mic\n"
431            "        0x04  - headset mic\n"
432            "        0x08  - ail\n"
433            "        0x10  - air\n"
434            "    driver_out- select driver out\n"
435            "        0x01  - speaker(d)\n"
436            "        0x02  - earpiece\n"
437            "        0x04  - headphone\n"
438            "        0x08  - speaker2\n"
439            "    loop      - select loop\n"
440            "        0x01  - digital loop(d)\n"
441            "        0x02  - analog loop\n"
442 );
443
444 #ifdef CONFIG_SOUND_DAI_VBC_R2P0
445 U_BOOT_CMD(audio_iis_fm, 4, 1, do_audio_iis_fm,
446            "select iis port to play fm",
447            "\n"
448            "    - select iis port to play fm with vbc fm mixer\n"
449            "audio_iis_fm enable [port] [driver_out]\n"
450            "    enable    - enable or diable audio loop\n"
451            "        d     - disable\n"
452            "        e     - enable\n"
453            "        a     - force all disable\n"
454            "    port      - select iis port\n"
455            "        0     - iis port 0\n"
456            "        1     - iis port 1\n"
457            "        2     - iis port 2\n"
458            "        3     - iis port 3(d)\n"
459            "    driver_out- select driver out\n"
460            "        0x01  - speaker(d)\n"
461            "        0x02  - earpiece\n"
462            "        0x04  - headphone\n"
463            "        0x08  - speaker2\n"
464 );
465 #endif