root/sound/soc/mediatek/mt8183/mt8183-dai-pcm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mtk_dai_pcm_hw_params
  2. mt8183_dai_pcm_register

   1 // SPDX-License-Identifier: GPL-2.0
   2 //
   3 // MediaTek ALSA SoC Audio DAI I2S Control
   4 //
   5 // Copyright (c) 2018 MediaTek Inc.
   6 // Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com>
   7 
   8 #include <linux/regmap.h>
   9 #include <sound/pcm_params.h>
  10 #include "mt8183-afe-common.h"
  11 #include "mt8183-interconnection.h"
  12 #include "mt8183-reg.h"
  13 
  14 enum AUD_TX_LCH_RPT {
  15         AUD_TX_LCH_RPT_NO_REPEAT = 0,
  16         AUD_TX_LCH_RPT_REPEAT = 1
  17 };
  18 
  19 enum AUD_VBT_16K_MODE {
  20         AUD_VBT_16K_MODE_DISABLE = 0,
  21         AUD_VBT_16K_MODE_ENABLE = 1
  22 };
  23 
  24 enum AUD_EXT_MODEM {
  25         AUD_EXT_MODEM_SELECT_INTERNAL = 0,
  26         AUD_EXT_MODEM_SELECT_EXTERNAL = 1
  27 };
  28 
  29 enum AUD_PCM_SYNC_TYPE {
  30         /* bck sync length = 1 */
  31         AUD_PCM_ONE_BCK_CYCLE_SYNC = 0,
  32         /* bck sync length = PCM_INTF_CON1[9:13] */
  33         AUD_PCM_EXTENDED_BCK_CYCLE_SYNC = 1
  34 };
  35 
  36 enum AUD_BT_MODE {
  37         AUD_BT_MODE_DUAL_MIC_ON_TX = 0,
  38         AUD_BT_MODE_SINGLE_MIC_ON_TX = 1
  39 };
  40 
  41 enum AUD_PCM_AFIFO_SRC {
  42         /* slave mode & external modem uses different crystal */
  43         AUD_PCM_AFIFO_ASRC = 0,
  44         /* slave mode & external modem uses the same crystal */
  45         AUD_PCM_AFIFO_AFIFO = 1
  46 };
  47 
  48 enum AUD_PCM_CLOCK_SOURCE {
  49         AUD_PCM_CLOCK_MASTER_MODE = 0,
  50         AUD_PCM_CLOCK_SLAVE_MODE = 1
  51 };
  52 
  53 enum AUD_PCM_WLEN {
  54         AUD_PCM_WLEN_PCM_32_BCK_CYCLES = 0,
  55         AUD_PCM_WLEN_PCM_64_BCK_CYCLES = 1
  56 };
  57 
  58 enum AUD_PCM_MODE {
  59         AUD_PCM_MODE_PCM_MODE_8K = 0,
  60         AUD_PCM_MODE_PCM_MODE_16K = 1,
  61         AUD_PCM_MODE_PCM_MODE_32K = 2,
  62         AUD_PCM_MODE_PCM_MODE_48K = 3,
  63 };
  64 
  65 enum AUD_PCM_FMT {
  66         AUD_PCM_FMT_I2S = 0,
  67         AUD_PCM_FMT_EIAJ = 1,
  68         AUD_PCM_FMT_PCM_MODE_A = 2,
  69         AUD_PCM_FMT_PCM_MODE_B = 3
  70 };
  71 
  72 enum AUD_BCLK_OUT_INV {
  73         AUD_BCLK_OUT_INV_NO_INVERSE = 0,
  74         AUD_BCLK_OUT_INV_INVERSE = 1
  75 };
  76 
  77 enum AUD_PCM_EN {
  78         AUD_PCM_EN_DISABLE = 0,
  79         AUD_PCM_EN_ENABLE = 1
  80 };
  81 
  82 /* dai component */
  83 static const struct snd_kcontrol_new mtk_pcm_1_playback_ch1_mix[] = {
  84         SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN7,
  85                                     I_ADDA_UL_CH1, 1, 0),
  86         SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN7,
  87                                     I_DL2_CH1, 1, 0),
  88 };
  89 
  90 static const struct snd_kcontrol_new mtk_pcm_1_playback_ch2_mix[] = {
  91         SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN8,
  92                                     I_ADDA_UL_CH2, 1, 0),
  93         SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN8,
  94                                     I_DL2_CH2, 1, 0),
  95 };
  96 
  97 static const struct snd_kcontrol_new mtk_pcm_1_playback_ch4_mix[] = {
  98         SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN27,
  99                                     I_DL1_CH1, 1, 0),
 100 };
 101 
 102 static const struct snd_kcontrol_new mtk_pcm_2_playback_ch1_mix[] = {
 103         SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN17,
 104                                     I_ADDA_UL_CH1, 1, 0),
 105         SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN17,
 106                                     I_DL2_CH1, 1, 0),
 107 };
 108 
 109 static const struct snd_kcontrol_new mtk_pcm_2_playback_ch2_mix[] = {
 110         SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN18,
 111                                     I_ADDA_UL_CH2, 1, 0),
 112         SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN18,
 113                                     I_DL2_CH2, 1, 0),
 114 };
 115 
 116 static const struct snd_kcontrol_new mtk_pcm_2_playback_ch4_mix[] = {
 117         SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN24,
 118                                     I_DL1_CH1, 1, 0),
 119 };
 120 
 121 static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = {
 122         /* inter-connections */
 123         SND_SOC_DAPM_MIXER("PCM_1_PB_CH1", SND_SOC_NOPM, 0, 0,
 124                            mtk_pcm_1_playback_ch1_mix,
 125                            ARRAY_SIZE(mtk_pcm_1_playback_ch1_mix)),
 126         SND_SOC_DAPM_MIXER("PCM_1_PB_CH2", SND_SOC_NOPM, 0, 0,
 127                            mtk_pcm_1_playback_ch2_mix,
 128                            ARRAY_SIZE(mtk_pcm_1_playback_ch2_mix)),
 129         SND_SOC_DAPM_MIXER("PCM_1_PB_CH4", SND_SOC_NOPM, 0, 0,
 130                            mtk_pcm_1_playback_ch4_mix,
 131                            ARRAY_SIZE(mtk_pcm_1_playback_ch4_mix)),
 132         SND_SOC_DAPM_MIXER("PCM_2_PB_CH1", SND_SOC_NOPM, 0, 0,
 133                            mtk_pcm_2_playback_ch1_mix,
 134                            ARRAY_SIZE(mtk_pcm_2_playback_ch1_mix)),
 135         SND_SOC_DAPM_MIXER("PCM_2_PB_CH2", SND_SOC_NOPM, 0, 0,
 136                            mtk_pcm_2_playback_ch2_mix,
 137                            ARRAY_SIZE(mtk_pcm_2_playback_ch2_mix)),
 138         SND_SOC_DAPM_MIXER("PCM_2_PB_CH4", SND_SOC_NOPM, 0, 0,
 139                            mtk_pcm_2_playback_ch4_mix,
 140                            ARRAY_SIZE(mtk_pcm_2_playback_ch4_mix)),
 141 
 142         SND_SOC_DAPM_SUPPLY("PCM_1_EN", PCM_INTF_CON1, PCM_EN_SFT, 0,
 143                             NULL, 0),
 144 
 145         SND_SOC_DAPM_SUPPLY("PCM_2_EN", PCM2_INTF_CON, PCM2_EN_SFT, 0,
 146                             NULL, 0),
 147 
 148         SND_SOC_DAPM_INPUT("MD1_TO_AFE"),
 149         SND_SOC_DAPM_INPUT("MD2_TO_AFE"),
 150         SND_SOC_DAPM_OUTPUT("AFE_TO_MD1"),
 151         SND_SOC_DAPM_OUTPUT("AFE_TO_MD2"),
 152 };
 153 
 154 static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = {
 155         {"PCM 1 Playback", NULL, "PCM_1_PB_CH1"},
 156         {"PCM 1 Playback", NULL, "PCM_1_PB_CH2"},
 157         {"PCM 1 Playback", NULL, "PCM_1_PB_CH4"},
 158         {"PCM 2 Playback", NULL, "PCM_2_PB_CH1"},
 159         {"PCM 2 Playback", NULL, "PCM_2_PB_CH2"},
 160         {"PCM 2 Playback", NULL, "PCM_2_PB_CH4"},
 161 
 162         {"PCM 1 Playback", NULL, "PCM_1_EN"},
 163         {"PCM 2 Playback", NULL, "PCM_2_EN"},
 164         {"PCM 1 Capture", NULL, "PCM_1_EN"},
 165         {"PCM 2 Capture", NULL, "PCM_2_EN"},
 166 
 167         {"AFE_TO_MD1", NULL, "PCM 2 Playback"},
 168         {"AFE_TO_MD2", NULL, "PCM 1 Playback"},
 169         {"PCM 2 Capture", NULL, "MD1_TO_AFE"},
 170         {"PCM 1 Capture", NULL, "MD2_TO_AFE"},
 171 
 172         {"PCM_1_PB_CH1", "DL2_CH1", "DL2"},
 173         {"PCM_1_PB_CH2", "DL2_CH2", "DL2"},
 174         {"PCM_1_PB_CH4", "DL1_CH1", "DL1"},
 175         {"PCM_2_PB_CH1", "DL2_CH1", "DL2"},
 176         {"PCM_2_PB_CH2", "DL2_CH2", "DL2"},
 177         {"PCM_2_PB_CH4", "DL1_CH1", "DL1"},
 178 };
 179 
 180 /* dai ops */
 181 static int mtk_dai_pcm_hw_params(struct snd_pcm_substream *substream,
 182                                  struct snd_pcm_hw_params *params,
 183                                  struct snd_soc_dai *dai)
 184 {
 185         struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
 186         unsigned int rate = params_rate(params);
 187         unsigned int rate_reg = mt8183_rate_transform(afe->dev, rate, dai->id);
 188         unsigned int pcm_con = 0;
 189 
 190         dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d, rate_reg %d, widget active p %d, c %d\n",
 191                 __func__,
 192                 dai->id,
 193                 substream->stream,
 194                 rate,
 195                 rate_reg,
 196                 dai->playback_widget->active,
 197                 dai->capture_widget->active);
 198 
 199         if (dai->playback_widget->active || dai->capture_widget->active)
 200                 return 0;
 201 
 202         switch (dai->id) {
 203         case MT8183_DAI_PCM_1:
 204                 pcm_con |= AUD_BCLK_OUT_INV_NO_INVERSE << PCM_BCLK_OUT_INV_SFT;
 205                 pcm_con |= AUD_TX_LCH_RPT_NO_REPEAT << PCM_TX_LCH_RPT_SFT;
 206                 pcm_con |= AUD_VBT_16K_MODE_DISABLE << PCM_VBT_16K_MODE_SFT;
 207                 pcm_con |= AUD_EXT_MODEM_SELECT_INTERNAL << PCM_EXT_MODEM_SFT;
 208                 pcm_con |= 0 << PCM_SYNC_LENGTH_SFT;
 209                 pcm_con |= AUD_PCM_ONE_BCK_CYCLE_SYNC << PCM_SYNC_TYPE_SFT;
 210                 pcm_con |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM_BT_MODE_SFT;
 211                 pcm_con |= AUD_PCM_AFIFO_AFIFO << PCM_BYP_ASRC_SFT;
 212                 pcm_con |= AUD_PCM_CLOCK_SLAVE_MODE << PCM_SLAVE_SFT;
 213                 pcm_con |= rate_reg << PCM_MODE_SFT;
 214                 pcm_con |= AUD_PCM_FMT_PCM_MODE_B << PCM_FMT_SFT;
 215 
 216                 regmap_update_bits(afe->regmap, PCM_INTF_CON1,
 217                                    0xfffffffe, pcm_con);
 218                 break;
 219         case MT8183_DAI_PCM_2:
 220                 pcm_con |= AUD_TX_LCH_RPT_NO_REPEAT << PCM2_TX_LCH_RPT_SFT;
 221                 pcm_con |= AUD_VBT_16K_MODE_DISABLE << PCM2_VBT_16K_MODE_SFT;
 222                 pcm_con |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM2_BT_MODE_SFT;
 223                 pcm_con |= AUD_PCM_AFIFO_AFIFO << PCM2_AFIFO_SFT;
 224                 pcm_con |= AUD_PCM_WLEN_PCM_32_BCK_CYCLES << PCM2_WLEN_SFT;
 225                 pcm_con |= rate_reg << PCM2_MODE_SFT;
 226                 pcm_con |= AUD_PCM_FMT_PCM_MODE_B << PCM2_FMT_SFT;
 227 
 228                 regmap_update_bits(afe->regmap, PCM2_INTF_CON,
 229                                    0xfffffffe, pcm_con);
 230                 break;
 231         default:
 232                 dev_warn(afe->dev, "%s(), id %d not support\n",
 233                          __func__, dai->id);
 234                 return -EINVAL;
 235         }
 236 
 237         return 0;
 238 }
 239 
 240 static const struct snd_soc_dai_ops mtk_dai_pcm_ops = {
 241         .hw_params = mtk_dai_pcm_hw_params,
 242 };
 243 
 244 /* dai driver */
 245 #define MTK_PCM_RATES (SNDRV_PCM_RATE_8000 |\
 246                        SNDRV_PCM_RATE_16000 |\
 247                        SNDRV_PCM_RATE_32000 |\
 248                        SNDRV_PCM_RATE_48000)
 249 
 250 #define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
 251                          SNDRV_PCM_FMTBIT_S24_LE |\
 252                          SNDRV_PCM_FMTBIT_S32_LE)
 253 
 254 static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
 255         {
 256                 .name = "PCM 1",
 257                 .id = MT8183_DAI_PCM_1,
 258                 .playback = {
 259                         .stream_name = "PCM 1 Playback",
 260                         .channels_min = 1,
 261                         .channels_max = 2,
 262                         .rates = MTK_PCM_RATES,
 263                         .formats = MTK_PCM_FORMATS,
 264                 },
 265                 .capture = {
 266                         .stream_name = "PCM 1 Capture",
 267                         .channels_min = 1,
 268                         .channels_max = 2,
 269                         .rates = MTK_PCM_RATES,
 270                         .formats = MTK_PCM_FORMATS,
 271                 },
 272                 .ops = &mtk_dai_pcm_ops,
 273                 .symmetric_rates = 1,
 274                 .symmetric_samplebits = 1,
 275         },
 276         {
 277                 .name = "PCM 2",
 278                 .id = MT8183_DAI_PCM_2,
 279                 .playback = {
 280                         .stream_name = "PCM 2 Playback",
 281                         .channels_min = 1,
 282                         .channels_max = 2,
 283                         .rates = MTK_PCM_RATES,
 284                         .formats = MTK_PCM_FORMATS,
 285                 },
 286                 .capture = {
 287                         .stream_name = "PCM 2 Capture",
 288                         .channels_min = 1,
 289                         .channels_max = 2,
 290                         .rates = MTK_PCM_RATES,
 291                         .formats = MTK_PCM_FORMATS,
 292                 },
 293                 .ops = &mtk_dai_pcm_ops,
 294                 .symmetric_rates = 1,
 295                 .symmetric_samplebits = 1,
 296         },
 297 };
 298 
 299 int mt8183_dai_pcm_register(struct mtk_base_afe *afe)
 300 {
 301         struct mtk_base_afe_dai *dai;
 302 
 303         dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
 304         if (!dai)
 305                 return -ENOMEM;
 306 
 307         list_add(&dai->list, &afe->sub_dais);
 308 
 309         dai->dai_drivers = mtk_dai_pcm_driver;
 310         dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver);
 311 
 312         dai->dapm_widgets = mtk_dai_pcm_widgets;
 313         dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets);
 314         dai->dapm_routes = mtk_dai_pcm_routes;
 315         dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes);
 316 
 317         return 0;
 318 }

/* [<][>][^][v][top][bottom][index][help] */