diff options
| -rw-r--r-- | Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5514.txt | 15 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/sound/mt8173-rt5650.txt | 15 | ||||
| -rw-r--r-- | sound/soc/codecs/max98926.c | 4 | ||||
| -rw-r--r-- | sound/soc/codecs/nau8825.c | 169 | ||||
| -rw-r--r-- | sound/soc/codecs/nau8825.h | 16 | ||||
| -rw-r--r-- | sound/soc/mediatek/Kconfig | 22 | ||||
| -rw-r--r-- | sound/soc/mediatek/Makefile | 2 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8173-rt5650-rt5514.c | 258 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8173-rt5650-rt5676.c | 18 | ||||
| -rw-r--r-- | sound/soc/mediatek/mt8173-rt5650.c | 236 | ||||
| -rw-r--r-- | sound/soc/mediatek/mtk-afe-common.h | 1 | ||||
| -rw-r--r-- | sound/soc/mediatek/mtk-afe-pcm.c | 47 | ||||
| -rw-r--r-- | sound/soc/mxs/mxs-saif.c | 2 | ||||
| -rw-r--r-- | sound/soc/omap/omap-hdmi-audio.c | 1 |
14 files changed, 744 insertions, 62 deletions
diff --git a/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5514.txt b/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5514.txt new file mode 100644 index 000000000000..e8b3c80c6fff --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5514.txt | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | MT8173 with RT5650 RT5514 CODECS | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : "mediatek,mt8173-rt5650-rt5514" | ||
| 5 | - mediatek,audio-codec: the phandles of rt5650 and rt5514 codecs | ||
| 6 | - mediatek,platform: the phandle of MT8173 ASoC platform | ||
| 7 | |||
| 8 | Example: | ||
| 9 | |||
| 10 | sound { | ||
| 11 | compatible = "mediatek,mt8173-rt5650-rt5514"; | ||
| 12 | mediatek,audio-codec = <&rt5650 &rt5514>; | ||
| 13 | mediatek,platform = <&afe>; | ||
| 14 | }; | ||
| 15 | |||
diff --git a/Documentation/devicetree/bindings/sound/mt8173-rt5650.txt b/Documentation/devicetree/bindings/sound/mt8173-rt5650.txt new file mode 100644 index 000000000000..fe5a5ef1714d --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mt8173-rt5650.txt | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | MT8173 with RT5650 CODECS | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : "mediatek,mt8173-rt5650" | ||
| 5 | - mediatek,audio-codec: the phandles of rt5650 codecs | ||
| 6 | - mediatek,platform: the phandle of MT8173 ASoC platform | ||
| 7 | |||
| 8 | Example: | ||
| 9 | |||
| 10 | sound { | ||
| 11 | compatible = "mediatek,mt8173-rt5650"; | ||
| 12 | mediatek,audio-codec = <&rt5650>; | ||
| 13 | mediatek,platform = <&afe>; | ||
| 14 | }; | ||
| 15 | |||
diff --git a/sound/soc/codecs/max98926.c b/sound/soc/codecs/max98926.c index 5245e107de30..8d14adae5cc5 100644 --- a/sound/soc/codecs/max98926.c +++ b/sound/soc/codecs/max98926.c | |||
| @@ -40,7 +40,7 @@ static const char *const max98926_hpf_cutoff_txt[] = { | |||
| 40 | "200Hz", "400Hz", "800Hz", | 40 | "200Hz", "400Hz", "800Hz", |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | static struct reg_default max98926_reg[] = { | 43 | static const struct reg_default max98926_reg[] = { |
| 44 | { 0x0B, 0x00 }, /* IRQ Enable0 */ | 44 | { 0x0B, 0x00 }, /* IRQ Enable0 */ |
| 45 | { 0x0C, 0x00 }, /* IRQ Enable1 */ | 45 | { 0x0C, 0x00 }, /* IRQ Enable1 */ |
| 46 | { 0x0D, 0x00 }, /* IRQ Enable2 */ | 46 | { 0x0D, 0x00 }, /* IRQ Enable2 */ |
| @@ -506,7 +506,7 @@ static struct snd_soc_codec_driver soc_codec_dev_max98926 = { | |||
| 506 | .num_dapm_widgets = ARRAY_SIZE(max98926_dapm_widgets), | 506 | .num_dapm_widgets = ARRAY_SIZE(max98926_dapm_widgets), |
| 507 | }; | 507 | }; |
| 508 | 508 | ||
| 509 | static struct regmap_config max98926_regmap = { | 509 | static const struct regmap_config max98926_regmap = { |
| 510 | .reg_bits = 8, | 510 | .reg_bits = 8, |
| 511 | .val_bits = 8, | 511 | .val_bits = 8, |
| 512 | .max_register = MAX98926_VERSION, | 512 | .max_register = MAX98926_VERSION, |
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index c1b87c5800b1..1c8729984c2b 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c | |||
| @@ -84,6 +84,7 @@ static const struct nau8825_fll_attr fll_pre_scalar[] = { | |||
| 84 | 84 | ||
| 85 | static const struct reg_default nau8825_reg_defaults[] = { | 85 | static const struct reg_default nau8825_reg_defaults[] = { |
| 86 | { NAU8825_REG_ENA_CTRL, 0x00ff }, | 86 | { NAU8825_REG_ENA_CTRL, 0x00ff }, |
| 87 | { NAU8825_REG_IIC_ADDR_SET, 0x0 }, | ||
| 87 | { NAU8825_REG_CLK_DIVIDER, 0x0050 }, | 88 | { NAU8825_REG_CLK_DIVIDER, 0x0050 }, |
| 88 | { NAU8825_REG_FLL1, 0x0 }, | 89 | { NAU8825_REG_FLL1, 0x0 }, |
| 89 | { NAU8825_REG_FLL2, 0x3126 }, | 90 | { NAU8825_REG_FLL2, 0x3126 }, |
| @@ -158,8 +159,7 @@ static const struct reg_default nau8825_reg_defaults[] = { | |||
| 158 | static bool nau8825_readable_reg(struct device *dev, unsigned int reg) | 159 | static bool nau8825_readable_reg(struct device *dev, unsigned int reg) |
| 159 | { | 160 | { |
| 160 | switch (reg) { | 161 | switch (reg) { |
| 161 | case NAU8825_REG_ENA_CTRL: | 162 | case NAU8825_REG_ENA_CTRL ... NAU8825_REG_FLL_VCO_RSV: |
| 162 | case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV: | ||
| 163 | case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL: | 163 | case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL: |
| 164 | case NAU8825_REG_INTERRUPT_MASK ... NAU8825_REG_KEYDET_CTRL: | 164 | case NAU8825_REG_INTERRUPT_MASK ... NAU8825_REG_KEYDET_CTRL: |
| 165 | case NAU8825_REG_VDET_THRESHOLD_1 ... NAU8825_REG_DACR_CTRL: | 165 | case NAU8825_REG_VDET_THRESHOLD_1 ... NAU8825_REG_DACR_CTRL: |
| @@ -184,8 +184,7 @@ static bool nau8825_readable_reg(struct device *dev, unsigned int reg) | |||
| 184 | static bool nau8825_writeable_reg(struct device *dev, unsigned int reg) | 184 | static bool nau8825_writeable_reg(struct device *dev, unsigned int reg) |
| 185 | { | 185 | { |
| 186 | switch (reg) { | 186 | switch (reg) { |
| 187 | case NAU8825_REG_RESET ... NAU8825_REG_ENA_CTRL: | 187 | case NAU8825_REG_RESET ... NAU8825_REG_FLL_VCO_RSV: |
| 188 | case NAU8825_REG_CLK_DIVIDER ... NAU8825_REG_FLL_VCO_RSV: | ||
| 189 | case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL: | 188 | case NAU8825_REG_HSD_CTRL ... NAU8825_REG_JACK_DET_CTRL: |
| 190 | case NAU8825_REG_INTERRUPT_MASK: | 189 | case NAU8825_REG_INTERRUPT_MASK: |
| 191 | case NAU8825_REG_INT_CLR_KEY_STATUS ... NAU8825_REG_KEYDET_CTRL: | 190 | case NAU8825_REG_INT_CLR_KEY_STATUS ... NAU8825_REG_KEYDET_CTRL: |
| @@ -227,10 +226,42 @@ static bool nau8825_volatile_reg(struct device *dev, unsigned int reg) | |||
| 227 | static int nau8825_pump_event(struct snd_soc_dapm_widget *w, | 226 | static int nau8825_pump_event(struct snd_soc_dapm_widget *w, |
| 228 | struct snd_kcontrol *kcontrol, int event) | 227 | struct snd_kcontrol *kcontrol, int event) |
| 229 | { | 228 | { |
| 229 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
| 230 | struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); | ||
| 231 | |||
| 230 | switch (event) { | 232 | switch (event) { |
| 231 | case SND_SOC_DAPM_POST_PMU: | 233 | case SND_SOC_DAPM_POST_PMU: |
| 232 | /* Prevent startup click by letting charge pump to ramp up */ | 234 | /* Prevent startup click by letting charge pump to ramp up */ |
| 233 | msleep(10); | 235 | msleep(10); |
| 236 | regmap_update_bits(nau8825->regmap, NAU8825_REG_CHARGE_PUMP, | ||
| 237 | NAU8825_JAMNODCLOW, NAU8825_JAMNODCLOW); | ||
| 238 | break; | ||
| 239 | case SND_SOC_DAPM_PRE_PMD: | ||
| 240 | regmap_update_bits(nau8825->regmap, NAU8825_REG_CHARGE_PUMP, | ||
| 241 | NAU8825_JAMNODCLOW, 0); | ||
| 242 | break; | ||
| 243 | default: | ||
| 244 | return -EINVAL; | ||
| 245 | } | ||
| 246 | |||
| 247 | return 0; | ||
| 248 | } | ||
| 249 | |||
| 250 | static int nau8825_output_dac_event(struct snd_soc_dapm_widget *w, | ||
| 251 | struct snd_kcontrol *kcontrol, int event) | ||
| 252 | { | ||
| 253 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); | ||
| 254 | struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); | ||
| 255 | |||
| 256 | switch (event) { | ||
| 257 | case SND_SOC_DAPM_PRE_PMU: | ||
| 258 | /* Disables the TESTDAC to let DAC signal pass through. */ | ||
| 259 | regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, | ||
| 260 | NAU8825_BIAS_TESTDAC_EN, 0); | ||
| 261 | break; | ||
| 262 | case SND_SOC_DAPM_POST_PMD: | ||
| 263 | regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, | ||
| 264 | NAU8825_BIAS_TESTDAC_EN, NAU8825_BIAS_TESTDAC_EN); | ||
| 234 | break; | 265 | break; |
| 235 | default: | 266 | default: |
| 236 | return -EINVAL; | 267 | return -EINVAL; |
| @@ -316,10 +347,10 @@ static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = { | |||
| 316 | SND_SOC_DAPM_ADC("SAR", NULL, NAU8825_REG_SAR_CTRL, | 347 | SND_SOC_DAPM_ADC("SAR", NULL, NAU8825_REG_SAR_CTRL, |
| 317 | NAU8825_SAR_ADC_EN_SFT, 0), | 348 | NAU8825_SAR_ADC_EN_SFT, 0), |
| 318 | 349 | ||
| 319 | SND_SOC_DAPM_DAC("ADACL", NULL, NAU8825_REG_RDAC, 12, 0), | 350 | SND_SOC_DAPM_PGA_S("ADACL", 2, NAU8825_REG_RDAC, 12, 0, NULL, 0), |
| 320 | SND_SOC_DAPM_DAC("ADACR", NULL, NAU8825_REG_RDAC, 13, 0), | 351 | SND_SOC_DAPM_PGA_S("ADACR", 2, NAU8825_REG_RDAC, 13, 0, NULL, 0), |
| 321 | SND_SOC_DAPM_SUPPLY("ADACL Clock", NAU8825_REG_RDAC, 8, 0, NULL, 0), | 352 | SND_SOC_DAPM_PGA_S("ADACL Clock", 3, NAU8825_REG_RDAC, 8, 0, NULL, 0), |
| 322 | SND_SOC_DAPM_SUPPLY("ADACR Clock", NAU8825_REG_RDAC, 9, 0, NULL, 0), | 353 | SND_SOC_DAPM_PGA_S("ADACR Clock", 3, NAU8825_REG_RDAC, 9, 0, NULL, 0), |
| 323 | 354 | ||
| 324 | SND_SOC_DAPM_DAC("DDACR", NULL, NAU8825_REG_ENA_CTRL, | 355 | SND_SOC_DAPM_DAC("DDACR", NULL, NAU8825_REG_ENA_CTRL, |
| 325 | NAU8825_ENABLE_DACR_SFT, 0), | 356 | NAU8825_ENABLE_DACR_SFT, 0), |
| @@ -330,29 +361,48 @@ static const struct snd_soc_dapm_widget nau8825_dapm_widgets[] = { | |||
| 330 | SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacl_mux), | 361 | SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacl_mux), |
| 331 | SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacr_mux), | 362 | SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &nau8825_dacr_mux), |
| 332 | 363 | ||
| 333 | SND_SOC_DAPM_PGA("HP amp L", NAU8825_REG_CLASSG_CTRL, 1, 0, NULL, 0), | 364 | SND_SOC_DAPM_PGA_S("HP amp L", 0, |
| 334 | SND_SOC_DAPM_PGA("HP amp R", NAU8825_REG_CLASSG_CTRL, 2, 0, NULL, 0), | 365 | NAU8825_REG_CLASSG_CTRL, 1, 0, NULL, 0), |
| 335 | SND_SOC_DAPM_SUPPLY("HP amp power", NAU8825_REG_CLASSG_CTRL, 0, 0, NULL, | 366 | SND_SOC_DAPM_PGA_S("HP amp R", 0, |
| 336 | 0), | 367 | NAU8825_REG_CLASSG_CTRL, 2, 0, NULL, 0), |
| 337 | 368 | ||
| 338 | SND_SOC_DAPM_SUPPLY("Charge Pump", NAU8825_REG_CHARGE_PUMP, 5, 0, | 369 | SND_SOC_DAPM_PGA_S("Charge Pump", 1, NAU8825_REG_CHARGE_PUMP, 5, 0, |
| 339 | nau8825_pump_event, SND_SOC_DAPM_POST_PMU), | 370 | nau8825_pump_event, SND_SOC_DAPM_POST_PMU | |
| 371 | SND_SOC_DAPM_PRE_PMD), | ||
| 340 | 372 | ||
| 341 | SND_SOC_DAPM_PGA("Output Driver R Stage 1", | 373 | SND_SOC_DAPM_PGA_S("Output Driver R Stage 1", 4, |
| 342 | NAU8825_REG_POWER_UP_CONTROL, 5, 0, NULL, 0), | 374 | NAU8825_REG_POWER_UP_CONTROL, 5, 0, NULL, 0), |
| 343 | SND_SOC_DAPM_PGA("Output Driver L Stage 1", | 375 | SND_SOC_DAPM_PGA_S("Output Driver L Stage 1", 4, |
| 344 | NAU8825_REG_POWER_UP_CONTROL, 4, 0, NULL, 0), | 376 | NAU8825_REG_POWER_UP_CONTROL, 4, 0, NULL, 0), |
| 345 | SND_SOC_DAPM_PGA("Output Driver R Stage 2", | 377 | SND_SOC_DAPM_PGA_S("Output Driver R Stage 2", 5, |
| 346 | NAU8825_REG_POWER_UP_CONTROL, 3, 0, NULL, 0), | 378 | NAU8825_REG_POWER_UP_CONTROL, 3, 0, NULL, 0), |
| 347 | SND_SOC_DAPM_PGA("Output Driver L Stage 2", | 379 | SND_SOC_DAPM_PGA_S("Output Driver L Stage 2", 5, |
| 348 | NAU8825_REG_POWER_UP_CONTROL, 2, 0, NULL, 0), | 380 | NAU8825_REG_POWER_UP_CONTROL, 2, 0, NULL, 0), |
| 349 | SND_SOC_DAPM_PGA_S("Output Driver R Stage 3", 1, | 381 | SND_SOC_DAPM_PGA_S("Output Driver R Stage 3", 6, |
| 350 | NAU8825_REG_POWER_UP_CONTROL, 1, 0, NULL, 0), | 382 | NAU8825_REG_POWER_UP_CONTROL, 1, 0, NULL, 0), |
| 351 | SND_SOC_DAPM_PGA_S("Output Driver L Stage 3", 1, | 383 | SND_SOC_DAPM_PGA_S("Output Driver L Stage 3", 6, |
| 352 | NAU8825_REG_POWER_UP_CONTROL, 0, 0, NULL, 0), | 384 | NAU8825_REG_POWER_UP_CONTROL, 0, 0, NULL, 0), |
| 353 | 385 | ||
| 354 | SND_SOC_DAPM_PGA_S("Output DACL", 2, NAU8825_REG_CHARGE_PUMP, 8, 1, NULL, 0), | 386 | SND_SOC_DAPM_PGA_S("Output DACL", 7, |
| 355 | SND_SOC_DAPM_PGA_S("Output DACR", 2, NAU8825_REG_CHARGE_PUMP, 9, 1, NULL, 0), | 387 | NAU8825_REG_CHARGE_PUMP, 8, 1, nau8825_output_dac_event, |
| 388 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
| 389 | SND_SOC_DAPM_PGA_S("Output DACR", 7, | ||
| 390 | NAU8825_REG_CHARGE_PUMP, 9, 1, nau8825_output_dac_event, | ||
| 391 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
| 392 | |||
| 393 | /* HPOL/R are ungrounded by disabling 16 Ohm pull-downs on playback */ | ||
| 394 | SND_SOC_DAPM_PGA_S("HPOL Pulldown", 8, | ||
| 395 | NAU8825_REG_HSD_CTRL, 0, 1, NULL, 0), | ||
| 396 | SND_SOC_DAPM_PGA_S("HPOR Pulldown", 8, | ||
| 397 | NAU8825_REG_HSD_CTRL, 1, 1, NULL, 0), | ||
| 398 | |||
| 399 | /* High current HPOL/R boost driver */ | ||
| 400 | SND_SOC_DAPM_PGA_S("HP Boost Driver", 9, | ||
| 401 | NAU8825_REG_BOOST, 9, 1, NULL, 0), | ||
| 402 | |||
| 403 | /* Class G operation control*/ | ||
| 404 | SND_SOC_DAPM_PGA_S("Class G", 10, | ||
| 405 | NAU8825_REG_CLASSG_CTRL, 0, 0, NULL, 0), | ||
| 356 | 406 | ||
| 357 | SND_SOC_DAPM_OUTPUT("HPOL"), | 407 | SND_SOC_DAPM_OUTPUT("HPOL"), |
| 358 | SND_SOC_DAPM_OUTPUT("HPOR"), | 408 | SND_SOC_DAPM_OUTPUT("HPOR"), |
| @@ -375,24 +425,27 @@ static const struct snd_soc_dapm_route nau8825_dapm_routes[] = { | |||
| 375 | {"DACR Mux", "DACR", "DDACR"}, | 425 | {"DACR Mux", "DACR", "DDACR"}, |
| 376 | {"HP amp L", NULL, "DACL Mux"}, | 426 | {"HP amp L", NULL, "DACL Mux"}, |
| 377 | {"HP amp R", NULL, "DACR Mux"}, | 427 | {"HP amp R", NULL, "DACR Mux"}, |
| 378 | {"HP amp L", NULL, "HP amp power"}, | 428 | {"Charge Pump", NULL, "HP amp L"}, |
| 379 | {"HP amp R", NULL, "HP amp power"}, | 429 | {"Charge Pump", NULL, "HP amp R"}, |
| 380 | {"ADACL", NULL, "HP amp L"}, | 430 | {"ADACL", NULL, "Charge Pump"}, |
| 381 | {"ADACR", NULL, "HP amp R"}, | 431 | {"ADACR", NULL, "Charge Pump"}, |
| 382 | {"ADACL", NULL, "ADACL Clock"}, | 432 | {"ADACL Clock", NULL, "ADACL"}, |
| 383 | {"ADACR", NULL, "ADACR Clock"}, | 433 | {"ADACR Clock", NULL, "ADACR"}, |
| 384 | {"Output Driver L Stage 1", NULL, "ADACL"}, | 434 | {"Output Driver L Stage 1", NULL, "ADACL Clock"}, |
| 385 | {"Output Driver R Stage 1", NULL, "ADACR"}, | 435 | {"Output Driver R Stage 1", NULL, "ADACR Clock"}, |
| 386 | {"Output Driver L Stage 2", NULL, "Output Driver L Stage 1"}, | 436 | {"Output Driver L Stage 2", NULL, "Output Driver L Stage 1"}, |
| 387 | {"Output Driver R Stage 2", NULL, "Output Driver R Stage 1"}, | 437 | {"Output Driver R Stage 2", NULL, "Output Driver R Stage 1"}, |
| 388 | {"Output Driver L Stage 3", NULL, "Output Driver L Stage 2"}, | 438 | {"Output Driver L Stage 3", NULL, "Output Driver L Stage 2"}, |
| 389 | {"Output Driver R Stage 3", NULL, "Output Driver R Stage 2"}, | 439 | {"Output Driver R Stage 3", NULL, "Output Driver R Stage 2"}, |
| 390 | {"Output DACL", NULL, "Output Driver L Stage 3"}, | 440 | {"Output DACL", NULL, "Output Driver L Stage 3"}, |
| 391 | {"Output DACR", NULL, "Output Driver R Stage 3"}, | 441 | {"Output DACR", NULL, "Output Driver R Stage 3"}, |
| 392 | {"HPOL", NULL, "Output DACL"}, | 442 | {"HPOL Pulldown", NULL, "Output DACL"}, |
| 393 | {"HPOR", NULL, "Output DACR"}, | 443 | {"HPOR Pulldown", NULL, "Output DACR"}, |
| 394 | {"HPOL", NULL, "Charge Pump"}, | 444 | {"HP Boost Driver", NULL, "HPOL Pulldown"}, |
| 395 | {"HPOR", NULL, "Charge Pump"}, | 445 | {"HP Boost Driver", NULL, "HPOR Pulldown"}, |
| 446 | {"Class G", NULL, "HP Boost Driver"}, | ||
| 447 | {"HPOL", NULL, "Class G"}, | ||
| 448 | {"HPOR", NULL, "Class G"}, | ||
| 396 | }; | 449 | }; |
| 397 | 450 | ||
| 398 | static int nau8825_hw_params(struct snd_pcm_substream *substream, | 451 | static int nau8825_hw_params(struct snd_pcm_substream *substream, |
| @@ -659,11 +712,10 @@ static int nau8825_jack_insert(struct nau8825 *nau8825) | |||
| 659 | break; | 712 | break; |
| 660 | } | 713 | } |
| 661 | 714 | ||
| 662 | if (type & SND_JACK_HEADPHONE) { | 715 | /* Leaving HPOL/R grounded after jack insert by default. They will be |
| 663 | /* Unground HPL/R */ | 716 | * ungrounded as part of the widget power up sequence at the beginning |
| 664 | regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL, 0x3, 0); | 717 | * of playback to reduce pop. |
| 665 | } | 718 | */ |
| 666 | |||
| 667 | return type; | 719 | return type; |
| 668 | } | 720 | } |
| 669 | 721 | ||
| @@ -768,6 +820,8 @@ static void nau8825_init_regs(struct nau8825 *nau8825) | |||
| 768 | { | 820 | { |
| 769 | struct regmap *regmap = nau8825->regmap; | 821 | struct regmap *regmap = nau8825->regmap; |
| 770 | 822 | ||
| 823 | /* Latch IIC LSB value */ | ||
| 824 | regmap_write(regmap, NAU8825_REG_IIC_ADDR_SET, 0x0001); | ||
| 771 | /* Enable Bias/Vmid */ | 825 | /* Enable Bias/Vmid */ |
| 772 | regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, | 826 | regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, |
| 773 | NAU8825_BIAS_VMID, NAU8825_BIAS_VMID); | 827 | NAU8825_BIAS_VMID, NAU8825_BIAS_VMID); |
| @@ -780,10 +834,10 @@ static void nau8825_init_regs(struct nau8825 *nau8825) | |||
| 780 | nau8825->vref_impedance << NAU8825_BIAS_VMID_SEL_SFT); | 834 | nau8825->vref_impedance << NAU8825_BIAS_VMID_SEL_SFT); |
| 781 | /* Disable Boost Driver, Automatic Short circuit protection enable */ | 835 | /* Disable Boost Driver, Automatic Short circuit protection enable */ |
| 782 | regmap_update_bits(regmap, NAU8825_REG_BOOST, | 836 | regmap_update_bits(regmap, NAU8825_REG_BOOST, |
| 783 | NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_G_DIS | | 837 | NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_DIS | |
| 784 | NAU8825_SHORT_SHUTDOWN_EN, | 838 | NAU8825_HP_BOOST_G_DIS | NAU8825_SHORT_SHUTDOWN_EN, |
| 785 | NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_G_DIS | | 839 | NAU8825_PRECHARGE_DIS | NAU8825_HP_BOOST_DIS | |
| 786 | NAU8825_SHORT_SHUTDOWN_EN); | 840 | NAU8825_HP_BOOST_G_DIS | NAU8825_SHORT_SHUTDOWN_EN); |
| 787 | 841 | ||
| 788 | regmap_update_bits(regmap, NAU8825_REG_GPIO12_CTRL, | 842 | regmap_update_bits(regmap, NAU8825_REG_GPIO12_CTRL, |
| 789 | NAU8825_JKDET_OUTPUT_EN, | 843 | NAU8825_JKDET_OUTPUT_EN, |
| @@ -822,6 +876,35 @@ static void nau8825_init_regs(struct nau8825 *nau8825) | |||
| 822 | NAU8825_ADC_SYNC_DOWN_MASK, NAU8825_ADC_SYNC_DOWN_128); | 876 | NAU8825_ADC_SYNC_DOWN_MASK, NAU8825_ADC_SYNC_DOWN_128); |
| 823 | regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1, | 877 | regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1, |
| 824 | NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_128); | 878 | NAU8825_DAC_OVERSAMPLE_MASK, NAU8825_DAC_OVERSAMPLE_128); |
| 879 | /* Disable DACR/L power */ | ||
| 880 | regmap_update_bits(regmap, NAU8825_REG_CHARGE_PUMP, | ||
| 881 | NAU8825_POWER_DOWN_DACR | NAU8825_POWER_DOWN_DACL, | ||
| 882 | NAU8825_POWER_DOWN_DACR | NAU8825_POWER_DOWN_DACL); | ||
| 883 | /* Enable TESTDAC. This sets the analog DAC inputs to a '0' input | ||
| 884 | * signal to avoid any glitches due to power up transients in both | ||
| 885 | * the analog and digital DAC circuit. | ||
| 886 | */ | ||
| 887 | regmap_update_bits(nau8825->regmap, NAU8825_REG_BIAS_ADJ, | ||
| 888 | NAU8825_BIAS_TESTDAC_EN, NAU8825_BIAS_TESTDAC_EN); | ||
| 889 | /* CICCLP off */ | ||
| 890 | regmap_update_bits(regmap, NAU8825_REG_DAC_CTRL1, | ||
| 891 | NAU8825_DAC_CLIP_OFF, NAU8825_DAC_CLIP_OFF); | ||
| 892 | |||
| 893 | /* Class AB bias current to 2x, DAC Capacitor enable MSB/LSB */ | ||
| 894 | regmap_update_bits(regmap, NAU8825_REG_ANALOG_CONTROL_2, | ||
| 895 | NAU8825_HP_NON_CLASSG_CURRENT_2xADJ | | ||
| 896 | NAU8825_DAC_CAPACITOR_MSB | NAU8825_DAC_CAPACITOR_LSB, | ||
| 897 | NAU8825_HP_NON_CLASSG_CURRENT_2xADJ | | ||
| 898 | NAU8825_DAC_CAPACITOR_MSB | NAU8825_DAC_CAPACITOR_LSB); | ||
| 899 | /* Class G timer 64ms */ | ||
| 900 | regmap_update_bits(regmap, NAU8825_REG_CLASSG_CTRL, | ||
| 901 | NAU8825_CLASSG_TIMER_MASK, | ||
| 902 | 0x20 << NAU8825_CLASSG_TIMER_SFT); | ||
| 903 | /* DAC clock delay 2ns, VREF */ | ||
| 904 | regmap_update_bits(regmap, NAU8825_REG_RDAC, | ||
| 905 | NAU8825_RDAC_CLK_DELAY_MASK | NAU8825_RDAC_VREF_MASK, | ||
| 906 | (0x2 << NAU8825_RDAC_CLK_DELAY_SFT) | | ||
| 907 | (0x3 << NAU8825_RDAC_VREF_SFT)); | ||
| 825 | } | 908 | } |
| 826 | 909 | ||
| 827 | static const struct regmap_config nau8825_regmap_config = { | 910 | static const struct regmap_config nau8825_regmap_config = { |
diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h index dff8edb83bfd..8ceb5f385478 100644 --- a/sound/soc/codecs/nau8825.h +++ b/sound/soc/codecs/nau8825.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | #define NAU8825_REG_RESET 0x00 | 15 | #define NAU8825_REG_RESET 0x00 |
| 16 | #define NAU8825_REG_ENA_CTRL 0x01 | 16 | #define NAU8825_REG_ENA_CTRL 0x01 |
| 17 | #define NAU8825_REG_IIC_ADDR_SET 0x02 | ||
| 17 | #define NAU8825_REG_CLK_DIVIDER 0x03 | 18 | #define NAU8825_REG_CLK_DIVIDER 0x03 |
| 18 | #define NAU8825_REG_FLL1 0x04 | 19 | #define NAU8825_REG_FLL1 0x04 |
| 19 | #define NAU8825_REG_FLL2 0x05 | 20 | #define NAU8825_REG_FLL2 0x05 |
| @@ -129,7 +130,7 @@ | |||
| 129 | 130 | ||
| 130 | /* HSD_CTRL (0xc) */ | 131 | /* HSD_CTRL (0xc) */ |
| 131 | #define NAU8825_HSD_AUTO_MODE (1 << 6) | 132 | #define NAU8825_HSD_AUTO_MODE (1 << 6) |
| 132 | /* 0 - short to GND, 1 - open */ | 133 | /* 0 - open, 1 - short to GND */ |
| 133 | #define NAU8825_SPKR_DWN1R (1 << 1) | 134 | #define NAU8825_SPKR_DWN1R (1 << 1) |
| 134 | #define NAU8825_SPKR_DWN1L (1 << 0) | 135 | #define NAU8825_SPKR_DWN1L (1 << 0) |
| 135 | 136 | ||
| @@ -251,12 +252,18 @@ | |||
| 251 | /* DACR_CTRL (0x34) */ | 252 | /* DACR_CTRL (0x34) */ |
| 252 | #define NAU8825_DACR_CH_SEL_SFT 9 | 253 | #define NAU8825_DACR_CH_SEL_SFT 9 |
| 253 | 254 | ||
| 255 | /* CLASSG_CTRL (0x50) */ | ||
| 256 | #define NAU8825_CLASSG_TIMER_SFT 8 | ||
| 257 | #define NAU8825_CLASSG_TIMER_MASK (0x3f << NAU8825_CLASSG_TIMER_SFT) | ||
| 258 | #define NAU8825_CLASSG_EN (1 << 0) | ||
| 259 | |||
| 254 | /* I2C_DEVICE_ID (0x58) */ | 260 | /* I2C_DEVICE_ID (0x58) */ |
| 255 | #define NAU8825_GPIO2JD1 (1 << 7) | 261 | #define NAU8825_GPIO2JD1 (1 << 7) |
| 256 | #define NAU8825_SOFTWARE_ID_MASK 0x3 | 262 | #define NAU8825_SOFTWARE_ID_MASK 0x3 |
| 257 | #define NAU8825_SOFTWARE_ID_NAU8825 0x0 | 263 | #define NAU8825_SOFTWARE_ID_NAU8825 0x0 |
| 258 | 264 | ||
| 259 | /* BIAS_ADJ (0x66) */ | 265 | /* BIAS_ADJ (0x66) */ |
| 266 | #define NAU8825_BIAS_TESTDAC_EN (0x3 << 8) | ||
| 260 | #define NAU8825_BIAS_VMID (1 << 6) | 267 | #define NAU8825_BIAS_VMID (1 << 6) |
| 261 | #define NAU8825_BIAS_VMID_SEL_SFT 4 | 268 | #define NAU8825_BIAS_VMID_SEL_SFT 4 |
| 262 | #define NAU8825_BIAS_VMID_SEL_MASK (3 << NAU8825_BIAS_VMID_SEL_SFT) | 269 | #define NAU8825_BIAS_VMID_SEL_MASK (3 << NAU8825_BIAS_VMID_SEL_SFT) |
| @@ -274,6 +281,12 @@ | |||
| 274 | #define NAU8825_ADC_VREFSEL_VMID_PLUS_1DB (3 << 8) | 281 | #define NAU8825_ADC_VREFSEL_VMID_PLUS_1DB (3 << 8) |
| 275 | #define NAU8825_POWERUP_ADCL (1 << 6) | 282 | #define NAU8825_POWERUP_ADCL (1 << 6) |
| 276 | 283 | ||
| 284 | /* RDAC (0x73) */ | ||
| 285 | #define NAU8825_RDAC_CLK_DELAY_SFT 4 | ||
| 286 | #define NAU8825_RDAC_CLK_DELAY_MASK (0x7 << NAU8825_RDAC_CLK_DELAY_SFT) | ||
| 287 | #define NAU8825_RDAC_VREF_SFT 2 | ||
| 288 | #define NAU8825_RDAC_VREF_MASK (0x3 << NAU8825_RDAC_VREF_SFT) | ||
| 289 | |||
| 277 | /* MIC_BIAS (0x74) */ | 290 | /* MIC_BIAS (0x74) */ |
| 278 | #define NAU8825_MICBIAS_JKSLV (1 << 14) | 291 | #define NAU8825_MICBIAS_JKSLV (1 << 14) |
| 279 | #define NAU8825_MICBIAS_JKR2 (1 << 12) | 292 | #define NAU8825_MICBIAS_JKR2 (1 << 12) |
| @@ -284,6 +297,7 @@ | |||
| 284 | /* BOOST (0x76) */ | 297 | /* BOOST (0x76) */ |
| 285 | #define NAU8825_PRECHARGE_DIS (1 << 13) | 298 | #define NAU8825_PRECHARGE_DIS (1 << 13) |
| 286 | #define NAU8825_GLOBAL_BIAS_EN (1 << 12) | 299 | #define NAU8825_GLOBAL_BIAS_EN (1 << 12) |
| 300 | #define NAU8825_HP_BOOST_DIS (1 << 9) | ||
| 287 | #define NAU8825_HP_BOOST_G_DIS (1 << 8) | 301 | #define NAU8825_HP_BOOST_G_DIS (1 << 8) |
| 288 | #define NAU8825_SHORT_SHUTDOWN_EN (1 << 6) | 302 | #define NAU8825_SHORT_SHUTDOWN_EN (1 << 6) |
| 289 | 303 | ||
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index 976967675387..f7e789e97fbc 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig | |||
| @@ -17,6 +17,27 @@ config SND_SOC_MT8173_MAX98090 | |||
| 17 | Select Y if you have such device. | 17 | Select Y if you have such device. |
| 18 | If unsure select "N". | 18 | If unsure select "N". |
| 19 | 19 | ||
| 20 | config SND_SOC_MT8173_RT5650 | ||
| 21 | tristate "ASoC Audio driver for MT8173 with RT5650 codec" | ||
| 22 | depends on SND_SOC_MEDIATEK && I2C | ||
| 23 | select SND_SOC_RT5645 | ||
| 24 | help | ||
| 25 | This adds ASoC driver for Mediatek MT8173 boards | ||
| 26 | with the RT5650 audio codec. | ||
| 27 | Select Y if you have such device. | ||
| 28 | If unsure select "N". | ||
| 29 | |||
| 30 | config SND_SOC_MT8173_RT5650_RT5514 | ||
| 31 | tristate "ASoC Audio driver for MT8173 with RT5650 RT5514 codecs" | ||
| 32 | depends on SND_SOC_MEDIATEK && I2C | ||
| 33 | select SND_SOC_RT5645 | ||
| 34 | select SND_SOC_RT5514 | ||
| 35 | help | ||
| 36 | This adds ASoC driver for Mediatek MT8173 boards | ||
| 37 | with the RT5650 and RT5514 codecs. | ||
| 38 | Select Y if you have such device. | ||
| 39 | If unsure select "N". | ||
| 40 | |||
| 20 | config SND_SOC_MT8173_RT5650_RT5676 | 41 | config SND_SOC_MT8173_RT5650_RT5676 |
| 21 | tristate "ASoC Audio driver for MT8173 with RT5650 RT5676 codecs" | 42 | tristate "ASoC Audio driver for MT8173 with RT5650 RT5676 codecs" |
| 22 | depends on SND_SOC_MEDIATEK && I2C | 43 | depends on SND_SOC_MEDIATEK && I2C |
| @@ -27,4 +48,3 @@ config SND_SOC_MT8173_RT5650_RT5676 | |||
| 27 | with the RT5650 and RT5676 codecs. | 48 | with the RT5650 and RT5676 codecs. |
| 28 | Select Y if you have such device. | 49 | Select Y if you have such device. |
| 29 | If unsure select "N". | 50 | If unsure select "N". |
| 30 | |||
diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile index 75effbec438d..d486860c0a88 100644 --- a/sound/soc/mediatek/Makefile +++ b/sound/soc/mediatek/Makefile | |||
| @@ -2,4 +2,6 @@ | |||
| 2 | obj-$(CONFIG_SND_SOC_MEDIATEK) += mtk-afe-pcm.o | 2 | obj-$(CONFIG_SND_SOC_MEDIATEK) += mtk-afe-pcm.o |
| 3 | # Machine support | 3 | # Machine support |
| 4 | obj-$(CONFIG_SND_SOC_MT8173_MAX98090) += mt8173-max98090.o | 4 | obj-$(CONFIG_SND_SOC_MT8173_MAX98090) += mt8173-max98090.o |
| 5 | obj-$(CONFIG_SND_SOC_MT8173_RT5650) += mt8173-rt5650.o | ||
| 6 | obj-$(CONFIG_SND_SOC_MT8173_RT5650_RT5514) += mt8173-rt5650-rt5514.o | ||
| 5 | obj-$(CONFIG_SND_SOC_MT8173_RT5650_RT5676) += mt8173-rt5650-rt5676.o | 7 | obj-$(CONFIG_SND_SOC_MT8173_RT5650_RT5676) += mt8173-rt5650-rt5676.o |
diff --git a/sound/soc/mediatek/mt8173-rt5650-rt5514.c b/sound/soc/mediatek/mt8173-rt5650-rt5514.c new file mode 100644 index 000000000000..58e083642dea --- /dev/null +++ b/sound/soc/mediatek/mt8173-rt5650-rt5514.c | |||
| @@ -0,0 +1,258 @@ | |||
| 1 | /* | ||
| 2 | * mt8173-rt5650-rt5514.c -- MT8173 machine driver with RT5650/5514 codecs | ||
| 3 | * | ||
| 4 | * Copyright (c) 2016 MediaTek Inc. | ||
| 5 | * Author: Koro Chen <koro.chen@mediatek.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 and | ||
| 9 | * only version 2 as published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/gpio.h> | ||
| 19 | #include <linux/of_gpio.h> | ||
| 20 | #include <sound/soc.h> | ||
| 21 | #include <sound/jack.h> | ||
| 22 | #include "../codecs/rt5645.h" | ||
| 23 | |||
| 24 | #define MCLK_FOR_CODECS 12288000 | ||
| 25 | |||
| 26 | static const struct snd_soc_dapm_widget mt8173_rt5650_rt5514_widgets[] = { | ||
| 27 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
| 28 | SND_SOC_DAPM_MIC("Int Mic", NULL), | ||
| 29 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
| 30 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
| 31 | }; | ||
| 32 | |||
| 33 | static const struct snd_soc_dapm_route mt8173_rt5650_rt5514_routes[] = { | ||
| 34 | {"Speaker", NULL, "SPOL"}, | ||
| 35 | {"Speaker", NULL, "SPOR"}, | ||
| 36 | {"Sub DMIC1L", NULL, "Int Mic"}, | ||
| 37 | {"Sub DMIC1R", NULL, "Int Mic"}, | ||
| 38 | {"Headphone", NULL, "HPOL"}, | ||
| 39 | {"Headphone", NULL, "HPOR"}, | ||
| 40 | {"Headset Mic", NULL, "micbias1"}, | ||
| 41 | {"Headset Mic", NULL, "micbias2"}, | ||
| 42 | {"IN1P", NULL, "Headset Mic"}, | ||
| 43 | {"IN1N", NULL, "Headset Mic"}, | ||
| 44 | }; | ||
| 45 | |||
| 46 | static const struct snd_kcontrol_new mt8173_rt5650_rt5514_controls[] = { | ||
| 47 | SOC_DAPM_PIN_SWITCH("Speaker"), | ||
| 48 | SOC_DAPM_PIN_SWITCH("Int Mic"), | ||
| 49 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
| 50 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
| 51 | }; | ||
| 52 | |||
| 53 | static int mt8173_rt5650_rt5514_hw_params(struct snd_pcm_substream *substream, | ||
| 54 | struct snd_pcm_hw_params *params) | ||
| 55 | { | ||
| 56 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 57 | int i, ret; | ||
| 58 | |||
| 59 | for (i = 0; i < rtd->num_codecs; i++) { | ||
| 60 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
| 61 | |||
| 62 | /* pll from mclk 12.288M */ | ||
| 63 | ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS, | ||
| 64 | params_rate(params) * 512); | ||
| 65 | if (ret) | ||
| 66 | return ret; | ||
| 67 | |||
| 68 | /* sysclk from pll */ | ||
| 69 | ret = snd_soc_dai_set_sysclk(codec_dai, 1, | ||
| 70 | params_rate(params) * 512, | ||
| 71 | SND_SOC_CLOCK_IN); | ||
| 72 | if (ret) | ||
| 73 | return ret; | ||
| 74 | } | ||
| 75 | return 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | static struct snd_soc_ops mt8173_rt5650_rt5514_ops = { | ||
| 79 | .hw_params = mt8173_rt5650_rt5514_hw_params, | ||
| 80 | }; | ||
| 81 | |||
| 82 | static struct snd_soc_jack mt8173_rt5650_rt5514_jack; | ||
| 83 | |||
| 84 | static int mt8173_rt5650_rt5514_init(struct snd_soc_pcm_runtime *runtime) | ||
| 85 | { | ||
| 86 | struct snd_soc_card *card = runtime->card; | ||
| 87 | struct snd_soc_codec *codec = runtime->codec_dais[0]->codec; | ||
| 88 | int ret; | ||
| 89 | |||
| 90 | rt5645_sel_asrc_clk_src(codec, | ||
| 91 | RT5645_DA_STEREO_FILTER | | ||
| 92 | RT5645_AD_STEREO_FILTER, | ||
| 93 | RT5645_CLK_SEL_I2S1_ASRC); | ||
| 94 | |||
| 95 | /* enable jack detection */ | ||
| 96 | ret = snd_soc_card_jack_new(card, "Headset Jack", | ||
| 97 | SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | | ||
| 98 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | ||
| 99 | SND_JACK_BTN_2 | SND_JACK_BTN_3, | ||
| 100 | &mt8173_rt5650_rt5514_jack, NULL, 0); | ||
| 101 | if (ret) { | ||
| 102 | dev_err(card->dev, "Can't new Headset Jack %d\n", ret); | ||
| 103 | return ret; | ||
| 104 | } | ||
| 105 | |||
| 106 | return rt5645_set_jack_detect(codec, | ||
| 107 | &mt8173_rt5650_rt5514_jack, | ||
| 108 | &mt8173_rt5650_rt5514_jack, | ||
| 109 | &mt8173_rt5650_rt5514_jack); | ||
| 110 | } | ||
| 111 | |||
| 112 | static struct snd_soc_dai_link_component mt8173_rt5650_rt5514_codecs[] = { | ||
| 113 | { | ||
| 114 | .dai_name = "rt5645-aif1", | ||
| 115 | }, | ||
| 116 | { | ||
| 117 | .dai_name = "rt5514-aif1", | ||
| 118 | }, | ||
| 119 | }; | ||
| 120 | |||
| 121 | enum { | ||
| 122 | DAI_LINK_PLAYBACK, | ||
| 123 | DAI_LINK_CAPTURE, | ||
| 124 | DAI_LINK_CODEC_I2S, | ||
| 125 | }; | ||
| 126 | |||
| 127 | /* Digital audio interface glue - connects codec <---> CPU */ | ||
| 128 | static struct snd_soc_dai_link mt8173_rt5650_rt5514_dais[] = { | ||
| 129 | /* Front End DAI links */ | ||
| 130 | [DAI_LINK_PLAYBACK] = { | ||
| 131 | .name = "rt5650_rt5514 Playback", | ||
| 132 | .stream_name = "rt5650_rt5514 Playback", | ||
| 133 | .cpu_dai_name = "DL1", | ||
| 134 | .codec_name = "snd-soc-dummy", | ||
| 135 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 136 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 137 | .dynamic = 1, | ||
| 138 | .dpcm_playback = 1, | ||
| 139 | }, | ||
| 140 | [DAI_LINK_CAPTURE] = { | ||
| 141 | .name = "rt5650_rt5514 Capture", | ||
| 142 | .stream_name = "rt5650_rt5514 Capture", | ||
| 143 | .cpu_dai_name = "VUL", | ||
| 144 | .codec_name = "snd-soc-dummy", | ||
| 145 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 146 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 147 | .dynamic = 1, | ||
| 148 | .dpcm_capture = 1, | ||
| 149 | }, | ||
| 150 | /* Back End DAI links */ | ||
| 151 | [DAI_LINK_CODEC_I2S] = { | ||
| 152 | .name = "Codec", | ||
| 153 | .cpu_dai_name = "I2S", | ||
| 154 | .no_pcm = 1, | ||
| 155 | .codecs = mt8173_rt5650_rt5514_codecs, | ||
| 156 | .num_codecs = 2, | ||
| 157 | .init = mt8173_rt5650_rt5514_init, | ||
| 158 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
| 159 | SND_SOC_DAIFMT_CBS_CFS, | ||
| 160 | .ops = &mt8173_rt5650_rt5514_ops, | ||
| 161 | .ignore_pmdown_time = 1, | ||
| 162 | .dpcm_playback = 1, | ||
| 163 | .dpcm_capture = 1, | ||
| 164 | }, | ||
| 165 | }; | ||
| 166 | |||
| 167 | static struct snd_soc_codec_conf mt8173_rt5650_rt5514_codec_conf[] = { | ||
| 168 | { | ||
| 169 | .name_prefix = "Sub", | ||
| 170 | }, | ||
| 171 | }; | ||
| 172 | |||
| 173 | static struct snd_soc_card mt8173_rt5650_rt5514_card = { | ||
| 174 | .name = "mtk-rt5650-rt5514", | ||
| 175 | .owner = THIS_MODULE, | ||
| 176 | .dai_link = mt8173_rt5650_rt5514_dais, | ||
| 177 | .num_links = ARRAY_SIZE(mt8173_rt5650_rt5514_dais), | ||
| 178 | .codec_conf = mt8173_rt5650_rt5514_codec_conf, | ||
| 179 | .num_configs = ARRAY_SIZE(mt8173_rt5650_rt5514_codec_conf), | ||
| 180 | .controls = mt8173_rt5650_rt5514_controls, | ||
| 181 | .num_controls = ARRAY_SIZE(mt8173_rt5650_rt5514_controls), | ||
| 182 | .dapm_widgets = mt8173_rt5650_rt5514_widgets, | ||
| 183 | .num_dapm_widgets = ARRAY_SIZE(mt8173_rt5650_rt5514_widgets), | ||
| 184 | .dapm_routes = mt8173_rt5650_rt5514_routes, | ||
| 185 | .num_dapm_routes = ARRAY_SIZE(mt8173_rt5650_rt5514_routes), | ||
| 186 | }; | ||
| 187 | |||
| 188 | static int mt8173_rt5650_rt5514_dev_probe(struct platform_device *pdev) | ||
| 189 | { | ||
| 190 | struct snd_soc_card *card = &mt8173_rt5650_rt5514_card; | ||
| 191 | struct device_node *platform_node; | ||
| 192 | int i, ret; | ||
| 193 | |||
| 194 | platform_node = of_parse_phandle(pdev->dev.of_node, | ||
| 195 | "mediatek,platform", 0); | ||
| 196 | if (!platform_node) { | ||
| 197 | dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); | ||
| 198 | return -EINVAL; | ||
| 199 | } | ||
| 200 | |||
| 201 | for (i = 0; i < card->num_links; i++) { | ||
| 202 | if (mt8173_rt5650_rt5514_dais[i].platform_name) | ||
| 203 | continue; | ||
| 204 | mt8173_rt5650_rt5514_dais[i].platform_of_node = platform_node; | ||
| 205 | } | ||
| 206 | |||
| 207 | mt8173_rt5650_rt5514_codecs[0].of_node = | ||
| 208 | of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0); | ||
| 209 | if (!mt8173_rt5650_rt5514_codecs[0].of_node) { | ||
| 210 | dev_err(&pdev->dev, | ||
| 211 | "Property 'audio-codec' missing or invalid\n"); | ||
| 212 | return -EINVAL; | ||
| 213 | } | ||
| 214 | mt8173_rt5650_rt5514_codecs[1].of_node = | ||
| 215 | of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 1); | ||
| 216 | if (!mt8173_rt5650_rt5514_codecs[1].of_node) { | ||
| 217 | dev_err(&pdev->dev, | ||
| 218 | "Property 'audio-codec' missing or invalid\n"); | ||
| 219 | return -EINVAL; | ||
| 220 | } | ||
| 221 | mt8173_rt5650_rt5514_codec_conf[0].of_node = | ||
| 222 | mt8173_rt5650_rt5514_codecs[1].of_node; | ||
| 223 | |||
| 224 | card->dev = &pdev->dev; | ||
| 225 | platform_set_drvdata(pdev, card); | ||
| 226 | |||
| 227 | ret = devm_snd_soc_register_card(&pdev->dev, card); | ||
| 228 | if (ret) | ||
| 229 | dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", | ||
| 230 | __func__, ret); | ||
| 231 | return ret; | ||
| 232 | } | ||
| 233 | |||
| 234 | static const struct of_device_id mt8173_rt5650_rt5514_dt_match[] = { | ||
| 235 | { .compatible = "mediatek,mt8173-rt5650-rt5514", }, | ||
| 236 | { } | ||
| 237 | }; | ||
| 238 | MODULE_DEVICE_TABLE(of, mt8173_rt5650_rt5514_dt_match); | ||
| 239 | |||
| 240 | static struct platform_driver mt8173_rt5650_rt5514_driver = { | ||
| 241 | .driver = { | ||
| 242 | .name = "mtk-rt5650-rt5514", | ||
| 243 | .of_match_table = mt8173_rt5650_rt5514_dt_match, | ||
| 244 | #ifdef CONFIG_PM | ||
| 245 | .pm = &snd_soc_pm_ops, | ||
| 246 | #endif | ||
| 247 | }, | ||
| 248 | .probe = mt8173_rt5650_rt5514_dev_probe, | ||
| 249 | }; | ||
| 250 | |||
| 251 | module_platform_driver(mt8173_rt5650_rt5514_driver); | ||
| 252 | |||
| 253 | /* Module information */ | ||
| 254 | MODULE_DESCRIPTION("MT8173 RT5650 and RT5514 SoC machine driver"); | ||
| 255 | MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>"); | ||
| 256 | MODULE_LICENSE("GPL v2"); | ||
| 257 | MODULE_ALIAS("platform:mtk-rt5650-rt5514"); | ||
| 258 | |||
diff --git a/sound/soc/mediatek/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173-rt5650-rt5676.c index 50ba538eccb3..5c4c58c69c51 100644 --- a/sound/soc/mediatek/mt8173-rt5650-rt5676.c +++ b/sound/soc/mediatek/mt8173-rt5650-rt5676.c | |||
| @@ -131,10 +131,17 @@ static struct snd_soc_dai_link_component mt8173_rt5650_rt5676_codecs[] = { | |||
| 131 | }, | 131 | }, |
| 132 | }; | 132 | }; |
| 133 | 133 | ||
| 134 | enum { | ||
| 135 | DAI_LINK_PLAYBACK, | ||
| 136 | DAI_LINK_CAPTURE, | ||
| 137 | DAI_LINK_CODEC_I2S, | ||
| 138 | DAI_LINK_INTERCODEC | ||
| 139 | }; | ||
| 140 | |||
| 134 | /* Digital audio interface glue - connects codec <---> CPU */ | 141 | /* Digital audio interface glue - connects codec <---> CPU */ |
| 135 | static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = { | 142 | static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = { |
| 136 | /* Front End DAI links */ | 143 | /* Front End DAI links */ |
| 137 | { | 144 | [DAI_LINK_PLAYBACK] = { |
| 138 | .name = "rt5650_rt5676 Playback", | 145 | .name = "rt5650_rt5676 Playback", |
| 139 | .stream_name = "rt5650_rt5676 Playback", | 146 | .stream_name = "rt5650_rt5676 Playback", |
| 140 | .cpu_dai_name = "DL1", | 147 | .cpu_dai_name = "DL1", |
| @@ -144,7 +151,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = { | |||
| 144 | .dynamic = 1, | 151 | .dynamic = 1, |
| 145 | .dpcm_playback = 1, | 152 | .dpcm_playback = 1, |
| 146 | }, | 153 | }, |
| 147 | { | 154 | [DAI_LINK_CAPTURE] = { |
| 148 | .name = "rt5650_rt5676 Capture", | 155 | .name = "rt5650_rt5676 Capture", |
| 149 | .stream_name = "rt5650_rt5676 Capture", | 156 | .stream_name = "rt5650_rt5676 Capture", |
| 150 | .cpu_dai_name = "VUL", | 157 | .cpu_dai_name = "VUL", |
| @@ -156,7 +163,7 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = { | |||
| 156 | }, | 163 | }, |
| 157 | 164 | ||
| 158 | /* Back End DAI links */ | 165 | /* Back End DAI links */ |
| 159 | { | 166 | [DAI_LINK_CODEC_I2S] = { |
| 160 | .name = "Codec", | 167 | .name = "Codec", |
| 161 | .cpu_dai_name = "I2S", | 168 | .cpu_dai_name = "I2S", |
| 162 | .no_pcm = 1, | 169 | .no_pcm = 1, |
| @@ -170,7 +177,8 @@ static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = { | |||
| 170 | .dpcm_playback = 1, | 177 | .dpcm_playback = 1, |
| 171 | .dpcm_capture = 1, | 178 | .dpcm_capture = 1, |
| 172 | }, | 179 | }, |
| 173 | { /* rt5676 <-> rt5650 intercodec link: Sets rt5676 I2S2 as master */ | 180 | /* rt5676 <-> rt5650 intercodec link: Sets rt5676 I2S2 as master */ |
| 181 | [DAI_LINK_INTERCODEC] = { | ||
| 174 | .name = "rt5650_rt5676 intercodec", | 182 | .name = "rt5650_rt5676 intercodec", |
| 175 | .stream_name = "rt5650_rt5676 intercodec", | 183 | .stream_name = "rt5650_rt5676 intercodec", |
| 176 | .cpu_dai_name = "snd-soc-dummy-dai", | 184 | .cpu_dai_name = "snd-soc-dummy-dai", |
| @@ -240,7 +248,7 @@ static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev) | |||
| 240 | mt8173_rt5650_rt5676_codec_conf[0].of_node = | 248 | mt8173_rt5650_rt5676_codec_conf[0].of_node = |
| 241 | mt8173_rt5650_rt5676_codecs[1].of_node; | 249 | mt8173_rt5650_rt5676_codecs[1].of_node; |
| 242 | 250 | ||
| 243 | mt8173_rt5650_rt5676_dais[3].codec_of_node = | 251 | mt8173_rt5650_rt5676_dais[DAI_LINK_INTERCODEC].codec_of_node = |
| 244 | mt8173_rt5650_rt5676_codecs[1].of_node; | 252 | mt8173_rt5650_rt5676_codecs[1].of_node; |
| 245 | 253 | ||
| 246 | card->dev = &pdev->dev; | 254 | card->dev = &pdev->dev; |
diff --git a/sound/soc/mediatek/mt8173-rt5650.c b/sound/soc/mediatek/mt8173-rt5650.c new file mode 100644 index 000000000000..bb09bb1b7f1c --- /dev/null +++ b/sound/soc/mediatek/mt8173-rt5650.c | |||
| @@ -0,0 +1,236 @@ | |||
| 1 | /* | ||
| 2 | * mt8173-rt5650.c -- MT8173 machine driver with RT5650 codecs | ||
| 3 | * | ||
| 4 | * Copyright (c) 2016 MediaTek Inc. | ||
| 5 | * Author: Koro Chen <koro.chen@mediatek.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 and | ||
| 9 | * only version 2 as published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/gpio.h> | ||
| 19 | #include <linux/of_gpio.h> | ||
| 20 | #include <sound/soc.h> | ||
| 21 | #include <sound/jack.h> | ||
| 22 | #include "../codecs/rt5645.h" | ||
| 23 | |||
| 24 | #define MCLK_FOR_CODECS 12288000 | ||
| 25 | |||
| 26 | static const struct snd_soc_dapm_widget mt8173_rt5650_widgets[] = { | ||
| 27 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
| 28 | SND_SOC_DAPM_MIC("Int Mic", NULL), | ||
| 29 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
| 30 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
| 31 | }; | ||
| 32 | |||
| 33 | static const struct snd_soc_dapm_route mt8173_rt5650_routes[] = { | ||
| 34 | {"Speaker", NULL, "SPOL"}, | ||
| 35 | {"Speaker", NULL, "SPOR"}, | ||
| 36 | {"DMIC L1", NULL, "Int Mic"}, | ||
| 37 | {"DMIC R1", NULL, "Int Mic"}, | ||
| 38 | {"Headphone", NULL, "HPOL"}, | ||
| 39 | {"Headphone", NULL, "HPOR"}, | ||
| 40 | {"Headset Mic", NULL, "micbias1"}, | ||
| 41 | {"Headset Mic", NULL, "micbias2"}, | ||
| 42 | {"IN1P", NULL, "Headset Mic"}, | ||
| 43 | {"IN1N", NULL, "Headset Mic"}, | ||
| 44 | }; | ||
| 45 | |||
| 46 | static const struct snd_kcontrol_new mt8173_rt5650_controls[] = { | ||
| 47 | SOC_DAPM_PIN_SWITCH("Speaker"), | ||
| 48 | SOC_DAPM_PIN_SWITCH("Int Mic"), | ||
| 49 | SOC_DAPM_PIN_SWITCH("Headphone"), | ||
| 50 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
| 51 | }; | ||
| 52 | |||
| 53 | static int mt8173_rt5650_hw_params(struct snd_pcm_substream *substream, | ||
| 54 | struct snd_pcm_hw_params *params) | ||
| 55 | { | ||
| 56 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 57 | int i, ret; | ||
| 58 | |||
| 59 | for (i = 0; i < rtd->num_codecs; i++) { | ||
| 60 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
| 61 | |||
| 62 | /* pll from mclk 12.288M */ | ||
| 63 | ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS, | ||
| 64 | params_rate(params) * 512); | ||
| 65 | if (ret) | ||
| 66 | return ret; | ||
| 67 | |||
| 68 | /* sysclk from pll */ | ||
| 69 | ret = snd_soc_dai_set_sysclk(codec_dai, 1, | ||
| 70 | params_rate(params) * 512, | ||
| 71 | SND_SOC_CLOCK_IN); | ||
| 72 | if (ret) | ||
| 73 | return ret; | ||
| 74 | } | ||
| 75 | return 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | static struct snd_soc_ops mt8173_rt5650_ops = { | ||
| 79 | .hw_params = mt8173_rt5650_hw_params, | ||
| 80 | }; | ||
| 81 | |||
| 82 | static struct snd_soc_jack mt8173_rt5650_jack; | ||
| 83 | |||
| 84 | static int mt8173_rt5650_init(struct snd_soc_pcm_runtime *runtime) | ||
| 85 | { | ||
| 86 | struct snd_soc_card *card = runtime->card; | ||
| 87 | struct snd_soc_codec *codec = runtime->codec_dais[0]->codec; | ||
| 88 | int ret; | ||
| 89 | |||
| 90 | rt5645_sel_asrc_clk_src(codec, | ||
| 91 | RT5645_DA_STEREO_FILTER | | ||
| 92 | RT5645_AD_STEREO_FILTER, | ||
| 93 | RT5645_CLK_SEL_I2S1_ASRC); | ||
| 94 | /* enable jack detection */ | ||
| 95 | ret = snd_soc_card_jack_new(card, "Headset Jack", | ||
| 96 | SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | | ||
| 97 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | | ||
| 98 | SND_JACK_BTN_2 | SND_JACK_BTN_3, | ||
| 99 | &mt8173_rt5650_jack, NULL, 0); | ||
| 100 | if (ret) { | ||
| 101 | dev_err(card->dev, "Can't new Headset Jack %d\n", ret); | ||
| 102 | return ret; | ||
| 103 | } | ||
| 104 | |||
| 105 | return rt5645_set_jack_detect(codec, | ||
| 106 | &mt8173_rt5650_jack, | ||
| 107 | &mt8173_rt5650_jack, | ||
| 108 | &mt8173_rt5650_jack); | ||
| 109 | } | ||
| 110 | |||
| 111 | static struct snd_soc_dai_link_component mt8173_rt5650_codecs[] = { | ||
| 112 | { | ||
| 113 | .dai_name = "rt5645-aif1", | ||
| 114 | }, | ||
| 115 | }; | ||
| 116 | |||
| 117 | enum { | ||
| 118 | DAI_LINK_PLAYBACK, | ||
| 119 | DAI_LINK_CAPTURE, | ||
| 120 | DAI_LINK_CODEC_I2S, | ||
| 121 | }; | ||
| 122 | |||
| 123 | /* Digital audio interface glue - connects codec <---> CPU */ | ||
| 124 | static struct snd_soc_dai_link mt8173_rt5650_dais[] = { | ||
| 125 | /* Front End DAI links */ | ||
| 126 | [DAI_LINK_PLAYBACK] = { | ||
| 127 | .name = "rt5650 Playback", | ||
| 128 | .stream_name = "rt5650 Playback", | ||
| 129 | .cpu_dai_name = "DL1", | ||
| 130 | .codec_name = "snd-soc-dummy", | ||
| 131 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 132 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 133 | .dynamic = 1, | ||
| 134 | .dpcm_playback = 1, | ||
| 135 | }, | ||
| 136 | [DAI_LINK_CAPTURE] = { | ||
| 137 | .name = "rt5650 Capture", | ||
| 138 | .stream_name = "rt5650 Capture", | ||
| 139 | .cpu_dai_name = "VUL", | ||
| 140 | .codec_name = "snd-soc-dummy", | ||
| 141 | .codec_dai_name = "snd-soc-dummy-dai", | ||
| 142 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
| 143 | .dynamic = 1, | ||
| 144 | .dpcm_capture = 1, | ||
| 145 | }, | ||
| 146 | /* Back End DAI links */ | ||
| 147 | [DAI_LINK_CODEC_I2S] = { | ||
| 148 | .name = "Codec", | ||
| 149 | .cpu_dai_name = "I2S", | ||
| 150 | .no_pcm = 1, | ||
| 151 | .codecs = mt8173_rt5650_codecs, | ||
| 152 | .num_codecs = 1, | ||
| 153 | .init = mt8173_rt5650_init, | ||
| 154 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
| 155 | SND_SOC_DAIFMT_CBS_CFS, | ||
| 156 | .ops = &mt8173_rt5650_ops, | ||
| 157 | .ignore_pmdown_time = 1, | ||
| 158 | .dpcm_playback = 1, | ||
| 159 | .dpcm_capture = 1, | ||
| 160 | }, | ||
| 161 | }; | ||
| 162 | |||
| 163 | static struct snd_soc_card mt8173_rt5650_card = { | ||
| 164 | .name = "mtk-rt5650", | ||
| 165 | .owner = THIS_MODULE, | ||
| 166 | .dai_link = mt8173_rt5650_dais, | ||
| 167 | .num_links = ARRAY_SIZE(mt8173_rt5650_dais), | ||
| 168 | .controls = mt8173_rt5650_controls, | ||
| 169 | .num_controls = ARRAY_SIZE(mt8173_rt5650_controls), | ||
| 170 | .dapm_widgets = mt8173_rt5650_widgets, | ||
| 171 | .num_dapm_widgets = ARRAY_SIZE(mt8173_rt5650_widgets), | ||
| 172 | .dapm_routes = mt8173_rt5650_routes, | ||
| 173 | .num_dapm_routes = ARRAY_SIZE(mt8173_rt5650_routes), | ||
| 174 | }; | ||
| 175 | |||
| 176 | static int mt8173_rt5650_dev_probe(struct platform_device *pdev) | ||
| 177 | { | ||
| 178 | struct snd_soc_card *card = &mt8173_rt5650_card; | ||
| 179 | struct device_node *platform_node; | ||
| 180 | int i, ret; | ||
| 181 | |||
| 182 | platform_node = of_parse_phandle(pdev->dev.of_node, | ||
| 183 | "mediatek,platform", 0); | ||
| 184 | if (!platform_node) { | ||
| 185 | dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); | ||
| 186 | return -EINVAL; | ||
| 187 | } | ||
| 188 | |||
| 189 | for (i = 0; i < card->num_links; i++) { | ||
| 190 | if (mt8173_rt5650_dais[i].platform_name) | ||
| 191 | continue; | ||
| 192 | mt8173_rt5650_dais[i].platform_of_node = platform_node; | ||
| 193 | } | ||
| 194 | |||
| 195 | mt8173_rt5650_codecs[0].of_node = | ||
| 196 | of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0); | ||
| 197 | if (!mt8173_rt5650_codecs[0].of_node) { | ||
| 198 | dev_err(&pdev->dev, | ||
| 199 | "Property 'audio-codec' missing or invalid\n"); | ||
| 200 | return -EINVAL; | ||
| 201 | } | ||
| 202 | card->dev = &pdev->dev; | ||
| 203 | platform_set_drvdata(pdev, card); | ||
| 204 | |||
| 205 | ret = devm_snd_soc_register_card(&pdev->dev, card); | ||
| 206 | if (ret) | ||
| 207 | dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n", | ||
| 208 | __func__, ret); | ||
| 209 | return ret; | ||
| 210 | } | ||
| 211 | |||
| 212 | static const struct of_device_id mt8173_rt5650_dt_match[] = { | ||
| 213 | { .compatible = "mediatek,mt8173-rt5650", }, | ||
| 214 | { } | ||
| 215 | }; | ||
| 216 | MODULE_DEVICE_TABLE(of, mt8173_rt5650_dt_match); | ||
| 217 | |||
| 218 | static struct platform_driver mt8173_rt5650_driver = { | ||
| 219 | .driver = { | ||
| 220 | .name = "mtk-rt5650", | ||
| 221 | .of_match_table = mt8173_rt5650_dt_match, | ||
| 222 | #ifdef CONFIG_PM | ||
| 223 | .pm = &snd_soc_pm_ops, | ||
| 224 | #endif | ||
| 225 | }, | ||
| 226 | .probe = mt8173_rt5650_dev_probe, | ||
| 227 | }; | ||
| 228 | |||
| 229 | module_platform_driver(mt8173_rt5650_driver); | ||
| 230 | |||
| 231 | /* Module information */ | ||
| 232 | MODULE_DESCRIPTION("MT8173 RT5650 SoC machine driver"); | ||
| 233 | MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>"); | ||
| 234 | MODULE_LICENSE("GPL v2"); | ||
| 235 | MODULE_ALIAS("platform:mtk-rt5650"); | ||
| 236 | |||
diff --git a/sound/soc/mediatek/mtk-afe-common.h b/sound/soc/mediatek/mtk-afe-common.h index 9b1af1a70874..f341f623e887 100644 --- a/sound/soc/mediatek/mtk-afe-common.h +++ b/sound/soc/mediatek/mtk-afe-common.h | |||
| @@ -87,6 +87,7 @@ struct mtk_afe_memif_data { | |||
| 87 | int irq_en_shift; | 87 | int irq_en_shift; |
| 88 | int irq_fs_shift; | 88 | int irq_fs_shift; |
| 89 | int irq_clr_shift; | 89 | int irq_clr_shift; |
| 90 | int msb_shift; | ||
| 90 | }; | 91 | }; |
| 91 | 92 | ||
| 92 | struct mtk_afe_memif { | 93 | struct mtk_afe_memif { |
diff --git a/sound/soc/mediatek/mtk-afe-pcm.c b/sound/soc/mediatek/mtk-afe-pcm.c index 08af9f5dc4ab..f1c58a2c12fb 100644 --- a/sound/soc/mediatek/mtk-afe-pcm.c +++ b/sound/soc/mediatek/mtk-afe-pcm.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 22 | #include <linux/of.h> | 22 | #include <linux/of.h> |
| 23 | #include <linux/of_address.h> | 23 | #include <linux/of_address.h> |
| 24 | #include <linux/dma-mapping.h> | ||
| 24 | #include <linux/pm_runtime.h> | 25 | #include <linux/pm_runtime.h> |
| 25 | #include <sound/soc.h> | 26 | #include <sound/soc.h> |
| 26 | #include "mtk-afe-common.h" | 27 | #include "mtk-afe-common.h" |
| @@ -35,9 +36,11 @@ | |||
| 35 | #define AFE_I2S_CON1 0x0034 | 36 | #define AFE_I2S_CON1 0x0034 |
| 36 | #define AFE_I2S_CON2 0x0038 | 37 | #define AFE_I2S_CON2 0x0038 |
| 37 | #define AFE_CONN_24BIT 0x006c | 38 | #define AFE_CONN_24BIT 0x006c |
| 39 | #define AFE_MEMIF_MSB 0x00cc | ||
| 38 | 40 | ||
| 39 | #define AFE_CONN1 0x0024 | 41 | #define AFE_CONN1 0x0024 |
| 40 | #define AFE_CONN2 0x0028 | 42 | #define AFE_CONN2 0x0028 |
| 43 | #define AFE_CONN3 0x002c | ||
| 41 | #define AFE_CONN7 0x0460 | 44 | #define AFE_CONN7 0x0460 |
| 42 | #define AFE_CONN8 0x0464 | 45 | #define AFE_CONN8 0x0464 |
| 43 | #define AFE_HDMI_CONN0 0x0390 | 46 | #define AFE_HDMI_CONN0 0x0390 |
| @@ -61,6 +64,7 @@ | |||
| 61 | #define AFE_HDMI_OUT_CUR 0x0378 | 64 | #define AFE_HDMI_OUT_CUR 0x0378 |
| 62 | #define AFE_HDMI_OUT_END 0x037c | 65 | #define AFE_HDMI_OUT_END 0x037c |
| 63 | 66 | ||
| 67 | #define AFE_ADDA_TOP_CON0 0x0120 | ||
| 64 | #define AFE_ADDA2_TOP_CON0 0x0600 | 68 | #define AFE_ADDA2_TOP_CON0 0x0600 |
| 65 | 69 | ||
| 66 | #define AFE_HDMI_OUT_CON0 0x0370 | 70 | #define AFE_HDMI_OUT_CON0 0x0370 |
| @@ -257,6 +261,7 @@ static int mtk_afe_set_i2s(struct mtk_afe *afe, unsigned int rate) | |||
| 257 | return -EINVAL; | 261 | return -EINVAL; |
| 258 | 262 | ||
| 259 | /* from external ADC */ | 263 | /* from external ADC */ |
| 264 | regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 0x1, 0x1); | ||
| 260 | regmap_update_bits(afe->regmap, AFE_ADDA2_TOP_CON0, 0x1, 0x1); | 265 | regmap_update_bits(afe->regmap, AFE_ADDA2_TOP_CON0, 0x1, 0x1); |
| 261 | 266 | ||
| 262 | /* set input */ | 267 | /* set input */ |
| @@ -281,20 +286,13 @@ static void mtk_afe_set_i2s_enable(struct mtk_afe *afe, bool enable) | |||
| 281 | 286 | ||
| 282 | regmap_read(afe->regmap, AFE_I2S_CON2, &val); | 287 | regmap_read(afe->regmap, AFE_I2S_CON2, &val); |
| 283 | if (!!(val & AFE_I2S_CON2_EN) == enable) | 288 | if (!!(val & AFE_I2S_CON2_EN) == enable) |
| 284 | return; /* must skip soft reset */ | 289 | return; |
| 285 | |||
| 286 | /* I2S soft reset begin */ | ||
| 287 | regmap_update_bits(afe->regmap, AUDIO_TOP_CON1, 0x4, 0x4); | ||
| 288 | 290 | ||
| 289 | /* input */ | 291 | /* input */ |
| 290 | regmap_update_bits(afe->regmap, AFE_I2S_CON2, 0x1, enable); | 292 | regmap_update_bits(afe->regmap, AFE_I2S_CON2, 0x1, enable); |
| 291 | 293 | ||
| 292 | /* output */ | 294 | /* output */ |
| 293 | regmap_update_bits(afe->regmap, AFE_I2S_CON1, 0x1, enable); | 295 | regmap_update_bits(afe->regmap, AFE_I2S_CON1, 0x1, enable); |
| 294 | |||
| 295 | /* I2S soft reset end */ | ||
| 296 | udelay(1); | ||
| 297 | regmap_update_bits(afe->regmap, AUDIO_TOP_CON1, 0x4, 0); | ||
| 298 | } | 296 | } |
| 299 | 297 | ||
| 300 | static int mtk_afe_dais_enable_clks(struct mtk_afe *afe, | 298 | static int mtk_afe_dais_enable_clks(struct mtk_afe *afe, |
| @@ -363,6 +361,7 @@ static int mtk_afe_i2s_startup(struct snd_pcm_substream *substream, | |||
| 363 | return 0; | 361 | return 0; |
| 364 | 362 | ||
| 365 | mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL); | 363 | mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL); |
| 364 | mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S2_M], NULL); | ||
| 366 | regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, | 365 | regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, |
| 367 | AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, 0); | 366 | AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, 0); |
| 368 | return 0; | 367 | return 0; |
| @@ -382,6 +381,7 @@ static void mtk_afe_i2s_shutdown(struct snd_pcm_substream *substream, | |||
| 382 | AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, | 381 | AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, |
| 383 | AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M); | 382 | AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M); |
| 384 | mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL); | 383 | mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL); |
| 384 | mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S2_M], NULL); | ||
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | static int mtk_afe_i2s_prepare(struct snd_pcm_substream *substream, | 387 | static int mtk_afe_i2s_prepare(struct snd_pcm_substream *substream, |
| @@ -395,6 +395,9 @@ static int mtk_afe_i2s_prepare(struct snd_pcm_substream *substream, | |||
| 395 | mtk_afe_dais_set_clks(afe, | 395 | mtk_afe_dais_set_clks(afe, |
| 396 | afe->clocks[MTK_CLK_I2S1_M], runtime->rate * 256, | 396 | afe->clocks[MTK_CLK_I2S1_M], runtime->rate * 256, |
| 397 | NULL, 0); | 397 | NULL, 0); |
| 398 | mtk_afe_dais_set_clks(afe, | ||
| 399 | afe->clocks[MTK_CLK_I2S2_M], runtime->rate * 256, | ||
| 400 | NULL, 0); | ||
| 398 | /* config I2S */ | 401 | /* config I2S */ |
| 399 | ret = mtk_afe_set_i2s(afe, substream->runtime->rate); | 402 | ret = mtk_afe_set_i2s(afe, substream->runtime->rate); |
| 400 | if (ret) | 403 | if (ret) |
| @@ -592,6 +595,7 @@ static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream, | |||
| 592 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 595 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 593 | struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | 596 | struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); |
| 594 | struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; | 597 | struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; |
| 598 | int msb_at_bit33 = 0; | ||
| 595 | int ret; | 599 | int ret; |
| 596 | 600 | ||
| 597 | dev_dbg(afe->dev, | 601 | dev_dbg(afe->dev, |
| @@ -603,7 +607,8 @@ static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream, | |||
| 603 | if (ret < 0) | 607 | if (ret < 0) |
| 604 | return ret; | 608 | return ret; |
| 605 | 609 | ||
| 606 | memif->phys_buf_addr = substream->runtime->dma_addr; | 610 | msb_at_bit33 = upper_32_bits(substream->runtime->dma_addr) ? 1 : 0; |
| 611 | memif->phys_buf_addr = lower_32_bits(substream->runtime->dma_addr); | ||
| 607 | memif->buffer_size = substream->runtime->dma_bytes; | 612 | memif->buffer_size = substream->runtime->dma_bytes; |
| 608 | 613 | ||
| 609 | /* start */ | 614 | /* start */ |
| @@ -614,6 +619,11 @@ static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream, | |||
| 614 | memif->data->reg_ofs_base + AFE_BASE_END_OFFSET, | 619 | memif->data->reg_ofs_base + AFE_BASE_END_OFFSET, |
| 615 | memif->phys_buf_addr + memif->buffer_size - 1); | 620 | memif->phys_buf_addr + memif->buffer_size - 1); |
| 616 | 621 | ||
| 622 | /* set MSB to 33-bit */ | ||
| 623 | regmap_update_bits(afe->regmap, AFE_MEMIF_MSB, | ||
| 624 | 1 << memif->data->msb_shift, | ||
| 625 | msb_at_bit33 << memif->data->msb_shift); | ||
| 626 | |||
| 617 | /* set channel */ | 627 | /* set channel */ |
| 618 | if (memif->data->mono_shift >= 0) { | 628 | if (memif->data->mono_shift >= 0) { |
| 619 | unsigned int mono = (params_channels(params) == 1) ? 1 : 0; | 629 | unsigned int mono = (params_channels(params) == 1) ? 1 : 0; |
| @@ -894,15 +904,19 @@ static const struct snd_kcontrol_new mtk_afe_o04_mix[] = { | |||
| 894 | }; | 904 | }; |
| 895 | 905 | ||
| 896 | static const struct snd_kcontrol_new mtk_afe_o09_mix[] = { | 906 | static const struct snd_kcontrol_new mtk_afe_o09_mix[] = { |
| 907 | SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN3, 0, 1, 0), | ||
| 897 | SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN7, 30, 1, 0), | 908 | SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN7, 30, 1, 0), |
| 898 | }; | 909 | }; |
| 899 | 910 | ||
| 900 | static const struct snd_kcontrol_new mtk_afe_o10_mix[] = { | 911 | static const struct snd_kcontrol_new mtk_afe_o10_mix[] = { |
| 912 | SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN3, 3, 1, 0), | ||
| 901 | SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN8, 0, 1, 0), | 913 | SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN8, 0, 1, 0), |
| 902 | }; | 914 | }; |
| 903 | 915 | ||
| 904 | static const struct snd_soc_dapm_widget mtk_afe_pcm_widgets[] = { | 916 | static const struct snd_soc_dapm_widget mtk_afe_pcm_widgets[] = { |
| 905 | /* inter-connections */ | 917 | /* inter-connections */ |
| 918 | SND_SOC_DAPM_MIXER("I03", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
| 919 | SND_SOC_DAPM_MIXER("I04", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
| 906 | SND_SOC_DAPM_MIXER("I05", SND_SOC_NOPM, 0, 0, NULL, 0), | 920 | SND_SOC_DAPM_MIXER("I05", SND_SOC_NOPM, 0, 0, NULL, 0), |
| 907 | SND_SOC_DAPM_MIXER("I06", SND_SOC_NOPM, 0, 0, NULL, 0), | 921 | SND_SOC_DAPM_MIXER("I06", SND_SOC_NOPM, 0, 0, NULL, 0), |
| 908 | SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0), | 922 | SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0), |
| @@ -925,12 +939,16 @@ static const struct snd_soc_dapm_route mtk_afe_pcm_routes[] = { | |||
| 925 | {"I2S Playback", NULL, "O04"}, | 939 | {"I2S Playback", NULL, "O04"}, |
| 926 | {"VUL", NULL, "O09"}, | 940 | {"VUL", NULL, "O09"}, |
| 927 | {"VUL", NULL, "O10"}, | 941 | {"VUL", NULL, "O10"}, |
| 942 | {"I03", NULL, "I2S Capture"}, | ||
| 943 | {"I04", NULL, "I2S Capture"}, | ||
| 928 | {"I17", NULL, "I2S Capture"}, | 944 | {"I17", NULL, "I2S Capture"}, |
| 929 | {"I18", NULL, "I2S Capture"}, | 945 | {"I18", NULL, "I2S Capture"}, |
| 930 | { "O03", "I05 Switch", "I05" }, | 946 | { "O03", "I05 Switch", "I05" }, |
| 931 | { "O04", "I06 Switch", "I06" }, | 947 | { "O04", "I06 Switch", "I06" }, |
| 932 | { "O09", "I17 Switch", "I17" }, | 948 | { "O09", "I17 Switch", "I17" }, |
| 949 | { "O09", "I03 Switch", "I03" }, | ||
| 933 | { "O10", "I18 Switch", "I18" }, | 950 | { "O10", "I18 Switch", "I18" }, |
| 951 | { "O10", "I04 Switch", "I04" }, | ||
| 934 | }; | 952 | }; |
| 935 | 953 | ||
| 936 | static const struct snd_soc_dapm_route mtk_afe_hdmi_routes[] = { | 954 | static const struct snd_soc_dapm_route mtk_afe_hdmi_routes[] = { |
| @@ -978,6 +996,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { | |||
| 978 | .irq_en_shift = 0, | 996 | .irq_en_shift = 0, |
| 979 | .irq_fs_shift = 4, | 997 | .irq_fs_shift = 4, |
| 980 | .irq_clr_shift = 0, | 998 | .irq_clr_shift = 0, |
| 999 | .msb_shift = 0, | ||
| 981 | }, { | 1000 | }, { |
| 982 | .name = "DL2", | 1001 | .name = "DL2", |
| 983 | .id = MTK_AFE_MEMIF_DL2, | 1002 | .id = MTK_AFE_MEMIF_DL2, |
| @@ -991,6 +1010,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { | |||
| 991 | .irq_en_shift = 2, | 1010 | .irq_en_shift = 2, |
| 992 | .irq_fs_shift = 16, | 1011 | .irq_fs_shift = 16, |
| 993 | .irq_clr_shift = 2, | 1012 | .irq_clr_shift = 2, |
| 1013 | .msb_shift = 1, | ||
| 994 | }, { | 1014 | }, { |
| 995 | .name = "VUL", | 1015 | .name = "VUL", |
| 996 | .id = MTK_AFE_MEMIF_VUL, | 1016 | .id = MTK_AFE_MEMIF_VUL, |
| @@ -1004,6 +1024,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { | |||
| 1004 | .irq_en_shift = 1, | 1024 | .irq_en_shift = 1, |
| 1005 | .irq_fs_shift = 8, | 1025 | .irq_fs_shift = 8, |
| 1006 | .irq_clr_shift = 1, | 1026 | .irq_clr_shift = 1, |
| 1027 | .msb_shift = 6, | ||
| 1007 | }, { | 1028 | }, { |
| 1008 | .name = "DAI", | 1029 | .name = "DAI", |
| 1009 | .id = MTK_AFE_MEMIF_DAI, | 1030 | .id = MTK_AFE_MEMIF_DAI, |
| @@ -1017,6 +1038,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { | |||
| 1017 | .irq_en_shift = 3, | 1038 | .irq_en_shift = 3, |
| 1018 | .irq_fs_shift = 20, | 1039 | .irq_fs_shift = 20, |
| 1019 | .irq_clr_shift = 3, | 1040 | .irq_clr_shift = 3, |
| 1041 | .msb_shift = 5, | ||
| 1020 | }, { | 1042 | }, { |
| 1021 | .name = "AWB", | 1043 | .name = "AWB", |
| 1022 | .id = MTK_AFE_MEMIF_AWB, | 1044 | .id = MTK_AFE_MEMIF_AWB, |
| @@ -1030,6 +1052,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { | |||
| 1030 | .irq_en_shift = 14, | 1052 | .irq_en_shift = 14, |
| 1031 | .irq_fs_shift = 24, | 1053 | .irq_fs_shift = 24, |
| 1032 | .irq_clr_shift = 6, | 1054 | .irq_clr_shift = 6, |
| 1055 | .msb_shift = 3, | ||
| 1033 | }, { | 1056 | }, { |
| 1034 | .name = "MOD_DAI", | 1057 | .name = "MOD_DAI", |
| 1035 | .id = MTK_AFE_MEMIF_MOD_DAI, | 1058 | .id = MTK_AFE_MEMIF_MOD_DAI, |
| @@ -1043,6 +1066,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { | |||
| 1043 | .irq_en_shift = 3, | 1066 | .irq_en_shift = 3, |
| 1044 | .irq_fs_shift = 20, | 1067 | .irq_fs_shift = 20, |
| 1045 | .irq_clr_shift = 3, | 1068 | .irq_clr_shift = 3, |
| 1069 | .msb_shift = 4, | ||
| 1046 | }, { | 1070 | }, { |
| 1047 | .name = "HDMI", | 1071 | .name = "HDMI", |
| 1048 | .id = MTK_AFE_MEMIF_HDMI, | 1072 | .id = MTK_AFE_MEMIF_HDMI, |
| @@ -1056,6 +1080,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { | |||
| 1056 | .irq_en_shift = 12, | 1080 | .irq_en_shift = 12, |
| 1057 | .irq_fs_shift = -1, | 1081 | .irq_fs_shift = -1, |
| 1058 | .irq_clr_shift = 4, | 1082 | .irq_clr_shift = 4, |
| 1083 | .msb_shift = 8, | ||
| 1059 | }, | 1084 | }, |
| 1060 | }; | 1085 | }; |
| 1061 | 1086 | ||
| @@ -1189,6 +1214,10 @@ static int mtk_afe_pcm_dev_probe(struct platform_device *pdev) | |||
| 1189 | struct mtk_afe *afe; | 1214 | struct mtk_afe *afe; |
| 1190 | struct resource *res; | 1215 | struct resource *res; |
| 1191 | 1216 | ||
| 1217 | ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33)); | ||
| 1218 | if (ret) | ||
| 1219 | return ret; | ||
| 1220 | |||
| 1192 | afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); | 1221 | afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); |
| 1193 | if (!afe) | 1222 | if (!afe) |
| 1194 | return -ENOMEM; | 1223 | return -ENOMEM; |
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index a6c7b8d87cd2..13631003cb7c 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
| @@ -418,7 +418,7 @@ static int mxs_saif_hw_params(struct snd_pcm_substream *substream, | |||
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | stat = __raw_readl(saif->base + SAIF_STAT); | 420 | stat = __raw_readl(saif->base + SAIF_STAT); |
| 421 | if (stat & BM_SAIF_STAT_BUSY) { | 421 | if (!saif->mclk_in_use && (stat & BM_SAIF_STAT_BUSY)) { |
| 422 | dev_err(cpu_dai->dev, "error: busy\n"); | 422 | dev_err(cpu_dai->dev, "error: busy\n"); |
| 423 | return -EBUSY; | 423 | return -EBUSY; |
| 424 | } | 424 | } |
diff --git a/sound/soc/omap/omap-hdmi-audio.c b/sound/soc/omap/omap-hdmi-audio.c index f83cc2bc0fc4..64425d352962 100644 --- a/sound/soc/omap/omap-hdmi-audio.c +++ b/sound/soc/omap/omap-hdmi-audio.c | |||
| @@ -345,6 +345,7 @@ static int omap_hdmi_audio_probe(struct platform_device *pdev) | |||
| 345 | dai_drv = &omap4_hdmi_dai; | 345 | dai_drv = &omap4_hdmi_dai; |
| 346 | break; | 346 | break; |
| 347 | case OMAPDSS_VER_OMAP5: | 347 | case OMAPDSS_VER_OMAP5: |
| 348 | case OMAPDSS_VER_DRA7xx: | ||
| 348 | dai_drv = &omap5_hdmi_dai; | 349 | dai_drv = &omap5_hdmi_dai; |
| 349 | break; | 350 | break; |
| 350 | default: | 351 | default: |
