import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / sound / soc / mediatek / mt_soc_audio_v3 / mt_soc_pcm_voice_md1_bt.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_pcm_voice_md1_bt.c
21 *
22 * Project:
23 * --------
24 * voice_bt 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_bt_probe(struct platform_device *pdev);
68 static int mtk_voice_bt_close(struct snd_pcm_substream *substream);
69 static int mtk_soc_voice_bt_new(struct snd_soc_pcm_runtime *rtd);
70 static int mtk_voice_bt_platform_probe(struct snd_soc_platform *platform);
71 static bool SetModemSpeechDAIBTAttribute(int sample_rate);
72
73 static bool voice_bt_Status = false;
74 static AudioDigtalI2S mAudioDigitalI2S;
75
76 bool get_voice_bt_status(void)
77 {
78 return voice_bt_Status;
79 }
80
81 EXPORT_SYMBOL(get_voice_bt_status);
82
83 static AudioDigitalPCM voice_bt1Pcm =
84 {
85 .mTxLchRepeatSel = Soc_Aud_TX_LCH_RPT_TX_LCH_NO_REPEAT,
86 .mVbt16kModeSel = Soc_Aud_VBT_16K_MODE_VBT_16K_MODE_DISABLE,
87 .mExtModemSel = Soc_Aud_EXT_MODEM_MODEM_2_USE_INTERNAL_MODEM,
88 .mExtendBckSyncLength = 0,
89 .mExtendBckSyncTypeSel = Soc_Aud_PCM_SYNC_TYPE_BCK_CYCLE_SYNC,
90 .mSingelMicSel = Soc_Aud_BT_MODE_DUAL_MIC_ON_TX,
91 .mAsyncFifoSel = Soc_Aud_BYPASS_SRC_SLAVE_USE_ASRC,
92 .mSlaveModeSel = Soc_Aud_PCM_CLOCK_SOURCE_SALVE_MODE,
93 .mPcmWordLength = Soc_Aud_PCM_WLEN_LEN_PCM_16BIT,
94 .mPcmModeWidebandSel = false,
95 .mPcmFormat = Soc_Aud_PCM_FMT_PCM_MODE_B,
96 .mModemPcmOn = false,
97 };
98
99 static struct snd_pcm_hw_constraint_list constraints_sample_rates =
100 {
101 .count = ARRAY_SIZE(soc_voice_supported_sample_rates),
102 .list = soc_voice_supported_sample_rates,
103 .mask = 0,
104 };
105
106 static struct snd_pcm_hardware mtk_pcm_hardware =
107 {
108 .info = (SNDRV_PCM_INFO_MMAP |
109 SNDRV_PCM_INFO_INTERLEAVED |
110 SNDRV_PCM_INFO_RESUME |
111 SNDRV_PCM_INFO_MMAP_VALID),
112 .formats = SND_SOC_STD_MT_FMTS,
113 .rates = SOC_NORMAL_USE_RATE,
114 .rate_min = SOC_NORMAL_USE_RATE_MIN,
115 .rate_max = SOC_NORMAL_USE_RATE_MAX,
116 .channels_min = SOC_NORMAL_USE_CHANNELS_MIN,
117 .channels_max = SOC_NORMAL_USE_CHANNELS_MAX,
118 .buffer_bytes_max = MAX_BUFFER_SIZE,
119 .period_bytes_max = MAX_PERIOD_SIZE,
120 .periods_min = 1,
121 .periods_max = 4096,
122 .fifo_size = 0,
123 };
124
125 static int mtk_voice_bt_pcm_open(struct snd_pcm_substream *substream)
126 {
127 struct snd_pcm_runtime *runtime = substream->runtime;
128 int err = 0;
129 int ret = 0;
130 AudDrv_Clk_On();
131
132 printk("mtk_voice_bt_pcm_open\n");
133
134 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
135 {
136 printk("%s with SNDRV_PCM_STREAM_CAPTURE \n", __func__);
137 runtime->rate = 16000;
138 return 0;
139 }
140 runtime->hw = mtk_pcm_hardware;
141 memcpy((void *)(&(runtime->hw)), (void *)&mtk_pcm_hardware , sizeof(struct snd_pcm_hardware));
142
143 ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
144 &constraints_sample_rates);
145 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
146
147 if (ret < 0)
148 {
149 printk("snd_pcm_hw_constraint_integer failed\n");
150 }
151
152 //print for hw pcm information
153 printk("mtk_voice_bt_pcm_open runtime rate = %d channels = %d \n", runtime->rate, runtime->channels);
154
155 runtime->hw.info |= SNDRV_PCM_INFO_INTERLEAVED;
156 runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
157
158 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
159 {
160 printk("SNDRV_PCM_STREAM_PLAYBACK mtkalsa_voice_bt_constraints\n");
161 runtime->rate = 16000;
162 }
163 else
164 {
165
166 }
167
168 if (err < 0)
169 {
170 printk("mtk_voice_bt_close\n");
171 mtk_voice_bt_close(substream);
172 return err;
173 }
174 printk("mtk_voice_bt_pcm_open return\n");
175 return 0;
176 }
177
178 #if 0 //not used
179 static void ConfigAdcI2S(struct snd_pcm_substream *substream)
180 {
181 mAudioDigitalI2S.mLR_SWAP = Soc_Aud_LR_SWAP_NO_SWAP;
182 mAudioDigitalI2S.mBuffer_Update_word = 8;
183 mAudioDigitalI2S.mFpga_bit_test = 0;
184 mAudioDigitalI2S.mFpga_bit = 0;
185 mAudioDigitalI2S.mloopback = 0;
186 mAudioDigitalI2S.mINV_LRCK = Soc_Aud_INV_LRCK_NO_INVERSE;
187 mAudioDigitalI2S.mI2S_FMT = Soc_Aud_I2S_FORMAT_I2S;
188 mAudioDigitalI2S.mI2S_WLEN = Soc_Aud_I2S_WLEN_WLEN_16BITS;
189 mAudioDigitalI2S.mI2S_SAMPLERATE = (substream->runtime->rate);
190 }
191 #endif
192
193 static int mtk_voice_bt_close(struct snd_pcm_substream *substream)
194 {
195 printk("mtk_voice_bt_close \n");
196 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
197 {
198 printk("%s with SNDRV_PCM_STREAM_CAPTURE \n", __func__);
199 AudDrv_Clk_Off();
200 return 0;
201 }
202
203 // interconnection setting
204 SetConnection(Soc_Aud_InterCon_DisConnect, Soc_Aud_InterConnectionInput_I02, Soc_Aud_InterConnectionOutput_O17);
205 SetConnection(Soc_Aud_InterCon_DisConnect, Soc_Aud_InterConnectionInput_I02, Soc_Aud_InterConnectionOutput_O18);
206 SetConnection(Soc_Aud_InterCon_DisConnect, Soc_Aud_InterConnectionInput_I14, Soc_Aud_InterConnectionOutput_O02);
207 SetConnection(Soc_Aud_InterCon_DisConnect, Soc_Aud_InterConnectionInput_I21, Soc_Aud_InterConnectionOutput_O02);
208
209 // here start digital part
210 SetMemoryPathEnable(Soc_Aud_Digital_Block_DAI_BT, false);
211 SetDaiBtEnable(false);
212
213 EnableAfe(false);
214 AudDrv_Clk_Off();
215
216 voice_bt_Status = false;
217
218 return 0;
219 }
220
221 static int mtk_voice_bt_trigger(struct snd_pcm_substream *substream, int cmd)
222 {
223 printk("mtk_voice_bt_trigger cmd = %d\n", cmd);
224 switch (cmd)
225 {
226 case SNDRV_PCM_TRIGGER_START:
227 case SNDRV_PCM_TRIGGER_RESUME:
228 case SNDRV_PCM_TRIGGER_STOP:
229 case SNDRV_PCM_TRIGGER_SUSPEND:
230 break;
231 }
232 return 0;
233 }
234
235 static int mtk_voice_bt_pcm_copy(struct snd_pcm_substream *substream,
236 int channel, snd_pcm_uframes_t pos,
237 void __user *dst, snd_pcm_uframes_t count)
238 {
239 return 0;
240 }
241
242 static int mtk_voice_bt_pcm_silence(struct snd_pcm_substream *substream,
243 int channel, snd_pcm_uframes_t pos,
244 snd_pcm_uframes_t count)
245 {
246 printk("mtk_voice_bt_pcm_silence \n");
247 return 0; /* do nothing */
248 }
249
250 static void *dummy_page[2];
251 static struct page *mtk_pcm_page(struct snd_pcm_substream *substream,
252 unsigned long offset)
253 {
254 return virt_to_page(dummy_page[substream->stream]); /* the same page */
255 }
256
257 static bool SetModemSpeechDAIBTAttribute(int sample_rate)
258 {
259 AudioDigitalDAIBT daibt_attribute;
260 memset((void *)&daibt_attribute, 0, sizeof(daibt_attribute));
261
262 #if 0 // temp for merge only support
263 daibt_attribute.mUSE_MRGIF_INPUT = Soc_Aud_BT_DAI_INPUT_FROM_BT;
264 #else
265 daibt_attribute.mUSE_MRGIF_INPUT = Soc_Aud_BT_DAI_INPUT_FROM_MGRIF;
266 #endif
267 daibt_attribute.mDAI_BT_MODE = (sample_rate == 8000) ? Soc_Aud_DATBT_MODE_Mode8K : Soc_Aud_DATBT_MODE_Mode16K;
268 daibt_attribute.mDAI_DEL = Soc_Aud_DAI_DEL_HighWord; // suggest always HighWord
269 daibt_attribute.mBT_LEN = 0;
270 daibt_attribute.mDATA_RDY = true;
271 daibt_attribute.mBT_SYNC = Soc_Aud_BTSYNC_Short_Sync;
272 daibt_attribute.mBT_ON = true;
273 daibt_attribute.mDAIBT_ON = false;
274 SetDaiBt(&daibt_attribute);
275 return true;
276 }
277
278 static int mtk_voice_bt1_prepare(struct snd_pcm_substream *substream)
279 {
280 struct snd_pcm_runtime *runtimeStream = substream->runtime;
281 printk("mtk_alsa_prepare rate = %d channels = %d period_size = %lu\n",
282 runtimeStream->rate, runtimeStream->channels, runtimeStream->period_size);
283
284 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
285 {
286 printk("%s with SNDRV_PCM_STREAM_CAPTURE \n", __func__);
287 return 0;
288 }
289 AudDrv_Clk_On();
290
291 // here start digital part
292 SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I02, Soc_Aud_InterConnectionOutput_O17);
293 SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I02, Soc_Aud_InterConnectionOutput_O18);
294 SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I14, Soc_Aud_InterConnectionOutput_O02);
295 SetConnection(Soc_Aud_InterCon_Connection, Soc_Aud_InterConnectionInput_I21, Soc_Aud_InterConnectionOutput_O08);
296
297 if (GetMemoryPathEnable(Soc_Aud_Digital_Block_DAI_BT) == false)
298 {
299 //set merge interface
300 SetMemoryPathEnable(Soc_Aud_Digital_Block_DAI_BT, true);
301 }
302 else
303 {
304 SetMemoryPathEnable(Soc_Aud_Digital_Block_DAI_BT, true);
305 }
306
307 // now use samplerate 8000
308 SetModemSpeechDAIBTAttribute(runtimeStream->rate);
309 SetDaiBtEnable(true);
310 voice_bt1Pcm.mPcmModeWidebandSel = (runtimeStream->rate == 8000) ? Soc_Aud_PCM_MODE_PCM_MODE_8K : Soc_Aud_PCM_MODE_PCM_MODE_16K;
311 voice_bt1Pcm.mAsyncFifoSel = Soc_Aud_BYPASS_SRC_SLAVE_USE_ASYNC_FIFO;
312 SetModemPcmConfig(MODEM_1, voice_bt1Pcm);
313 SetModemPcmEnable(MODEM_1, true);
314 EnableAfe(true);
315 voice_bt_Status = true;
316
317 return 0;
318 }
319
320 static int mtk_pcm_hw_params(struct snd_pcm_substream *substream,
321 struct snd_pcm_hw_params *hw_params)
322 {
323 int ret = 0;
324 printk("mtk_pcm_hw_params \n");
325 return ret;
326 }
327
328 static int mtk_voice_bt_hw_free(struct snd_pcm_substream *substream)
329 {
330 PRINTK_AUDDRV("mtk_voice_bt_hw_free \n");
331 return snd_pcm_lib_free_pages(substream);
332 }
333
334 static struct snd_pcm_ops mtk_voice_bt_ops =
335 {
336 .open = mtk_voice_bt_pcm_open,
337 .close = mtk_voice_bt_close,
338 .ioctl = snd_pcm_lib_ioctl,
339 .hw_params = mtk_pcm_hw_params,
340 .hw_free = mtk_voice_bt_hw_free,
341 .prepare = mtk_voice_bt1_prepare,
342 .trigger = mtk_voice_bt_trigger,
343 .copy = mtk_voice_bt_pcm_copy,
344 .silence = mtk_voice_bt_pcm_silence,
345 .page = mtk_pcm_page,
346 };
347
348 static struct snd_soc_platform_driver mtk_soc_voice_bt_platform =
349 {
350 .ops = &mtk_voice_bt_ops,
351 .pcm_new = mtk_soc_voice_bt_new,
352 .probe = mtk_voice_bt_platform_probe,
353 };
354
355 static int mtk_voice_bt_probe(struct platform_device *pdev)
356 {
357 printk("mtk_voice_bt_probe\n");
358
359 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
360 if (!pdev->dev.dma_mask)
361 {
362 pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
363 }
364
365 if (pdev->dev.of_node)
366 {
367 dev_set_name(&pdev->dev, "%s", MT_SOC_VOICE_MD1_BT);
368 }
369 printk("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
370 return snd_soc_register_platform(&pdev->dev,
371 &mtk_soc_voice_bt_platform);
372 }
373
374 static int mtk_soc_voice_bt_new(struct snd_soc_pcm_runtime *rtd)
375 {
376 int ret = 0;
377 printk("%s\n", __func__);
378 return ret;
379 }
380
381 static int mtk_voice_bt_platform_probe(struct snd_soc_platform *platform)
382 {
383 printk("mtk_voice_bt_platform_probe\n");
384 return 0;
385 }
386
387 static int mtk_voice_bt_remove(struct platform_device *pdev)
388 {
389 pr_debug("%s\n", __func__);
390 snd_soc_unregister_platform(&pdev->dev);
391 return 0;
392 }
393
394
395 //supend and resume function
396 static int mtk_voice_bt_pm_ops_suspend(struct device *device)
397 {
398 // if now in phone call state, not suspend!!
399 bool b_modem1_speech_on;
400 bool b_modem2_speech_on;
401 AudDrv_Clk_On();//should enable clk for access reg
402 b_modem1_speech_on = (bool)(Afe_Get_Reg(PCM2_INTF_CON) & 0x1);
403 b_modem2_speech_on = (bool)(Afe_Get_Reg(PCM_INTF_CON) & 0x1);
404 AudDrv_Clk_Off();
405 if (b_modem1_speech_on == true || b_modem2_speech_on == true)
406 {
407 clkmux_sel(MT_MUX_AUDINTBUS, 0, "AUDIO"); //select 26M
408 return 0;
409 }
410 return 0;
411 }
412
413 static int mtk_voice_bt_pm_ops_resume(struct device *device)
414 {
415 bool b_modem1_speech_on;
416 bool b_modem2_speech_on;
417 AudDrv_Clk_On();//should enable clk for access reg
418 b_modem1_speech_on = (bool)(Afe_Get_Reg(PCM2_INTF_CON) & 0x1);
419 b_modem2_speech_on = (bool)(Afe_Get_Reg(PCM_INTF_CON) & 0x1);
420 AudDrv_Clk_Off();
421 if (b_modem1_speech_on == true || b_modem2_speech_on == true)
422 {
423 clkmux_sel(MT_MUX_AUDINTBUS, 1, "AUDIO"); //mainpll
424 return 0;
425 }
426
427 return 0;
428 }
429
430 struct dev_pm_ops mtk_voice_bt_pm_ops =
431 {
432 .suspend = mtk_voice_bt_pm_ops_suspend,
433 .resume = mtk_voice_bt_pm_ops_resume,
434 .freeze = NULL,
435 .thaw = NULL,
436 .poweroff = NULL,
437 .restore = NULL,
438 .restore_noirq = NULL,
439 };
440
441 #ifdef CONFIG_OF
442 static const struct of_device_id mt_soc_pcm_voice_md1_bt_of_ids[] =
443 {
444 { .compatible = "mediatek,mt_soc_pcm_voice_md1_bt", },
445 {}
446 };
447 #endif
448
449 static struct platform_driver mtk_voice_bt_driver =
450 {
451 .driver = {
452 .name = MT_SOC_VOICE_MD1_BT,
453 .owner = THIS_MODULE,
454 #ifdef CONFIG_OF
455 .of_match_table = mt_soc_pcm_voice_md1_bt_of_ids,
456 #endif
457 #ifdef CONFIG_PM
458 .pm = &mtk_voice_bt_pm_ops,
459 #endif
460 },
461 .probe = mtk_voice_bt_probe,
462 .remove = mtk_voice_bt_remove,
463 };
464
465 #ifndef CONFIG_OF
466 static struct platform_device *soc_mtk_voice_bt_dev;
467 #endif
468
469 static int __init mtk_soc_voice_bt_platform_init(void)
470 {
471 int ret = 0;
472 printk("%s\n", __func__);
473 #ifndef CONFIG_OF
474 soc_mtk_voice_bt_dev = platform_device_alloc(MT_SOC_VOICE_MD1_BT, -1);
475 if (!soc_mtk_voice_bt_dev)
476 {
477 return -ENOMEM;
478 }
479
480 ret = platform_device_add(soc_mtk_voice_bt_dev);
481 if (ret != 0)
482 {
483 platform_device_put(soc_mtk_voice_bt_dev);
484 return ret;
485 }
486 #endif
487 ret = platform_driver_register(&mtk_voice_bt_driver);
488
489 return ret;
490
491 }
492 module_init(mtk_soc_voice_bt_platform_init);
493
494 static void __exit mtk_soc_voice_bt_platform_exit(void)
495 {
496
497 printk("%s\n", __func__);
498 platform_driver_unregister(&mtk_voice_bt_driver);
499 }
500 module_exit(mtk_soc_voice_bt_platform_exit);
501
502 MODULE_DESCRIPTION("AFE PCM module platform driver");
503 MODULE_LICENSE("GPL");
504
505