linux/sound/soc/mediatek/mt8192/mt8192-dai-tdm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// MediaTek ALSA SoC Audio DAI TDM Control
   4//
   5// Copyright (c) 2020 MediaTek Inc.
   6// Author: Shane Chien <shane.chien@mediatek.com>
   7
   8#include <linux/regmap.h>
   9#include <sound/pcm_params.h>
  10
  11#include "mt8192-afe-clk.h"
  12#include "mt8192-afe-common.h"
  13#include "mt8192-afe-gpio.h"
  14#include "mt8192-interconnection.h"
  15
  16struct mtk_afe_tdm_priv {
  17        int id;
  18        int bck_id;
  19        int bck_rate;
  20        int tdm_out_mode;
  21        int bck_invert;
  22        int lck_invert;
  23        int mclk_id;
  24        int mclk_multiple; /* according to sample rate */
  25        int mclk_rate;
  26        int mclk_apll;
  27};
  28
  29enum {
  30        TDM_OUT_I2S = 0,
  31        TDM_OUT_DSP_A = 1,
  32        TDM_OUT_DSP_B = 2,
  33};
  34
  35enum {
  36        TDM_BCK_NON_INV = 0,
  37        TDM_BCK_INV = 1,
  38};
  39
  40enum {
  41        TDM_LCK_NON_INV = 0,
  42        TDM_LCK_INV = 1,
  43};
  44
  45enum {
  46        TDM_WLEN_16_BIT = 1,
  47        TDM_WLEN_32_BIT = 2,
  48};
  49
  50enum {
  51        TDM_CHANNEL_BCK_16 = 0,
  52        TDM_CHANNEL_BCK_24 = 1,
  53        TDM_CHANNEL_BCK_32 = 2,
  54};
  55
  56enum {
  57        TDM_CHANNEL_NUM_2 = 0,
  58        TDM_CHANNEL_NUM_4 = 1,
  59        TDM_CHANNEL_NUM_8 = 2,
  60};
  61
  62enum  {
  63        TDM_CH_START_O30_O31 = 0,
  64        TDM_CH_START_O32_O33,
  65        TDM_CH_START_O34_O35,
  66        TDM_CH_START_O36_O37,
  67        TDM_CH_ZERO,
  68};
  69
  70static unsigned int get_tdm_wlen(snd_pcm_format_t format)
  71{
  72        return snd_pcm_format_physical_width(format) <= 16 ?
  73               TDM_WLEN_16_BIT : TDM_WLEN_32_BIT;
  74}
  75
  76static unsigned int get_tdm_channel_bck(snd_pcm_format_t format)
  77{
  78        return snd_pcm_format_physical_width(format) <= 16 ?
  79               TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32;
  80}
  81
  82static unsigned int get_tdm_lrck_width(snd_pcm_format_t format)
  83{
  84        return snd_pcm_format_physical_width(format) - 1;
  85}
  86
  87static unsigned int get_tdm_ch(unsigned int ch)
  88{
  89        switch (ch) {
  90        case 1:
  91        case 2:
  92                return TDM_CHANNEL_NUM_2;
  93        case 3:
  94        case 4:
  95                return TDM_CHANNEL_NUM_4;
  96        case 5:
  97        case 6:
  98        case 7:
  99        case 8:
 100        default:
 101                return TDM_CHANNEL_NUM_8;
 102        }
 103}
 104
 105static unsigned int get_tdm_ch_fixup(unsigned int channels)
 106{
 107        if (channels > 4)
 108                return 8;
 109        else if (channels > 2)
 110                return 4;
 111        else
 112                return 2;
 113}
 114
 115static unsigned int get_tdm_ch_per_sdata(unsigned int mode,
 116                                         unsigned int channels)
 117{
 118        if (mode == TDM_OUT_DSP_A || mode == TDM_OUT_DSP_B)
 119                return get_tdm_ch_fixup(channels);
 120        else
 121                return 2;
 122}
 123
 124/* interconnection */
 125enum {
 126        HDMI_CONN_CH0 = 0,
 127        HDMI_CONN_CH1,
 128        HDMI_CONN_CH2,
 129        HDMI_CONN_CH3,
 130        HDMI_CONN_CH4,
 131        HDMI_CONN_CH5,
 132        HDMI_CONN_CH6,
 133        HDMI_CONN_CH7,
 134};
 135
 136static const char *const hdmi_conn_mux_map[] = {
 137        "CH0", "CH1", "CH2", "CH3",
 138        "CH4", "CH5", "CH6", "CH7",
 139};
 140
 141static int hdmi_conn_mux_map_value[] = {
 142        HDMI_CONN_CH0,
 143        HDMI_CONN_CH1,
 144        HDMI_CONN_CH2,
 145        HDMI_CONN_CH3,
 146        HDMI_CONN_CH4,
 147        HDMI_CONN_CH5,
 148        HDMI_CONN_CH6,
 149        HDMI_CONN_CH7,
 150};
 151
 152static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum,
 153                                  AFE_HDMI_CONN0,
 154                                  HDMI_O_0_SFT,
 155                                  HDMI_O_0_MASK,
 156                                  hdmi_conn_mux_map,
 157                                  hdmi_conn_mux_map_value);
 158
 159static const struct snd_kcontrol_new hdmi_ch0_mux_control =
 160        SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum);
 161
 162static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum,
 163                                  AFE_HDMI_CONN0,
 164                                  HDMI_O_1_SFT,
 165                                  HDMI_O_1_MASK,
 166                                  hdmi_conn_mux_map,
 167                                  hdmi_conn_mux_map_value);
 168
 169static const struct snd_kcontrol_new hdmi_ch1_mux_control =
 170        SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum);
 171
 172static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum,
 173                                  AFE_HDMI_CONN0,
 174                                  HDMI_O_2_SFT,
 175                                  HDMI_O_2_MASK,
 176                                  hdmi_conn_mux_map,
 177                                  hdmi_conn_mux_map_value);
 178
 179static const struct snd_kcontrol_new hdmi_ch2_mux_control =
 180        SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum);
 181
 182static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum,
 183                                  AFE_HDMI_CONN0,
 184                                  HDMI_O_3_SFT,
 185                                  HDMI_O_3_MASK,
 186                                  hdmi_conn_mux_map,
 187                                  hdmi_conn_mux_map_value);
 188
 189static const struct snd_kcontrol_new hdmi_ch3_mux_control =
 190        SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum);
 191
 192static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum,
 193                                  AFE_HDMI_CONN0,
 194                                  HDMI_O_4_SFT,
 195                                  HDMI_O_4_MASK,
 196                                  hdmi_conn_mux_map,
 197                                  hdmi_conn_mux_map_value);
 198
 199static const struct snd_kcontrol_new hdmi_ch4_mux_control =
 200        SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum);
 201
 202static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum,
 203                                  AFE_HDMI_CONN0,
 204                                  HDMI_O_5_SFT,
 205                                  HDMI_O_5_MASK,
 206                                  hdmi_conn_mux_map,
 207                                  hdmi_conn_mux_map_value);
 208
 209static const struct snd_kcontrol_new hdmi_ch5_mux_control =
 210        SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum);
 211
 212static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum,
 213                                  AFE_HDMI_CONN0,
 214                                  HDMI_O_6_SFT,
 215                                  HDMI_O_6_MASK,
 216                                  hdmi_conn_mux_map,
 217                                  hdmi_conn_mux_map_value);
 218
 219static const struct snd_kcontrol_new hdmi_ch6_mux_control =
 220        SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum);
 221
 222static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum,
 223                                  AFE_HDMI_CONN0,
 224                                  HDMI_O_7_SFT,
 225                                  HDMI_O_7_MASK,
 226                                  hdmi_conn_mux_map,
 227                                  hdmi_conn_mux_map_value);
 228
 229static const struct snd_kcontrol_new hdmi_ch7_mux_control =
 230        SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum);
 231
 232enum {
 233        SUPPLY_SEQ_APLL,
 234        SUPPLY_SEQ_TDM_MCK_EN,
 235        SUPPLY_SEQ_TDM_BCK_EN,
 236        SUPPLY_SEQ_TDM_EN,
 237};
 238
 239static int get_tdm_id_by_name(const char *name)
 240{
 241        return MT8192_DAI_TDM;
 242}
 243
 244static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w,
 245                            struct snd_kcontrol *kcontrol,
 246                            int event)
 247{
 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];
 253
 254        if (!tdm_priv) {
 255                dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
 256                return -EINVAL;
 257        }
 258
 259        dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n",
 260                 __func__, w->name, event);
 261
 262        switch (event) {
 263        case SND_SOC_DAPM_PRE_PMU:
 264                mt8192_afe_gpio_request(afe->dev, true, tdm_priv->id, 0);
 265                break;
 266        case SND_SOC_DAPM_POST_PMD:
 267                mt8192_afe_gpio_request(afe->dev, false, tdm_priv->id, 0);
 268                break;
 269        default:
 270                break;
 271        }
 272
 273        return 0;
 274}
 275
 276static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w,
 277                                struct snd_kcontrol *kcontrol,
 278                                int event)
 279{
 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];
 285
 286        if (!tdm_priv) {
 287                dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
 288                return -EINVAL;
 289        }
 290
 291        dev_info(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
 292                 __func__, w->name, event, dai_id);
 293
 294        switch (event) {
 295        case SND_SOC_DAPM_PRE_PMU:
 296                mt8192_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate);
 297                break;
 298        case SND_SOC_DAPM_POST_PMD:
 299                mt8192_mck_disable(afe, tdm_priv->bck_id);
 300                break;
 301        default:
 302                break;
 303        }
 304
 305        return 0;
 306}
 307
 308static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
 309                                struct snd_kcontrol *kcontrol,
 310                                int event)
 311{
 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];
 317
 318        if (!tdm_priv) {
 319                dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
 320                return -EINVAL;
 321        }
 322
 323        dev_info(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
 324                 __func__, w->name, event, dai_id);
 325
 326        switch (event) {
 327        case SND_SOC_DAPM_PRE_PMU:
 328                mt8192_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
 329                break;
 330        case SND_SOC_DAPM_POST_PMD:
 331                tdm_priv->mclk_rate = 0;
 332                mt8192_mck_disable(afe, tdm_priv->mclk_id);
 333                break;
 334        default:
 335                break;
 336        }
 337
 338        return 0;
 339}
 340
 341static 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),
 358
 359        SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"),
 360
 361        SND_SOC_DAPM_SUPPLY_S("TDM_EN", SUPPLY_SEQ_TDM_EN,
 362                              AFE_TDM_CON1, TDM_EN_SFT, 0,
 363                              mtk_tdm_en_event,
 364                              SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 365
 366        SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN,
 367                              SND_SOC_NOPM, 0, 0,
 368                              mtk_tdm_bck_en_event,
 369                              SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 370
 371        SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN,
 372                              SND_SOC_NOPM, 0, 0,
 373                              mtk_tdm_mck_en_event,
 374                              SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 375};
 376
 377static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
 378                                    struct snd_soc_dapm_widget *sink)
 379{
 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];
 386        int cur_apll;
 387
 388        /* which apll */
 389        cur_apll = mt8192_get_apll_by_name(afe, source->name);
 390
 391        return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;
 392}
 393
 394static 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"},
 403
 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"},
 412
 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"},
 421
 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"},
 430
 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"},
 439
 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"},
 448
 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"},
 457
 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"},
 466
 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"},
 475
 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},
 482};
 483
 484/* dai ops */
 485static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
 486                                struct mtk_afe_tdm_priv *tdm_priv,
 487                                int freq)
 488{
 489        int apll;
 490        int apll_rate;
 491
 492        apll = mt8192_get_apll_by_rate(afe, freq);
 493        apll_rate = mt8192_get_apll_rate(afe, apll);
 494
 495        if (!freq || freq > apll_rate) {
 496                dev_warn(afe->dev,
 497                         "%s(), freq(%d Hz) invalid\n", __func__, freq);
 498                return -EINVAL;
 499        }
 500
 501        if (apll_rate % freq != 0) {
 502                dev_warn(afe->dev,
 503                         "%s(), APLL cannot generate %d Hz", __func__, freq);
 504                return -EINVAL;
 505        }
 506
 507        tdm_priv->mclk_rate = freq;
 508        tdm_priv->mclk_apll = apll;
 509
 510        return 0;
 511}
 512
 513static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
 514                                 struct snd_pcm_hw_params *params,
 515                                 struct snd_soc_dai *dai)
 516{
 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;
 528
 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,
 533                                     tdm_priv,
 534                                     tdm_priv->mclk_rate);
 535        }
 536
 537        /* calculate bck */
 538        tdm_priv->bck_rate = rate *
 539                             out_channels_per_sdata *
 540                             snd_pcm_format_physical_width(format);
 541
 542        if (tdm_priv->bck_rate > tdm_priv->mclk_rate)
 543                dev_warn(afe->dev, "%s(), bck_rate > mclk_rate rate", __func__);
 544
 545        if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0)
 546                dev_warn(afe->dev, "%s(), bck cannot generate", __func__);
 547
 548        dev_info(afe->dev, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n",
 549                 __func__,
 550                 tdm_id, rate, channels, format,
 551                 tdm_priv->mclk_rate, tdm_priv->bck_rate);
 552
 553        dev_info(afe->dev, "%s(), out_channels_per_sdata = %d\n",
 554                 __func__, out_channels_per_sdata);
 555
 556        /* set tdm */
 557        if (tdm_priv->bck_invert)
 558                regmap_update_bits(afe->regmap, AUDIO_TOP_CON3,
 559                                   BCK_INVERSE_MASK_SFT,
 560                                   0x1 << BCK_INVERSE_SFT);
 561
 562        if (tdm_priv->lck_invert)
 563                tdm_con |= 1 << LRCK_INVERSE_SFT;
 564
 565        if (tdm_priv->tdm_out_mode == TDM_OUT_I2S) {
 566                tdm_con |= 1 << DELAY_DATA_SFT;
 567                tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT;
 568        } else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_A) {
 569                tdm_con |= 0 << DELAY_DATA_SFT;
 570                tdm_con |= 0 << LRCK_TDM_WIDTH_SFT;
 571        } else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_B) {
 572                tdm_con |= 1 << DELAY_DATA_SFT;
 573                tdm_con |= 0 << LRCK_TDM_WIDTH_SFT;
 574        }
 575
 576        tdm_con |= 1 << LEFT_ALIGN_SFT;
 577        tdm_con |= get_tdm_wlen(format) << WLEN_SFT;
 578        tdm_con |= get_tdm_ch(out_channels_per_sdata) << CHANNEL_NUM_SFT;
 579        tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT;
 580        regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con);
 581
 582        if (out_channels_per_sdata == 2) {
 583                switch (channels) {
 584                case 1:
 585                case 2:
 586                        tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
 587                        tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
 588                        tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
 589                        tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
 590                        break;
 591                case 3:
 592                case 4:
 593                        tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
 594                        tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
 595                        tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
 596                        tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
 597                        break;
 598                case 5:
 599                case 6:
 600                        tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
 601                        tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
 602                        tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
 603                        tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
 604                        break;
 605                case 7:
 606                case 8:
 607                        tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
 608                        tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
 609                        tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
 610                        tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT;
 611                        break;
 612                default:
 613                        tdm_con = 0;
 614                }
 615        } else {
 616                tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
 617                tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
 618                tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
 619                tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
 620        }
 621
 622        regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con);
 623
 624        regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
 625                           HDMI_CH_NUM_MASK_SFT,
 626                           channels << HDMI_CH_NUM_SFT);
 627        return 0;
 628}
 629
 630static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
 631                                  int clk_id, unsigned int freq, int dir)
 632{
 633        struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
 634        struct mt8192_afe_private *afe_priv = afe->platform_priv;
 635        struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
 636
 637        if (!tdm_priv) {
 638                dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
 639                return -EINVAL;
 640        }
 641
 642        if (dir != SND_SOC_CLOCK_OUT) {
 643                dev_warn(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
 644                return -EINVAL;
 645        }
 646
 647        dev_info(afe->dev, "%s(), freq %d\n", __func__, freq);
 648
 649        return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);
 650}
 651
 652static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 653{
 654        struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
 655        struct mt8192_afe_private *afe_priv = afe->platform_priv;
 656        struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
 657
 658        if (!tdm_priv) {
 659                dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
 660                return -EINVAL;
 661        }
 662
 663        /* DAI mode*/
 664        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 665        case SND_SOC_DAIFMT_I2S:
 666                tdm_priv->tdm_out_mode = TDM_OUT_I2S;
 667                break;
 668        case SND_SOC_DAIFMT_DSP_A:
 669                tdm_priv->tdm_out_mode = TDM_OUT_DSP_A;
 670                break;
 671        case SND_SOC_DAIFMT_DSP_B:
 672                tdm_priv->tdm_out_mode = TDM_OUT_DSP_B;
 673                break;
 674        default:
 675                tdm_priv->tdm_out_mode = TDM_OUT_I2S;
 676        }
 677
 678        /* DAI clock inversion*/
 679        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 680        case SND_SOC_DAIFMT_NB_NF:
 681                tdm_priv->bck_invert = TDM_BCK_NON_INV;
 682                tdm_priv->lck_invert = TDM_LCK_NON_INV;
 683                break;
 684        case SND_SOC_DAIFMT_NB_IF:
 685                tdm_priv->bck_invert = TDM_BCK_NON_INV;
 686                tdm_priv->lck_invert = TDM_LCK_INV;
 687                break;
 688        case SND_SOC_DAIFMT_IB_NF:
 689                tdm_priv->bck_invert = TDM_BCK_INV;
 690                tdm_priv->lck_invert = TDM_LCK_NON_INV;
 691                break;
 692        case SND_SOC_DAIFMT_IB_IF:
 693        default:
 694                tdm_priv->bck_invert = TDM_BCK_INV;
 695                tdm_priv->lck_invert = TDM_LCK_INV;
 696                break;
 697        }
 698
 699        return 0;
 700}
 701
 702static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {
 703        .hw_params = mtk_dai_tdm_hw_params,
 704        .set_sysclk = mtk_dai_tdm_set_sysclk,
 705        .set_fmt = mtk_dai_tdm_set_fmt,
 706};
 707
 708/* dai driver */
 709#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
 710                       SNDRV_PCM_RATE_88200 |\
 711                       SNDRV_PCM_RATE_96000 |\
 712                       SNDRV_PCM_RATE_176400 |\
 713                       SNDRV_PCM_RATE_192000)
 714
 715#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
 716                         SNDRV_PCM_FMTBIT_S24_LE |\
 717                         SNDRV_PCM_FMTBIT_S32_LE)
 718
 719static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {
 720        {
 721                .name = "TDM",
 722                .id = MT8192_DAI_TDM,
 723                .playback = {
 724                        .stream_name = "TDM",
 725                        .channels_min = 2,
 726                        .channels_max = 8,
 727                        .rates = MTK_TDM_RATES,
 728                        .formats = MTK_TDM_FORMATS,
 729                },
 730                .ops = &mtk_dai_tdm_ops,
 731        },
 732};
 733
 734static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe)
 735{
 736        struct mtk_afe_tdm_priv *tdm_priv;
 737
 738        tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),
 739                                GFP_KERNEL);
 740        if (!tdm_priv)
 741                return NULL;
 742
 743        tdm_priv->mclk_multiple = 512;
 744        tdm_priv->bck_id = MT8192_I2S4_BCK;
 745        tdm_priv->mclk_id = MT8192_I2S4_MCK;
 746        tdm_priv->id = MT8192_DAI_TDM;
 747
 748        return tdm_priv;
 749}
 750
 751int mt8192_dai_tdm_register(struct mtk_base_afe *afe)
 752{
 753        struct mt8192_afe_private *afe_priv = afe->platform_priv;
 754        struct mtk_afe_tdm_priv *tdm_priv;
 755        struct mtk_base_afe_dai *dai;
 756
 757        dev_info(afe->dev, "%s()\n", __func__);
 758
 759        dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
 760        if (!dai)
 761                return -ENOMEM;
 762
 763        list_add(&dai->list, &afe->sub_dais);
 764
 765        dai->dai_drivers = mtk_dai_tdm_driver;
 766        dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);
 767
 768        dai->dapm_widgets = mtk_dai_tdm_widgets;
 769        dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);
 770        dai->dapm_routes = mtk_dai_tdm_routes;
 771        dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);
 772
 773        tdm_priv = init_tdm_priv_data(afe);
 774        if (!tdm_priv)
 775                return -ENOMEM;
 776
 777        afe_priv->dai_priv[MT8192_DAI_TDM] = tdm_priv;
 778
 779        return 0;
 780}
 781