Path: blob/master/sound/soc/intel/boards/bytcr_rt5640.c
29268 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* byt_cr_dpcm_rt5640.c - ASoc Machine driver for Intel Byt CR platform3*4* Copyright (C) 2014 Intel Corp5* Author: Subhransu S. Prusty <[email protected]>6* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~7*8* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~9*/1011#include <linux/i2c.h>12#include <linux/init.h>13#include <linux/module.h>14#include <linux/moduleparam.h>15#include <linux/platform_device.h>16#include <linux/acpi.h>17#include <linux/clk.h>18#include <linux/device.h>19#include <linux/device/bus.h>20#include <linux/dmi.h>21#include <linux/gpio/consumer.h>22#include <linux/gpio/machine.h>23#include <linux/input.h>24#include <linux/slab.h>25#include <sound/pcm.h>26#include <sound/pcm_params.h>27#include <sound/soc.h>28#include <sound/jack.h>29#include <sound/soc-acpi.h>30#include <dt-bindings/sound/rt5640.h>31#include "../../codecs/rt5640.h"32#include "../atom/sst-atom-controls.h"33#include "../common/soc-intel-quirks.h"3435#define BYT_RT5640_FALLBACK_CODEC_DEV_NAME "i2c-rt5640"3637enum {38BYT_RT5640_DMIC1_MAP,39BYT_RT5640_DMIC2_MAP,40BYT_RT5640_IN1_MAP,41BYT_RT5640_IN3_MAP,42BYT_RT5640_NO_INTERNAL_MIC_MAP,43};4445#define RT5640_JD_SRC_EXT_GPIO 0x0f4647enum {48BYT_RT5640_JD_SRC_GPIO1 = (RT5640_JD_SRC_GPIO1 << 4),49BYT_RT5640_JD_SRC_JD1_IN4P = (RT5640_JD_SRC_JD1_IN4P << 4),50BYT_RT5640_JD_SRC_JD2_IN4N = (RT5640_JD_SRC_JD2_IN4N << 4),51BYT_RT5640_JD_SRC_GPIO2 = (RT5640_JD_SRC_GPIO2 << 4),52BYT_RT5640_JD_SRC_GPIO3 = (RT5640_JD_SRC_GPIO3 << 4),53BYT_RT5640_JD_SRC_GPIO4 = (RT5640_JD_SRC_GPIO4 << 4),54BYT_RT5640_JD_SRC_EXT_GPIO = (RT5640_JD_SRC_EXT_GPIO << 4)55};5657enum {58BYT_RT5640_OVCD_TH_600UA = (6 << 8),59BYT_RT5640_OVCD_TH_1500UA = (15 << 8),60BYT_RT5640_OVCD_TH_2000UA = (20 << 8),61};6263enum {64BYT_RT5640_OVCD_SF_0P5 = (RT5640_OVCD_SF_0P5 << 13),65BYT_RT5640_OVCD_SF_0P75 = (RT5640_OVCD_SF_0P75 << 13),66BYT_RT5640_OVCD_SF_1P0 = (RT5640_OVCD_SF_1P0 << 13),67BYT_RT5640_OVCD_SF_1P5 = (RT5640_OVCD_SF_1P5 << 13),68};6970#define BYT_RT5640_MAP_MASK GENMASK(3, 0)71#define BYT_RT5640_MAP(quirk) ((quirk) & BYT_RT5640_MAP_MASK)72#define BYT_RT5640_JDSRC(quirk) (((quirk) & GENMASK(7, 4)) >> 4)73#define BYT_RT5640_OVCD_TH(quirk) (((quirk) & GENMASK(12, 8)) >> 8)74#define BYT_RT5640_OVCD_SF(quirk) (((quirk) & GENMASK(14, 13)) >> 13)75#define BYT_RT5640_JD_NOT_INV BIT(16)76#define BYT_RT5640_MONO_SPEAKER BIT(17)77#define BYT_RT5640_DIFF_MIC BIT(18) /* default is single-ended */78#define BYT_RT5640_SSP2_AIF2 BIT(19) /* default is using AIF1 */79#define BYT_RT5640_SSP0_AIF1 BIT(20)80#define BYT_RT5640_SSP0_AIF2 BIT(21)81#define BYT_RT5640_MCLK_EN BIT(22)82#define BYT_RT5640_MCLK_25MHZ BIT(23)83#define BYT_RT5640_NO_SPEAKERS BIT(24)84#define BYT_RT5640_LINEOUT BIT(25)85#define BYT_RT5640_LINEOUT_AS_HP2 BIT(26)86#define BYT_RT5640_HSMIC2_ON_IN1 BIT(27)87#define BYT_RT5640_JD_HP_ELITEP_1000G2 BIT(28)88#define BYT_RT5640_USE_AMCR0F28 BIT(29)89#define BYT_RT5640_SWAPPED_SPEAKERS BIT(30)9091#define BYTCR_INPUT_DEFAULTS \92(BYT_RT5640_IN3_MAP | \93BYT_RT5640_JD_SRC_JD1_IN4P | \94BYT_RT5640_OVCD_TH_2000UA | \95BYT_RT5640_OVCD_SF_0P75 | \96BYT_RT5640_DIFF_MIC)9798/* in-diff or dmic-pin + jdsrc + ovcd-th + -sf + jd-inv + terminating entry */99#define MAX_NO_PROPS 6100101struct byt_rt5640_private {102struct snd_soc_jack jack;103struct snd_soc_jack jack2;104struct rt5640_set_jack_data jack_data;105struct gpio_desc *hsmic_detect;106struct clk *mclk;107struct device *codec_dev;108};109static bool is_bytcr;110111static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN;112static int quirk_override = -1;113module_param_named(quirk, quirk_override, int, 0444);114MODULE_PARM_DESC(quirk, "Board-specific quirk override");115116static void log_quirks(struct device *dev)117{118int map;119bool has_mclk = false;120bool has_ssp0 = false;121bool has_ssp0_aif1 = false;122bool has_ssp0_aif2 = false;123bool has_ssp2_aif2 = false;124125map = BYT_RT5640_MAP(byt_rt5640_quirk);126switch (map) {127case BYT_RT5640_DMIC1_MAP:128dev_info(dev, "quirk DMIC1_MAP enabled\n");129break;130case BYT_RT5640_DMIC2_MAP:131dev_info(dev, "quirk DMIC2_MAP enabled\n");132break;133case BYT_RT5640_IN1_MAP:134dev_info(dev, "quirk IN1_MAP enabled\n");135break;136case BYT_RT5640_IN3_MAP:137dev_info(dev, "quirk IN3_MAP enabled\n");138break;139case BYT_RT5640_NO_INTERNAL_MIC_MAP:140dev_info(dev, "quirk NO_INTERNAL_MIC_MAP enabled\n");141break;142default:143dev_warn_once(dev, "quirk sets invalid input map: 0x%x, default to DMIC1_MAP\n", map);144byt_rt5640_quirk &= ~BYT_RT5640_MAP_MASK;145byt_rt5640_quirk |= BYT_RT5640_DMIC1_MAP;146break;147}148if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1)149dev_info(dev, "quirk HSMIC2_ON_IN1 enabled\n");150if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {151dev_info(dev, "quirk realtek,jack-detect-source %ld\n",152BYT_RT5640_JDSRC(byt_rt5640_quirk));153dev_info(dev, "quirk realtek,over-current-threshold-microamp %ld\n",154BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100);155dev_info(dev, "quirk realtek,over-current-scale-factor %ld\n",156BYT_RT5640_OVCD_SF(byt_rt5640_quirk));157}158if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)159dev_info(dev, "quirk JD_NOT_INV enabled\n");160if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)161dev_info(dev, "quirk JD_HP_ELITEPAD_1000G2 enabled\n");162if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER)163dev_info(dev, "quirk MONO_SPEAKER enabled\n");164if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)165dev_info(dev, "quirk NO_SPEAKERS enabled\n");166if (byt_rt5640_quirk & BYT_RT5640_SWAPPED_SPEAKERS)167dev_info(dev, "quirk SWAPPED_SPEAKERS enabled\n");168if (byt_rt5640_quirk & BYT_RT5640_LINEOUT)169dev_info(dev, "quirk LINEOUT enabled\n");170if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)171dev_info(dev, "quirk LINEOUT_AS_HP2 enabled\n");172if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)173dev_info(dev, "quirk DIFF_MIC enabled\n");174if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {175dev_info(dev, "quirk SSP0_AIF1 enabled\n");176has_ssp0 = true;177has_ssp0_aif1 = true;178}179if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) {180dev_info(dev, "quirk SSP0_AIF2 enabled\n");181has_ssp0 = true;182has_ssp0_aif2 = true;183}184if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {185dev_info(dev, "quirk SSP2_AIF2 enabled\n");186has_ssp2_aif2 = true;187}188if (is_bytcr && !has_ssp0)189dev_err(dev, "Invalid routing, bytcr detected but no SSP0-based quirk, audio cannot work with SSP2 on bytcr\n");190if (has_ssp0_aif1 && has_ssp0_aif2)191dev_err(dev, "Invalid routing, SSP0 cannot be connected to both AIF1 and AIF2\n");192if (has_ssp0 && has_ssp2_aif2)193dev_err(dev, "Invalid routing, cannot have both SSP0 and SSP2 connected to codec\n");194195if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {196dev_info(dev, "quirk MCLK_EN enabled\n");197has_mclk = true;198}199if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) {200if (has_mclk)201dev_info(dev, "quirk MCLK_25MHZ enabled\n");202else203dev_err(dev, "quirk MCLK_25MHZ enabled but quirk MCLK not selected, will be ignored\n");204}205}206207static int byt_rt5640_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,208int rate)209{210int ret;211212/* Configure the PLL before selecting it */213if (!(byt_rt5640_quirk & BYT_RT5640_MCLK_EN)) {214/* use bitclock as PLL input */215if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||216(byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {217/* 2x16 bit slots on SSP0 */218ret = snd_soc_dai_set_pll(codec_dai, 0,219RT5640_PLL1_S_BCLK1,220rate * 32, rate * 512);221} else {222/* 2x15 bit slots on SSP2 */223ret = snd_soc_dai_set_pll(codec_dai, 0,224RT5640_PLL1_S_BCLK1,225rate * 50, rate * 512);226}227} else {228if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) {229ret = snd_soc_dai_set_pll(codec_dai, 0,230RT5640_PLL1_S_MCLK,23125000000, rate * 512);232} else {233ret = snd_soc_dai_set_pll(codec_dai, 0,234RT5640_PLL1_S_MCLK,23519200000, rate * 512);236}237}238239if (ret < 0) {240dev_err(codec_dai->component->dev, "can't set pll: %d\n", ret);241return ret;242}243244ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1,245rate * 512, SND_SOC_CLOCK_IN);246if (ret < 0) {247dev_err(codec_dai->component->dev, "can't set clock %d\n", ret);248return ret;249}250251return 0;252}253254#define BYT_CODEC_DAI1 "rt5640-aif1"255#define BYT_CODEC_DAI2 "rt5640-aif2"256257static struct snd_soc_dai *byt_rt5640_get_codec_dai(struct snd_soc_dapm_context *dapm)258{259struct snd_soc_card *card = dapm->card;260struct snd_soc_dai *codec_dai;261262codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);263if (!codec_dai)264codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);265if (!codec_dai)266dev_err(card->dev, "Error codec dai not found\n");267268return codec_dai;269}270271static int platform_clock_control(struct snd_soc_dapm_widget *w,272struct snd_kcontrol *k, int event)273{274struct snd_soc_dapm_context *dapm = w->dapm;275struct snd_soc_card *card = dapm->card;276struct snd_soc_dai *codec_dai;277struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);278int ret;279280codec_dai = byt_rt5640_get_codec_dai(dapm);281if (!codec_dai)282return -EIO;283284if (SND_SOC_DAPM_EVENT_ON(event)) {285ret = clk_prepare_enable(priv->mclk);286if (ret < 0) {287dev_err(card->dev, "could not configure MCLK state\n");288return ret;289}290ret = byt_rt5640_prepare_and_enable_pll1(codec_dai, 48000);291} else {292/*293* Set codec clock source to internal clock before294* turning off the platform clock. Codec needs clock295* for Jack detection and button press296*/297ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_RCCLK,29848000 * 512,299SND_SOC_CLOCK_IN);300if (!ret)301clk_disable_unprepare(priv->mclk);302}303304if (ret < 0) {305dev_err(card->dev, "can't set codec sysclk: %d\n", ret);306return ret;307}308309return 0;310}311312static int byt_rt5640_event_lineout(struct snd_soc_dapm_widget *w,313struct snd_kcontrol *k, int event)314{315unsigned int gpio_ctrl3_val = RT5640_GP1_PF_OUT;316struct snd_soc_dai *codec_dai;317318if (!(byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2))319return 0;320321/*322* On devices which use line-out as a second headphones output,323* the codec's GPIO1 pin is used to enable an external HP-amp.324*/325326codec_dai = byt_rt5640_get_codec_dai(w->dapm);327if (!codec_dai)328return -EIO;329330if (SND_SOC_DAPM_EVENT_ON(event))331gpio_ctrl3_val |= RT5640_GP1_OUT_HI;332333snd_soc_component_update_bits(codec_dai->component, RT5640_GPIO_CTRL3,334RT5640_GP1_PF_MASK | RT5640_GP1_OUT_MASK, gpio_ctrl3_val);335336return 0;337}338339static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {340SND_SOC_DAPM_HP("Headphone", NULL),341SND_SOC_DAPM_MIC("Headset Mic", NULL),342SND_SOC_DAPM_MIC("Headset Mic 2", NULL),343SND_SOC_DAPM_MIC("Internal Mic", NULL),344SND_SOC_DAPM_SPK("Speaker", NULL),345SND_SOC_DAPM_LINE("Line Out", byt_rt5640_event_lineout),346SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,347platform_clock_control, SND_SOC_DAPM_PRE_PMU |348SND_SOC_DAPM_POST_PMD),349};350351static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {352{"Headphone", NULL, "Platform Clock"},353{"Headset Mic", NULL, "Platform Clock"},354{"Headset Mic", NULL, "MICBIAS1"},355{"IN2P", NULL, "Headset Mic"},356{"Headphone", NULL, "HPOL"},357{"Headphone", NULL, "HPOR"},358};359360static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = {361{"Internal Mic", NULL, "Platform Clock"},362{"DMIC1", NULL, "Internal Mic"},363};364365static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = {366{"Internal Mic", NULL, "Platform Clock"},367{"DMIC2", NULL, "Internal Mic"},368};369370static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = {371{"Internal Mic", NULL, "Platform Clock"},372{"Internal Mic", NULL, "MICBIAS1"},373{"IN1P", NULL, "Internal Mic"},374};375376static const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = {377{"Internal Mic", NULL, "Platform Clock"},378{"Internal Mic", NULL, "MICBIAS1"},379{"IN3P", NULL, "Internal Mic"},380};381382static const struct snd_soc_dapm_route byt_rt5640_hsmic2_in1_map[] = {383{"Headset Mic 2", NULL, "Platform Clock"},384{"Headset Mic 2", NULL, "MICBIAS1"},385{"IN1P", NULL, "Headset Mic 2"},386};387388static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = {389{"ssp2 Tx", NULL, "codec_out0"},390{"ssp2 Tx", NULL, "codec_out1"},391{"codec_in0", NULL, "ssp2 Rx"},392{"codec_in1", NULL, "ssp2 Rx"},393394{"AIF1 Playback", NULL, "ssp2 Tx"},395{"ssp2 Rx", NULL, "AIF1 Capture"},396};397398static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif2_map[] = {399{"ssp2 Tx", NULL, "codec_out0"},400{"ssp2 Tx", NULL, "codec_out1"},401{"codec_in0", NULL, "ssp2 Rx"},402{"codec_in1", NULL, "ssp2 Rx"},403404{"AIF2 Playback", NULL, "ssp2 Tx"},405{"ssp2 Rx", NULL, "AIF2 Capture"},406};407408static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif1_map[] = {409{"ssp0 Tx", NULL, "modem_out"},410{"modem_in", NULL, "ssp0 Rx"},411412{"AIF1 Playback", NULL, "ssp0 Tx"},413{"ssp0 Rx", NULL, "AIF1 Capture"},414};415416static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = {417{"ssp0 Tx", NULL, "modem_out"},418{"modem_in", NULL, "ssp0 Rx"},419420{"AIF2 Playback", NULL, "ssp0 Tx"},421{"ssp0 Rx", NULL, "AIF2 Capture"},422};423424static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = {425{"Speaker", NULL, "Platform Clock"},426{"Speaker", NULL, "SPOLP"},427{"Speaker", NULL, "SPOLN"},428{"Speaker", NULL, "SPORP"},429{"Speaker", NULL, "SPORN"},430};431432static const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = {433{"Speaker", NULL, "Platform Clock"},434{"Speaker", NULL, "SPOLP"},435{"Speaker", NULL, "SPOLN"},436};437438static const struct snd_soc_dapm_route byt_rt5640_lineout_map[] = {439{"Line Out", NULL, "Platform Clock"},440{"Line Out", NULL, "LOUTR"},441{"Line Out", NULL, "LOUTL"},442};443444static const struct snd_kcontrol_new byt_rt5640_controls[] = {445SOC_DAPM_PIN_SWITCH("Headphone"),446SOC_DAPM_PIN_SWITCH("Headset Mic"),447SOC_DAPM_PIN_SWITCH("Headset Mic 2"),448SOC_DAPM_PIN_SWITCH("Internal Mic"),449SOC_DAPM_PIN_SWITCH("Speaker"),450SOC_DAPM_PIN_SWITCH("Line Out"),451};452453static struct snd_soc_jack_pin rt5640_pins[] = {454{455.pin = "Headphone",456.mask = SND_JACK_HEADPHONE,457},458{459.pin = "Headset Mic",460.mask = SND_JACK_MICROPHONE,461},462};463464static struct snd_soc_jack_pin rt5640_pins2[] = {465{466/* The 2nd headset jack uses lineout with an external HP-amp */467.pin = "Line Out",468.mask = SND_JACK_HEADPHONE,469},470{471.pin = "Headset Mic 2",472.mask = SND_JACK_MICROPHONE,473},474};475476static struct snd_soc_jack_gpio rt5640_jack_gpio = {477.name = "hp-detect",478.report = SND_JACK_HEADSET,479.invert = true,480.debounce_time = 200,481};482483static struct snd_soc_jack_gpio rt5640_jack2_gpio = {484.name = "hp2-detect",485.report = SND_JACK_HEADSET,486.invert = true,487.debounce_time = 200,488};489490static const struct acpi_gpio_params acpi_gpio0 = { 0, 0, false };491static const struct acpi_gpio_params acpi_gpio1 = { 1, 0, false };492static const struct acpi_gpio_params acpi_gpio2 = { 2, 0, false };493494static const struct acpi_gpio_mapping byt_rt5640_hp_elitepad_1000g2_gpios[] = {495{ "hp-detect-gpios", &acpi_gpio0, 1, },496{ "headset-mic-detect-gpios", &acpi_gpio1, 1, },497{ "hp2-detect-gpios", &acpi_gpio2, 1, },498{ },499};500501static int byt_rt5640_hp_elitepad_1000g2_jack1_check(void *data)502{503struct byt_rt5640_private *priv = data;504int jack_status, mic_status;505506jack_status = gpiod_get_value_cansleep(rt5640_jack_gpio.desc);507if (jack_status)508return 0;509510mic_status = gpiod_get_value_cansleep(priv->hsmic_detect);511if (mic_status)512return SND_JACK_HEADPHONE;513else514return SND_JACK_HEADSET;515}516517static int byt_rt5640_hp_elitepad_1000g2_jack2_check(void *data)518{519struct snd_soc_component *component = data;520int jack_status, report;521522jack_status = gpiod_get_value_cansleep(rt5640_jack2_gpio.desc);523if (jack_status)524return 0;525526rt5640_enable_micbias1_for_ovcd(component);527report = rt5640_detect_headset(component, rt5640_jack2_gpio.desc);528rt5640_disable_micbias1_for_ovcd(component);529530return report;531}532533static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream,534struct snd_pcm_hw_params *params)535{536struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);537struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0);538539return byt_rt5640_prepare_and_enable_pll1(dai, params_rate(params));540}541542/* Please keep this list alphabetically sorted */543static const struct dmi_system_id byt_rt5640_quirk_table[] = {544{ /* Acer Iconia One 7 B1-750 */545.matches = {546DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),547DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "VESPA2"),548},549.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |550BYT_RT5640_JD_SRC_JD1_IN4P |551BYT_RT5640_OVCD_TH_1500UA |552BYT_RT5640_OVCD_SF_0P75 |553BYT_RT5640_SSP0_AIF1 |554BYT_RT5640_MCLK_EN),555},556{ /* Acer Iconia Tab 8 W1-810 */557.matches = {558DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),559DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Iconia W1-810"),560},561.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |562BYT_RT5640_JD_SRC_JD1_IN4P |563BYT_RT5640_OVCD_TH_1500UA |564BYT_RT5640_OVCD_SF_0P75 |565BYT_RT5640_SSP0_AIF1 |566BYT_RT5640_MCLK_EN),567},568{ /* Acer One 10 S1002 */569.matches = {570DMI_MATCH(DMI_SYS_VENDOR, "Acer"),571DMI_MATCH(DMI_PRODUCT_NAME, "One S1002"),572},573.driver_data = (void *)(BYT_RT5640_IN1_MAP |574BYT_RT5640_JD_SRC_JD2_IN4N |575BYT_RT5640_OVCD_TH_2000UA |576BYT_RT5640_OVCD_SF_0P75 |577BYT_RT5640_DIFF_MIC |578BYT_RT5640_SSP0_AIF2 |579BYT_RT5640_MCLK_EN),580},581{ /* Acer Aspire SW3-013 */582.matches = {583DMI_MATCH(DMI_SYS_VENDOR, "Acer"),584DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW3-013"),585},586.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |587BYT_RT5640_JD_SRC_JD2_IN4N |588BYT_RT5640_OVCD_TH_2000UA |589BYT_RT5640_OVCD_SF_0P75 |590BYT_RT5640_DIFF_MIC |591BYT_RT5640_SSP0_AIF1 |592BYT_RT5640_MCLK_EN),593},594{595.matches = {596DMI_MATCH(DMI_SYS_VENDOR, "Acer"),597DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),598},599.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |600BYT_RT5640_JD_SRC_JD2_IN4N |601BYT_RT5640_OVCD_TH_2000UA |602BYT_RT5640_OVCD_SF_0P75 |603BYT_RT5640_SSP0_AIF1 |604BYT_RT5640_MCLK_EN),605},606{607/* Advantech MICA-071 */608.matches = {609DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Advantech"),610DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MICA-071"),611},612/* OVCD Th = 1500uA to reliable detect head-phones vs -set */613.driver_data = (void *)(BYT_RT5640_IN3_MAP |614BYT_RT5640_JD_SRC_JD2_IN4N |615BYT_RT5640_OVCD_TH_1500UA |616BYT_RT5640_OVCD_SF_0P75 |617BYT_RT5640_MONO_SPEAKER |618BYT_RT5640_DIFF_MIC |619BYT_RT5640_MCLK_EN),620},621{622.matches = {623DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),624DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 80 Cesium"),625},626.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |627BYT_RT5640_MONO_SPEAKER |628BYT_RT5640_SSP0_AIF1 |629BYT_RT5640_MCLK_EN),630},631{632.matches = {633DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),634DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 101 CESIUM"),635},636.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |637BYT_RT5640_JD_NOT_INV |638BYT_RT5640_DIFF_MIC |639BYT_RT5640_SSP0_AIF1 |640BYT_RT5640_MCLK_EN),641},642{643.matches = {644DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),645DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 140 CESIUM"),646},647.driver_data = (void *)(BYT_RT5640_IN1_MAP |648BYT_RT5640_JD_SRC_JD2_IN4N |649BYT_RT5640_OVCD_TH_2000UA |650BYT_RT5640_OVCD_SF_0P75 |651BYT_RT5640_SSP0_AIF1 |652BYT_RT5640_MCLK_EN),653},654{655.matches = {656DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),657DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),658},659.driver_data = (void *)(BYT_RT5640_IN1_MAP |660BYT_RT5640_JD_SRC_JD2_IN4N |661BYT_RT5640_OVCD_TH_2000UA |662BYT_RT5640_OVCD_SF_0P75 |663BYT_RT5640_SSP0_AIF1 |664BYT_RT5640_MCLK_EN |665BYT_RT5640_USE_AMCR0F28),666},667{668/* Asus T100TAF, unlike other T100TA* models this one has a mono speaker */669.matches = {670DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),671DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),672},673.driver_data = (void *)(BYT_RT5640_IN1_MAP |674BYT_RT5640_JD_SRC_JD2_IN4N |675BYT_RT5640_OVCD_TH_2000UA |676BYT_RT5640_OVCD_SF_0P75 |677BYT_RT5640_MONO_SPEAKER |678BYT_RT5640_DIFF_MIC |679BYT_RT5640_SSP0_AIF2 |680BYT_RT5640_MCLK_EN),681},682{683/* Asus T100TA and T100TAM, must come after T100TAF (mono spk) match */684.matches = {685DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),686DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"),687},688.driver_data = (void *)(BYT_RT5640_IN1_MAP |689BYT_RT5640_JD_SRC_JD2_IN4N |690BYT_RT5640_OVCD_TH_2000UA |691BYT_RT5640_OVCD_SF_0P75 |692BYT_RT5640_MCLK_EN),693},694{695.matches = {696DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),697DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),698},699.driver_data = (void *)(BYT_RT5640_IN1_MAP |700BYT_RT5640_JD_SRC_EXT_GPIO |701BYT_RT5640_OVCD_TH_2000UA |702BYT_RT5640_OVCD_SF_0P75 |703BYT_RT5640_SSP0_AIF1 |704BYT_RT5640_MCLK_EN |705BYT_RT5640_USE_AMCR0F28),706},707{ /* Chuwi Vi8 (CWI506) */708.matches = {709DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),710DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "i86"),711/* The above are too generic, also match BIOS info */712DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"),713},714.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |715BYT_RT5640_MONO_SPEAKER |716BYT_RT5640_SSP0_AIF1 |717BYT_RT5640_MCLK_EN),718},719{ /* Chuwi Vi8 dual-boot (CWI506) */720.matches = {721DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),722DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "i86"),723/* The above are too generic, also match BIOS info */724DMI_MATCH(DMI_BIOS_VERSION, "CHUWI2.D86JHBNR02"),725},726.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |727BYT_RT5640_MONO_SPEAKER |728BYT_RT5640_SSP0_AIF1 |729BYT_RT5640_MCLK_EN),730},731{732/* Chuwi Vi10 (CWI505) */733.matches = {734DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),735DMI_MATCH(DMI_BOARD_NAME, "BYT-PF02"),736DMI_MATCH(DMI_SYS_VENDOR, "ilife"),737DMI_MATCH(DMI_PRODUCT_NAME, "S165"),738},739.driver_data = (void *)(BYT_RT5640_IN1_MAP |740BYT_RT5640_JD_SRC_JD2_IN4N |741BYT_RT5640_OVCD_TH_2000UA |742BYT_RT5640_OVCD_SF_0P75 |743BYT_RT5640_DIFF_MIC |744BYT_RT5640_SSP0_AIF1 |745BYT_RT5640_MCLK_EN),746},747{748/* Chuwi Hi8 (CWI509) */749.matches = {750DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),751DMI_MATCH(DMI_BOARD_NAME, "BYT-PA03C"),752DMI_MATCH(DMI_SYS_VENDOR, "ilife"),753DMI_MATCH(DMI_PRODUCT_NAME, "S806"),754},755.driver_data = (void *)(BYT_RT5640_IN1_MAP |756BYT_RT5640_JD_SRC_JD2_IN4N |757BYT_RT5640_OVCD_TH_2000UA |758BYT_RT5640_OVCD_SF_0P75 |759BYT_RT5640_MONO_SPEAKER |760BYT_RT5640_DIFF_MIC |761BYT_RT5640_SSP0_AIF1 |762BYT_RT5640_MCLK_EN),763},764{765.matches = {766DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),767DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),768},769.driver_data = (void *)(BYT_RT5640_DMIC1_MAP),770},771{ /* Connect Tablet 9 */772.matches = {773DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Connect"),774DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Tablet 9"),775},776.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |777BYT_RT5640_MONO_SPEAKER |778BYT_RT5640_SSP0_AIF1 |779BYT_RT5640_MCLK_EN),780},781{782.matches = {783DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),784DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"),785},786.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |787BYT_RT5640_JD_SRC_JD2_IN4N |788BYT_RT5640_OVCD_TH_2000UA |789BYT_RT5640_OVCD_SF_0P75 |790BYT_RT5640_MONO_SPEAKER |791BYT_RT5640_MCLK_EN),792},793{ /* Estar Beauty HD MID 7316R */794.matches = {795DMI_MATCH(DMI_SYS_VENDOR, "Estar"),796DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"),797},798.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |799BYT_RT5640_MONO_SPEAKER |800BYT_RT5640_SSP0_AIF1 |801BYT_RT5640_MCLK_EN),802},803{ /* Glavey TM800A550L */804.matches = {805DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),806DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),807/* Above strings are too generic, also match on BIOS version */808DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),809},810.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |811BYT_RT5640_SSP0_AIF1 |812BYT_RT5640_MCLK_EN),813},814{815.matches = {816DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),817DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"),818},819.driver_data = (void *)(BYT_RT5640_DMIC2_MAP |820BYT_RT5640_MCLK_EN |821BYT_RT5640_LINEOUT |822BYT_RT5640_LINEOUT_AS_HP2 |823BYT_RT5640_HSMIC2_ON_IN1 |824BYT_RT5640_JD_HP_ELITEP_1000G2),825},826{ /* HP Pavilion x2 10-k0XX, 10-n0XX */827.matches = {828DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),829DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),830},831.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |832BYT_RT5640_JD_SRC_JD2_IN4N |833BYT_RT5640_OVCD_TH_1500UA |834BYT_RT5640_OVCD_SF_0P75 |835BYT_RT5640_SSP0_AIF1 |836BYT_RT5640_MCLK_EN),837},838{ /* HP Pavilion x2 10-p0XX */839.matches = {840DMI_MATCH(DMI_SYS_VENDOR, "HP"),841DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),842},843.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |844BYT_RT5640_JD_SRC_JD1_IN4P |845BYT_RT5640_OVCD_TH_2000UA |846BYT_RT5640_OVCD_SF_0P75 |847BYT_RT5640_MCLK_EN),848},849{ /* HP Pro Tablet 408 */850.matches = {851DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),852DMI_MATCH(DMI_PRODUCT_NAME, "HP Pro Tablet 408"),853},854.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |855BYT_RT5640_JD_SRC_JD2_IN4N |856BYT_RT5640_OVCD_TH_1500UA |857BYT_RT5640_OVCD_SF_0P75 |858BYT_RT5640_SSP0_AIF1 |859BYT_RT5640_MCLK_EN),860},861{ /* HP Stream 7 */862.matches = {863DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),864DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 7 Tablet"),865},866.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |867BYT_RT5640_MONO_SPEAKER |868BYT_RT5640_JD_NOT_INV |869BYT_RT5640_SSP0_AIF1 |870BYT_RT5640_MCLK_EN),871},872{ /* HP Stream 8 */873.matches = {874DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),875DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 8 Tablet"),876},877.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |878BYT_RT5640_JD_NOT_INV |879BYT_RT5640_SSP0_AIF1 |880BYT_RT5640_MCLK_EN),881},882{ /* I.T.Works TW891 */883.matches = {884DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),885DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TW891"),886DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."),887DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"),888},889.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |890BYT_RT5640_MONO_SPEAKER |891BYT_RT5640_SSP0_AIF1 |892BYT_RT5640_MCLK_EN),893},894{ /* Lamina I8270 / T701BR.SE */895.matches = {896DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Lamina"),897DMI_EXACT_MATCH(DMI_BOARD_NAME, "T701BR.SE"),898},899.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |900BYT_RT5640_MONO_SPEAKER |901BYT_RT5640_JD_NOT_INV |902BYT_RT5640_SSP0_AIF1 |903BYT_RT5640_MCLK_EN),904},905{ /* Lenovo Miix 2 8 */906.matches = {907DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),908DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "20326"),909DMI_EXACT_MATCH(DMI_BOARD_NAME, "Hiking"),910},911.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |912BYT_RT5640_JD_SRC_JD2_IN4N |913BYT_RT5640_OVCD_TH_2000UA |914BYT_RT5640_OVCD_SF_0P75 |915BYT_RT5640_MONO_SPEAKER |916BYT_RT5640_MCLK_EN),917},918{ /* Lenovo Miix 3-830 */919.matches = {920DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),921DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 3-830"),922},923.driver_data = (void *)(BYT_RT5640_IN1_MAP |924BYT_RT5640_JD_SRC_JD2_IN4N |925BYT_RT5640_OVCD_TH_2000UA |926BYT_RT5640_OVCD_SF_0P75 |927BYT_RT5640_MONO_SPEAKER |928BYT_RT5640_DIFF_MIC |929BYT_RT5640_SSP0_AIF1 |930BYT_RT5640_MCLK_EN),931},932{ /* Linx Linx7 tablet */933.matches = {934DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LINX"),935DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LINX7"),936},937.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |938BYT_RT5640_MONO_SPEAKER |939BYT_RT5640_JD_NOT_INV |940BYT_RT5640_SSP0_AIF1 |941BYT_RT5640_MCLK_EN),942},943{944/* Medion Lifetab S10346 */945.matches = {946DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),947DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),948/* Above strings are much too generic, also match on BIOS date */949DMI_MATCH(DMI_BIOS_DATE, "10/22/2015"),950},951.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |952BYT_RT5640_SWAPPED_SPEAKERS |953BYT_RT5640_SSP0_AIF1 |954BYT_RT5640_MCLK_EN),955},956{ /* Mele PCG03 Mini PC */957.matches = {958DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"),959DMI_EXACT_MATCH(DMI_BOARD_NAME, "Mini PC"),960},961.driver_data = (void *)(BYT_RT5640_NO_INTERNAL_MIC_MAP |962BYT_RT5640_NO_SPEAKERS |963BYT_RT5640_SSP0_AIF1),964},965{ /* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */966.matches = {967DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"),968DMI_MATCH(DMI_PRODUCT_NAME, "Converter9"),969},970.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |971BYT_RT5640_MONO_SPEAKER |972BYT_RT5640_SSP0_AIF1 |973BYT_RT5640_MCLK_EN),974},975{976/* MPMAN MPWIN895CL */977.matches = {978DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MPMAN"),979DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MPWIN8900CL"),980},981.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |982BYT_RT5640_MONO_SPEAKER |983BYT_RT5640_SSP0_AIF1 |984BYT_RT5640_MCLK_EN),985},986{ /* MSI S100 tablet */987.matches = {988DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),989DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "S100"),990},991.driver_data = (void *)(BYT_RT5640_IN1_MAP |992BYT_RT5640_JD_SRC_JD2_IN4N |993BYT_RT5640_OVCD_TH_2000UA |994BYT_RT5640_OVCD_SF_0P75 |995BYT_RT5640_MONO_SPEAKER |996BYT_RT5640_DIFF_MIC |997BYT_RT5640_MCLK_EN),998},999{ /* Nuvison/TMax TM800W560 */1000.matches = {1001DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TMAX"),1002DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TM800W560L"),1003},1004.driver_data = (void *)(BYT_RT5640_IN1_MAP |1005BYT_RT5640_JD_SRC_JD2_IN4N |1006BYT_RT5640_OVCD_TH_2000UA |1007BYT_RT5640_OVCD_SF_0P75 |1008BYT_RT5640_JD_NOT_INV |1009BYT_RT5640_DIFF_MIC |1010BYT_RT5640_SSP0_AIF1 |1011BYT_RT5640_MCLK_EN),1012},1013{ /* Onda v975w */1014.matches = {1015DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),1016DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),1017/* The above are too generic, also match BIOS info */1018DMI_EXACT_MATCH(DMI_BIOS_VERSION, "5.6.5"),1019DMI_EXACT_MATCH(DMI_BIOS_DATE, "07/25/2014"),1020},1021.driver_data = (void *)(BYT_RT5640_IN1_MAP |1022BYT_RT5640_JD_SRC_JD2_IN4N |1023BYT_RT5640_OVCD_TH_2000UA |1024BYT_RT5640_OVCD_SF_0P75 |1025BYT_RT5640_DIFF_MIC |1026BYT_RT5640_MCLK_EN),1027},1028{ /* Pipo W4 */1029.matches = {1030DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),1031DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),1032/* The above are too generic, also match BIOS info */1033DMI_MATCH(DMI_BIOS_VERSION, "V8L_WIN32_CHIPHD"),1034},1035.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |1036BYT_RT5640_MONO_SPEAKER |1037BYT_RT5640_SSP0_AIF1 |1038BYT_RT5640_MCLK_EN),1039},1040{ /* Point of View Mobii TAB-P800W (V2.0) */1041.matches = {1042DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),1043DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),1044/* The above are too generic, also match BIOS info */1045DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1014"),1046DMI_EXACT_MATCH(DMI_BIOS_DATE, "10/24/2014"),1047},1048.driver_data = (void *)(BYT_RT5640_IN1_MAP |1049BYT_RT5640_JD_SRC_JD2_IN4N |1050BYT_RT5640_OVCD_TH_2000UA |1051BYT_RT5640_OVCD_SF_0P75 |1052BYT_RT5640_MONO_SPEAKER |1053BYT_RT5640_DIFF_MIC |1054BYT_RT5640_SSP0_AIF2 |1055BYT_RT5640_MCLK_EN),1056},1057{ /* Point of View Mobii TAB-P800W (V2.1) */1058.matches = {1059DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),1060DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),1061/* The above are too generic, also match BIOS info */1062DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),1063DMI_EXACT_MATCH(DMI_BIOS_DATE, "08/22/2014"),1064},1065.driver_data = (void *)(BYT_RT5640_IN1_MAP |1066BYT_RT5640_JD_SRC_JD2_IN4N |1067BYT_RT5640_OVCD_TH_2000UA |1068BYT_RT5640_OVCD_SF_0P75 |1069BYT_RT5640_MONO_SPEAKER |1070BYT_RT5640_DIFF_MIC |1071BYT_RT5640_SSP0_AIF2 |1072BYT_RT5640_MCLK_EN),1073},1074{ /* Point of View Mobii TAB-P1005W-232 (V2.0) */1075.matches = {1076DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "POV"),1077DMI_EXACT_MATCH(DMI_BOARD_NAME, "I102A"),1078},1079.driver_data = (void *)(BYT_RT5640_IN1_MAP |1080BYT_RT5640_JD_SRC_JD2_IN4N |1081BYT_RT5640_OVCD_TH_2000UA |1082BYT_RT5640_OVCD_SF_0P75 |1083BYT_RT5640_DIFF_MIC |1084BYT_RT5640_SSP0_AIF1 |1085BYT_RT5640_MCLK_EN),1086},1087{1088/* Prowise PT301 */1089.matches = {1090DMI_MATCH(DMI_SYS_VENDOR, "Prowise"),1091DMI_MATCH(DMI_PRODUCT_NAME, "PT301"),1092},1093.driver_data = (void *)(BYT_RT5640_IN1_MAP |1094BYT_RT5640_JD_SRC_JD2_IN4N |1095BYT_RT5640_OVCD_TH_2000UA |1096BYT_RT5640_OVCD_SF_0P75 |1097BYT_RT5640_DIFF_MIC |1098BYT_RT5640_SSP0_AIF1 |1099BYT_RT5640_MCLK_EN),1100},1101{1102/* Teclast X89 */1103.matches = {1104DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),1105DMI_MATCH(DMI_BOARD_NAME, "tPAD"),1106},1107.driver_data = (void *)(BYT_RT5640_IN3_MAP |1108BYT_RT5640_JD_SRC_JD1_IN4P |1109BYT_RT5640_OVCD_TH_2000UA |1110BYT_RT5640_OVCD_SF_1P0 |1111BYT_RT5640_SSP0_AIF1 |1112BYT_RT5640_MCLK_EN),1113},1114{ /* Toshiba Satellite Click Mini L9W-B */1115.matches = {1116DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),1117DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SATELLITE Click Mini L9W-B"),1118},1119.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |1120BYT_RT5640_JD_SRC_JD2_IN4N |1121BYT_RT5640_OVCD_TH_1500UA |1122BYT_RT5640_OVCD_SF_0P75 |1123BYT_RT5640_SSP0_AIF1 |1124BYT_RT5640_MCLK_EN),1125},1126{ /* Toshiba Encore WT8-A */1127.matches = {1128DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),1129DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT8-A"),1130},1131.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |1132BYT_RT5640_JD_SRC_JD2_IN4N |1133BYT_RT5640_OVCD_TH_2000UA |1134BYT_RT5640_OVCD_SF_0P75 |1135BYT_RT5640_JD_NOT_INV |1136BYT_RT5640_MCLK_EN),1137},1138{ /* Toshiba Encore WT10-A */1139.matches = {1140DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),1141DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT10-A-103"),1142},1143.driver_data = (void *)(BYT_RT5640_DMIC1_MAP |1144BYT_RT5640_JD_SRC_JD1_IN4P |1145BYT_RT5640_OVCD_TH_2000UA |1146BYT_RT5640_OVCD_SF_0P75 |1147BYT_RT5640_SSP0_AIF2 |1148BYT_RT5640_MCLK_EN),1149},1150{1151/* Vexia Edu Atla 10 tablet 5V version */1152.matches = {1153/* Having all 3 of these not set is somewhat unique */1154DMI_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),1155DMI_MATCH(DMI_PRODUCT_NAME, "To be filled by O.E.M."),1156DMI_MATCH(DMI_BOARD_NAME, "To be filled by O.E.M."),1157/* Above strings are too generic, also match on BIOS date */1158DMI_MATCH(DMI_BIOS_DATE, "05/14/2015"),1159},1160.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |1161BYT_RT5640_JD_NOT_INV |1162BYT_RT5640_SSP0_AIF1 |1163BYT_RT5640_MCLK_EN),1164},1165{ /* Vexia Edu Atla 10 tablet 9V version */1166.matches = {1167DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),1168DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),1169/* Above strings are too generic, also match on BIOS date */1170DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"),1171},1172.driver_data = (void *)(BYT_RT5640_IN1_MAP |1173BYT_RT5640_JD_SRC_JD2_IN4N |1174BYT_RT5640_OVCD_TH_2000UA |1175BYT_RT5640_OVCD_SF_0P75 |1176BYT_RT5640_DIFF_MIC |1177BYT_RT5640_SSP0_AIF2 |1178BYT_RT5640_MCLK_EN),1179},1180{ /* Voyo Winpad A15 */1181.matches = {1182DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),1183DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),1184/* Above strings are too generic, also match on BIOS date */1185DMI_MATCH(DMI_BIOS_DATE, "11/20/2014"),1186},1187.driver_data = (void *)(BYT_RT5640_IN1_MAP |1188BYT_RT5640_JD_SRC_JD2_IN4N |1189BYT_RT5640_OVCD_TH_2000UA |1190BYT_RT5640_OVCD_SF_0P75 |1191BYT_RT5640_DIFF_MIC |1192BYT_RT5640_MCLK_EN),1193},1194{ /* Catch-all for generic Insyde tablets, must be last */1195.matches = {1196DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),1197},1198.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |1199BYT_RT5640_MCLK_EN |1200BYT_RT5640_SSP0_AIF1),12011202},1203{}1204};12051206/*1207* Note this MUST be called before snd_soc_register_card(), so that the props1208* are in place before the codec component driver's probe function parses them.1209*/1210static int byt_rt5640_add_codec_device_props(struct device *i2c_dev,1211struct byt_rt5640_private *priv)1212{1213struct property_entry props[MAX_NO_PROPS] = {};1214struct fwnode_handle *fwnode;1215int cnt = 0;1216int ret;12171218switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {1219case BYT_RT5640_DMIC1_MAP:1220props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic1-data-pin",1221RT5640_DMIC1_DATA_PIN_IN1P);1222break;1223case BYT_RT5640_DMIC2_MAP:1224props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic2-data-pin",1225RT5640_DMIC2_DATA_PIN_IN1N);1226break;1227case BYT_RT5640_IN1_MAP:1228if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)1229props[cnt++] =1230PROPERTY_ENTRY_BOOL("realtek,in1-differential");1231break;1232case BYT_RT5640_IN3_MAP:1233if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)1234props[cnt++] =1235PROPERTY_ENTRY_BOOL("realtek,in3-differential");1236break;1237}12381239if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {1240if (BYT_RT5640_JDSRC(byt_rt5640_quirk) != RT5640_JD_SRC_EXT_GPIO) {1241props[cnt++] = PROPERTY_ENTRY_U32(1242"realtek,jack-detect-source",1243BYT_RT5640_JDSRC(byt_rt5640_quirk));1244}12451246props[cnt++] = PROPERTY_ENTRY_U32(1247"realtek,over-current-threshold-microamp",1248BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100);12491250props[cnt++] = PROPERTY_ENTRY_U32(1251"realtek,over-current-scale-factor",1252BYT_RT5640_OVCD_SF(byt_rt5640_quirk));1253}12541255if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)1256props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");12571258fwnode = fwnode_create_software_node(props, NULL);1259if (IS_ERR(fwnode)) {1260/* put_device() is handled in caller */1261return PTR_ERR(fwnode);1262}12631264ret = device_add_software_node(i2c_dev, to_software_node(fwnode));12651266fwnode_handle_put(fwnode);12671268return ret;1269}12701271/* Some Android devs specify IRQs/GPIOS in a special AMCR0F28 ACPI device */1272static const struct acpi_gpio_params amcr0f28_jd_gpio = { 1, 0, false };12731274static const struct acpi_gpio_mapping amcr0f28_gpios[] = {1275{ "rt5640-jd-gpios", &amcr0f28_jd_gpio, 1 },1276{ }1277};12781279static int byt_rt5640_get_amcr0f28_settings(struct snd_soc_card *card)1280{1281struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);1282struct rt5640_set_jack_data *data = &priv->jack_data;1283struct acpi_device *adev;1284int ret = 0;12851286adev = acpi_dev_get_first_match_dev("AMCR0F28", "1", -1);1287if (!adev) {1288dev_err(card->dev, "error cannot find AMCR0F28 adev\n");1289return -ENOENT;1290}12911292data->codec_irq_override = acpi_dev_gpio_irq_get(adev, 0);1293if (data->codec_irq_override < 0) {1294ret = data->codec_irq_override;1295dev_err(card->dev, "error %d getting codec IRQ\n", ret);1296goto put_adev;1297}12981299if (BYT_RT5640_JDSRC(byt_rt5640_quirk) == RT5640_JD_SRC_EXT_GPIO) {1300acpi_dev_add_driver_gpios(adev, amcr0f28_gpios);1301data->jd_gpio = devm_fwnode_gpiod_get(card->dev, acpi_fwnode_handle(adev),1302"rt5640-jd", GPIOD_IN, "rt5640-jd");1303acpi_dev_remove_driver_gpios(adev);13041305if (IS_ERR(data->jd_gpio)) {1306ret = PTR_ERR(data->jd_gpio);1307dev_err(card->dev, "error %d getting jd GPIO\n", ret);1308}1309}13101311put_adev:1312acpi_dev_put(adev);1313return ret;1314}13151316static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)1317{1318struct snd_soc_card *card = runtime->card;1319struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);1320struct rt5640_set_jack_data *jack_data = &priv->jack_data;1321struct snd_soc_component *component = snd_soc_rtd_to_codec(runtime, 0)->component;1322const struct snd_soc_dapm_route *custom_map = NULL;1323int num_routes = 0;1324int ret;13251326card->dapm.idle_bias = false;1327jack_data->use_platform_clock = true;13281329/* Start with RC clk for jack-detect (we disable MCLK below) */1330if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN)1331snd_soc_component_update_bits(component, RT5640_GLB_CLK,1332RT5640_SCLK_SRC_MASK, RT5640_SCLK_SRC_RCCLK);13331334rt5640_sel_asrc_clk_src(component,1335RT5640_DA_STEREO_FILTER |1336RT5640_DA_MONO_L_FILTER |1337RT5640_DA_MONO_R_FILTER |1338RT5640_AD_STEREO_FILTER |1339RT5640_AD_MONO_L_FILTER |1340RT5640_AD_MONO_R_FILTER,1341RT5640_CLK_SEL_ASRC);13421343ret = snd_soc_add_card_controls(card, byt_rt5640_controls,1344ARRAY_SIZE(byt_rt5640_controls));1345if (ret) {1346dev_err(card->dev, "unable to add card controls\n");1347return ret;1348}13491350switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {1351case BYT_RT5640_IN1_MAP:1352custom_map = byt_rt5640_intmic_in1_map;1353num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map);1354break;1355case BYT_RT5640_IN3_MAP:1356custom_map = byt_rt5640_intmic_in3_map;1357num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map);1358break;1359case BYT_RT5640_DMIC1_MAP:1360custom_map = byt_rt5640_intmic_dmic1_map;1361num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);1362break;1363case BYT_RT5640_DMIC2_MAP:1364custom_map = byt_rt5640_intmic_dmic2_map;1365num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map);1366break;1367}13681369ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);1370if (ret)1371return ret;13721373if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1) {1374ret = snd_soc_dapm_add_routes(&card->dapm,1375byt_rt5640_hsmic2_in1_map,1376ARRAY_SIZE(byt_rt5640_hsmic2_in1_map));1377if (ret)1378return ret;1379}13801381if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {1382ret = snd_soc_dapm_add_routes(&card->dapm,1383byt_rt5640_ssp2_aif2_map,1384ARRAY_SIZE(byt_rt5640_ssp2_aif2_map));1385} else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {1386ret = snd_soc_dapm_add_routes(&card->dapm,1387byt_rt5640_ssp0_aif1_map,1388ARRAY_SIZE(byt_rt5640_ssp0_aif1_map));1389} else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) {1390ret = snd_soc_dapm_add_routes(&card->dapm,1391byt_rt5640_ssp0_aif2_map,1392ARRAY_SIZE(byt_rt5640_ssp0_aif2_map));1393} else {1394ret = snd_soc_dapm_add_routes(&card->dapm,1395byt_rt5640_ssp2_aif1_map,1396ARRAY_SIZE(byt_rt5640_ssp2_aif1_map));1397}1398if (ret)1399return ret;14001401if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {1402ret = snd_soc_dapm_add_routes(&card->dapm,1403byt_rt5640_mono_spk_map,1404ARRAY_SIZE(byt_rt5640_mono_spk_map));1405} else if (!(byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)) {1406ret = snd_soc_dapm_add_routes(&card->dapm,1407byt_rt5640_stereo_spk_map,1408ARRAY_SIZE(byt_rt5640_stereo_spk_map));1409}1410if (ret)1411return ret;14121413if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) {1414ret = snd_soc_dapm_add_routes(&card->dapm,1415byt_rt5640_lineout_map,1416ARRAY_SIZE(byt_rt5640_lineout_map));1417if (ret)1418return ret;1419}14201421/*1422* The firmware might enable the clock at boot (this information1423* may or may not be reflected in the enable clock register).1424* To change the rate we must disable the clock first to cover1425* these cases. Due to common clock framework restrictions that1426* do not allow to disable a clock that has not been enabled,1427* we need to enable the clock first.1428*/1429ret = clk_prepare_enable(priv->mclk);1430if (!ret)1431clk_disable_unprepare(priv->mclk);14321433if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ)1434ret = clk_set_rate(priv->mclk, 25000000);1435else1436ret = clk_set_rate(priv->mclk, 19200000);1437if (ret) {1438dev_err(card->dev, "unable to set MCLK rate\n");1439return ret;1440}14411442if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {1443ret = snd_soc_card_jack_new_pins(card, "Headset",1444SND_JACK_HEADSET | SND_JACK_BTN_0,1445&priv->jack, rt5640_pins,1446ARRAY_SIZE(rt5640_pins));1447if (ret) {1448dev_err(card->dev, "Jack creation failed %d\n", ret);1449return ret;1450}1451snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0,1452KEY_PLAYPAUSE);14531454if (byt_rt5640_quirk & BYT_RT5640_USE_AMCR0F28) {1455ret = byt_rt5640_get_amcr0f28_settings(card);1456if (ret)1457return ret;1458}14591460snd_soc_component_set_jack(component, &priv->jack, &priv->jack_data);1461}14621463if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {1464ret = snd_soc_card_jack_new_pins(card, "Headset",1465SND_JACK_HEADSET,1466&priv->jack, rt5640_pins,1467ARRAY_SIZE(rt5640_pins));1468if (ret)1469return ret;14701471ret = snd_soc_card_jack_new_pins(card, "Headset 2",1472SND_JACK_HEADSET,1473&priv->jack2, rt5640_pins2,1474ARRAY_SIZE(rt5640_pins2));1475if (ret)1476return ret;14771478rt5640_jack_gpio.data = priv;1479rt5640_jack_gpio.gpiod_dev = priv->codec_dev;1480rt5640_jack_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack1_check;1481ret = snd_soc_jack_add_gpios(&priv->jack, 1, &rt5640_jack_gpio);1482if (ret)1483return ret;14841485rt5640_set_ovcd_params(component);1486rt5640_jack2_gpio.data = component;1487rt5640_jack2_gpio.gpiod_dev = priv->codec_dev;1488rt5640_jack2_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack2_check;1489ret = snd_soc_jack_add_gpios(&priv->jack2, 1, &rt5640_jack2_gpio);1490if (ret) {1491snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio);1492return ret;1493}1494}14951496return 0;1497}14981499static void byt_rt5640_exit(struct snd_soc_pcm_runtime *runtime)1500{1501struct snd_soc_card *card = runtime->card;1502struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);15031504if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {1505snd_soc_jack_free_gpios(&priv->jack2, 1, &rt5640_jack2_gpio);1506snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio);1507}1508}15091510static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd,1511struct snd_pcm_hw_params *params)1512{1513struct snd_interval *rate = hw_param_interval(params,1514SNDRV_PCM_HW_PARAM_RATE);1515struct snd_interval *channels = hw_param_interval(params,1516SNDRV_PCM_HW_PARAM_CHANNELS);1517int ret, bits;15181519/* The DSP will convert the FE rate to 48k, stereo */1520rate->min = rate->max = 48000;1521channels->min = channels->max = 2;15221523if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||1524(byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {1525/* set SSP0 to 16-bit */1526params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);1527bits = 16;1528} else {1529/* set SSP2 to 24-bit */1530params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);1531bits = 24;1532}15331534/*1535* Default mode for SSP configuration is TDM 4 slot, override config1536* with explicit setting to I2S 2ch. The word length is set with1537* dai_set_tdm_slot() since there is no other API exposed1538*/1539ret = snd_soc_dai_set_fmt(snd_soc_rtd_to_cpu(rtd, 0),1540SND_SOC_DAIFMT_I2S |1541SND_SOC_DAIFMT_NB_NF |1542SND_SOC_DAIFMT_BP_FP);1543if (ret < 0) {1544dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);1545return ret;1546}15471548ret = snd_soc_dai_set_tdm_slot(snd_soc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits);1549if (ret < 0) {1550dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);1551return ret;1552}15531554return 0;1555}15561557static int byt_rt5640_aif1_startup(struct snd_pcm_substream *substream)1558{1559return snd_pcm_hw_constraint_single(substream->runtime,1560SNDRV_PCM_HW_PARAM_RATE, 48000);1561}15621563static const struct snd_soc_ops byt_rt5640_aif1_ops = {1564.startup = byt_rt5640_aif1_startup,1565};15661567static const struct snd_soc_ops byt_rt5640_be_ssp2_ops = {1568.hw_params = byt_rt5640_aif1_hw_params,1569};15701571SND_SOC_DAILINK_DEF(dummy,1572DAILINK_COMP_ARRAY(COMP_DUMMY()));15731574SND_SOC_DAILINK_DEF(media,1575DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));15761577SND_SOC_DAILINK_DEF(deepbuffer,1578DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));15791580SND_SOC_DAILINK_DEF(ssp2_port,1581/* overwritten for ssp0 routing */1582DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));1583SND_SOC_DAILINK_DEF(ssp2_codec,1584DAILINK_COMP_ARRAY(COMP_CODEC(1585/* overwritten with HID */ "i2c-10EC5640:00",1586/* changed w/ quirk */ "rt5640-aif1")));15871588SND_SOC_DAILINK_DEF(platform,1589DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));15901591static struct snd_soc_dai_link byt_rt5640_dais[] = {1592[MERR_DPCM_AUDIO] = {1593.name = "Baytrail Audio Port",1594.stream_name = "Baytrail Audio",1595.nonatomic = true,1596.dynamic = 1,1597.ops = &byt_rt5640_aif1_ops,1598SND_SOC_DAILINK_REG(media, dummy, platform),1599},1600[MERR_DPCM_DEEP_BUFFER] = {1601.name = "Deep-Buffer Audio Port",1602.stream_name = "Deep-Buffer Audio",1603.nonatomic = true,1604.dynamic = 1,1605.playback_only = 1,1606.ops = &byt_rt5640_aif1_ops,1607SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),1608},1609/* back ends */1610{1611.name = "SSP2-Codec",1612.id = 0,1613.no_pcm = 1,1614.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF1615| SND_SOC_DAIFMT_CBC_CFC,1616.be_hw_params_fixup = byt_rt5640_codec_fixup,1617.init = byt_rt5640_init,1618.exit = byt_rt5640_exit,1619.ops = &byt_rt5640_be_ssp2_ops,1620SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),1621},1622};16231624/* SoC card */1625static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN];1626#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)1627static char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */1628#endif1629static char byt_rt5640_components[64]; /* = "cfg-spk:* cfg-mic:* ..." */16301631static int byt_rt5640_suspend(struct snd_soc_card *card)1632{1633struct snd_soc_component *component;16341635if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))1636return 0;16371638for_each_card_components(card, component) {1639if (!strcmp(component->name, byt_rt5640_codec_name)) {1640dev_dbg(component->dev, "disabling jack detect before suspend\n");1641snd_soc_component_set_jack(component, NULL, NULL);1642break;1643}1644}16451646return 0;1647}16481649static int byt_rt5640_resume(struct snd_soc_card *card)1650{1651struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);1652struct snd_soc_component *component;16531654if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))1655return 0;16561657for_each_card_components(card, component) {1658if (!strcmp(component->name, byt_rt5640_codec_name)) {1659dev_dbg(component->dev, "re-enabling jack detect after resume\n");1660snd_soc_component_set_jack(component, &priv->jack,1661&priv->jack_data);1662break;1663}1664}16651666return 0;1667}16681669/* use space before codec name to simplify card ID, and simplify driver name */1670#define SOF_CARD_NAME "bytcht rt5640" /* card name will be 'sof-bytcht rt5640' */1671#define SOF_DRIVER_NAME "SOF"16721673#define CARD_NAME "bytcr-rt5640"1674#define DRIVER_NAME NULL /* card name will be used for driver name */16751676static struct snd_soc_card byt_rt5640_card = {1677.owner = THIS_MODULE,1678.dai_link = byt_rt5640_dais,1679.num_links = ARRAY_SIZE(byt_rt5640_dais),1680.dapm_widgets = byt_rt5640_widgets,1681.num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets),1682.dapm_routes = byt_rt5640_audio_map,1683.num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map),1684.fully_routed = true,1685.suspend_pre = byt_rt5640_suspend,1686.resume_post = byt_rt5640_resume,1687};16881689struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */1690u64 aif_value; /* 1: AIF1, 2: AIF2 */1691u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */1692};16931694static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)1695{1696struct device *dev = &pdev->dev;1697static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" };1698struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);1699__maybe_unused const char *spk_type;1700const struct dmi_system_id *dmi_id;1701const char *headset2_string = "";1702const char *lineout_string = "";1703struct byt_rt5640_private *priv;1704const char *platform_name;1705struct acpi_device *adev;1706struct device *codec_dev;1707const char *cfg_spk;1708bool sof_parent;1709int ret_val = 0;1710int dai_index = 0;1711int i, aif;17121713is_bytcr = false;1714priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);1715if (!priv)1716return -ENOMEM;17171718/* register the soc card */1719byt_rt5640_card.dev = dev;1720snd_soc_card_set_drvdata(&byt_rt5640_card, priv);17211722/* fix index of codec dai */1723for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) {1724if (byt_rt5640_dais[i].num_codecs &&1725!strcmp(byt_rt5640_dais[i].codecs->name,1726"i2c-10EC5640:00")) {1727dai_index = i;1728break;1729}1730}17311732/* fixup codec name based on HID */1733adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);1734if (adev) {1735snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),1736"i2c-%s", acpi_dev_name(adev));1737byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name;1738} else {1739dev_err(dev, "Error cannot find '%s' dev\n", mach->id);1740return -ENOENT;1741}17421743codec_dev = acpi_get_first_physical_node(adev);1744acpi_dev_put(adev);17451746if (codec_dev) {1747priv->codec_dev = get_device(codec_dev);1748} else {1749/*1750* Special case for Android tablets where the codec i2c_client1751* has been manually instantiated by x86_android_tablets.ko due1752* to a broken DSDT.1753*/1754codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,1755BYT_RT5640_FALLBACK_CODEC_DEV_NAME);1756if (!codec_dev)1757return -EPROBE_DEFER;17581759if (!i2c_verify_client(codec_dev)) {1760dev_err(dev, "Error '%s' is not an i2c_client\n",1761BYT_RT5640_FALLBACK_CODEC_DEV_NAME);1762put_device(codec_dev);1763}17641765/* fixup codec name */1766strscpy(byt_rt5640_codec_name, BYT_RT5640_FALLBACK_CODEC_DEV_NAME,1767sizeof(byt_rt5640_codec_name));17681769/* bus_find_device() returns a reference no need to get() */1770priv->codec_dev = codec_dev;1771}17721773/*1774* swap SSP0 if bytcr is detected1775* (will be overridden if DMI quirk is detected)1776*/1777if (soc_intel_is_byt()) {1778if (mach->mach_params.acpi_ipc_irq_index == 0)1779is_bytcr = true;1780}17811782if (is_bytcr) {1783/*1784* Baytrail CR platforms may have CHAN package in BIOS, try1785* to find relevant routing quirk based as done on Windows1786* platforms. We have to read the information directly from the1787* BIOS, at this stage the card is not created and the links1788* with the codec driver/pdata are non-existent1789*/17901791struct acpi_chan_package chan_package = { 0 };17921793/* format specified: 2 64-bit integers */1794struct acpi_buffer format = {sizeof("NN"), "NN"};1795struct acpi_buffer state = {0, NULL};1796struct snd_soc_acpi_package_context pkg_ctx;1797bool pkg_found = false;17981799state.length = sizeof(chan_package);1800state.pointer = &chan_package;18011802pkg_ctx.name = "CHAN";1803pkg_ctx.length = 2;1804pkg_ctx.format = &format;1805pkg_ctx.state = &state;1806pkg_ctx.data_valid = false;18071808pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,1809&pkg_ctx);1810if (pkg_found) {1811if (chan_package.aif_value == 1) {1812dev_info(dev, "BIOS Routing: AIF1 connected\n");1813byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1;1814} else if (chan_package.aif_value == 2) {1815dev_info(dev, "BIOS Routing: AIF2 connected\n");1816byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;1817} else {1818dev_info(dev, "BIOS Routing isn't valid, ignored\n");1819pkg_found = false;1820}1821}18221823if (!pkg_found) {1824/* no BIOS indications, assume SSP0-AIF2 connection */1825byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;1826}18271828/* change defaults for Baytrail-CR capture */1829byt_rt5640_quirk |= BYTCR_INPUT_DEFAULTS;1830} else {1831byt_rt5640_quirk |= BYT_RT5640_DMIC1_MAP |1832BYT_RT5640_JD_SRC_JD2_IN4N |1833BYT_RT5640_OVCD_TH_2000UA |1834BYT_RT5640_OVCD_SF_0P75;1835}18361837/* check quirks before creating card */1838dmi_id = dmi_first_match(byt_rt5640_quirk_table);1839if (dmi_id)1840byt_rt5640_quirk = (unsigned long)dmi_id->driver_data;1841if (quirk_override != -1) {1842dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n",1843byt_rt5640_quirk, quirk_override);1844byt_rt5640_quirk = quirk_override;1845}18461847if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {1848acpi_dev_add_driver_gpios(ACPI_COMPANION(priv->codec_dev),1849byt_rt5640_hp_elitepad_1000g2_gpios);18501851priv->hsmic_detect = devm_fwnode_gpiod_get(dev, codec_dev->fwnode,1852"headset-mic-detect", GPIOD_IN,1853"headset-mic-detect");1854if (IS_ERR(priv->hsmic_detect)) {1855ret_val = dev_err_probe(dev, PTR_ERR(priv->hsmic_detect),1856"getting hsmic-detect GPIO\n");1857goto err_device;1858}1859}18601861/* Must be called before register_card, also see declaration comment. */1862ret_val = byt_rt5640_add_codec_device_props(codec_dev, priv);1863if (ret_val)1864goto err_remove_gpios;18651866log_quirks(dev);18671868if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) ||1869(byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {1870byt_rt5640_dais[dai_index].codecs->dai_name = "rt5640-aif2";1871aif = 2;1872} else {1873aif = 1;1874}18751876if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||1877(byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2))1878byt_rt5640_dais[dai_index].cpus->dai_name = "ssp0-port";18791880if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {1881priv->mclk = devm_clk_get_optional(dev, "pmc_plt_clk_3");1882if (IS_ERR(priv->mclk)) {1883ret_val = dev_err_probe(dev, PTR_ERR(priv->mclk),1884"Failed to get MCLK from pmc_plt_clk_3\n");1885goto err;1886}1887/*1888* Fall back to bit clock usage when clock is not1889* available likely due to missing dependencies.1890*/1891if (!priv->mclk)1892byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;1893}18941895if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) {1896cfg_spk = "0";1897spk_type = "none";1898} else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {1899cfg_spk = "1";1900spk_type = "mono";1901} else if (byt_rt5640_quirk & BYT_RT5640_SWAPPED_SPEAKERS) {1902cfg_spk = "swapped";1903spk_type = "swapped";1904} else {1905cfg_spk = "2";1906spk_type = "stereo";1907}19081909if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) {1910if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)1911lineout_string = " cfg-hp2:lineout";1912else1913lineout_string = " cfg-lineout:2";1914}19151916if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1)1917headset2_string = " cfg-hs2:in1";19181919snprintf(byt_rt5640_components, sizeof(byt_rt5640_components),1920"cfg-spk:%s cfg-mic:%s aif:%d%s%s", cfg_spk,1921map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif,1922lineout_string, headset2_string);1923byt_rt5640_card.components = byt_rt5640_components;1924#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)1925snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name),1926"bytcr-rt5640-%s-spk-%s-mic", spk_type,1927map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]);1928byt_rt5640_card.long_name = byt_rt5640_long_name;1929#endif19301931/* override platform name, if required */1932platform_name = mach->mach_params.platform;19331934ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card,1935platform_name);1936if (ret_val)1937goto err;19381939sof_parent = snd_soc_acpi_sof_parent(dev);19401941/* set card and driver name */1942if (sof_parent) {1943byt_rt5640_card.name = SOF_CARD_NAME;1944byt_rt5640_card.driver_name = SOF_DRIVER_NAME;1945} else {1946byt_rt5640_card.name = CARD_NAME;1947byt_rt5640_card.driver_name = DRIVER_NAME;1948}19491950/* set pm ops */1951if (sof_parent)1952dev->driver->pm = &snd_soc_pm_ops;19531954ret_val = devm_snd_soc_register_card(dev, &byt_rt5640_card);1955if (ret_val) {1956dev_err(dev, "devm_snd_soc_register_card failed %d\n", ret_val);1957goto err;1958}1959platform_set_drvdata(pdev, &byt_rt5640_card);1960return ret_val;19611962err:1963device_remove_software_node(priv->codec_dev);1964err_remove_gpios:1965if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)1966acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev));1967err_device:1968put_device(priv->codec_dev);1969return ret_val;1970}19711972static void snd_byt_rt5640_mc_remove(struct platform_device *pdev)1973{1974struct snd_soc_card *card = platform_get_drvdata(pdev);1975struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);19761977if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)1978acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev));19791980device_remove_software_node(priv->codec_dev);1981put_device(priv->codec_dev);1982}19831984static struct platform_driver snd_byt_rt5640_mc_driver = {1985.driver = {1986.name = "bytcr_rt5640",1987},1988.probe = snd_byt_rt5640_mc_probe,1989.remove = snd_byt_rt5640_mc_remove,1990};19911992module_platform_driver(snd_byt_rt5640_mc_driver);19931994MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver");1995MODULE_AUTHOR("Subhransu S. Prusty <[email protected]>");1996MODULE_LICENSE("GPL v2");1997MODULE_ALIAS("platform:bytcr_rt5640");199819992000