Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: mt8188: add new board support

Merge series from Trevor Wu <trevor.wu@mediatek.com>:

In the series, we extend the capability of mt8188-mt6359 driver.

The following changes are included.
1. Divide ADDA BE dai into two dais for SOF.
2. Register hdmi/dp jack pins.
3. dai_fmt can be configured from device tree.
4. Add some I2S codecs support.

In addition, new compatible string "mediatek,mt8188-nau8825" is
included for a new board support.

+507 -55
+23 -4
Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml
··· 11 11 12 12 properties: 13 13 compatible: 14 - const: mediatek,mt8188-mt6359-evb 14 + enum: 15 + - mediatek,mt8188-mt6359-evb 16 + - mediatek,mt8188-nau8825 15 17 16 18 model: 17 19 $ref: /schemas/types.yaml#/definitions/string ··· 44 42 we are going to update parameters in this node. 45 43 items: 46 44 enum: 47 - - ADDA_BE 48 45 - DPTX_BE 49 46 - ETDM1_IN_BE 50 47 - ETDM2_IN_BE ··· 63 62 required: 64 63 - sound-dai 65 64 65 + dai-format: 66 + description: audio format. 67 + items: 68 + enum: 69 + - i2s 70 + - right_j 71 + - left_j 72 + - dsp_a 73 + - dsp_b 74 + 75 + mediatek,clk-provider: 76 + $ref: /schemas/types.yaml#/definitions/string 77 + description: Indicates dai-link clock master. 78 + items: 79 + enum: 80 + - cpu 81 + - codec 82 + 66 83 additionalProperties: false 67 84 68 85 required: 69 86 - link-name 70 - - codec 71 87 72 88 additionalProperties: false 73 89 ··· 105 87 "AIN1", "Headset Mic"; 106 88 dai-link-0 { 107 89 link-name = "ETDM3_OUT_BE"; 108 - 90 + dai-format = "i2s"; 91 + mediatek,clk-provider = "cpu"; 109 92 codec { 110 93 sound-dai = <&hdmi0>; 111 94 };
+4
sound/soc/mediatek/Kconfig
··· 225 225 depends on SND_SOC_MT8188 && MTK_PMIC_WRAP 226 226 select SND_SOC_MT6359 227 227 select SND_SOC_HDMI_CODEC 228 + select SND_SOC_DMIC 229 + select SND_SOC_MAX98390 230 + select SND_SOC_NAU8315 231 + select SND_SOC_NAU8825 228 232 help 229 233 This adds support for ASoC machine driver for MediaTek MT8188 230 234 boards with the MT6359 and other I2S audio codecs.
+51 -2
sound/soc/mediatek/common/mtk-soundcard-driver.c
··· 21 21 int ret; 22 22 23 23 codec_node = of_get_child_by_name(sub_node, "codec"); 24 - if (!codec_node) 25 - return -EINVAL; 24 + if (!codec_node) { 25 + dev_dbg(dev, "%s no specified codec\n", dai_link->name); 26 + return 0; 27 + } 26 28 27 29 /* set card codec info */ 28 30 ret = snd_soc_of_get_dai_link_codecs(dev, codec_node, dai_link); ··· 34 32 if (ret < 0) 35 33 return dev_err_probe(dev, ret, "%s: codec dai not found\n", 36 34 dai_link->name); 35 + 36 + return 0; 37 + } 38 + 39 + static int set_dailink_daifmt(struct snd_soc_card *card, 40 + struct device_node *sub_node, 41 + struct snd_soc_dai_link *dai_link) 42 + { 43 + unsigned int daifmt; 44 + const char *str; 45 + int ret; 46 + struct { 47 + char *name; 48 + unsigned int val; 49 + } of_clk_table[] = { 50 + { "cpu", SND_SOC_DAIFMT_CBC_CFC }, 51 + { "codec", SND_SOC_DAIFMT_CBP_CFP }, 52 + }; 53 + 54 + daifmt = snd_soc_daifmt_parse_format(sub_node, NULL); 55 + if (daifmt) { 56 + dai_link->dai_fmt &= SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; 57 + dai_link->dai_fmt |= daifmt; 58 + } 59 + 60 + /* 61 + * check "mediatek,clk-provider = xxx" 62 + * SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK area 63 + */ 64 + ret = of_property_read_string(sub_node, "mediatek,clk-provider", &str); 65 + if (ret == 0) { 66 + int i; 67 + 68 + for (i = 0; i < ARRAY_SIZE(of_clk_table); i++) { 69 + if (strcmp(str, of_clk_table[i].name) == 0) { 70 + dai_link->dai_fmt &= ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; 71 + dai_link->dai_fmt |= of_clk_table[i].val; 72 + break; 73 + } 74 + } 75 + } 37 76 38 77 return 0; 39 78 } ··· 106 63 } 107 64 108 65 ret = set_card_codec_info(card, sub_node, dai_link); 66 + if (ret < 0) { 67 + of_node_put(sub_node); 68 + return ret; 69 + } 70 + 71 + ret = set_dailink_daifmt(card, sub_node, dai_link); 109 72 if (ret < 0) { 110 73 of_node_put(sub_node); 111 74 return ret;
+2 -1
sound/soc/mediatek/mt8188/mt8188-afe-common.h
··· 39 39 MT8188_AFE_MEMIF_END, 40 40 MT8188_AFE_MEMIF_NUM = (MT8188_AFE_MEMIF_END - MT8188_AFE_MEMIF_START), 41 41 MT8188_AFE_IO_START = MT8188_AFE_MEMIF_END, 42 - MT8188_AFE_IO_ADDA = MT8188_AFE_IO_START, 42 + MT8188_AFE_IO_DL_SRC = MT8188_AFE_IO_START, 43 43 MT8188_AFE_IO_DMIC_IN, 44 44 MT8188_AFE_IO_DPTX, 45 45 MT8188_AFE_IO_ETDM_START, ··· 52 52 MT8188_AFE_IO_ETDM_NUM = 53 53 (MT8188_AFE_IO_ETDM_END - MT8188_AFE_IO_ETDM_START), 54 54 MT8188_AFE_IO_PCM = MT8188_AFE_IO_ETDM_END, 55 + MT8188_AFE_IO_UL_SRC, 55 56 MT8188_AFE_IO_END, 56 57 MT8188_AFE_IO_NUM = (MT8188_AFE_IO_END - MT8188_AFE_IO_START), 57 58 MT8188_DAI_END = MT8188_AFE_IO_END,
+37 -36
sound/soc/mediatek/mt8188/mt8188-dai-adda.c
··· 53 53 }; 54 54 55 55 struct mtk_dai_adda_priv { 56 - unsigned int dl_rate; 57 - unsigned int ul_rate; 56 + bool hires_required; 58 57 }; 59 58 60 59 static unsigned int afe_adda_dl_rate_transform(struct mtk_base_afe *afe, ··· 240 241 return 0; 241 242 } 242 243 243 - static int mtk_afe_adc_hires_connect(struct snd_soc_dapm_widget *source, 244 - struct snd_soc_dapm_widget *sink) 244 + static struct mtk_dai_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe, 245 + const char *name) 245 246 { 246 - struct snd_soc_dapm_widget *w = source; 247 - struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); 248 - struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); 249 247 struct mt8188_afe_private *afe_priv = afe->platform_priv; 250 - struct mtk_dai_adda_priv *adda_priv; 251 248 252 - adda_priv = afe_priv->dai_priv[MT8188_AFE_IO_ADDA]; 253 - 254 - if (!adda_priv) { 255 - dev_err(afe->dev, "%s adda_priv == NULL", __func__); 256 - return 0; 257 - } 258 - 259 - return !!(adda_priv->ul_rate > ADDA_HIRES_THRES); 249 + if (strstr(name, "aud_adc_hires")) 250 + return afe_priv->dai_priv[MT8188_AFE_IO_UL_SRC]; 251 + else if (strstr(name, "aud_dac_hires")) 252 + return afe_priv->dai_priv[MT8188_AFE_IO_DL_SRC]; 253 + else 254 + return NULL; 260 255 } 261 256 262 - static int mtk_afe_dac_hires_connect(struct snd_soc_dapm_widget *source, 263 - struct snd_soc_dapm_widget *sink) 257 + static int mtk_afe_adda_hires_connect(struct snd_soc_dapm_widget *source, 258 + struct snd_soc_dapm_widget *sink) 264 259 { 265 260 struct snd_soc_dapm_widget *w = source; 266 261 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); 267 262 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); 268 - struct mt8188_afe_private *afe_priv = afe->platform_priv; 269 263 struct mtk_dai_adda_priv *adda_priv; 270 264 271 - adda_priv = afe_priv->dai_priv[MT8188_AFE_IO_ADDA]; 265 + adda_priv = get_adda_priv_by_name(afe, w->name); 272 266 273 267 if (!adda_priv) { 274 - dev_err(afe->dev, "%s adda_priv == NULL", __func__); 268 + dev_dbg(afe->dev, "adda_priv == NULL"); 275 269 return 0; 276 270 } 277 271 278 - return !!(adda_priv->dl_rate > ADDA_HIRES_THRES); 272 + return (adda_priv->hires_required) ? 1 : 0; 279 273 } 280 274 281 275 static const struct snd_kcontrol_new mtk_dai_adda_o176_mix[] = { ··· 353 361 {"ADDA Capture", NULL, "ADDA Capture Enable"}, 354 362 {"ADDA Capture", NULL, "ADDA_MTKAIF_CFG"}, 355 363 {"ADDA Capture", NULL, "aud_adc"}, 356 - {"ADDA Capture", NULL, "aud_adc_hires", mtk_afe_adc_hires_connect}, 364 + {"ADDA Capture", NULL, "aud_adc_hires", mtk_afe_adda_hires_connect}, 357 365 358 366 {"I168", NULL, "ADDA Capture"}, 359 367 {"I169", NULL, "ADDA Capture"}, ··· 361 369 {"ADDA Playback", NULL, "ADDA Enable"}, 362 370 {"ADDA Playback", NULL, "ADDA Playback Enable"}, 363 371 {"ADDA Playback", NULL, "aud_dac"}, 364 - {"ADDA Playback", NULL, "aud_dac_hires", mtk_afe_dac_hires_connect}, 372 + {"ADDA Playback", NULL, "aud_dac_hires", mtk_afe_adda_hires_connect}, 365 373 366 374 {"DL_GAIN", NULL, "O176"}, 367 375 {"DL_GAIN", NULL, "O177"}, ··· 495 503 dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %u\n", 496 504 __func__, id, substream->stream, rate); 497 505 498 - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 499 - adda_priv->dl_rate = rate; 506 + adda_priv->hires_required = (rate > ADDA_HIRES_THRES); 507 + 508 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 500 509 ret = mtk_dai_da_configure(afe, rate, id); 501 - } else { 502 - adda_priv->ul_rate = rate; 510 + else 503 511 ret = mtk_dai_ad_configure(afe, rate, id); 504 - } 505 512 506 513 return ret; 507 514 } ··· 527 536 528 537 static struct snd_soc_dai_driver mtk_dai_adda_driver[] = { 529 538 { 530 - .name = "ADDA", 531 - .id = MT8188_AFE_IO_ADDA, 539 + .name = "DL_SRC", 540 + .id = MT8188_AFE_IO_DL_SRC, 532 541 .playback = { 533 542 .stream_name = "ADDA Playback", 534 543 .channels_min = 1, ··· 536 545 .rates = MTK_ADDA_PLAYBACK_RATES, 537 546 .formats = MTK_ADDA_FORMATS, 538 547 }, 548 + .ops = &mtk_dai_adda_ops, 549 + }, 550 + { 551 + .name = "UL_SRC", 552 + .id = MT8188_AFE_IO_UL_SRC, 539 553 .capture = { 540 554 .stream_name = "ADDA Capture", 541 555 .channels_min = 1, ··· 556 560 { 557 561 struct mt8188_afe_private *afe_priv = afe->platform_priv; 558 562 struct mtk_dai_adda_priv *adda_priv; 563 + int adda_dai_list[] = {MT8188_AFE_IO_DL_SRC, MT8188_AFE_IO_UL_SRC}; 564 + int i; 559 565 560 - adda_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_adda_priv), 561 - GFP_KERNEL); 562 - if (!adda_priv) 563 - return -ENOMEM; 566 + for (i = 0; i < ARRAY_SIZE(adda_dai_list); i++) { 567 + adda_priv = devm_kzalloc(afe->dev, 568 + sizeof(struct mtk_dai_adda_priv), 569 + GFP_KERNEL); 570 + if (!adda_priv) 571 + return -ENOMEM; 564 572 565 - afe_priv->dai_priv[MT8188_AFE_IO_ADDA] = adda_priv; 573 + afe_priv->dai_priv[adda_dai_list[i]] = adda_priv; 574 + } 566 575 567 576 return 0; 568 577 }
+374 -12
sound/soc/mediatek/mt8188/mt8188-mt6359.c
··· 6 6 * Author: Trevor Wu <trevor.wu@mediatek.com> 7 7 */ 8 8 9 + #include <linux/input.h> 9 10 #include <linux/module.h> 10 11 #include <linux/of_device.h> 11 12 #include <linux/pm_runtime.h> ··· 14 13 #include <sound/pcm_params.h> 15 14 #include <sound/soc.h> 16 15 #include "mt8188-afe-common.h" 16 + #include "../../codecs/nau8825.h" 17 17 #include "../../codecs/mt6359.h" 18 18 #include "../common/mtk-afe-platform-driver.h" 19 19 #include "../common/mtk-soundcard-driver.h" 20 + 21 + #define NAU8825_HS_PRESENT BIT(0) 22 + 23 + /* 24 + * Maxim MAX98390 25 + */ 26 + #define MAX98390_CODEC_DAI "max98390-aif1" 27 + #define MAX98390_DEV0_NAME "max98390.0-0038" /* rear right */ 28 + #define MAX98390_DEV1_NAME "max98390.0-0039" /* rear left */ 29 + #define MAX98390_DEV2_NAME "max98390.0-003a" /* front right */ 30 + #define MAX98390_DEV3_NAME "max98390.0-003b" /* front left */ 31 + 32 + /* 33 + * Nau88l25 34 + */ 35 + #define NAU8825_CODEC_DAI "nau8825-hifi" 20 36 21 37 /* FE */ 22 38 SND_SOC_DAILINK_DEFS(playback2, ··· 117 99 DAILINK_COMP_ARRAY(COMP_EMPTY())); 118 100 119 101 /* BE */ 120 - SND_SOC_DAILINK_DEFS(adda, 121 - DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), 102 + SND_SOC_DAILINK_DEFS(dl_src, 103 + DAILINK_COMP_ARRAY(COMP_CPU("DL_SRC")), 122 104 DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound", 123 105 "mt6359-snd-codec-aif1")), 124 106 DAILINK_COMP_ARRAY(COMP_EMPTY())); ··· 158 140 DAILINK_COMP_ARRAY(COMP_DUMMY()), 159 141 DAILINK_COMP_ARRAY(COMP_EMPTY())); 160 142 143 + SND_SOC_DAILINK_DEFS(ul_src, 144 + DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC")), 145 + DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound", 146 + "mt6359-snd-codec-aif1"), 147 + COMP_CODEC("dmic-codec", 148 + "dmic-hifi")), 149 + DAILINK_COMP_ARRAY(COMP_EMPTY())); 150 + 161 151 struct mt8188_mt6359_priv { 162 152 struct snd_soc_jack dp_jack; 163 153 struct snd_soc_jack hdmi_jack; 154 + struct snd_soc_jack headset_jack; 155 + void *private_data; 156 + }; 157 + 158 + static struct snd_soc_jack_pin mt8188_hdmi_jack_pins[] = { 159 + { 160 + .pin = "HDMI", 161 + .mask = SND_JACK_LINEOUT, 162 + }, 163 + }; 164 + 165 + static struct snd_soc_jack_pin mt8188_dp_jack_pins[] = { 166 + { 167 + .pin = "DP", 168 + .mask = SND_JACK_LINEOUT, 169 + }, 170 + }; 171 + 172 + static struct snd_soc_jack_pin nau8825_jack_pins[] = { 173 + { 174 + .pin = "Headphone Jack", 175 + .mask = SND_JACK_HEADPHONE, 176 + }, 177 + { 178 + .pin = "Headset Mic", 179 + .mask = SND_JACK_MICROPHONE, 180 + }, 164 181 }; 165 182 166 183 struct mt8188_card_data { ··· 203 150 unsigned long quirk; 204 151 }; 205 152 153 + static const struct snd_kcontrol_new mt8188_dumb_spk_controls[] = { 154 + SOC_DAPM_PIN_SWITCH("Ext Spk"), 155 + }; 156 + 157 + static const struct snd_soc_dapm_widget mt8188_dumb_spk_widgets[] = { 158 + SND_SOC_DAPM_SPK("Ext Spk", NULL), 159 + }; 160 + 161 + static const struct snd_kcontrol_new mt8188_dual_spk_controls[] = { 162 + SOC_DAPM_PIN_SWITCH("Left Spk"), 163 + SOC_DAPM_PIN_SWITCH("Right Spk"), 164 + }; 165 + 166 + static const struct snd_soc_dapm_widget mt8188_dual_spk_widgets[] = { 167 + SND_SOC_DAPM_SPK("Left Spk", NULL), 168 + SND_SOC_DAPM_SPK("Right Spk", NULL), 169 + }; 170 + 171 + static const struct snd_kcontrol_new mt8188_rear_spk_controls[] = { 172 + SOC_DAPM_PIN_SWITCH("Rear Left Spk"), 173 + SOC_DAPM_PIN_SWITCH("Rear Right Spk"), 174 + }; 175 + 176 + static const struct snd_soc_dapm_widget mt8188_rear_spk_widgets[] = { 177 + SND_SOC_DAPM_SPK("Rear Left Spk", NULL), 178 + SND_SOC_DAPM_SPK("Rear Right Spk", NULL), 179 + }; 180 + 206 181 static const struct snd_soc_dapm_widget mt8188_mt6359_widgets[] = { 207 182 SND_SOC_DAPM_HP("Headphone", NULL), 208 183 SND_SOC_DAPM_MIC("Headset Mic", NULL), 184 + SND_SOC_DAPM_SINK("HDMI"), 185 + SND_SOC_DAPM_SINK("DP"), 209 186 }; 210 187 211 188 static const struct snd_kcontrol_new mt8188_mt6359_controls[] = { 212 189 SOC_DAPM_PIN_SWITCH("Headphone"), 213 190 SOC_DAPM_PIN_SWITCH("Headset Mic"), 191 + }; 192 + 193 + static const struct snd_soc_dapm_widget mt8188_nau8825_widgets[] = { 194 + SND_SOC_DAPM_HP("Headphone Jack", NULL), 195 + }; 196 + 197 + static const struct snd_kcontrol_new mt8188_nau8825_controls[] = { 198 + SOC_DAPM_PIN_SWITCH("Headphone Jack"), 214 199 }; 215 200 216 201 #define CKSYS_AUD_TOP_CFG 0x032c ··· 436 345 DAI_LINK_UL8_FE, 437 346 DAI_LINK_UL9_FE, 438 347 DAI_LINK_UL10_FE, 439 - DAI_LINK_ADDA_BE, 348 + DAI_LINK_DL_SRC_BE, 440 349 DAI_LINK_DPTX_BE, 441 350 DAI_LINK_ETDM1_IN_BE, 442 351 DAI_LINK_ETDM2_IN_BE, ··· 444 353 DAI_LINK_ETDM2_OUT_BE, 445 354 DAI_LINK_ETDM3_OUT_BE, 446 355 DAI_LINK_PCM1_BE, 356 + DAI_LINK_UL_SRC_BE, 447 357 }; 448 358 449 359 static int mt8188_dptx_hw_params(struct snd_pcm_substream *substream, ··· 481 389 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 482 390 int ret = 0; 483 391 484 - ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, 485 - &priv->hdmi_jack); 392 + ret = snd_soc_card_jack_new_pins(rtd->card, "HDMI Jack", 393 + SND_JACK_LINEOUT, &priv->hdmi_jack, 394 + mt8188_hdmi_jack_pins, 395 + ARRAY_SIZE(mt8188_hdmi_jack_pins)); 486 396 if (ret) { 487 397 dev_info(rtd->dev, "%s, new jack failed: %d\n", __func__, ret); 488 398 return ret; ··· 504 410 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 505 411 int ret = 0; 506 412 507 - ret = snd_soc_card_jack_new(rtd->card, "DP Jack", SND_JACK_LINEOUT, 508 - &priv->dp_jack); 413 + ret = snd_soc_card_jack_new_pins(rtd->card, "DP Jack", SND_JACK_LINEOUT, 414 + &priv->dp_jack, mt8188_dp_jack_pins, 415 + ARRAY_SIZE(mt8188_dp_jack_pins)); 509 416 if (ret) { 510 417 dev_info(rtd->dev, "%s, new jack failed: %d\n", __func__, ret); 511 418 return ret; ··· 520 425 return ret; 521 426 } 522 427 428 + static int mt8188_dumb_amp_init(struct snd_soc_pcm_runtime *rtd) 429 + { 430 + struct snd_soc_card *card = rtd->card; 431 + int ret = 0; 432 + 433 + ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_dumb_spk_widgets, 434 + ARRAY_SIZE(mt8188_dumb_spk_widgets)); 435 + if (ret) { 436 + dev_err(rtd->dev, "unable to add Dumb Speaker dapm, ret %d\n", ret); 437 + return ret; 438 + } 439 + 440 + ret = snd_soc_add_card_controls(card, mt8188_dumb_spk_controls, 441 + ARRAY_SIZE(mt8188_dumb_spk_controls)); 442 + if (ret) { 443 + dev_err(rtd->dev, "unable to add Dumb card controls, ret %d\n", ret); 444 + return ret; 445 + } 446 + 447 + return ret; 448 + } 449 + 450 + static int mt8188_max98390_hw_params(struct snd_pcm_substream *substream, 451 + struct snd_pcm_hw_params *params) 452 + { 453 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 454 + unsigned int bit_width = params_width(params); 455 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 456 + struct snd_soc_dai *codec_dai; 457 + int i; 458 + 459 + snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0xf, 4, bit_width); 460 + 461 + for_each_rtd_codec_dais(rtd, i, codec_dai) { 462 + if (!strcmp(codec_dai->component->name, MAX98390_DEV0_NAME)) 463 + snd_soc_dai_set_tdm_slot(codec_dai, 0x8, 0x3, 4, bit_width); 464 + 465 + if (!strcmp(codec_dai->component->name, MAX98390_DEV1_NAME)) 466 + snd_soc_dai_set_tdm_slot(codec_dai, 0x4, 0x3, 4, bit_width); 467 + 468 + if (!strcmp(codec_dai->component->name, MAX98390_DEV2_NAME)) 469 + snd_soc_dai_set_tdm_slot(codec_dai, 0x2, 0x3, 4, bit_width); 470 + 471 + if (!strcmp(codec_dai->component->name, MAX98390_DEV3_NAME)) 472 + snd_soc_dai_set_tdm_slot(codec_dai, 0x1, 0x3, 4, bit_width); 473 + } 474 + return 0; 475 + } 476 + 477 + static const struct snd_soc_ops mt8188_max98390_ops = { 478 + .hw_params = mt8188_max98390_hw_params, 479 + }; 480 + 481 + static int mt8188_max98390_codec_init(struct snd_soc_pcm_runtime *rtd) 482 + { 483 + struct snd_soc_card *card = rtd->card; 484 + int ret; 485 + 486 + /* add regular speakers dapm route */ 487 + ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_dual_spk_widgets, 488 + ARRAY_SIZE(mt8188_dual_spk_widgets)); 489 + if (ret) { 490 + dev_err(rtd->dev, "unable to add Left/Right Speaker widget, ret %d\n", ret); 491 + return ret; 492 + } 493 + 494 + ret = snd_soc_add_card_controls(card, mt8188_dual_spk_controls, 495 + ARRAY_SIZE(mt8188_dual_spk_controls)); 496 + if (ret) { 497 + dev_err(rtd->dev, "unable to add Left/Right card controls, ret %d\n", ret); 498 + return ret; 499 + } 500 + 501 + if (rtd->dai_link->num_codecs <= 2) 502 + return ret; 503 + 504 + /* add widgets/controls/dapm for rear speakers */ 505 + ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_rear_spk_widgets, 506 + ARRAY_SIZE(mt8188_rear_spk_widgets)); 507 + if (ret) { 508 + dev_err(rtd->dev, "unable to add Rear Speaker widget, ret %d\n", ret); 509 + /* Don't need to add routes if widget addition failed */ 510 + return ret; 511 + } 512 + 513 + ret = snd_soc_add_card_controls(card, mt8188_rear_spk_controls, 514 + ARRAY_SIZE(mt8188_rear_spk_controls)); 515 + if (ret) { 516 + dev_err(rtd->dev, "unable to add Rear card controls, ret %d\n", ret); 517 + return ret; 518 + } 519 + 520 + return ret; 521 + } 522 + 523 + static int mt8188_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) 524 + { 525 + struct snd_soc_card *card = rtd->card; 526 + struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(card); 527 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 528 + struct snd_soc_jack *jack = &priv->headset_jack; 529 + int ret; 530 + 531 + ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_nau8825_widgets, 532 + ARRAY_SIZE(mt8188_nau8825_widgets)); 533 + if (ret) { 534 + dev_err(rtd->dev, "unable to add nau8825 card widget, ret %d\n", ret); 535 + return ret; 536 + } 537 + 538 + ret = snd_soc_add_card_controls(card, mt8188_nau8825_controls, 539 + ARRAY_SIZE(mt8188_nau8825_controls)); 540 + if (ret) { 541 + dev_err(rtd->dev, "unable to add nau8825 card controls, ret %d\n", ret); 542 + return ret; 543 + } 544 + 545 + ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", 546 + SND_JACK_HEADSET | SND_JACK_BTN_0 | 547 + SND_JACK_BTN_1 | SND_JACK_BTN_2 | 548 + SND_JACK_BTN_3, 549 + jack, 550 + nau8825_jack_pins, 551 + ARRAY_SIZE(nau8825_jack_pins)); 552 + if (ret) { 553 + dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); 554 + return ret; 555 + } 556 + 557 + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 558 + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); 559 + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); 560 + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); 561 + ret = snd_soc_component_set_jack(component, jack, NULL); 562 + 563 + if (ret) { 564 + dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); 565 + return ret; 566 + } 567 + 568 + return ret; 569 + }; 570 + 571 + static void mt8188_nau8825_codec_exit(struct snd_soc_pcm_runtime *rtd) 572 + { 573 + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 574 + 575 + snd_soc_component_set_jack(component, NULL, NULL); 576 + } 577 + 578 + static int mt8188_nau8825_hw_params(struct snd_pcm_substream *substream, 579 + struct snd_pcm_hw_params *params) 580 + { 581 + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 582 + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 583 + unsigned int rate = params_rate(params); 584 + unsigned int bit_width = params_width(params); 585 + int clk_freq, ret; 586 + 587 + clk_freq = rate * 2 * bit_width; 588 + 589 + /* Configure clock for codec */ 590 + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_BLK, 0, 591 + SND_SOC_CLOCK_IN); 592 + if (ret < 0) { 593 + dev_err(codec_dai->dev, "can't set BCLK clock %d\n", ret); 594 + return ret; 595 + } 596 + 597 + /* Configure pll for codec */ 598 + ret = snd_soc_dai_set_pll(codec_dai, 0, 0, clk_freq, 599 + params_rate(params) * 256); 600 + if (ret < 0) { 601 + dev_err(codec_dai->dev, "can't set BCLK: %d\n", ret); 602 + return ret; 603 + } 604 + 605 + return ret; 606 + } 607 + 608 + static const struct snd_soc_ops mt8188_nau8825_ops = { 609 + .hw_params = mt8188_nau8825_hw_params, 610 + }; 523 611 static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = { 524 612 /* FE */ 525 613 [DAI_LINK_DL2_FE] = { ··· 882 604 SND_SOC_DAILINK_REG(capture10), 883 605 }, 884 606 /* BE */ 885 - [DAI_LINK_ADDA_BE] = { 886 - .name = "ADDA_BE", 607 + [DAI_LINK_DL_SRC_BE] = { 608 + .name = "DL_SRC_BE", 887 609 .no_pcm = 1, 888 610 .dpcm_playback = 1, 889 - .dpcm_capture = 1, 890 - .init = mt8188_mt6359_init, 891 - SND_SOC_DAILINK_REG(adda), 611 + SND_SOC_DAILINK_REG(dl_src), 892 612 }, 893 613 [DAI_LINK_DPTX_BE] = { 894 614 .name = "DPTX_BE", ··· 952 676 .dpcm_capture = 1, 953 677 SND_SOC_DAILINK_REG(pcm1), 954 678 }, 679 + [DAI_LINK_UL_SRC_BE] = { 680 + .name = "UL_SRC_BE", 681 + .no_pcm = 1, 682 + .dpcm_capture = 1, 683 + SND_SOC_DAILINK_REG(ul_src), 684 + }, 955 685 }; 686 + 687 + static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name) 688 + { 689 + struct snd_ctl_elem_id sid; 690 + 691 + memset(&sid, 0, sizeof(sid)); 692 + strcpy(sid.name, name); 693 + sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 694 + return snd_ctl_find_id(card, &sid); 695 + } 696 + 697 + static void mt8188_fixup_controls(struct snd_soc_card *card) 698 + { 699 + struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(card); 700 + struct mt8188_card_data *card_data = (struct mt8188_card_data *)priv->private_data; 701 + struct snd_kcontrol *kctl; 702 + 703 + if (card_data->quirk & NAU8825_HS_PRESENT) { 704 + struct snd_soc_dapm_widget *w, *next_w; 705 + 706 + for_each_card_widgets_safe(card, w, next_w) { 707 + if (strcmp(w->name, "Headphone")) 708 + continue; 709 + 710 + snd_soc_dapm_free_widget(w); 711 + } 712 + 713 + kctl = ctl_find(card->snd_card, "Headphone Switch"); 714 + if (kctl) 715 + snd_ctl_remove(card->snd_card, kctl); 716 + else 717 + dev_warn(card->dev, "Cannot find ctl : Headphone Switch\n"); 718 + } 719 + } 956 720 957 721 static struct snd_soc_card mt8188_mt6359_soc_card = { 958 722 .owner = THIS_MODULE, ··· 1002 686 .num_dapm_widgets = ARRAY_SIZE(mt8188_mt6359_widgets), 1003 687 .controls = mt8188_mt6359_controls, 1004 688 .num_controls = ARRAY_SIZE(mt8188_mt6359_controls), 689 + .fixup_controls = mt8188_fixup_controls, 1005 690 }; 1006 691 1007 692 static int mt8188_mt6359_dev_probe(struct platform_device *pdev) ··· 1012 695 struct mt8188_mt6359_priv *priv; 1013 696 struct mt8188_card_data *card_data; 1014 697 struct snd_soc_dai_link *dai_link; 698 + bool init_mt6359 = false; 699 + bool init_nau8825 = false; 700 + bool init_max98390 = false; 701 + bool init_dumb = false; 1015 702 int ret, i; 1016 703 1017 704 card_data = (struct mt8188_card_data *)of_device_get_match_data(&pdev->dev); ··· 1060 739 } else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) { 1061 740 if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) 1062 741 dai_link->init = mt8188_hdmi_codec_init; 742 + } else if (strcmp(dai_link->name, "DL_SRC_BE") == 0 || 743 + strcmp(dai_link->name, "UL_SRC_BE") == 0) { 744 + if (!init_mt6359) { 745 + dai_link->init = mt8188_mt6359_init; 746 + init_mt6359 = true; 747 + } 748 + } else if (strcmp(dai_link->name, "ETDM1_OUT_BE") == 0 || 749 + strcmp(dai_link->name, "ETDM2_OUT_BE") == 0 || 750 + strcmp(dai_link->name, "ETDM1_IN_BE") == 0 || 751 + strcmp(dai_link->name, "ETDM2_IN_BE") == 0) { 752 + if (!strcmp(dai_link->codecs->dai_name, MAX98390_CODEC_DAI)) { 753 + dai_link->ops = &mt8188_max98390_ops; 754 + if (!init_max98390) { 755 + dai_link->init = mt8188_max98390_codec_init; 756 + init_max98390 = true; 757 + } 758 + } else if (!strcmp(dai_link->codecs->dai_name, NAU8825_CODEC_DAI)) { 759 + dai_link->ops = &mt8188_nau8825_ops; 760 + if (!init_nau8825) { 761 + dai_link->init = mt8188_nau8825_codec_init; 762 + dai_link->exit = mt8188_nau8825_codec_exit; 763 + init_nau8825 = true; 764 + } 765 + } else { 766 + if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) { 767 + if (!init_dumb) { 768 + dai_link->init = mt8188_dumb_amp_init; 769 + init_dumb = true; 770 + } 771 + } 772 + } 1063 773 } 1064 774 } 1065 775 776 + priv->private_data = card_data; 1066 777 snd_soc_card_set_drvdata(card, priv); 1067 778 1068 779 ret = devm_snd_soc_register_card(&pdev->dev, card); ··· 1111 758 .name = "mt8188_mt6359", 1112 759 }; 1113 760 761 + static struct mt8188_card_data mt8188_nau8825_card = { 762 + .name = "mt8188_nau8825", 763 + .quirk = NAU8825_HS_PRESENT, 764 + }; 765 + 1114 766 static const struct of_device_id mt8188_mt6359_dt_match[] = { 1115 767 { 1116 768 .compatible = "mediatek,mt8188-mt6359-evb", 1117 769 .data = &mt8188_evb_card, 770 + }, 771 + { 772 + .compatible = "mediatek,mt8188-nau8825", 773 + .data = &mt8188_nau8825_card, 1118 774 }, 1119 775 {}, 1120 776 };
+16
sound/soc/soc-dapm.c
··· 2216 2216 &dapm_widget_power_fops); 2217 2217 } 2218 2218 2219 + static void dapm_debugfs_free_widget(struct snd_soc_dapm_widget *w) 2220 + { 2221 + struct snd_soc_dapm_context *dapm = w->dapm; 2222 + 2223 + if (!dapm->debugfs_dapm || !w->name) 2224 + return; 2225 + 2226 + debugfs_lookup_and_remove(w->name, dapm->debugfs_dapm); 2227 + } 2228 + 2219 2229 static void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm) 2220 2230 { 2221 2231 debugfs_remove_recursive(dapm->debugfs_dapm); ··· 2239 2229 } 2240 2230 2241 2231 static inline void dapm_debugfs_add_widget(struct snd_soc_dapm_widget *w) 2232 + { 2233 + } 2234 + 2235 + static inline void dapm_debugfs_free_widget(struct snd_soc_dapm_widget *w) 2242 2236 { 2243 2237 } 2244 2238 ··· 2508 2494 snd_soc_dapm_widget_for_each_path_safe(w, dir, p, next_p) 2509 2495 dapm_free_path(p); 2510 2496 } 2497 + 2498 + dapm_debugfs_free_widget(w); 2511 2499 2512 2500 kfree(w->kcontrols); 2513 2501 kfree_const(w->name);