import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / sound / soc / mediatek / mt_soc_audio_v1 / mt_soc_pcm_voice.c
1 /*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 /*******************************************************************************
17 *
18 * Filename:
19 * ---------
20 * mt_soc_voice.c
21 *
22 * Project:
23 * --------
24 * voice call platform driver
25 *
26 * Description:
27 * ------------
28 *
29 *
30 * Author:
31 * -------
32 * Chipeng Chang
33 *
34 *------------------------------------------------------------------------------
35 * $Revision: #1 $
36 * $Modtime:$
37 * $Log:$
38 *
39 *
40 *******************************************************************************/
41
42
43 /*****************************************************************************
44 * C O M P I L E R F L A G S
45 *****************************************************************************/
46
47
48 /*****************************************************************************
49 * E X T E R N A L R E F E R E N C E S
50 *****************************************************************************/
51
52 #include <linux/dma-mapping.h>
53 #include "AudDrv_Common.h"
54 #include "AudDrv_Def.h"
55 #include "AudDrv_Afe.h"
56 #include "AudDrv_Ana.h"
57 #include "AudDrv_Clk.h"
58 #include "AudDrv_Kernel.h"
59 #include "mt_soc_afe_control.h"
60 #include "mt_soc_digital_type.h"
61 #include "mt_soc_pcm_common.h"
62
63 /*
64 * function implementation
65 */
66
67 static int mtk_voice_probe(struct platform_device *pdev);
68 static int mtk_voice_close(struct snd_pcm_substream *substream);
69 static int mtk_soc_voice_new(struct snd_soc_pcm_runtime *rtd);
70 static int mtk_voice_platform_probe(struct snd_soc_platform *platform);
71
72 static uint16 Voice_Status = 0;
73 static AudioDigtalI2S mAudioDigitalI2S;
74 #define VOICE_UL_ON (1<<0)
75 #define VOICE_DL_ON (1<<1)
76 bool get_voice_status(void)
77 {
78 return (Voice_Status != 0) | GetExternalModemStatus();
79 }
80 EXPORT_SYMBOL(get_voice_status);
81 static AudioDigitalPCM Voice1Pcm =
82 {
83 .mTxLchRepeatSel = Soc_Aud_TX_LCH_RPT_TX_LCH_NO_REPEAT,
84 .mVbt16kModeSel = Soc_Aud_VBT_16K_MODE_VBT_16K_MODE_DISABLE,
85 .mExtModemSel = Soc_Aud_EXT_MODEM_MODEM_2_USE_INTERNAL_MODEM,
86 .mExtendBckSyncLength = 0,
87 .mExtendBckSyncTypeSel = Soc_Aud_PCM_SYNC_TYPE_BCK_CYCLE_SYNC,
88 .mSingelMicSel = Soc_Aud_BT_MODE_DUAL_MIC_ON_TX,
89 .mAsyncFifoSel = Soc_Aud_BYPASS_SRC_SLAVE_USE_ASRC,
90 .mSlaveModeSel = Soc_Aud_PCM_CLOCK_SOURCE_SALVE_MODE,
91 .mPcmWordLength = Soc_Aud_PCM_WLEN_LEN_PCM_16BIT,
92 .mPcmModeWidebandSel = false,
93 .mPcmFormat = Soc_Aud_PCM_FMT_PCM_MODE_B,
94 .mModemPcmOn = false,
95 };
96
97 static struct snd_pcm_hw_constraint_list constraints_sample_rates =
98 {
99 .count = ARRAY_SIZE(soc_voice_supported_sample_rates),
100 .list = soc_voice_supported_sample_rates,
101 .mask = 0,
102 };
103
104 static struct snd_pcm_hardware mtk_pcm_hardware =
105 {
106 .info = (SNDRV_PCM_INFO_MMAP |
107 SNDRV_PCM_INFO_INTERLEAVED |
108 SNDRV_PCM_INFO_RESUME |
109 SNDRV_PCM_INFO_MMAP_VALID),
110 .formats = SND_SOC_STD_MT_FMTS,
111 .rates = SOC_NORMAL_USE_RATE,
112 .rate_min = SOC_NORMAL_USE_RATE_MIN,
113 .rate_max = SOC_NORMAL_USE_RATE_MAX,
114 .channels_min = SOC_NORMAL_USE_CHANNELS_MIN,
115 .channels_max = SOC_NORMAL_USE_CHANNELS_MAX,
116 .buffer_bytes_max = MAX_BUFFER_SIZE,
117 .period_bytes_max = MAX_PERIOD_SIZE,
118 .periods_min = 1,
119 .periods_max = 4096,
120 .fifo_size = 0,
121 };
122
123 static int mtk_voice_pcm_open(struct snd_pcm_substream *substream)
124 {
125 struct snd_pcm_runtime *runtime = substream->runtime;
126 int err = 0;
127 int ret = 0;
128 AudDrv_Clk_On();
129 AudDrv_ADC_Clk_On();
130
131 printk("mtk_voice_pcm_open\n");
132
133 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
134 {
135 printk("%s with SNDRV_PCM_STREAM_CAPTURE \n",__func__);
136 runtime->rate = 16000;
137 if(Voice_Status != 0)
138 {
139 return 0;
140 }
141 }
142 runtime->hw = mtk_pcm_hardware;
143 memcpy((void *)(&(runtime->hw)), (void *)&mtk_pcm_hardware , sizeof(struct snd_pcm_hardware));
144
145 ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
146 &constraints_sample_rates);
147 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
148
149 if (ret < 0)
150 {
151 printk("snd_pcm_hw_constraint_integer failed\n");
152 }
153
154 //print for hw pcm information
155 printk("mtk_voice_pcm_open runtime rate = %d channels = %d \n", runtime->rate, runtime->channels);
156
157 runtime->hw.info |= SNDRV_PCM_INFO_INTERLEAVED;
158 runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
159
160 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
161 {
162 printk("SNDRV_PCM_STREAM_PLAYBACK mtkalsa_voice_constraints\n");
163 runtime->rate = 16000;
164 }
165 else
166 {
167
168 }
169
170 if (err < 0)
171 {
172 printk("mtk_voice_close\n");
173 mtk_voice_close(substream);
174 return err;
175 }
176 printk("mtk_voice_pcm_open return\n");
177 return 0;
178 }
179
180 static void ConfigAdcI2S(struct snd_pcm_substream *substream)
181 {
182 mAudioDigitalI2S.mLR_SWAP = Soc_Aud_LR_SWAP_NO_SWAP;
183 mAudioDigitalI2S.mBuffer_Update_word = 8;
184 mAudioDigitalI2S.mFpga_bit_test = 0;
185 mAudioDigitalI2S.mFpga_bit = 0;
186 mAudioDigitalI2S.mloopback = 0;
187 mAudioDigitalI2S.mINV_LRCK = Soc_Aud_INV_LRCK_NO_INVERSE;
188 mAudioDigitalI2S.mI2S_FMT = Soc_Aud_I2S_FORMAT_I2S;
189 mAudioDigitalI2S.mI2S_WLEN = Soc_Aud_I2S_WLEN_WLEN_16BITS;
190 mAudioDigitalI2S.mI2S_SAMPLERATE = (substream->runtime->rate);
191 }
192
193 static int mtk_voice_close(struct snd_pcm_substream *substream)
194 {
195 printk("mtk_voice_close \n");
196
197 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
198 {
199 printk("%s with SNDRV_PCM_STREAM_PLAYBACK \n",__func__);
200 SetConnection(Soc_Aud_InterCon_DisConnect, Soc_Aud_InterConnectionInput_I14, Soc_Aud_InterConnectionOutput_O03);
201 SetConnection(Soc_Aud_InterCon_DisConnect, Soc_Aud_InterConnectionInput_I14, Soc_Aud_InterConnectionOutput_O04);
202 SetI2SDacEnable(false);
203 SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_OUT_DAC, false);
204 Voice_Status &= ~VOICE_DL_ON;
205 if(Voice_Status == 0)
206 {
207 SetModemPcmEnable(MODEM_1, false);
208 }
209 EnableAfe(false);
210 AudDrv_Clk_Off();
211 AudDrv_ADC_Clk_Off();
212 }
213 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
214 {
215 printk("%s with SNDRV_PCM_STREAM_CAPTURE \n",__func__);
216 SetConnection(Soc_Aud_InterCon_DisConnect, Soc_Aud_InterConnectionInput_I03, Soc_Aud_InterConnectionOutput_O17);
217 SetConnection(Soc_Aud_InterCon_DisConnect, Soc_Aud_InterConnectionInput_I04, Soc_Aud_InterConnectionOutput_O18);
218 SetI2SAdcEnable(false);
219 SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_ADC, false);
220
221 Voice_Status &= ~VOICE_UL_ON;
222 if(Voice_Status == 0)
223 {
224 SetModemPcmEnable(MODEM_1, false);
225 }
226 EnableAfe(false);
227 AudDrv_Clk_Off();
228 AudDrv_ADC_Clk_Off();
229 }
230
231 return 0;
232 }
233
234 static int mtk_voice_trigger(struct snd_pcm_substream *substream, int cmd)
235 {
236 printk("mtk_voice_trigger cmd = %d\n", cmd);
237 switch (cmd)
238 {
239 case SNDRV_PCM_TRIGGER_START:
240 case SNDRV_PCM_TRIGGER_RESUME:
241 case SNDRV_PCM_TRIGGER_STOP:
242 case SNDRV_PCM_TRIGGER_SUSPEND:
243 break;
244 }
245 return 0;
246 }
247
248 static int mtk_voice_pcm_copy(struct snd_pcm_substream *substream,
249 int channel, snd_pcm_uframes_t pos,
250 void __user *dst, snd_pcm_uframes_t count)
251 {
252 return 0;
253 }
254
255 static int mtk_voice_pcm_silence(struct snd_pcm_substream *substream,
256 int channel, snd_pcm_uframes_t pos,
257 snd_pcm_uframes_t count)
258 {
259 printk("mtk_voice_pcm_silence \n");
260 return 0; /* do nothing */
261 }
262
263 static void *dummy_page[2];
264 static struct page *mtk_pcm_page(struct snd_pcm_substream *substream,
265 unsigned long offset)
266 {
267 return virt_to_page(dummy_page[substream->stream]); /* the same page */
268 }
269
270 static int mtk_voice1_prepare(struct snd_pcm_substream *substream)
271 {
272 struct snd_pcm_runtime *runtimeStream = substream->runtime;
273 printk("mtk_voice1_prepare rate = %d channels = %d period_size = %lu\n",
274 runtimeStream->rate, runtimeStream->channels, runtimeStream->period_size);
275
276 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
277 {
278 printk("%s with SNDRV_PCM_STREAM_PLAYBACK \n",__func__);
279 SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I14, Soc_Aud_InterConnectionOutput_O03);
280 SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I14, Soc_Aud_InterConnectionOutput_O04);
281 // start I2S DAC out
282 SetI2SDacOut(substream->runtime->rate);
283 SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_OUT_DAC, true);
284 SetI2SDacEnable(true);
285 EnableAfe(true);
286 }
287 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
288 {
289 printk("%s with SNDRV_PCM_STREAM_CAPTURE \n",__func__);
290 SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I03, Soc_Aud_InterConnectionOutput_O17);
291 SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I04, Soc_Aud_InterConnectionOutput_O18);
292 ConfigAdcI2S(substream);
293 SetI2SAdcIn(&mAudioDigitalI2S);
294 SetMemoryPathEnable(Soc_Aud_Digital_Block_I2S_IN_ADC, true);
295 SetI2SAdcEnable(true);
296 EnableAfe(true);
297
298 }
299 if(Voice_Status == 0)
300 {
301 Voice1Pcm.mPcmModeWidebandSel = (runtimeStream->rate == 8000) ? Soc_Aud_PCM_MODE_PCM_MODE_8K : Soc_Aud_PCM_MODE_PCM_MODE_16K;
302 Voice1Pcm.mAsyncFifoSel = Soc_Aud_BYPASS_SRC_SLAVE_USE_ASYNC_FIFO;
303 SetModemPcmConfig(MODEM_1, Voice1Pcm);
304 SetModemPcmEnable(MODEM_1, true);
305 }
306 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
307 {
308 Voice_Status |= VOICE_DL_ON;
309 }
310 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
311 {
312 Voice_Status |= VOICE_UL_ON;
313 }
314
315 return 0;
316 }
317
318 static int mtk_pcm_hw_params(struct snd_pcm_substream *substream,
319 struct snd_pcm_hw_params *hw_params)
320 {
321 int ret = 0;
322 printk("mtk_pcm_hw_params \n");
323 return ret;
324 }
325
326 static int mtk_voice_hw_free(struct snd_pcm_substream *substream)
327 {
328 PRINTK_AUDDRV("mtk_voice_hw_free \n");
329 return snd_pcm_lib_free_pages(substream);
330 }
331
332 static struct snd_pcm_ops mtk_voice_ops =
333 {
334 .open = mtk_voice_pcm_open,
335 .close = mtk_voice_close,
336 .ioctl = snd_pcm_lib_ioctl,
337 .hw_params = mtk_pcm_hw_params,
338 .hw_free = mtk_voice_hw_free,
339 .prepare = mtk_voice1_prepare,
340 .trigger = mtk_voice_trigger,
341 .copy = mtk_voice_pcm_copy,
342 .silence = mtk_voice_pcm_silence,
343 .page = mtk_pcm_page,
344 };
345
346 static struct snd_soc_platform_driver mtk_soc_voice_platform =
347 {
348 .ops = &mtk_voice_ops,
349 .pcm_new = mtk_soc_voice_new,
350 .probe = mtk_voice_platform_probe,
351 };
352
353 static int mtk_voice_probe(struct platform_device *pdev)
354 {
355 printk("mtk_voice_probe\n");
356
357 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
358 if (!pdev->dev.dma_mask)
359 {
360 pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
361 }
362
363 if (pdev->dev.of_node)
364 {
365 dev_set_name(&pdev->dev, "%s", MT_SOC_VOICE);
366 }
367 printk("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
368 return snd_soc_register_platform(&pdev->dev,
369 &mtk_soc_voice_platform);
370 }
371
372 static int mtk_soc_voice_new(struct snd_soc_pcm_runtime *rtd)
373 {
374 int ret = 0;
375 printk("%s\n", __func__);
376 return ret;
377 }
378
379 static int mtk_voice_platform_probe(struct snd_soc_platform *platform)
380 {
381 printk("mtk_voice_platform_probe\n");
382 return 0;
383 }
384
385 static int mtk_voice_remove(struct platform_device *pdev)
386 {
387 pr_debug("%s\n", __func__);
388 snd_soc_unregister_platform(&pdev->dev);
389 return 0;
390 }
391
392
393 //supend and resume function
394 static int mtk_voice_pm_ops_suspend(struct device *device)
395 {
396 // if now in phone call state, not suspend!!
397 bool b_modem1_speech_on;
398 bool b_modem2_speech_on;
399 AudDrv_Clk_On();//should enable clk for access reg
400 b_modem1_speech_on = (bool)(Afe_Get_Reg(PCM2_INTF_CON) & 0x1);
401 b_modem2_speech_on = (bool)(Afe_Get_Reg(PCM_INTF_CON) & 0x1);
402 AudDrv_Clk_Off();//should enable clk for access reg
403 if (b_modem1_speech_on == true || b_modem2_speech_on == true)
404 {
405 clkmux_sel(MT_MUX_AUDINTBUS, 0, "AUDIO"); //select 26M
406 return 0;
407 }
408 return 0;
409 }
410
411 static int mtk_voice_pm_ops_resume(struct device *device)
412 {
413 bool b_modem1_speech_on;
414 bool b_modem2_speech_on;
415 AudDrv_Clk_On();//should enable clk for access reg
416 b_modem1_speech_on = (bool)(Afe_Get_Reg(PCM2_INTF_CON) & 0x1);
417 b_modem2_speech_on = (bool)(Afe_Get_Reg(PCM_INTF_CON) & 0x1);
418 AudDrv_Clk_Off();
419 if (b_modem1_speech_on == true || b_modem2_speech_on == true)
420 {
421 clkmux_sel(MT_MUX_AUDINTBUS, 1, "AUDIO"); //mainpll
422 return 0;
423 }
424 return 0;
425 }
426
427 struct dev_pm_ops mtk_voice_pm_ops =
428 {
429 .suspend = mtk_voice_pm_ops_suspend,
430 .resume = mtk_voice_pm_ops_resume,
431 .freeze = NULL,
432 .thaw = NULL,
433 .poweroff = NULL,
434 .restore = NULL,
435 .restore_noirq = NULL,
436 };
437
438 #ifdef CONFIG_OF
439 static const struct of_device_id mt_soc_pcm_voice_of_ids[] =
440 {
441 { .compatible = "mediatek,mt_soc_pcm_voice", },
442 {}
443 };
444 #endif
445
446 static struct platform_driver mtk_voice_driver =
447 {
448 .driver = {
449 .name = MT_SOC_VOICE,
450 .owner = THIS_MODULE,
451 #ifdef CONFIG_OF
452 .of_match_table = mt_soc_pcm_voice_of_ids,
453 #endif
454 #ifdef CONFIG_PM
455 .pm = &mtk_voice_pm_ops,
456 #endif
457 },
458 .probe = mtk_voice_probe,
459 .remove = mtk_voice_remove,
460 };
461
462 #ifndef CONFIG_OF
463 static struct platform_device *soc_mtk_voice_dev;
464 #endif
465
466 static int __init mtk_soc_voice_platform_init(void)
467 {
468 int ret = 0;
469 printk("%s\n", __func__);
470 #ifndef CONFIG_OF
471 soc_mtk_voice_dev = platform_device_alloc(MT_SOC_VOICE , -1);
472 if (!soc_mtk_voice_dev)
473 {
474 return -ENOMEM;
475 }
476
477 ret = platform_device_add(soc_mtk_voice_dev);
478 if (ret != 0)
479 {
480 platform_device_put(soc_mtk_voice_dev);
481 return ret;
482 }
483 #endif
484 ret = platform_driver_register(&mtk_voice_driver);
485
486 return ret;
487
488 }
489 module_init(mtk_soc_voice_platform_init);
490
491 static void __exit mtk_soc_voice_platform_exit(void)
492 {
493
494 printk("%s\n", __func__);
495 platform_driver_unregister(&mtk_voice_driver);
496 }
497 module_exit(mtk_soc_voice_platform_exit);
498
499 MODULE_DESCRIPTION("AFE PCM module platform driver");
500 MODULE_LICENSE("GPL");
501
502