1 // SPDX-License-Identifier: GPL-2.0
3 // MediaTek ALSA SoC Audio DAI TDM Control
5 // Copyright (c) 2018 MediaTek Inc.
6 // Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com>
8 #include <linux/regmap.h>
9 #include <sound/pcm_params.h>
10 #include "mt8183-afe-clk.h"
11 #include "mt8183-afe-common.h"
12 #include "mt8183-interconnection.h"
13 #include "mt8183-reg.h"
15 struct mtk_afe_tdm_priv
{
22 int mclk_multiple
; /* according to sample rate */
48 TDM_CHANNEL_BCK_16
= 0,
49 TDM_CHANNEL_BCK_24
= 1,
50 TDM_CHANNEL_BCK_32
= 2,
54 TDM_CHANNEL_NUM_2
= 0,
55 TDM_CHANNEL_NUM_4
= 1,
56 TDM_CHANNEL_NUM_8
= 2,
60 TDM_CH_START_O30_O31
= 0,
68 HDMI_BIT_WIDTH_16_BIT
= 0,
69 HDMI_BIT_WIDTH_32_BIT
= 1,
72 static unsigned int get_hdmi_wlen(snd_pcm_format_t format
)
74 return snd_pcm_format_physical_width(format
) <= 16 ?
75 HDMI_BIT_WIDTH_16_BIT
: HDMI_BIT_WIDTH_32_BIT
;
78 static unsigned int get_tdm_wlen(snd_pcm_format_t format
)
80 return snd_pcm_format_physical_width(format
) <= 16 ?
81 TDM_WLEN_16_BIT
: TDM_WLEN_32_BIT
;
84 static unsigned int get_tdm_channel_bck(snd_pcm_format_t format
)
86 return snd_pcm_format_physical_width(format
) <= 16 ?
87 TDM_CHANNEL_BCK_16
: TDM_CHANNEL_BCK_32
;
90 static unsigned int get_tdm_lrck_width(snd_pcm_format_t format
)
92 return snd_pcm_format_physical_width(format
) - 1;
95 static unsigned int get_tdm_ch(unsigned int ch
)
100 return TDM_CHANNEL_NUM_2
;
103 return TDM_CHANNEL_NUM_4
;
109 return TDM_CHANNEL_NUM_8
;
113 static unsigned int get_tdm_ch_fixup(unsigned int channels
)
117 else if (channels
> 2)
123 static unsigned int get_tdm_ch_per_sdata(unsigned int mode
,
124 unsigned int channels
)
126 if (mode
== TDM_OUT_TDM
)
127 return get_tdm_ch_fixup(channels
);
132 /* interconnection */
144 static const char *const hdmi_conn_mux_map
[] = {
145 "CH0", "CH1", "CH2", "CH3",
146 "CH4", "CH5", "CH6", "CH7",
149 static int hdmi_conn_mux_map_value
[] = {
160 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum
,
165 hdmi_conn_mux_map_value
);
167 static const struct snd_kcontrol_new hdmi_ch0_mux_control
=
168 SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum
);
170 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum
,
175 hdmi_conn_mux_map_value
);
177 static const struct snd_kcontrol_new hdmi_ch1_mux_control
=
178 SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum
);
180 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum
,
185 hdmi_conn_mux_map_value
);
187 static const struct snd_kcontrol_new hdmi_ch2_mux_control
=
188 SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum
);
190 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum
,
195 hdmi_conn_mux_map_value
);
197 static const struct snd_kcontrol_new hdmi_ch3_mux_control
=
198 SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum
);
200 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum
,
205 hdmi_conn_mux_map_value
);
207 static const struct snd_kcontrol_new hdmi_ch4_mux_control
=
208 SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum
);
210 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum
,
215 hdmi_conn_mux_map_value
);
217 static const struct snd_kcontrol_new hdmi_ch5_mux_control
=
218 SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum
);
220 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum
,
225 hdmi_conn_mux_map_value
);
227 static const struct snd_kcontrol_new hdmi_ch6_mux_control
=
228 SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum
);
230 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum
,
235 hdmi_conn_mux_map_value
);
237 static const struct snd_kcontrol_new hdmi_ch7_mux_control
=
238 SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum
);
242 SUPPLY_SEQ_TDM_MCK_EN
,
243 SUPPLY_SEQ_TDM_BCK_EN
,
246 static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget
*w
,
247 struct snd_kcontrol
*kcontrol
,
250 struct snd_soc_component
*cmpnt
= snd_soc_dapm_to_component(w
->dapm
);
251 struct mtk_base_afe
*afe
= snd_soc_component_get_drvdata(cmpnt
);
252 struct mt8183_afe_private
*afe_priv
= afe
->platform_priv
;
253 struct mtk_afe_tdm_priv
*tdm_priv
= afe_priv
->dai_priv
[MT8183_DAI_TDM
];
255 dev_info(cmpnt
->dev
, "%s(), name %s, event 0x%x\n",
256 __func__
, w
->name
, event
);
259 case SND_SOC_DAPM_PRE_PMU
:
260 mt8183_mck_enable(afe
, tdm_priv
->bck_id
, tdm_priv
->bck_rate
);
262 case SND_SOC_DAPM_POST_PMD
:
263 mt8183_mck_disable(afe
, tdm_priv
->bck_id
);
272 static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget
*w
,
273 struct snd_kcontrol
*kcontrol
,
276 struct snd_soc_component
*cmpnt
= snd_soc_dapm_to_component(w
->dapm
);
277 struct mtk_base_afe
*afe
= snd_soc_component_get_drvdata(cmpnt
);
278 struct mt8183_afe_private
*afe_priv
= afe
->platform_priv
;
279 struct mtk_afe_tdm_priv
*tdm_priv
= afe_priv
->dai_priv
[MT8183_DAI_TDM
];
281 dev_info(cmpnt
->dev
, "%s(), name %s, event 0x%x\n",
282 __func__
, w
->name
, event
);
285 case SND_SOC_DAPM_PRE_PMU
:
286 mt8183_mck_enable(afe
, tdm_priv
->mclk_id
, tdm_priv
->mclk_rate
);
288 case SND_SOC_DAPM_POST_PMD
:
289 tdm_priv
->mclk_rate
= 0;
290 mt8183_mck_disable(afe
, tdm_priv
->mclk_id
);
299 static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets
[] = {
300 SND_SOC_DAPM_MUX("HDMI_CH0_MUX", SND_SOC_NOPM
, 0, 0,
301 &hdmi_ch0_mux_control
),
302 SND_SOC_DAPM_MUX("HDMI_CH1_MUX", SND_SOC_NOPM
, 0, 0,
303 &hdmi_ch1_mux_control
),
304 SND_SOC_DAPM_MUX("HDMI_CH2_MUX", SND_SOC_NOPM
, 0, 0,
305 &hdmi_ch2_mux_control
),
306 SND_SOC_DAPM_MUX("HDMI_CH3_MUX", SND_SOC_NOPM
, 0, 0,
307 &hdmi_ch3_mux_control
),
308 SND_SOC_DAPM_MUX("HDMI_CH4_MUX", SND_SOC_NOPM
, 0, 0,
309 &hdmi_ch4_mux_control
),
310 SND_SOC_DAPM_MUX("HDMI_CH5_MUX", SND_SOC_NOPM
, 0, 0,
311 &hdmi_ch5_mux_control
),
312 SND_SOC_DAPM_MUX("HDMI_CH6_MUX", SND_SOC_NOPM
, 0, 0,
313 &hdmi_ch6_mux_control
),
314 SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM
, 0, 0,
315 &hdmi_ch7_mux_control
),
317 SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"),
319 SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN
,
321 mtk_tdm_bck_en_event
,
322 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
324 SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN
,
326 mtk_tdm_mck_en_event
,
327 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
330 static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget
*source
,
331 struct snd_soc_dapm_widget
*sink
)
333 struct snd_soc_dapm_widget
*w
= sink
;
334 struct snd_soc_component
*cmpnt
= snd_soc_dapm_to_component(w
->dapm
);
335 struct mtk_base_afe
*afe
= snd_soc_component_get_drvdata(cmpnt
);
336 struct mt8183_afe_private
*afe_priv
= afe
->platform_priv
;
337 struct mtk_afe_tdm_priv
*tdm_priv
= afe_priv
->dai_priv
[MT8183_DAI_TDM
];
341 cur_apll
= mt8183_get_apll_by_name(afe
, source
->name
);
343 return (tdm_priv
->mclk_apll
== cur_apll
) ? 1 : 0;
346 static const struct snd_soc_dapm_route mtk_dai_tdm_routes
[] = {
347 {"HDMI_CH0_MUX", "CH0", "HDMI"},
348 {"HDMI_CH0_MUX", "CH1", "HDMI"},
349 {"HDMI_CH0_MUX", "CH2", "HDMI"},
350 {"HDMI_CH0_MUX", "CH3", "HDMI"},
351 {"HDMI_CH0_MUX", "CH4", "HDMI"},
352 {"HDMI_CH0_MUX", "CH5", "HDMI"},
353 {"HDMI_CH0_MUX", "CH6", "HDMI"},
354 {"HDMI_CH0_MUX", "CH7", "HDMI"},
356 {"HDMI_CH1_MUX", "CH0", "HDMI"},
357 {"HDMI_CH1_MUX", "CH1", "HDMI"},
358 {"HDMI_CH1_MUX", "CH2", "HDMI"},
359 {"HDMI_CH1_MUX", "CH3", "HDMI"},
360 {"HDMI_CH1_MUX", "CH4", "HDMI"},
361 {"HDMI_CH1_MUX", "CH5", "HDMI"},
362 {"HDMI_CH1_MUX", "CH6", "HDMI"},
363 {"HDMI_CH1_MUX", "CH7", "HDMI"},
365 {"HDMI_CH2_MUX", "CH0", "HDMI"},
366 {"HDMI_CH2_MUX", "CH1", "HDMI"},
367 {"HDMI_CH2_MUX", "CH2", "HDMI"},
368 {"HDMI_CH2_MUX", "CH3", "HDMI"},
369 {"HDMI_CH2_MUX", "CH4", "HDMI"},
370 {"HDMI_CH2_MUX", "CH5", "HDMI"},
371 {"HDMI_CH2_MUX", "CH6", "HDMI"},
372 {"HDMI_CH2_MUX", "CH7", "HDMI"},
374 {"HDMI_CH3_MUX", "CH0", "HDMI"},
375 {"HDMI_CH3_MUX", "CH1", "HDMI"},
376 {"HDMI_CH3_MUX", "CH2", "HDMI"},
377 {"HDMI_CH3_MUX", "CH3", "HDMI"},
378 {"HDMI_CH3_MUX", "CH4", "HDMI"},
379 {"HDMI_CH3_MUX", "CH5", "HDMI"},
380 {"HDMI_CH3_MUX", "CH6", "HDMI"},
381 {"HDMI_CH3_MUX", "CH7", "HDMI"},
383 {"HDMI_CH4_MUX", "CH0", "HDMI"},
384 {"HDMI_CH4_MUX", "CH1", "HDMI"},
385 {"HDMI_CH4_MUX", "CH2", "HDMI"},
386 {"HDMI_CH4_MUX", "CH3", "HDMI"},
387 {"HDMI_CH4_MUX", "CH4", "HDMI"},
388 {"HDMI_CH4_MUX", "CH5", "HDMI"},
389 {"HDMI_CH4_MUX", "CH6", "HDMI"},
390 {"HDMI_CH4_MUX", "CH7", "HDMI"},
392 {"HDMI_CH5_MUX", "CH0", "HDMI"},
393 {"HDMI_CH5_MUX", "CH1", "HDMI"},
394 {"HDMI_CH5_MUX", "CH2", "HDMI"},
395 {"HDMI_CH5_MUX", "CH3", "HDMI"},
396 {"HDMI_CH5_MUX", "CH4", "HDMI"},
397 {"HDMI_CH5_MUX", "CH5", "HDMI"},
398 {"HDMI_CH5_MUX", "CH6", "HDMI"},
399 {"HDMI_CH5_MUX", "CH7", "HDMI"},
401 {"HDMI_CH6_MUX", "CH0", "HDMI"},
402 {"HDMI_CH6_MUX", "CH1", "HDMI"},
403 {"HDMI_CH6_MUX", "CH2", "HDMI"},
404 {"HDMI_CH6_MUX", "CH3", "HDMI"},
405 {"HDMI_CH6_MUX", "CH4", "HDMI"},
406 {"HDMI_CH6_MUX", "CH5", "HDMI"},
407 {"HDMI_CH6_MUX", "CH6", "HDMI"},
408 {"HDMI_CH6_MUX", "CH7", "HDMI"},
410 {"HDMI_CH7_MUX", "CH0", "HDMI"},
411 {"HDMI_CH7_MUX", "CH1", "HDMI"},
412 {"HDMI_CH7_MUX", "CH2", "HDMI"},
413 {"HDMI_CH7_MUX", "CH3", "HDMI"},
414 {"HDMI_CH7_MUX", "CH4", "HDMI"},
415 {"HDMI_CH7_MUX", "CH5", "HDMI"},
416 {"HDMI_CH7_MUX", "CH6", "HDMI"},
417 {"HDMI_CH7_MUX", "CH7", "HDMI"},
419 {"TDM", NULL
, "HDMI_CH0_MUX"},
420 {"TDM", NULL
, "HDMI_CH1_MUX"},
421 {"TDM", NULL
, "HDMI_CH2_MUX"},
422 {"TDM", NULL
, "HDMI_CH3_MUX"},
423 {"TDM", NULL
, "HDMI_CH4_MUX"},
424 {"TDM", NULL
, "HDMI_CH5_MUX"},
425 {"TDM", NULL
, "HDMI_CH6_MUX"},
426 {"TDM", NULL
, "HDMI_CH7_MUX"},
428 {"TDM", NULL
, "aud_tdm_clk"},
429 {"TDM", NULL
, "TDM_BCK"},
430 {"TDM_BCK", NULL
, "TDM_MCK"},
431 {"TDM_MCK", NULL
, APLL1_W_NAME
, mtk_afe_tdm_apll_connect
},
432 {"TDM_MCK", NULL
, APLL2_W_NAME
, mtk_afe_tdm_apll_connect
},
436 static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe
*afe
,
437 struct mtk_afe_tdm_priv
*tdm_priv
,
443 apll
= mt8183_get_apll_by_rate(afe
, freq
);
444 apll_rate
= mt8183_get_apll_rate(afe
, apll
);
446 if (!freq
|| freq
> apll_rate
) {
448 "%s(), freq(%d Hz) invalid\n", __func__
, freq
);
452 if (apll_rate
% freq
!= 0) {
454 "%s(), APLL cannot generate %d Hz", __func__
, freq
);
458 tdm_priv
->mclk_rate
= freq
;
459 tdm_priv
->mclk_apll
= apll
;
464 static int mtk_dai_tdm_hw_params(struct snd_pcm_substream
*substream
,
465 struct snd_pcm_hw_params
*params
,
466 struct snd_soc_dai
*dai
)
468 struct mtk_base_afe
*afe
= snd_soc_dai_get_drvdata(dai
);
469 struct mt8183_afe_private
*afe_priv
= afe
->platform_priv
;
470 int tdm_id
= dai
->id
;
471 struct mtk_afe_tdm_priv
*tdm_priv
= afe_priv
->dai_priv
[tdm_id
];
472 unsigned int tdm_out_mode
= tdm_priv
->tdm_out_mode
;
473 unsigned int rate
= params_rate(params
);
474 unsigned int channels
= params_channels(params
);
475 unsigned int out_channels_per_sdata
=
476 get_tdm_ch_per_sdata(tdm_out_mode
, channels
);
477 snd_pcm_format_t format
= params_format(params
);
478 unsigned int tdm_con
= 0;
480 /* calculate mclk_rate, if not set explicitly */
481 if (!tdm_priv
->mclk_rate
) {
482 tdm_priv
->mclk_rate
= rate
* tdm_priv
->mclk_multiple
;
483 mtk_dai_tdm_cal_mclk(afe
,
485 tdm_priv
->mclk_rate
);
489 tdm_priv
->bck_rate
= rate
*
490 out_channels_per_sdata
*
491 snd_pcm_format_physical_width(format
);
493 if (tdm_priv
->bck_rate
> tdm_priv
->mclk_rate
)
494 dev_warn(afe
->dev
, "%s(), bck_rate > mclk_rate rate", __func__
);
496 if (tdm_priv
->mclk_rate
% tdm_priv
->bck_rate
!= 0)
497 dev_warn(afe
->dev
, "%s(), bck cannot generate", __func__
);
499 dev_info(afe
->dev
, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n",
501 tdm_id
, rate
, channels
, format
,
502 tdm_priv
->mclk_rate
, tdm_priv
->bck_rate
);
503 dev_info(afe
->dev
, "%s(), out_channels_per_sdata = %d\n",
504 __func__
, out_channels_per_sdata
);
507 if (tdm_priv
->bck_invert
)
508 regmap_update_bits(afe
->regmap
, AUDIO_TOP_CON3
,
509 BCK_INVERSE_MASK_SFT
,
510 0x1 << BCK_INVERSE_SFT
);
512 if (tdm_priv
->lck_invert
)
513 tdm_con
|= 1 << LRCK_INVERSE_SFT
;
515 if (tdm_priv
->tdm_out_mode
== TDM_OUT_I2S
) {
516 tdm_con
|= 1 << DELAY_DATA_SFT
;
517 tdm_con
|= get_tdm_lrck_width(format
) << LRCK_TDM_WIDTH_SFT
;
518 } else if (tdm_priv
->tdm_out_mode
== TDM_OUT_TDM
) {
519 tdm_con
|= 0 << DELAY_DATA_SFT
;
520 tdm_con
|= 0 << LRCK_TDM_WIDTH_SFT
;
523 tdm_con
|= 1 << LEFT_ALIGN_SFT
;
524 tdm_con
|= get_tdm_wlen(format
) << WLEN_SFT
;
525 tdm_con
|= get_tdm_ch(out_channels_per_sdata
) << CHANNEL_NUM_SFT
;
526 tdm_con
|= get_tdm_channel_bck(format
) << CHANNEL_BCK_CYCLES_SFT
;
527 regmap_write(afe
->regmap
, AFE_TDM_CON1
, tdm_con
);
529 if (out_channels_per_sdata
== 2) {
533 tdm_con
= TDM_CH_START_O30_O31
<< ST_CH_PAIR_SOUT0_SFT
;
534 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT1_SFT
;
535 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT2_SFT
;
536 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT3_SFT
;
540 tdm_con
= TDM_CH_START_O30_O31
<< ST_CH_PAIR_SOUT0_SFT
;
541 tdm_con
|= TDM_CH_START_O32_O33
<< ST_CH_PAIR_SOUT1_SFT
;
542 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT2_SFT
;
543 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT3_SFT
;
547 tdm_con
= TDM_CH_START_O30_O31
<< ST_CH_PAIR_SOUT0_SFT
;
548 tdm_con
|= TDM_CH_START_O32_O33
<< ST_CH_PAIR_SOUT1_SFT
;
549 tdm_con
|= TDM_CH_START_O34_O35
<< ST_CH_PAIR_SOUT2_SFT
;
550 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT3_SFT
;
554 tdm_con
= TDM_CH_START_O30_O31
<< ST_CH_PAIR_SOUT0_SFT
;
555 tdm_con
|= TDM_CH_START_O32_O33
<< ST_CH_PAIR_SOUT1_SFT
;
556 tdm_con
|= TDM_CH_START_O34_O35
<< ST_CH_PAIR_SOUT2_SFT
;
557 tdm_con
|= TDM_CH_START_O36_O37
<< ST_CH_PAIR_SOUT3_SFT
;
563 tdm_con
= TDM_CH_START_O30_O31
<< ST_CH_PAIR_SOUT0_SFT
;
564 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT1_SFT
;
565 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT2_SFT
;
566 tdm_con
|= TDM_CH_ZERO
<< ST_CH_PAIR_SOUT3_SFT
;
569 regmap_write(afe
->regmap
, AFE_TDM_CON2
, tdm_con
);
571 regmap_update_bits(afe
->regmap
, AFE_HDMI_OUT_CON0
,
572 AFE_HDMI_OUT_CH_NUM_MASK_SFT
,
573 channels
<< AFE_HDMI_OUT_CH_NUM_SFT
);
575 regmap_update_bits(afe
->regmap
, AFE_HDMI_OUT_CON0
,
576 AFE_HDMI_OUT_BIT_WIDTH_MASK_SFT
,
577 get_hdmi_wlen(format
) << AFE_HDMI_OUT_BIT_WIDTH_SFT
);
581 static int mtk_dai_tdm_trigger(struct snd_pcm_substream
*substream
,
583 struct snd_soc_dai
*dai
)
585 struct mtk_base_afe
*afe
= snd_soc_dai_get_drvdata(dai
);
588 case SNDRV_PCM_TRIGGER_START
:
589 case SNDRV_PCM_TRIGGER_RESUME
:
590 /* enable Out control */
591 regmap_update_bits(afe
->regmap
, AFE_HDMI_OUT_CON0
,
592 AFE_HDMI_OUT_ON_MASK_SFT
,
593 0x1 << AFE_HDMI_OUT_ON_SFT
);
595 regmap_update_bits(afe
->regmap
, AFE_TDM_CON1
,
596 TDM_EN_MASK_SFT
, 0x1 << TDM_EN_SFT
);
598 case SNDRV_PCM_TRIGGER_STOP
:
599 case SNDRV_PCM_TRIGGER_SUSPEND
:
601 regmap_update_bits(afe
->regmap
, AFE_TDM_CON1
,
603 /* disable Out control */
604 regmap_update_bits(afe
->regmap
, AFE_HDMI_OUT_CON0
,
605 AFE_HDMI_OUT_ON_MASK_SFT
,
615 static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai
*dai
,
616 int clk_id
, unsigned int freq
, int dir
)
618 struct mtk_base_afe
*afe
= dev_get_drvdata(dai
->dev
);
619 struct mt8183_afe_private
*afe_priv
= afe
->platform_priv
;
620 struct mtk_afe_tdm_priv
*tdm_priv
= afe_priv
->dai_priv
[dai
->id
];
623 dev_warn(afe
->dev
, "%s(), tdm_priv == NULL", __func__
);
627 if (dir
!= SND_SOC_CLOCK_OUT
) {
628 dev_warn(afe
->dev
, "%s(), dir != SND_SOC_CLOCK_OUT", __func__
);
632 dev_info(afe
->dev
, "%s(), freq %d\n", __func__
, freq
);
634 return mtk_dai_tdm_cal_mclk(afe
, tdm_priv
, freq
);
637 static int mtk_dai_tdm_set_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
639 struct mtk_base_afe
*afe
= dev_get_drvdata(dai
->dev
);
640 struct mt8183_afe_private
*afe_priv
= afe
->platform_priv
;
641 struct mtk_afe_tdm_priv
*tdm_priv
= afe_priv
->dai_priv
[dai
->id
];
644 dev_warn(afe
->dev
, "%s(), tdm_priv == NULL", __func__
);
649 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
650 case SND_SOC_DAIFMT_I2S
:
651 tdm_priv
->tdm_out_mode
= TDM_OUT_I2S
;
653 case SND_SOC_DAIFMT_DSP_A
:
654 tdm_priv
->tdm_out_mode
= TDM_OUT_TDM
;
657 tdm_priv
->tdm_out_mode
= TDM_OUT_I2S
;
660 /* DAI clock inversion*/
661 switch (fmt
& SND_SOC_DAIFMT_INV_MASK
) {
662 case SND_SOC_DAIFMT_NB_NF
:
663 tdm_priv
->bck_invert
= TDM_BCK_NON_INV
;
664 tdm_priv
->lck_invert
= TDM_LCK_NON_INV
;
666 case SND_SOC_DAIFMT_NB_IF
:
667 tdm_priv
->bck_invert
= TDM_BCK_NON_INV
;
668 tdm_priv
->lck_invert
= TDM_LCK_INV
;
670 case SND_SOC_DAIFMT_IB_NF
:
671 tdm_priv
->bck_invert
= TDM_BCK_INV
;
672 tdm_priv
->lck_invert
= TDM_LCK_NON_INV
;
674 case SND_SOC_DAIFMT_IB_IF
:
676 tdm_priv
->bck_invert
= TDM_BCK_INV
;
677 tdm_priv
->lck_invert
= TDM_LCK_INV
;
684 static const struct snd_soc_dai_ops mtk_dai_tdm_ops
= {
685 .hw_params
= mtk_dai_tdm_hw_params
,
686 .trigger
= mtk_dai_tdm_trigger
,
687 .set_sysclk
= mtk_dai_tdm_set_sysclk
,
688 .set_fmt
= mtk_dai_tdm_set_fmt
,
692 #define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
693 SNDRV_PCM_RATE_88200 |\
694 SNDRV_PCM_RATE_96000 |\
695 SNDRV_PCM_RATE_176400 |\
696 SNDRV_PCM_RATE_192000)
698 #define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
699 SNDRV_PCM_FMTBIT_S24_LE |\
700 SNDRV_PCM_FMTBIT_S32_LE)
702 static struct snd_soc_dai_driver mtk_dai_tdm_driver
[] = {
705 .id
= MT8183_DAI_TDM
,
707 .stream_name
= "TDM",
710 .rates
= MTK_TDM_RATES
,
711 .formats
= MTK_TDM_FORMATS
,
713 .ops
= &mtk_dai_tdm_ops
,
717 int mt8183_dai_tdm_register(struct mtk_base_afe
*afe
)
719 struct mt8183_afe_private
*afe_priv
= afe
->platform_priv
;
720 struct mtk_afe_tdm_priv
*tdm_priv
;
721 struct mtk_base_afe_dai
*dai
;
723 dai
= devm_kzalloc(afe
->dev
, sizeof(*dai
), GFP_KERNEL
);
727 list_add(&dai
->list
, &afe
->sub_dais
);
729 dai
->dai_drivers
= mtk_dai_tdm_driver
;
730 dai
->num_dai_drivers
= ARRAY_SIZE(mtk_dai_tdm_driver
);
732 dai
->dapm_widgets
= mtk_dai_tdm_widgets
;
733 dai
->num_dapm_widgets
= ARRAY_SIZE(mtk_dai_tdm_widgets
);
734 dai
->dapm_routes
= mtk_dai_tdm_routes
;
735 dai
->num_dapm_routes
= ARRAY_SIZE(mtk_dai_tdm_routes
);
737 tdm_priv
= devm_kzalloc(afe
->dev
, sizeof(struct mtk_afe_tdm_priv
),
742 tdm_priv
->mclk_multiple
= 128;
743 tdm_priv
->bck_id
= MT8183_I2S4_BCK
;
744 tdm_priv
->mclk_id
= MT8183_I2S4_MCK
;
746 afe_priv
->dai_priv
[MT8183_DAI_TDM
] = tdm_priv
;