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