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_pcm_voice_md1_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_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
);
73 static bool voice_bt_Status
= false;
74 static AudioDigtalI2S mAudioDigitalI2S
;
76 bool get_voice_bt_status(void)
78 return voice_bt_Status
;
81 EXPORT_SYMBOL(get_voice_bt_status
);
83 static AudioDigitalPCM voice_bt1Pcm
=
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
,
99 static struct snd_pcm_hw_constraint_list constraints_sample_rates
=
101 .count
= ARRAY_SIZE(soc_voice_supported_sample_rates
),
102 .list
= soc_voice_supported_sample_rates
,
106 static struct snd_pcm_hardware mtk_pcm_hardware
=
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
,
125 static int mtk_voice_bt_pcm_open(struct snd_pcm_substream
*substream
)
127 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
132 printk("mtk_voice_bt_pcm_open\n");
134 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
)
136 printk("%s with SNDRV_PCM_STREAM_CAPTURE \n", __func__
);
137 runtime
->rate
= 16000;
140 runtime
->hw
= mtk_pcm_hardware
;
141 memcpy((void *)(&(runtime
->hw
)), (void *)&mtk_pcm_hardware
, sizeof(struct snd_pcm_hardware
));
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
);
149 printk("snd_pcm_hw_constraint_integer failed\n");
152 //print for hw pcm information
153 printk("mtk_voice_bt_pcm_open runtime rate = %d channels = %d \n", runtime
->rate
, runtime
->channels
);
155 runtime
->hw
.info
|= SNDRV_PCM_INFO_INTERLEAVED
;
156 runtime
->hw
.info
|= SNDRV_PCM_INFO_NONINTERLEAVED
;
158 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
160 printk("SNDRV_PCM_STREAM_PLAYBACK mtkalsa_voice_bt_constraints\n");
161 runtime
->rate
= 16000;
170 printk("mtk_voice_bt_close\n");
171 mtk_voice_bt_close(substream
);
174 printk("mtk_voice_bt_pcm_open return\n");
179 static void ConfigAdcI2S(struct snd_pcm_substream
*substream
)
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
);
193 static int mtk_voice_bt_close(struct snd_pcm_substream
*substream
)
195 printk("mtk_voice_bt_close \n");
196 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
)
198 printk("%s with SNDRV_PCM_STREAM_CAPTURE \n", __func__
);
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
);
209 // here start digital part
210 SetMemoryPathEnable(Soc_Aud_Digital_Block_DAI_BT
, false);
211 SetDaiBtEnable(false);
216 voice_bt_Status
= false;
221 static int mtk_voice_bt_trigger(struct snd_pcm_substream
*substream
, int cmd
)
223 printk("mtk_voice_bt_trigger cmd = %d\n", cmd
);
226 case SNDRV_PCM_TRIGGER_START
:
227 case SNDRV_PCM_TRIGGER_RESUME
:
228 case SNDRV_PCM_TRIGGER_STOP
:
229 case SNDRV_PCM_TRIGGER_SUSPEND
:
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
)
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
)
246 printk("mtk_voice_bt_pcm_silence \n");
247 return 0; /* do nothing */
250 static void *dummy_page
[2];
251 static struct page
*mtk_pcm_page(struct snd_pcm_substream
*substream
,
252 unsigned long offset
)
254 return virt_to_page(dummy_page
[substream
->stream
]); /* the same page */
257 static bool SetModemSpeechDAIBTAttribute(int sample_rate
)
259 AudioDigitalDAIBT daibt_attribute
;
260 memset((void *)&daibt_attribute
, 0, sizeof(daibt_attribute
));
262 #if 0 // temp for merge only support
263 daibt_attribute
.mUSE_MRGIF_INPUT
= Soc_Aud_BT_DAI_INPUT_FROM_BT
;
265 daibt_attribute
.mUSE_MRGIF_INPUT
= Soc_Aud_BT_DAI_INPUT_FROM_MGRIF
;
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
);
278 static int mtk_voice_bt1_prepare(struct snd_pcm_substream
*substream
)
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
);
284 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
)
286 printk("%s with SNDRV_PCM_STREAM_CAPTURE \n", __func__
);
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
);
297 if (GetMemoryPathEnable(Soc_Aud_Digital_Block_DAI_BT
) == false)
299 //set merge interface
300 SetMemoryPathEnable(Soc_Aud_Digital_Block_DAI_BT
, true);
304 SetMemoryPathEnable(Soc_Aud_Digital_Block_DAI_BT
, true);
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);
315 voice_bt_Status
= true;
320 static int mtk_pcm_hw_params(struct snd_pcm_substream
*substream
,
321 struct snd_pcm_hw_params
*hw_params
)
324 printk("mtk_pcm_hw_params \n");
328 static int mtk_voice_bt_hw_free(struct snd_pcm_substream
*substream
)
330 PRINTK_AUDDRV("mtk_voice_bt_hw_free \n");
331 return snd_pcm_lib_free_pages(substream
);
334 static struct snd_pcm_ops mtk_voice_bt_ops
=
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
,
348 static struct snd_soc_platform_driver mtk_soc_voice_bt_platform
=
350 .ops
= &mtk_voice_bt_ops
,
351 .pcm_new
= mtk_soc_voice_bt_new
,
352 .probe
= mtk_voice_bt_platform_probe
,
355 static int mtk_voice_bt_probe(struct platform_device
*pdev
)
357 printk("mtk_voice_bt_probe\n");
359 pdev
->dev
.coherent_dma_mask
= DMA_BIT_MASK(64);
360 if (!pdev
->dev
.dma_mask
)
362 pdev
->dev
.dma_mask
= &pdev
->dev
.coherent_dma_mask
;
365 if (pdev
->dev
.of_node
)
367 dev_set_name(&pdev
->dev
, "%s", MT_SOC_VOICE_MD1_BT
);
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
);
374 static int mtk_soc_voice_bt_new(struct snd_soc_pcm_runtime
*rtd
)
377 printk("%s\n", __func__
);
381 static int mtk_voice_bt_platform_probe(struct snd_soc_platform
*platform
)
383 printk("mtk_voice_bt_platform_probe\n");
387 static int mtk_voice_bt_remove(struct platform_device
*pdev
)
389 pr_debug("%s\n", __func__
);
390 snd_soc_unregister_platform(&pdev
->dev
);
395 //supend and resume function
396 static int mtk_voice_bt_pm_ops_suspend(struct device
*device
)
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);
405 if (b_modem1_speech_on
== true || b_modem2_speech_on
== true)
407 clkmux_sel(MT_MUX_AUDINTBUS
, 0, "AUDIO"); //select 26M
413 static int mtk_voice_bt_pm_ops_resume(struct device
*device
)
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);
421 if (b_modem1_speech_on
== true || b_modem2_speech_on
== true)
423 clkmux_sel(MT_MUX_AUDINTBUS
, 1, "AUDIO"); //mainpll
430 struct dev_pm_ops mtk_voice_bt_pm_ops
=
432 .suspend
= mtk_voice_bt_pm_ops_suspend
,
433 .resume
= mtk_voice_bt_pm_ops_resume
,
438 .restore_noirq
= NULL
,
442 static const struct of_device_id mt_soc_pcm_voice_md1_bt_of_ids
[] =
444 { .compatible
= "mediatek,mt_soc_pcm_voice_md1_bt", },
449 static struct platform_driver mtk_voice_bt_driver
=
452 .name
= MT_SOC_VOICE_MD1_BT
,
453 .owner
= THIS_MODULE
,
455 .of_match_table
= mt_soc_pcm_voice_md1_bt_of_ids
,
458 .pm
= &mtk_voice_bt_pm_ops
,
461 .probe
= mtk_voice_bt_probe
,
462 .remove
= mtk_voice_bt_remove
,
466 static struct platform_device
*soc_mtk_voice_bt_dev
;
469 static int __init
mtk_soc_voice_bt_platform_init(void)
472 printk("%s\n", __func__
);
474 soc_mtk_voice_bt_dev
= platform_device_alloc(MT_SOC_VOICE_MD1_BT
, -1);
475 if (!soc_mtk_voice_bt_dev
)
480 ret
= platform_device_add(soc_mtk_voice_bt_dev
);
483 platform_device_put(soc_mtk_voice_bt_dev
);
487 ret
= platform_driver_register(&mtk_voice_bt_driver
);
492 module_init(mtk_soc_voice_bt_platform_init
);
494 static void __exit
mtk_soc_voice_bt_platform_exit(void)
497 printk("%s\n", __func__
);
498 platform_driver_unregister(&mtk_voice_bt_driver
);
500 module_exit(mtk_soc_voice_bt_platform_exit
);
502 MODULE_DESCRIPTION("AFE PCM module platform driver");
503 MODULE_LICENSE("GPL");