1 // SPDX-License-Identifier: GPL-2.0
3 // MediaTek ALSA SoC Audio DAI TDM Control
5 // Copyright (c) 2020 MediaTek Inc.
6 // Author: Shane Chien <shane.chien@mediatek.com>
8 #include <linux/regmap.h>
9 #include <sound/pcm_params.h>
11 #include "mt8192-afe-clk.h"
12 #include "mt8192-afe-common.h"
13 #include "mt8192-afe-gpio.h"
14 #include "mt8192-interconnection.h"
16 struct mtk_afe_tdm_priv
{
24 int mclk_multiple
; /* according to sample rate */
51 TDM_CHANNEL_BCK_16
= 0,
52 TDM_CHANNEL_BCK_24
= 1,
53 TDM_CHANNEL_BCK_32
= 2,
57 TDM_CHANNEL_NUM_2
= 0,
58 TDM_CHANNEL_NUM_4
= 1,
59 TDM_CHANNEL_NUM_8
= 2,
63 TDM_CH_START_O30_O31
= 0,
70 static unsigned int get_tdm_wlen(snd_pcm_format_t format
)
72 return snd_pcm_format_physical_width(format
) <= 16 ?
73 TDM_WLEN_16_BIT
: TDM_WLEN_32_BIT
;
76 static unsigned int get_tdm_channel_bck(snd_pcm_format_t format
)
78 return snd_pcm_format_physical_width(format
) <= 16 ?
79 TDM_CHANNEL_BCK_16
: TDM_CHANNEL_BCK_32
;
82 static unsigned int get_tdm_lrck_width(snd_pcm_format_t format
)
84 return snd_pcm_format_physical_width(format
) - 1;
87 static unsigned int get_tdm_ch(unsigned int ch
)
92 return TDM_CHANNEL_NUM_2
;
95 return TDM_CHANNEL_NUM_4
;
101 return TDM_CHANNEL_NUM_8
;
105 static unsigned int get_tdm_ch_fixup(unsigned int channels
)
109 else if (channels
> 2)
115 static unsigned int get_tdm_ch_per_sdata(unsigned int mode
,
116 unsigned int channels
)
118 if (mode
== TDM_OUT_DSP_A
|| mode
== TDM_OUT_DSP_B
)
119 return get_tdm_ch_fixup(channels
);
124 /* interconnection */
136 static const char *const hdmi_conn_mux_map
[] = {
137 "CH0", "CH1", "CH2", "CH3",
138 "CH4", "CH5", "CH6", "CH7",
141 static int hdmi_conn_mux_map_value
[] = {
152 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum
,
157 hdmi_conn_mux_map_value
);
159 static const struct snd_kcontrol_new hdmi_ch0_mux_control
=
160 SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum
);
162 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum
,
167 hdmi_conn_mux_map_value
);
169 static const struct snd_kcontrol_new hdmi_ch1_mux_control
=
170 SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum
);
172 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum
,
177 hdmi_conn_mux_map_value
);
179 static const struct snd_kcontrol_new hdmi_ch2_mux_control
=
180 SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum
);
182 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum
,
187 hdmi_conn_mux_map_value
);
189 static const struct snd_kcontrol_new hdmi_ch3_mux_control
=
190 SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum
);
192 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum
,
197 hdmi_conn_mux_map_value
);
199 static const struct snd_kcontrol_new hdmi_ch4_mux_control
=
200 SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum
);
202 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum
,
207 hdmi_conn_mux_map_value
);
209 static const struct snd_kcontrol_new hdmi_ch5_mux_control
=
210 SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum
);
212 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum
,
217 hdmi_conn_mux_map_value
);
219 static const struct snd_kcontrol_new hdmi_ch6_mux_control
=
220 SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum
);
222 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum
,
227 hdmi_conn_mux_map_value
);
229 static const struct snd_kcontrol_new hdmi_ch7_mux_control
=
230 SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum
);
234 SUPPLY_SEQ_TDM_MCK_EN
,
235 SUPPLY_SEQ_TDM_BCK_EN
,
239 static int get_tdm_id_by_name(const char *name
)
241 return MT8192_DAI_TDM
;
244 static int mtk_tdm_en_event(struct snd_soc_dapm_widget
*w
,
245 struct snd_kcontrol
*kcontrol
,
248 struct snd_soc_component
*cmpnt
= snd_soc_dapm_to_component(w
->dapm
);
249 struct mtk_base_afe
*afe
= snd_soc_component_get_drvdata(cmpnt
);
250 struct mt8192_afe_private
*afe_priv
= afe
->platform_priv
;
251 int dai_id
= get_tdm_id_by_name(w
->name
);
252 struct mtk_afe_tdm_priv
*tdm_priv
= afe_priv
->dai_priv
[dai_id
];
255 dev_warn(afe
->dev
, "%s(), tdm_priv == NULL", __func__
);
259 dev_info(cmpnt
->dev
, "%s(), name %s, event 0x%x\n",
260 __func__
, w
->name
, event
);
263 case SND_SOC_DAPM_PRE_PMU
:
264 mt8192_afe_gpio_request(afe
->dev
, true, tdm_priv
->id
, 0);
266 case SND_SOC_DAPM_POST_PMD
:
267 mt8192_afe_gpio_request(afe
->dev
, false, tdm_priv
->id
, 0);
276 static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget
*w
,
277 struct snd_kcontrol
*kcontrol
,
280 struct snd_soc_component
*cmpnt
= snd_soc_dapm_to_component(w
->dapm
);
281 struct mtk_base_afe
*afe
= snd_soc_component_get_drvdata(cmpnt
);
282 struct mt8192_afe_private
*afe_priv
= afe
->platform_priv
;
283 int dai_id
= get_tdm_id_by_name(w
->name
);
284 struct mtk_afe_tdm_priv
*tdm_priv
= afe_priv
->dai_priv
[dai_id
];
287 dev_warn(afe
->dev
, "%s(), tdm_priv == NULL", __func__
);
291 dev_info(cmpnt
->dev
, "%s(), name %s, event 0x%x, dai_id %d\n",
292 __func__
, w
->name
, event
, dai_id
);
295 case SND_SOC_DAPM_PRE_PMU
:
296 mt8192_mck_enable(afe
, tdm_priv
->bck_id
, tdm_priv
->bck_rate
);
298 case SND_SOC_DAPM_POST_PMD
:
299 mt8192_mck_disable(afe
, tdm_priv
->bck_id
);
308 static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget
*w
,
309 struct snd_kcontrol
*kcontrol
,
312 struct snd_soc_component
*cmpnt
= snd_soc_dapm_to_component(w
->dapm
);
313 struct mtk_base_afe
*afe
= snd_soc_component_get_drvdata(cmpnt
);
314 struct mt8192_afe_private
*afe_priv
= afe
->platform_priv
;
315 int dai_id
= get_tdm_id_by_name(w
->name
);
316 struct mtk_afe_tdm_priv
*tdm_priv
= afe_priv
->dai_priv
[dai_id
];
319 dev_warn(afe
->dev
, "%s(), tdm_priv == NULL", __func__
);
323 dev_info(cmpnt
->dev
, "%s(), name %s, event 0x%x, dai_id %d\n",
324 __func__
, w
->name
, event
, dai_id
);
327 case SND_SOC_DAPM_PRE_PMU
:
328 mt8192_mck_enable(afe
, tdm_priv
->mclk_id
, tdm_priv
->mclk_rate
);
330 case SND_SOC_DAPM_POST_PMD
:
331 tdm_priv
->mclk_rate
= 0;
332 mt8192_mck_disable(afe
, tdm_priv
->mclk_id
);
341 static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets
[] = {
342 SND_SOC_DAPM_MUX("HDMI_CH0_MUX", SND_SOC_NOPM
, 0, 0,
343 &hdmi_ch0_mux_control
),
344 SND_SOC_DAPM_MUX("HDMI_CH1_MUX", SND_SOC_NOPM
, 0, 0,
345 &hdmi_ch1_mux_control
),
346 SND_SOC_DAPM_MUX("HDMI_CH2_MUX", SND_SOC_NOPM
, 0, 0,
347 &hdmi_ch2_mux_control
),
348 SND_SOC_DAPM_MUX("HDMI_CH3_MUX", SND_SOC_NOPM
, 0, 0,
349 &hdmi_ch3_mux_control
),
350 SND_SOC_DAPM_MUX("HDMI_CH4_MUX", SND_SOC_NOPM
, 0, 0,
351 &hdmi_ch4_mux_control
),
352 SND_SOC_DAPM_MUX("HDMI_CH5_MUX", SND_SOC_NOPM
, 0, 0,
353 &hdmi_ch5_mux_control
),
354 SND_SOC_DAPM_MUX("HDMI_CH6_MUX", SND_SOC_NOPM
, 0, 0,
355 &hdmi_ch6_mux_control
),
356 SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM
, 0, 0,
357 &hdmi_ch7_mux_control
),
359 SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"),
361 SND_SOC_DAPM_SUPPLY_S("TDM_EN", SUPPLY_SEQ_TDM_EN
,
362 AFE_TDM_CON1
, TDM_EN_SFT
, 0,
364 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
366 SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN
,
368 mtk_tdm_bck_en_event
,
369 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
371 SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN
,
373 mtk_tdm_mck_en_event
,
374 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
377 static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget
*source
,
378 struct snd_soc_dapm_widget
*sink
)
380 struct snd_soc_dapm_widget
*w
= sink
;
381 struct snd_soc_component
*cmpnt
= snd_soc_dapm_to_component(w
->dapm
);
382 struct mtk_base_afe
*afe
= snd_soc_component_get_drvdata(cmpnt
);
383 struct mt8192_afe_private
*afe_priv
= afe
->platform_priv
;
384 int dai_id
= get_tdm_id_by_name(w
->name
);
385 struct mtk_afe_tdm_priv
*tdm_priv
= afe_priv
->dai_priv
[dai_id
];
389 cur_apll
= mt8192_get_apll_by_name(afe
, source
->name
);
391 return (tdm_priv
->mclk_apll
== cur_apll
) ? 1 : 0;
394 static const struct snd_soc_dapm_route mtk_dai_tdm_routes
[] = {
395 {"HDMI_CH0_MUX", "CH0", "HDMI"},
396 {"HDMI_CH0_MUX", "CH1", "HDMI"},
397 {"HDMI_CH0_MUX", "CH2", "HDMI"},
398 {"HDMI_CH0_MUX", "CH3", "HDMI"},
399 {"HDMI_CH0_MUX", "CH4", "HDMI"},
400 {"HDMI_CH0_MUX", "CH5", "HDMI"},
401 {"HDMI_CH0_MUX", "CH6", "HDMI"},
402 {"HDMI_CH0_MUX", "CH7", "HDMI"},
404 {"HDMI_CH1_MUX", "CH0", "HDMI"},
405 {"HDMI_CH1_MUX", "CH1", "HDMI"},
406 {"HDMI_CH1_MUX", "CH2", "HDMI"},
407 {"HDMI_CH1_MUX", "CH3", "HDMI"},
408 {"HDMI_CH1_MUX", "CH4", "HDMI"},
409 {"HDMI_CH1_MUX", "CH5", "HDMI"},
410 {"HDMI_CH1_MUX", "CH6", "HDMI"},
411 {"HDMI_CH1_MUX", "CH7", "HDMI"},
413 {"HDMI_CH2_MUX", "CH0", "HDMI"},
414 {"HDMI_CH2_MUX", "CH1", "HDMI"},
415 {"HDMI_CH2_MUX", "CH2", "HDMI"},
416 {"HDMI_CH2_MUX", "CH3", "HDMI"},
417 {"HDMI_CH2_MUX", "CH4", "HDMI"},
418 {"HDMI_CH2_MUX", "CH5", "HDMI"},
419 {"HDMI_CH2_MUX", "CH6", "HDMI"},
420 {"HDMI_CH2_MUX", "CH7", "HDMI"},
422 {"HDMI_CH3_MUX", "CH0", "HDMI"},
423 {"HDMI_CH3_MUX", "CH1", "HDMI"},
424 {"HDMI_CH3_MUX", "CH2", "HDMI"},
425 {"HDMI_CH3_MUX", "CH3", "HDMI"},
426 {"HDMI_CH3_MUX", "CH4", "HDMI"},
427 {"HDMI_CH3_MUX", "CH5", "HDMI"},
428 {"HDMI_CH3_MUX", "CH6", "HDMI"},
429 {"HDMI_CH3_MUX", "CH7", "HDMI"},
431 {"HDMI_CH4_MUX", "CH0", "HDMI"},
432 {"HDMI_CH4_MUX", "CH1", "HDMI"},
433 {"HDMI_CH4_MUX", "CH2", "HDMI"},
434 {"HDMI_CH4_MUX", "CH3", "HDMI"},
435 {"HDMI_CH4_MUX", "CH4", "HDMI"},
436 {"HDMI_CH4_MUX", "CH5", "HDMI"},
437 {"HDMI_CH4_MUX", "CH6", "HDMI"},
438 {"HDMI_CH4_MUX", "CH7", "HDMI"},
440 {"HDMI_CH5_MUX", "CH0", "HDMI"},
441 {"HDMI_CH5_MUX", "CH1", "HDMI"},
442 {"HDMI_CH5_MUX", "CH2", "HDMI"},
443 {"HDMI_CH5_MUX", "CH3", "HDMI"},
444 {"HDMI_CH5_MUX", "CH4", "HDMI"},
445 {"HDMI_CH5_MUX", "CH5", "HDMI"},
446 {"HDMI_CH5_MUX", "CH6", "HDMI"},
447 {"HDMI_CH5_MUX", "CH7", "HDMI"},
449 {"HDMI_CH6_MUX", "CH0", "HDMI"},
450 {"HDMI_CH6_MUX", "CH1", "HDMI"},
451 {"HDMI_CH6_MUX", "CH2", "HDMI"},
452 {"HDMI_CH6_MUX", "CH3", "HDMI"},
453 {"HDMI_CH6_MUX", "CH4", "HDMI"},
454 {"HDMI_CH6_MUX", "CH5", "HDMI"},
455 {"HDMI_CH6_MUX", "CH6", "HDMI"},
456 {"HDMI_CH6_MUX", "CH7", "HDMI"},
458 {"HDMI_CH7_MUX", "CH0", "HDMI"},
459 {"HDMI_CH7_MUX", "CH1", "HDMI"},
460 {"HDMI_CH7_MUX", "CH2", "HDMI"},
461 {"HDMI_CH7_MUX", "CH3", "HDMI"},
462 {"HDMI_CH7_MUX", "CH4", "HDMI"},
463 {"HDMI_CH7_MUX", "CH5", "HDMI"},
464 {"HDMI_CH7_MUX", "CH6", "HDMI"},
465 {"HDMI_CH7_MUX", "CH7", "HDMI"},
467 {"TDM", NULL
, "HDMI_CH0_MUX"},
468 {"TDM", NULL
, "HDMI_CH1_MUX"},
469 {"TDM", NULL
, "HDMI_CH2_MUX"},
470 {"TDM", NULL
, "HDMI_CH3_MUX"},
471 {"TDM", NULL
, "HDMI_CH4_MUX"},
472 {"TDM", NULL
, "HDMI_CH5_MUX"},
473 {"TDM", NULL
, "HDMI_CH6_MUX"},
474 {"TDM", NULL
, "HDMI_CH7_MUX"},
476 {"TDM", NULL
, "aud_tdm_clk"},
477 {"TDM", NULL
, "TDM_BCK"},
478 {"TDM", NULL
, "TDM_EN"},
479 {"TDM_BCK", NULL
, "TDM_MCK"},
480 {"TDM_MCK", NULL
, APLL1_W_NAME
, mtk_afe_tdm_apll_connect
},
481 {"TDM_MCK", NULL
, APLL2_W_NAME
, mtk_afe_tdm_apll_connect
},
485 static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe
*afe
,
486 struct mtk_afe_tdm_priv
*tdm_priv
,
492 apll
= mt8192_get_apll_by_rate(afe
, freq
);
493 apll_rate
= mt8192_get_apll_rate(afe
, apll
);
495 if (!freq
|| freq
> apll_rate
) {
497 "%s(), freq(%d Hz) invalid\n", __func__
, freq
);
501 if (apll_rate
% freq
!= 0) {
503 "%s(), APLL cannot generate %d Hz", __func__
, freq
);
507 tdm_priv
->mclk_rate
= freq
;
508 tdm_priv
->mclk_apll
= apll
;
513 static int mtk_dai_tdm_hw_params(struct snd_pcm_substream
*substream
,
514 struct snd_pcm_hw_params
*params
,
515 struct snd_soc_dai
*dai
)
517 struct mtk_base_afe
*afe
= snd_soc_dai_get_drvdata(dai
);
518 struct mt8192_afe_private
*afe_priv
= afe
->platform_priv
;
519 int tdm_id
= dai
->id
;
520 struct mtk_afe_tdm_priv
*tdm_priv
= afe_priv
->dai_priv
[tdm_id
];
521 unsigned int tdm_out_mode
= tdm_priv
->tdm_out_mode
;
522 unsigned int rate
= params_rate(params
);
523 unsigned int channels
= params_channels(params
);
524 unsigned int out_channels_per_sdata
=
525 get_tdm_ch_per_sdata(tdm_out_mode
, channels
);
526 snd_pcm_format_t format
= params_format(params
);
527 unsigned int tdm_con
= 0;
529 /* calculate mclk_rate, if not set explicitly */
530 if (!tdm_priv
->mclk_rate
) {
531 tdm_priv
->mclk_rate
= rate
* tdm_priv
->mclk_multiple
;
532 mtk_dai_tdm_cal_mclk(afe
,
534 tdm_priv
->mclk_rate
);
538 tdm_priv
->bck_rate
= rate
*
539 out_channels_per_sdata
*
540 snd_pcm_format_physical_width(format
);
542 if (tdm_priv
->bck_rate
> tdm_priv
->mclk_rate
)
543 dev_warn(afe
->dev
, "%s(), bck_rate > mclk_rate rate", __func__
);
545 if (tdm_priv
->mclk_rate
% tdm_priv
->bck_rate
!= 0)
546 dev_warn(afe
->dev
, "%s(), bck cannot generate", __func__
);
548 dev_info(afe
->dev
, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n",
550 tdm_id
, rate
, channels
, format
,
551 tdm_priv
->mclk_rate
, tdm_priv
->bck_rate
);
553 dev_info(afe
->dev
, "%s(), out_channels_per_sdata = %d\n",
554 __func__
, out_channels_per_sdata
);
557 if (tdm_priv
->bck_invert
)
558 tdm_con
|= 1 << BCK_INVERSE_SFT
;
560 if (tdm_priv
->lck_invert
)
561 tdm_con
|= 1 << LRCK_INVERSE_SFT
;
563 if (tdm_priv
->tdm_out_mode
== TDM_OUT_I2S
) {
564 tdm_con
|= 1 << DELAY_DATA_SFT
;
565 tdm_con
|= get_tdm_lrck_width(format
) << LRCK_TDM_WIDTH_SFT
;
566 } else if (tdm_priv
->tdm_out_mode
== TDM_OUT_DSP_A
) {
567 tdm_con
|= 0 << DELAY_DATA_SFT
;
568 tdm_con
|= 0 << LRCK_TDM_WIDTH_SFT
;
569 } else if (tdm_priv
->tdm_out_mode
== TDM_OUT_DSP_B
) {
570 tdm_con
|= 1 << DELAY_DATA_SFT
;
571 tdm_con
|= 0 << LRCK_TDM_WIDTH_SFT
;
574 tdm_con
|= 1 << LEFT_ALIGN_SFT
;
575 tdm_con
|= get_tdm_wlen(format
) << WLEN_SFT
;
576 tdm_con
|= get_tdm_ch(out_channels_per_sdata
) << CHANNEL_NUM_SFT
;
577 tdm_con
|= get_tdm_channel_bck(format
) << CHANNEL_BCK_CYCLES_SFT
;
578 regmap_write(afe
->regmap
, AFE_TDM_CON1
, tdm_con
);
580 if (out_channels_per_sdata
== 2) {
584 tdm_con
= TDM_CH_START_O30_O31
<< ST_CH_PAIR_SOUT0_SFT
;
585 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT1_SFT
;
586 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT2_SFT
;
587 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT3_SFT
;
591 tdm_con
= TDM_CH_START_O30_O31
<< ST_CH_PAIR_SOUT0_SFT
;
592 tdm_con
|= TDM_CH_START_O32_O33
<< ST_CH_PAIR_SOUT1_SFT
;
593 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT2_SFT
;
594 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT3_SFT
;
598 tdm_con
= TDM_CH_START_O30_O31
<< ST_CH_PAIR_SOUT0_SFT
;
599 tdm_con
|= TDM_CH_START_O32_O33
<< ST_CH_PAIR_SOUT1_SFT
;
600 tdm_con
|= TDM_CH_START_O34_O35
<< ST_CH_PAIR_SOUT2_SFT
;
601 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT3_SFT
;
605 tdm_con
= TDM_CH_START_O30_O31
<< ST_CH_PAIR_SOUT0_SFT
;
606 tdm_con
|= TDM_CH_START_O32_O33
<< ST_CH_PAIR_SOUT1_SFT
;
607 tdm_con
|= TDM_CH_START_O34_O35
<< ST_CH_PAIR_SOUT2_SFT
;
608 tdm_con
|= TDM_CH_START_O36_O37
<< ST_CH_PAIR_SOUT3_SFT
;
614 tdm_con
= TDM_CH_START_O30_O31
<< ST_CH_PAIR_SOUT0_SFT
;
615 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT1_SFT
;
616 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT2_SFT
;
617 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT3_SFT
;
620 regmap_write(afe
->regmap
, AFE_TDM_CON2
, tdm_con
);
622 regmap_update_bits(afe
->regmap
, AFE_HDMI_OUT_CON0
,
623 HDMI_CH_NUM_MASK_SFT
,
624 channels
<< HDMI_CH_NUM_SFT
);
628 static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai
*dai
,
629 int clk_id
, unsigned int freq
, int dir
)
631 struct mtk_base_afe
*afe
= dev_get_drvdata(dai
->dev
);
632 struct mt8192_afe_private
*afe_priv
= afe
->platform_priv
;
633 struct mtk_afe_tdm_priv
*tdm_priv
= afe_priv
->dai_priv
[dai
->id
];
636 dev_warn(afe
->dev
, "%s(), tdm_priv == NULL", __func__
);
640 if (dir
!= SND_SOC_CLOCK_OUT
) {
641 dev_warn(afe
->dev
, "%s(), dir != SND_SOC_CLOCK_OUT", __func__
);
645 dev_info(afe
->dev
, "%s(), freq %d\n", __func__
, freq
);
647 return mtk_dai_tdm_cal_mclk(afe
, tdm_priv
, freq
);
650 static int mtk_dai_tdm_set_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
652 struct mtk_base_afe
*afe
= dev_get_drvdata(dai
->dev
);
653 struct mt8192_afe_private
*afe_priv
= afe
->platform_priv
;
654 struct mtk_afe_tdm_priv
*tdm_priv
= afe_priv
->dai_priv
[dai
->id
];
657 dev_warn(afe
->dev
, "%s(), tdm_priv == NULL", __func__
);
662 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
663 case SND_SOC_DAIFMT_I2S
:
664 tdm_priv
->tdm_out_mode
= TDM_OUT_I2S
;
666 case SND_SOC_DAIFMT_DSP_A
:
667 tdm_priv
->tdm_out_mode
= TDM_OUT_DSP_A
;
669 case SND_SOC_DAIFMT_DSP_B
:
670 tdm_priv
->tdm_out_mode
= TDM_OUT_DSP_B
;
673 tdm_priv
->tdm_out_mode
= TDM_OUT_I2S
;
676 /* DAI clock inversion*/
677 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
678 case SND_SOC_DAIFMT_NB_NF
:
679 tdm_priv
->bck_invert
= TDM_BCK_NON_INV
;
680 tdm_priv
->lck_invert
= TDM_LCK_NON_INV
;
682 case SND_SOC_DAIFMT_NB_IF
:
683 tdm_priv
->bck_invert
= TDM_BCK_NON_INV
;
684 tdm_priv
->lck_invert
= TDM_LCK_INV
;
686 case SND_SOC_DAIFMT_IB_NF
:
687 tdm_priv
->bck_invert
= TDM_BCK_INV
;
688 tdm_priv
->lck_invert
= TDM_LCK_NON_INV
;
690 case SND_SOC_DAIFMT_IB_IF
:
692 tdm_priv
->bck_invert
= TDM_BCK_INV
;
693 tdm_priv
->lck_invert
= TDM_LCK_INV
;
700 static const struct snd_soc_dai_ops mtk_dai_tdm_ops
= {
701 .hw_params
= mtk_dai_tdm_hw_params
,
702 .set_sysclk
= mtk_dai_tdm_set_sysclk
,
703 .set_fmt
= mtk_dai_tdm_set_fmt
,
707 #define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
708 SNDRV_PCM_RATE_88200 |\
709 SNDRV_PCM_RATE_96000 |\
710 SNDRV_PCM_RATE_176400 |\
711 SNDRV_PCM_RATE_192000)
713 #define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
714 SNDRV_PCM_FMTBIT_S24_LE |\
715 SNDRV_PCM_FMTBIT_S32_LE)
717 static struct snd_soc_dai_driver mtk_dai_tdm_driver
[] = {
720 .id
= MT8192_DAI_TDM
,
722 .stream_name
= "TDM",
725 .rates
= MTK_TDM_RATES
,
726 .formats
= MTK_TDM_FORMATS
,
728 .ops
= &mtk_dai_tdm_ops
,
732 static struct mtk_afe_tdm_priv
*init_tdm_priv_data(struct mtk_base_afe
*afe
)
734 struct mtk_afe_tdm_priv
*tdm_priv
;
736 tdm_priv
= devm_kzalloc(afe
->dev
, sizeof(struct mtk_afe_tdm_priv
),
741 tdm_priv
->mclk_multiple
= 128;
742 tdm_priv
->bck_id
= MT8192_I2S4_BCK
;
743 tdm_priv
->mclk_id
= MT8192_I2S4_MCK
;
744 tdm_priv
->id
= MT8192_DAI_TDM
;
749 int mt8192_dai_tdm_register(struct mtk_base_afe
*afe
)
751 struct mt8192_afe_private
*afe_priv
= afe
->platform_priv
;
752 struct mtk_afe_tdm_priv
*tdm_priv
;
753 struct mtk_base_afe_dai
*dai
;
755 dev_info(afe
->dev
, "%s()\n", __func__
);
757 dai
= devm_kzalloc(afe
->dev
, sizeof(*dai
), GFP_KERNEL
);
761 list_add(&dai
->list
, &afe
->sub_dais
);
763 dai
->dai_drivers
= mtk_dai_tdm_driver
;
764 dai
->num_dai_drivers
= ARRAY_SIZE(mtk_dai_tdm_driver
);
766 dai
->dapm_widgets
= mtk_dai_tdm_widgets
;
767 dai
->num_dapm_widgets
= ARRAY_SIZE(mtk_dai_tdm_widgets
);
768 dai
->dapm_routes
= mtk_dai_tdm_routes
;
769 dai
->num_dapm_routes
= ARRAY_SIZE(mtk_dai_tdm_routes
);
771 tdm_priv
= init_tdm_priv_data(afe
);
775 afe_priv
->dai_priv
[MT8192_DAI_TDM
] = tdm_priv
;