2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 /*******************************************************************************
20 * mt_soc_voice_ext_bt.c
24 * voice_bt call platform driver
34 *------------------------------------------------------------------------------
40 *******************************************************************************/
43 /*****************************************************************************
44 * C O M P I L E R F L A G S
45 *****************************************************************************/
48 /*****************************************************************************
49 * E X T E R N A L R E F E R E N C E S
50 *****************************************************************************/
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"
64 * function implementation
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
);
72 static bool voice_ext_bt_Status
= false;
74 bool get_voice_ext_bt_status(void)
76 return voice_ext_bt_Status
;
79 EXPORT_SYMBOL(get_voice_ext_bt_status
);
81 static AudioDigitalPCM voice_ExtBt1Pcm
=
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
,
98 static struct snd_pcm_hw_constraint_list constraints_sample_rates
=
100 .count
= ARRAY_SIZE(soc_voice_supported_sample_rates
),
101 .list
= soc_voice_supported_sample_rates
,
105 static struct snd_pcm_hardware mtk_pcm_hardware
=
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
,
124 static int mtk_voice_ext_bt_pcm_open(struct snd_pcm_substream
*substream
)
126 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
131 printk("mtk_voice_ext_bt_pcm_open\n");
133 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
)
135 printk("%s with SNDRV_PCM_STREAM_CAPTURE \n",__func__
);
136 runtime
->rate
= 16000;
139 runtime
->hw
= mtk_pcm_hardware
;
140 memcpy((void *)(&(runtime
->hw
)), (void *)&mtk_pcm_hardware
, sizeof(struct snd_pcm_hardware
));
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
);
148 printk("snd_pcm_hw_constraint_integer failed\n");
151 //print for hw pcm information
152 printk("mtk_voice_ext_bt_pcm_open runtime rate = %d channels = %d \n", runtime
->rate
, runtime
->channels
);
154 runtime
->hw
.info
|= SNDRV_PCM_INFO_INTERLEAVED
;
155 runtime
->hw
.info
|= SNDRV_PCM_INFO_NONINTERLEAVED
;
157 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
159 printk("SNDRV_PCM_STREAM_PLAYBACK mtkalsa_voice_ext_bt_constraints\n");
160 runtime
->rate
= 16000;
169 printk("mtk_voice_ext_bt_close\n");
170 mtk_voice_ext_bt_close(substream
);
173 printk("mtk_voice_ext_bt_pcm_open return\n");
177 static int mtk_voice_ext_bt_close(struct snd_pcm_substream
*substream
)
179 printk("mtk_voice_ext_bt_close \n");
180 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
)
182 printk("%s with SNDRV_PCM_STREAM_CAPTURE \n",__func__
);
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
);
193 // here start digital part
194 SetMemoryPathEnable(Soc_Aud_Digital_Block_DAI_BT
, false);
195 SetDaiBtEnable(false);
200 voice_ext_bt_Status
= false;
201 SetExternalModemStatus(false);
206 static int mtk_voice_ext_bt_trigger(struct snd_pcm_substream
*substream
, int cmd
)
208 printk("mtk_ext_voice_bt_trigger cmd = %d\n", cmd
);
211 case SNDRV_PCM_TRIGGER_START
:
212 case SNDRV_PCM_TRIGGER_RESUME
:
213 case SNDRV_PCM_TRIGGER_STOP
:
214 case SNDRV_PCM_TRIGGER_SUSPEND
:
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
)
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
)
231 printk("mtk_voice_ext_bt_pcm_silence \n");
232 return 0; /* do nothing */
235 static void *dummy_page
[2];
236 static struct page
*mtk_pcm_page(struct snd_pcm_substream
*substream
,
237 unsigned long offset
)
239 return virt_to_page(dummy_page
[substream
->stream
]); /* the same page */
242 static int mtk_voice_ext_bt1_prepare(struct snd_pcm_substream
*substream
)
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
);
248 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
)
250 printk("%s with SNDRV_PCM_STREAM_CAPTURE \n",__func__
);
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
);
260 if(GetMemoryPathEnable(Soc_Aud_Digital_Block_DAI_BT
)== false)
262 //set merge interface
263 SetMemoryPathEnable(Soc_Aud_Digital_Block_DAI_BT
, true);
267 SetMemoryPathEnable(Soc_Aud_Digital_Block_DAI_BT
, true);
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);
278 voice_ext_bt_Status
= true;
279 SetExternalModemStatus(true);
284 static int mtk_pcm_hw_params(struct snd_pcm_substream
*substream
,
285 struct snd_pcm_hw_params
*hw_params
)
288 printk("mtk_pcm_hw_params \n");
292 static int mtk_voice_ext_bt_hw_free(struct snd_pcm_substream
*substream
)
294 PRINTK_AUDDRV("mtk_voice_ext_bt_hw_free \n");
295 return snd_pcm_lib_free_pages(substream
);
298 static struct snd_pcm_ops mtk_voice_ext_bt_ops
=
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
,
312 static struct snd_soc_platform_driver mtk_soc_voice_ext_bt_platform
=
314 .ops
= &mtk_voice_ext_bt_ops
,
315 .pcm_new
= mtk_soc_voice_ext_bt_new
,
316 .probe
= mtk_voice_ext_bt_platform_probe
,
319 static int mtk_voice_ext_bt_probe(struct platform_device
*pdev
)
321 printk("mtk_voice_ext_bt_probe\n");
323 pdev
->dev
.coherent_dma_mask
= DMA_BIT_MASK(64);
324 if (!pdev
->dev
.dma_mask
)
326 pdev
->dev
.dma_mask
= &pdev
->dev
.coherent_dma_mask
;
329 if (pdev
->dev
.of_node
)
331 dev_set_name(&pdev
->dev
, "%s", MT_SOC_VOICE_EXT_BT
);
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
);
338 static int mtk_soc_voice_ext_bt_new(struct snd_soc_pcm_runtime
*rtd
)
341 printk("%s\n", __func__
);
345 static int mtk_voice_ext_bt_platform_probe(struct snd_soc_platform
*platform
)
347 printk("mtk_voice_ext_bt_platform_probe\n");
351 static int mtk_voice_ext_bt_remove(struct platform_device
*pdev
)
353 pr_debug("%s\n", __func__
);
354 snd_soc_unregister_platform(&pdev
->dev
);
359 //supend and resume function
360 static int mtk_voice_ext_bt_pm_ops_suspend(struct device
*device
)
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)
371 clkmux_sel(MT_MUX_AUDINTBUS
, 0, "AUDIO"); //select 26M
377 static int mtk_voice_ext_bt_pm_ops_resume(struct device
*device
)
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)
387 clkmux_sel(MT_MUX_AUDINTBUS
, 1, "AUDIO"); //mainpll
394 struct dev_pm_ops mtk_voice_ext_bt_pm_ops
=
396 .suspend
= mtk_voice_ext_bt_pm_ops_suspend
,
397 .resume
= mtk_voice_ext_bt_pm_ops_resume
,
402 .restore_noirq
= NULL
,
406 static const struct of_device_id mt_soc_pcm_voice_ext_bt_of_ids
[] =
408 { .compatible
= "mediatek,mt_soc_pcm_voice_ext_bt", },
413 static struct platform_driver mtk_voice_ext_bt_driver
=
416 .name
= MT_SOC_VOICE_EXT_BT
,
417 .owner
= THIS_MODULE
,
419 .of_match_table
= mt_soc_pcm_voice_ext_bt_of_ids
,
422 .pm
= &mtk_voice_ext_bt_pm_ops
,
425 .probe
= mtk_voice_ext_bt_probe
,
426 .remove
= mtk_voice_ext_bt_remove
,
430 static struct platform_device
*soc_mtk_voice_ext_bt_dev
;
433 static int __init
mtk_soc_voice_ext_bt_platform_init(void)
436 printk("%s\n", __func__
);
438 soc_mtk_voice_ext_bt_dev
= platform_device_alloc(MT_SOC_VOICE_EXT_BT
, -1);
439 if (!soc_mtk_voice_ext_bt_dev
)
444 ret
= platform_device_add(soc_mtk_voice_ext_bt_dev
);
447 platform_device_put(soc_mtk_voice_ext_bt_dev
);
451 ret
= platform_driver_register(&mtk_voice_ext_bt_driver
);
456 module_init(mtk_soc_voice_ext_bt_platform_init
);
458 static void __exit
mtk_soc_voice_ext_bt_platform_exit(void)
461 printk("%s\n", __func__
);
462 platform_driver_unregister(&mtk_voice_ext_bt_driver
);
464 module_exit(mtk_soc_voice_ext_bt_platform_exit
);
466 MODULE_DESCRIPTION("AFE PCM module platform driver");
467 MODULE_LICENSE("GPL");