static void log_quirks(struct device *dev) { if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_DMIC_MAP) dev_info(dev, "quirk DMIC_MAP enabled"); if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_MAP) dev_info(dev, "quirk IN1_MAP enabled"); if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN2_MAP) dev_info(dev, "quirk IN2_MAP enabled"); if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_IN2_MAP) dev_info(dev, "quirk IN1_IN2_MAP enabled"); if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) { dev_info(dev, "quirk realtek,jack-detect-source %ld\n", BYT_RT5651_JDSRC(byt_rt5651_quirk)); dev_info(dev, "quirk realtek,over-current-threshold-microamp %ld\n", BYT_RT5651_OVCD_TH(byt_rt5651_quirk) * 100); dev_info(dev, "quirk realtek,over-current-scale-factor %ld\n", BYT_RT5651_OVCD_SF(byt_rt5651_quirk)); } if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN) dev_info(dev, "quirk DMIC enabled"); if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) dev_info(dev, "quirk MCLK_EN enabled"); if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ) dev_info(dev, "quirk MCLK_25MHZ enabled"); if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) dev_info(dev, "quirk SSP2_AIF2 enabled\n"); if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) dev_info(dev, "quirk SSP0_AIF1 enabled\n"); if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2) dev_info(dev, "quirk SSP0_AIF2 enabled\n"); if (byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER) dev_info(dev, "quirk MONO_SPEAKER enabled\n"); }
static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime) { int ret; struct snd_soc_card *card = runtime->card; const struct snd_soc_dapm_route *custom_map; int num_routes; card->dapm.idle_bias_off = true; dmi_check_system(byt_rt5651_quirk_table); switch (BYT_RT5651_MAP(byt_rt5651_quirk)) { case BYT_RT5651_IN1_MAP: custom_map = byt_rt5651_intmic_in1_map; num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_map); break; case BYT_RT5651_DMIC2_MAP: custom_map = byt_rt5651_intmic_dmic2_map; num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic2_map); break; default: custom_map = byt_rt5651_intmic_dmic1_map; num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic1_map); } ret = snd_soc_add_card_controls(card, byt_rt5651_controls, ARRAY_SIZE(byt_rt5651_controls)); if (ret) { dev_err(card->dev, "unable to add card controls\n"); return ret; } snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); return ret; }
static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) { const char * const mic_name[] = { "dmic", "in1", "in2", "in12" }; struct byt_rt5651_private *priv; struct snd_soc_acpi_mach *mach; struct device *codec_dev; const char *i2c_name = NULL; const char *hp_swapped; bool is_bytcr = false; int ret_val = 0; int dai_index = 0; int i; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; /* register the soc card */ byt_rt5651_card.dev = &pdev->dev; mach = byt_rt5651_card.dev->platform_data; snd_soc_card_set_drvdata(&byt_rt5651_card, priv); /* fix index of codec dai */ for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) { if (!strcmp(byt_rt5651_dais[i].codec_name, "i2c-10EC5651:00")) { dai_index = i; break; } } /* fixup codec name based on HID */ i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1); if (!i2c_name) { dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id); return -ENODEV; } snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name), "%s%s", "i2c-", i2c_name); byt_rt5651_dais[dai_index].codec_name = byt_rt5651_codec_name; codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, byt_rt5651_codec_name); if (!codec_dev) return -EPROBE_DEFER; /* * swap SSP0 if bytcr is detected * (will be overridden if DMI quirk is detected) */ if (x86_match_cpu(baytrail_cpu_ids)) { struct sst_platform_info *p_info = mach->pdata; const struct sst_res_info *res_info = p_info->res_info; if (res_info->acpi_ipc_irq_index == 0) is_bytcr = true; } if (is_bytcr) { /* * Baytrail CR platforms may have CHAN package in BIOS, try * to find relevant routing quirk based as done on Windows * platforms. We have to read the information directly from the * BIOS, at this stage the card is not created and the links * with the codec driver/pdata are non-existent */ struct acpi_chan_package chan_package; /* format specified: 2 64-bit integers */ struct acpi_buffer format = {sizeof("NN"), "NN"}; struct acpi_buffer state = {0, NULL}; struct snd_soc_acpi_package_context pkg_ctx; bool pkg_found = false; state.length = sizeof(chan_package); state.pointer = &chan_package; pkg_ctx.name = "CHAN"; pkg_ctx.length = 2; pkg_ctx.format = &format; pkg_ctx.state = &state; pkg_ctx.data_valid = false; pkg_found = snd_soc_acpi_find_package_from_hid(mach->id, &pkg_ctx); if (pkg_found) { if (chan_package.aif_value == 1) { dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n"); byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF1; } else if (chan_package.aif_value == 2) { dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n"); byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2; } else { dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n"); pkg_found = false; } } if (!pkg_found) { /* no BIOS indications, assume SSP0-AIF2 connection */ byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2; } } /* check quirks before creating card */ dmi_check_system(byt_rt5651_quirk_table); /* Must be called before register_card, also see declaration comment. */ ret_val = byt_rt5651_add_codec_device_props(codec_dev); if (ret_val) { put_device(codec_dev); return ret_val; } /* Cherry Trail devices use an external amplifier enable gpio */ if (x86_match_cpu(cherrytrail_cpu_ids)) { snd_byt_rt5651_mc_add_amp_en_gpio_mapping(codec_dev); priv->ext_amp_gpio = devm_fwnode_get_index_gpiod_from_child( &pdev->dev, "ext-amp-enable", 0, codec_dev->fwnode, GPIOD_OUT_LOW, "speaker-amp"); if (IS_ERR(priv->ext_amp_gpio)) { ret_val = PTR_ERR(priv->ext_amp_gpio); switch (ret_val) { case -ENOENT: priv->ext_amp_gpio = NULL; break; default: dev_err(&pdev->dev, "Failed to get ext-amp-enable GPIO: %d\n", ret_val); /* fall through */ case -EPROBE_DEFER: put_device(codec_dev); return ret_val; } } } put_device(codec_dev); log_quirks(&pdev->dev); if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) || (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) { /* fixup codec aif name */ snprintf(byt_rt5651_codec_aif_name, sizeof(byt_rt5651_codec_aif_name), "%s", "rt5651-aif2"); byt_rt5651_dais[dai_index].codec_dai_name = byt_rt5651_codec_aif_name; } if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) || (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) { /* fixup cpu dai name name */ snprintf(byt_rt5651_cpu_dai_name, sizeof(byt_rt5651_cpu_dai_name), "%s", "ssp0-port"); byt_rt5651_dais[dai_index].cpu_dai_name = byt_rt5651_cpu_dai_name; } if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) { priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); if (IS_ERR(priv->mclk)) { ret_val = PTR_ERR(priv->mclk); dev_err(&pdev->dev, "Failed to get MCLK from pmc_plt_clk_3: %d\n", ret_val); /* * Fall back to bit clock usage for -ENOENT (clock not * available likely due to missing dependencies), bail * for all other errors, including -EPROBE_DEFER */ if (ret_val != -ENOENT) return ret_val; byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN; } } if (byt_rt5651_quirk & BYT_RT5651_HP_LR_SWAPPED) hp_swapped = "-hp-swapped"; else hp_swapped = ""; snprintf(byt_rt5651_long_name, sizeof(byt_rt5651_long_name), "bytcr-rt5651-%s-spk-%s-mic%s", (byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER) ? "mono" : "stereo", mic_name[BYT_RT5651_MAP(byt_rt5651_quirk)], hp_swapped); byt_rt5651_card.long_name = byt_rt5651_long_name; ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card); if (ret_val) { dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n", ret_val); return ret_val; } platform_set_drvdata(pdev, &byt_rt5651_card); return ret_val; }
static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime) { struct snd_soc_card *card = runtime->card; struct snd_soc_component *codec = runtime->codec_dai->component; struct byt_rt5651_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; /* Start with RC clk for jack-detect (we disable MCLK below) */ if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) snd_soc_component_update_bits(codec, RT5651_GLB_CLK, RT5651_SCLK_SRC_MASK, RT5651_SCLK_SRC_RCCLK); switch (BYT_RT5651_MAP(byt_rt5651_quirk)) { case BYT_RT5651_IN1_MAP: custom_map = byt_rt5651_intmic_in1_map; num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_map); break; case BYT_RT5651_IN2_MAP: custom_map = byt_rt5651_intmic_in2_map; num_routes = ARRAY_SIZE(byt_rt5651_intmic_in2_map); break; case BYT_RT5651_IN1_IN2_MAP: custom_map = byt_rt5651_intmic_in1_in2_map; num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_in2_map); break; default: custom_map = byt_rt5651_intmic_dmic_map; num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic_map); } ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes); if (ret) return ret; if (byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) { ret = snd_soc_dapm_add_routes(&card->dapm, byt_rt5651_ssp2_aif2_map, ARRAY_SIZE(byt_rt5651_ssp2_aif2_map)); } else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) { ret = snd_soc_dapm_add_routes(&card->dapm, byt_rt5651_ssp0_aif1_map, ARRAY_SIZE(byt_rt5651_ssp0_aif1_map)); } else if (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2) { ret = snd_soc_dapm_add_routes(&card->dapm, byt_rt5651_ssp0_aif2_map, ARRAY_SIZE(byt_rt5651_ssp0_aif2_map)); } else { ret = snd_soc_dapm_add_routes(&card->dapm, byt_rt5651_ssp2_aif1_map, ARRAY_SIZE(byt_rt5651_ssp2_aif1_map)); } if (ret) return ret; ret = snd_soc_add_card_controls(card, byt_rt5651_controls, ARRAY_SIZE(byt_rt5651_controls)); if (ret) { dev_err(card->dev, "unable to add card controls\n"); return ret; } snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone"); snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) { /* * The firmware might enable the clock at * boot (this information may or may not * be reflected in the enable clock register). * To change the rate we must disable the clock * first to cover these cases. Due to common * clock framework restrictions that do not allow * to disable a clock that has not been enabled, * we need to enable the clock first. */ ret = clk_prepare_enable(priv->mclk); if (!ret) clk_disable_unprepare(priv->mclk); if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ) ret = clk_set_rate(priv->mclk, 25000000); else ret = clk_set_rate(priv->mclk, 19200000); if (ret) dev_err(card->dev, "unable to set MCLK rate\n"); } if (BYT_RT5651_JDSRC(byt_rt5651_quirk)) { ret = snd_soc_card_jack_new(runtime->card, "Headset", SND_JACK_HEADSET | SND_JACK_BTN_0, &priv->jack, bytcr_jack_pins, ARRAY_SIZE(bytcr_jack_pins)); if (ret) { dev_err(runtime->dev, "jack creation failed %d\n", ret); return ret; } snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); ret = snd_soc_component_set_jack(codec, &priv->jack, NULL); if (ret) return ret; } return 0; }