diff options
Diffstat (limited to 'sound/soc/intel/boards/bytcht_es8316.c')
| -rw-r--r-- | sound/soc/intel/boards/bytcht_es8316.c | 121 |
1 files changed, 99 insertions, 22 deletions
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index 7a30d2d36f19..192e2a394ff3 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -27,6 +27,7 @@ #include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/soc-acpi.h> +#include "../../codecs/es83xx-dsm-common.h" #include "../atom/sst-atom-controls.h" #include "../common/soc-intel-quirks.h" @@ -46,7 +47,8 @@ enum { BYT_CHT_ES8316_INTMIC_IN2_MAP, }; -#define BYT_CHT_ES8316_MAP(quirk) ((quirk) & GENMASK(3, 0)) +#define BYT_CHT_ES8316_MAP_MASK GENMASK(3, 0) +#define BYT_CHT_ES8316_MAP(quirk) ((quirk) & BYT_CHT_ES8316_MAP_MASK) #define BYT_CHT_ES8316_SSP0 BIT(16) #define BYT_CHT_ES8316_MONO_SPEAKER BIT(17) #define BYT_CHT_ES8316_JD_INVERTED BIT(18) @@ -59,10 +61,23 @@ MODULE_PARM_DESC(quirk, "Board-specific quirk override"); static void log_quirks(struct device *dev) { - if (BYT_CHT_ES8316_MAP(quirk) == BYT_CHT_ES8316_INTMIC_IN1_MAP) + int map; + + map = BYT_CHT_ES8316_MAP(quirk); + switch (map) { + case BYT_CHT_ES8316_INTMIC_IN1_MAP: dev_info(dev, "quirk IN1_MAP enabled"); - if (BYT_CHT_ES8316_MAP(quirk) == BYT_CHT_ES8316_INTMIC_IN2_MAP) + break; + case BYT_CHT_ES8316_INTMIC_IN2_MAP: dev_info(dev, "quirk IN2_MAP enabled"); + break; + default: + dev_warn_once(dev, "quirk sets invalid input map: 0x%x, default to INTMIC_IN1_MAP\n", map); + quirk &= ~BYT_CHT_ES8316_MAP_MASK; + quirk |= BYT_CHT_ES8316_INTMIC_IN1_MAP; + break; + } + if (quirk & BYT_CHT_ES8316_SSP0) dev_info(dev, "quirk SSP0 enabled"); if (quirk & BYT_CHT_ES8316_MONO_SPEAKER) @@ -74,7 +89,7 @@ static void log_quirks(struct device *dev) static int byt_cht_es8316_speaker_power_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { - struct snd_soc_card *card = w->dapm->card; + struct snd_soc_card *card = snd_soc_dapm_to_card(w->dapm); struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card); if (SND_SOC_DAPM_EVENT_ON(event)) @@ -157,14 +172,15 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = { static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime) { - struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component; + struct snd_soc_component *codec = snd_soc_rtd_to_codec(runtime, 0)->component; struct snd_soc_card *card = runtime->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card); const struct snd_soc_dapm_route *custom_map; int num_routes; int ret; - card->dapm.idle_bias_off = true; + snd_soc_dapm_set_idle_bias(dapm, false); switch (BYT_CHT_ES8316_MAP(quirk)) { case BYT_CHT_ES8316_INTMIC_IN1_MAP: @@ -177,7 +193,7 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime) num_routes = ARRAY_SIZE(byt_cht_es8316_intmic_in2_map); break; } - ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes); + ret = snd_soc_dapm_add_routes(dapm, custom_map, num_routes); if (ret) return ret; @@ -188,7 +204,7 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime) custom_map = byt_cht_es8316_ssp2_map; num_routes = ARRAY_SIZE(byt_cht_es8316_ssp2_map); } - ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes); + ret = snd_soc_dapm_add_routes(dapm, custom_map, num_routes); if (ret) return ret; @@ -212,7 +228,7 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime) if (ret) dev_err(card->dev, "unable to enable MCLK\n"); - ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(runtime, 0), 0, 19200000, + ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(runtime, 0), 0, 19200000, SND_SOC_CLOCK_IN); if (ret < 0) { dev_err(card->dev, "can't set codec clock %d\n", ret); @@ -262,7 +278,7 @@ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd, * with explicit setting to I2S 2ch 24-bit. The word length is set with * dai_set_tdm_slot() since there is no other API exposed */ - ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), + ret = snd_soc_dai_set_fmt(snd_soc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_BP_FP @@ -272,7 +288,7 @@ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd, return ret; } - ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits); + ret = snd_soc_dai_set_tdm_slot(snd_soc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits); if (ret < 0) { dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); return ret; @@ -314,8 +330,6 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = { .stream_name = "Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, .ops = &byt_cht_es8316_aif1_ops, SND_SOC_DAILINK_REG(media, dummy, platform), }, @@ -325,7 +339,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = { .stream_name = "Deep-Buffer Audio", .nonatomic = true, .dynamic = 1, - .dpcm_playback = 1, + .playback_only = 1, .ops = &byt_cht_es8316_aif1_ops, SND_SOC_DAILINK_REG(deepbuffer, dummy, platform), }, @@ -338,8 +352,6 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = { .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC, .be_hw_params_fixup = byt_cht_es8316_codec_fixup, - .dpcm_playback = 1, - .dpcm_capture = 1, .init = byt_cht_es8316_init, SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, @@ -461,6 +473,66 @@ static const struct dmi_system_id byt_cht_es8316_quirk_table[] = { {} }; +static int byt_cht_es8316_get_quirks_from_dsm(struct byt_cht_es8316_private *priv, + bool is_bytcr) +{ + int ret, val1, val2, dsm_quirk = 0; + + if (is_bytcr) + dsm_quirk |= BYT_CHT_ES8316_SSP0; + + ret = es83xx_dsm(priv->codec_dev, PLATFORM_MAINMIC_TYPE_ARG, &val1); + if (ret < 0) + return ret; + + ret = es83xx_dsm(priv->codec_dev, PLATFORM_HPMIC_TYPE_ARG, &val2); + if (ret < 0) + return ret; + + if (val1 == PLATFORM_MIC_AMIC_LIN1RIN1 && val2 == PLATFORM_MIC_AMIC_LIN2RIN2) { + dsm_quirk |= BYT_CHT_ES8316_INTMIC_IN1_MAP; + } else if (val1 == PLATFORM_MIC_AMIC_LIN2RIN2 && val2 == PLATFORM_MIC_AMIC_LIN1RIN1) { + dsm_quirk |= BYT_CHT_ES8316_INTMIC_IN2_MAP; + } else { + dev_warn(priv->codec_dev, "Unknown mic settings mainmic 0x%02x hpmic 0x%02x\n", + val1, val2); + return -EINVAL; + } + + ret = es83xx_dsm(priv->codec_dev, PLATFORM_SPK_TYPE_ARG, &val1); + if (ret < 0) + return ret; + + switch (val1) { + case PLATFORM_SPK_MONO: + dsm_quirk |= BYT_CHT_ES8316_MONO_SPEAKER; + break; + case PLATFORM_SPK_STEREO: + break; + default: + dev_warn(priv->codec_dev, "Unknown speaker setting 0x%02x\n", val1); + return -EINVAL; + } + + ret = es83xx_dsm(priv->codec_dev, PLATFORM_HPDET_INV_ARG, &val1); + if (ret < 0) + return ret; + + switch (val1) { + case PLATFORM_HPDET_NORMAL: + break; + case PLATFORM_HPDET_INVERTED: + dsm_quirk |= BYT_CHT_ES8316_JD_INVERTED; + break; + default: + dev_warn(priv->codec_dev, "Unknown hpdet-inv setting 0x%02x\n", val1); + return -EINVAL; + } + + quirk = dsm_quirk; + return 0; +} + static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -470,10 +542,10 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) struct byt_cht_es8316_private *priv; const struct dmi_system_id *dmi_id; struct fwnode_handle *fwnode; + bool sof_parent, is_bytcr; const char *platform_name; struct acpi_device *adev; struct device *codec_dev; - bool sof_parent; unsigned int cnt = 0; int dai_index = 0; int i; @@ -485,7 +557,8 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) /* fix index of codec dai */ for (i = 0; i < ARRAY_SIZE(byt_cht_es8316_dais); i++) { - if (!strcmp(byt_cht_es8316_dais[i].codecs->name, + if (byt_cht_es8316_dais[i].num_codecs && + !strcmp(byt_cht_es8316_dais[i].codecs->name, "i2c-ESSX8316:00")) { dai_index = i; break; @@ -500,7 +573,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) byt_cht_es8316_dais[dai_index].codecs->name = codec_name; } else { dev_err(dev, "Error cannot find '%s' dev\n", mach->id); - return -ENXIO; + return -ENOENT; } codec_dev = acpi_get_first_physical_node(adev); @@ -520,12 +593,16 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) return ret; } + es83xx_dsm_dump(priv->codec_dev); + /* Check for BYTCR or other platform and setup quirks */ + is_bytcr = soc_intel_is_byt() && mach->mach_params.acpi_ipc_irq_index == 0; dmi_id = dmi_first_match(byt_cht_es8316_quirk_table); if (dmi_id) { quirk = (unsigned long)dmi_id->driver_data; - } else if (soc_intel_is_byt() && - mach->mach_params.acpi_ipc_irq_index == 0) { + } else if (!byt_cht_es8316_get_quirks_from_dsm(priv, is_bytcr)) { + dev_info(dev, "Using ACPI DSM info for quirks\n"); + } else if (is_bytcr) { /* On BYTCR default to SSP0, internal-mic-in2-map, mono-spk */ quirk = BYT_CHT_ES8316_SSP0 | BYT_CHT_ES8316_INTMIC_IN2_MAP | BYT_CHT_ES8316_MONO_SPEAKER; @@ -643,7 +720,7 @@ static struct platform_driver snd_byt_cht_es8316_mc_driver = { .name = "bytcht_es8316", }, .probe = snd_byt_cht_es8316_mc_probe, - .remove_new = snd_byt_cht_es8316_mc_remove, + .remove = snd_byt_cht_es8316_mc_remove, }; module_platform_driver(snd_byt_cht_es8316_mc_driver); |
