Path: blob/master/sound/soc/intel/boards/bytcr_rt5640.c
54294 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 = snd_soc_dapm_to_card(dapm);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 = snd_soc_dapm_to_card(dapm);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 snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);1320struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);1321struct rt5640_set_jack_data *jack_data = &priv->jack_data;1322struct snd_soc_component *component = snd_soc_rtd_to_codec(runtime, 0)->component;1323const struct snd_soc_dapm_route *custom_map = NULL;1324int num_routes = 0;1325int ret;13261327snd_soc_dapm_set_idle_bias(dapm, false);1328jack_data->use_platform_clock = true;13291330/* Start with RC clk for jack-detect (we disable MCLK below) */1331if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN)1332snd_soc_component_update_bits(component, RT5640_GLB_CLK,1333RT5640_SCLK_SRC_MASK, RT5640_SCLK_SRC_RCCLK);13341335rt5640_sel_asrc_clk_src(component,1336RT5640_DA_STEREO_FILTER |1337RT5640_DA_MONO_L_FILTER |1338RT5640_DA_MONO_R_FILTER |1339RT5640_AD_STEREO_FILTER |1340RT5640_AD_MONO_L_FILTER |1341RT5640_AD_MONO_R_FILTER,1342RT5640_CLK_SEL_ASRC);13431344ret = snd_soc_add_card_controls(card, byt_rt5640_controls,1345ARRAY_SIZE(byt_rt5640_controls));1346if (ret) {1347dev_err(card->dev, "unable to add card controls\n");1348return ret;1349}13501351switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {1352case BYT_RT5640_IN1_MAP:1353custom_map = byt_rt5640_intmic_in1_map;1354num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map);1355break;1356case BYT_RT5640_IN3_MAP:1357custom_map = byt_rt5640_intmic_in3_map;1358num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map);1359break;1360case BYT_RT5640_DMIC1_MAP:1361custom_map = byt_rt5640_intmic_dmic1_map;1362num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);1363break;1364case BYT_RT5640_DMIC2_MAP:1365custom_map = byt_rt5640_intmic_dmic2_map;1366num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map);1367break;1368}13691370ret = snd_soc_dapm_add_routes(dapm, custom_map, num_routes);1371if (ret)1372return ret;13731374if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1) {1375ret = snd_soc_dapm_add_routes(dapm,1376byt_rt5640_hsmic2_in1_map,1377ARRAY_SIZE(byt_rt5640_hsmic2_in1_map));1378if (ret)1379return ret;1380}13811382if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {1383ret = snd_soc_dapm_add_routes(dapm,1384byt_rt5640_ssp2_aif2_map,1385ARRAY_SIZE(byt_rt5640_ssp2_aif2_map));1386} else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {1387ret = snd_soc_dapm_add_routes(dapm,1388byt_rt5640_ssp0_aif1_map,1389ARRAY_SIZE(byt_rt5640_ssp0_aif1_map));1390} else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) {1391ret = snd_soc_dapm_add_routes(dapm,1392byt_rt5640_ssp0_aif2_map,1393ARRAY_SIZE(byt_rt5640_ssp0_aif2_map));1394} else {1395ret = snd_soc_dapm_add_routes(dapm,1396byt_rt5640_ssp2_aif1_map,1397ARRAY_SIZE(byt_rt5640_ssp2_aif1_map));1398}1399if (ret)1400return ret;14011402if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {1403ret = snd_soc_dapm_add_routes(dapm,1404byt_rt5640_mono_spk_map,1405ARRAY_SIZE(byt_rt5640_mono_spk_map));1406} else if (!(byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)) {1407ret = snd_soc_dapm_add_routes(dapm,1408byt_rt5640_stereo_spk_map,1409ARRAY_SIZE(byt_rt5640_stereo_spk_map));1410}1411if (ret)1412return ret;14131414if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) {1415ret = snd_soc_dapm_add_routes(dapm,1416byt_rt5640_lineout_map,1417ARRAY_SIZE(byt_rt5640_lineout_map));1418if (ret)1419return ret;1420}14211422/*1423* The firmware might enable the clock at boot (this information1424* may or may not be reflected in the enable clock register).1425* To change the rate we must disable the clock first to cover1426* these cases. Due to common clock framework restrictions that1427* do not allow to disable a clock that has not been enabled,1428* we need to enable the clock first.1429*/1430ret = clk_prepare_enable(priv->mclk);1431if (!ret)1432clk_disable_unprepare(priv->mclk);14331434if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ)1435ret = clk_set_rate(priv->mclk, 25000000);1436else1437ret = clk_set_rate(priv->mclk, 19200000);1438if (ret) {1439dev_err(card->dev, "unable to set MCLK rate\n");1440return ret;1441}14421443if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {1444ret = snd_soc_card_jack_new_pins(card, "Headset",1445SND_JACK_HEADSET | SND_JACK_BTN_0,1446&priv->jack, rt5640_pins,1447ARRAY_SIZE(rt5640_pins));1448if (ret) {1449dev_err(card->dev, "Jack creation failed %d\n", ret);1450return ret;1451}1452snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0,1453KEY_PLAYPAUSE);14541455if (byt_rt5640_quirk & BYT_RT5640_USE_AMCR0F28) {1456ret = byt_rt5640_get_amcr0f28_settings(card);1457if (ret)1458return ret;1459}14601461snd_soc_component_set_jack(component, &priv->jack, &priv->jack_data);1462}14631464if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {1465ret = snd_soc_card_jack_new_pins(card, "Headset",1466SND_JACK_HEADSET,1467&priv->jack, rt5640_pins,1468ARRAY_SIZE(rt5640_pins));1469if (ret)1470return ret;14711472ret = snd_soc_card_jack_new_pins(card, "Headset 2",1473SND_JACK_HEADSET,1474&priv->jack2, rt5640_pins2,1475ARRAY_SIZE(rt5640_pins2));1476if (ret)1477return ret;14781479rt5640_jack_gpio.data = priv;1480rt5640_jack_gpio.gpiod_dev = priv->codec_dev;1481rt5640_jack_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack1_check;1482ret = snd_soc_jack_add_gpios(&priv->jack, 1, &rt5640_jack_gpio);1483if (ret)1484return ret;14851486rt5640_set_ovcd_params(component);1487rt5640_jack2_gpio.data = component;1488rt5640_jack2_gpio.gpiod_dev = priv->codec_dev;1489rt5640_jack2_gpio.jack_status_check = byt_rt5640_hp_elitepad_1000g2_jack2_check;1490ret = snd_soc_jack_add_gpios(&priv->jack2, 1, &rt5640_jack2_gpio);1491if (ret) {1492snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio);1493return ret;1494}1495}14961497return 0;1498}14991500static void byt_rt5640_exit(struct snd_soc_pcm_runtime *runtime)1501{1502struct snd_soc_card *card = runtime->card;1503struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);15041505if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {1506snd_soc_jack_free_gpios(&priv->jack2, 1, &rt5640_jack2_gpio);1507snd_soc_jack_free_gpios(&priv->jack, 1, &rt5640_jack_gpio);1508}1509}15101511static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd,1512struct snd_pcm_hw_params *params)1513{1514struct snd_interval *rate = hw_param_interval(params,1515SNDRV_PCM_HW_PARAM_RATE);1516struct snd_interval *channels = hw_param_interval(params,1517SNDRV_PCM_HW_PARAM_CHANNELS);1518int ret, bits;15191520/* The DSP will convert the FE rate to 48k, stereo */1521rate->min = rate->max = 48000;1522channels->min = channels->max = 2;15231524if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||1525(byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {1526/* set SSP0 to 16-bit */1527params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);1528bits = 16;1529} else {1530/* set SSP2 to 24-bit */1531params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);1532bits = 24;1533}15341535/*1536* Default mode for SSP configuration is TDM 4 slot, override config1537* with explicit setting to I2S 2ch. The word length is set with1538* dai_set_tdm_slot() since there is no other API exposed1539*/1540ret = snd_soc_dai_set_fmt(snd_soc_rtd_to_cpu(rtd, 0),1541SND_SOC_DAIFMT_I2S |1542SND_SOC_DAIFMT_NB_NF |1543SND_SOC_DAIFMT_BP_FP);1544if (ret < 0) {1545dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);1546return ret;1547}15481549ret = snd_soc_dai_set_tdm_slot(snd_soc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits);1550if (ret < 0) {1551dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);1552return ret;1553}15541555return 0;1556}15571558static int byt_rt5640_aif1_startup(struct snd_pcm_substream *substream)1559{1560return snd_pcm_hw_constraint_single(substream->runtime,1561SNDRV_PCM_HW_PARAM_RATE, 48000);1562}15631564static const struct snd_soc_ops byt_rt5640_aif1_ops = {1565.startup = byt_rt5640_aif1_startup,1566};15671568static const struct snd_soc_ops byt_rt5640_be_ssp2_ops = {1569.hw_params = byt_rt5640_aif1_hw_params,1570};15711572SND_SOC_DAILINK_DEF(dummy,1573DAILINK_COMP_ARRAY(COMP_DUMMY()));15741575SND_SOC_DAILINK_DEF(media,1576DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));15771578SND_SOC_DAILINK_DEF(deepbuffer,1579DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));15801581SND_SOC_DAILINK_DEF(ssp2_port,1582/* overwritten for ssp0 routing */1583DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));1584SND_SOC_DAILINK_DEF(ssp2_codec,1585DAILINK_COMP_ARRAY(COMP_CODEC(1586/* overwritten with HID */ "i2c-10EC5640:00",1587/* changed w/ quirk */ "rt5640-aif1")));15881589SND_SOC_DAILINK_DEF(platform,1590DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));15911592static struct snd_soc_dai_link byt_rt5640_dais[] = {1593[MERR_DPCM_AUDIO] = {1594.name = "Baytrail Audio Port",1595.stream_name = "Baytrail Audio",1596.nonatomic = true,1597.dynamic = 1,1598.ops = &byt_rt5640_aif1_ops,1599SND_SOC_DAILINK_REG(media, dummy, platform),1600},1601[MERR_DPCM_DEEP_BUFFER] = {1602.name = "Deep-Buffer Audio Port",1603.stream_name = "Deep-Buffer Audio",1604.nonatomic = true,1605.dynamic = 1,1606.playback_only = 1,1607.ops = &byt_rt5640_aif1_ops,1608SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),1609},1610/* back ends */1611{1612.name = "SSP2-Codec",1613.id = 0,1614.no_pcm = 1,1615.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF1616| SND_SOC_DAIFMT_CBC_CFC,1617.be_hw_params_fixup = byt_rt5640_codec_fixup,1618.init = byt_rt5640_init,1619.exit = byt_rt5640_exit,1620.ops = &byt_rt5640_be_ssp2_ops,1621SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),1622},1623};16241625/* SoC card */1626static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN];1627#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)1628static char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */1629#endif1630static char byt_rt5640_components[64]; /* = "cfg-spk:* cfg-mic:* ..." */16311632static int byt_rt5640_suspend(struct snd_soc_card *card)1633{1634struct snd_soc_component *component;16351636if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))1637return 0;16381639for_each_card_components(card, component) {1640if (!strcmp(component->name, byt_rt5640_codec_name)) {1641dev_dbg(component->dev, "disabling jack detect before suspend\n");1642snd_soc_component_set_jack(component, NULL, NULL);1643break;1644}1645}16461647return 0;1648}16491650static int byt_rt5640_resume(struct snd_soc_card *card)1651{1652struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);1653struct snd_soc_component *component;16541655if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))1656return 0;16571658for_each_card_components(card, component) {1659if (!strcmp(component->name, byt_rt5640_codec_name)) {1660dev_dbg(component->dev, "re-enabling jack detect after resume\n");1661snd_soc_component_set_jack(component, &priv->jack,1662&priv->jack_data);1663break;1664}1665}16661667return 0;1668}16691670/* use space before codec name to simplify card ID, and simplify driver name */1671#define SOF_CARD_NAME "bytcht rt5640" /* card name will be 'sof-bytcht rt5640' */1672#define SOF_DRIVER_NAME "SOF"16731674#define CARD_NAME "bytcr-rt5640"1675#define DRIVER_NAME NULL /* card name will be used for driver name */16761677static struct snd_soc_card byt_rt5640_card = {1678.owner = THIS_MODULE,1679.dai_link = byt_rt5640_dais,1680.num_links = ARRAY_SIZE(byt_rt5640_dais),1681.dapm_widgets = byt_rt5640_widgets,1682.num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets),1683.dapm_routes = byt_rt5640_audio_map,1684.num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map),1685.fully_routed = true,1686.suspend_pre = byt_rt5640_suspend,1687.resume_post = byt_rt5640_resume,1688};16891690struct acpi_chan_package { /* ACPICA seems to require 64 bit integers */1691u64 aif_value; /* 1: AIF1, 2: AIF2 */1692u64 mclock_value; /* usually 25MHz (0x17d7940), ignored */1693};16941695static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)1696{1697struct device *dev = &pdev->dev;1698static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" };1699struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);1700__maybe_unused const char *spk_type;1701const struct dmi_system_id *dmi_id;1702const char *headset2_string = "";1703const char *lineout_string = "";1704struct byt_rt5640_private *priv;1705const char *platform_name;1706struct acpi_device *adev;1707struct device *codec_dev;1708const char *cfg_spk;1709bool sof_parent;1710int ret_val = 0;1711int dai_index = 0;1712int i, aif;17131714is_bytcr = false;1715priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);1716if (!priv)1717return -ENOMEM;17181719/* register the soc card */1720byt_rt5640_card.dev = dev;1721snd_soc_card_set_drvdata(&byt_rt5640_card, priv);17221723/* fix index of codec dai */1724for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) {1725if (byt_rt5640_dais[i].num_codecs &&1726!strcmp(byt_rt5640_dais[i].codecs->name,1727"i2c-10EC5640:00")) {1728dai_index = i;1729break;1730}1731}17321733/* fixup codec name based on HID */1734adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);1735if (adev) {1736snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),1737"i2c-%s", acpi_dev_name(adev));1738byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name;1739} else {1740dev_err(dev, "Error cannot find '%s' dev\n", mach->id);1741return -ENOENT;1742}17431744codec_dev = acpi_get_first_physical_node(adev);1745acpi_dev_put(adev);17461747if (codec_dev) {1748priv->codec_dev = get_device(codec_dev);1749} else {1750/*1751* Special case for Android tablets where the codec i2c_client1752* has been manually instantiated by x86_android_tablets.ko due1753* to a broken DSDT.1754*/1755codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,1756BYT_RT5640_FALLBACK_CODEC_DEV_NAME);1757if (!codec_dev)1758return -EPROBE_DEFER;17591760if (!i2c_verify_client(codec_dev)) {1761dev_err(dev, "Error '%s' is not an i2c_client\n",1762BYT_RT5640_FALLBACK_CODEC_DEV_NAME);1763put_device(codec_dev);1764}17651766/* fixup codec name */1767strscpy(byt_rt5640_codec_name, BYT_RT5640_FALLBACK_CODEC_DEV_NAME,1768sizeof(byt_rt5640_codec_name));17691770/* bus_find_device() returns a reference no need to get() */1771priv->codec_dev = codec_dev;1772}17731774/*1775* swap SSP0 if bytcr is detected1776* (will be overridden if DMI quirk is detected)1777*/1778if (soc_intel_is_byt()) {1779if (mach->mach_params.acpi_ipc_irq_index == 0)1780is_bytcr = true;1781}17821783if (is_bytcr) {1784/*1785* Baytrail CR platforms may have CHAN package in BIOS, try1786* to find relevant routing quirk based as done on Windows1787* platforms. We have to read the information directly from the1788* BIOS, at this stage the card is not created and the links1789* with the codec driver/pdata are non-existent1790*/17911792struct acpi_chan_package chan_package = { 0 };17931794/* format specified: 2 64-bit integers */1795struct acpi_buffer format = {sizeof("NN"), "NN"};1796struct acpi_buffer state = {0, NULL};1797struct snd_soc_acpi_package_context pkg_ctx;1798bool pkg_found = false;17991800state.length = sizeof(chan_package);1801state.pointer = &chan_package;18021803pkg_ctx.name = "CHAN";1804pkg_ctx.length = 2;1805pkg_ctx.format = &format;1806pkg_ctx.state = &state;1807pkg_ctx.data_valid = false;18081809pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,1810&pkg_ctx);1811if (pkg_found) {1812if (chan_package.aif_value == 1) {1813dev_info(dev, "BIOS Routing: AIF1 connected\n");1814byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1;1815} else if (chan_package.aif_value == 2) {1816dev_info(dev, "BIOS Routing: AIF2 connected\n");1817byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;1818} else {1819dev_info(dev, "BIOS Routing isn't valid, ignored\n");1820pkg_found = false;1821}1822}18231824if (!pkg_found) {1825/* no BIOS indications, assume SSP0-AIF2 connection */1826byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;1827}18281829/* change defaults for Baytrail-CR capture */1830byt_rt5640_quirk |= BYTCR_INPUT_DEFAULTS;1831} else {1832byt_rt5640_quirk |= BYT_RT5640_DMIC1_MAP |1833BYT_RT5640_JD_SRC_JD2_IN4N |1834BYT_RT5640_OVCD_TH_2000UA |1835BYT_RT5640_OVCD_SF_0P75;1836}18371838/* check quirks before creating card */1839dmi_id = dmi_first_match(byt_rt5640_quirk_table);1840if (dmi_id)1841byt_rt5640_quirk = (unsigned long)dmi_id->driver_data;1842if (quirk_override != -1) {1843dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n",1844byt_rt5640_quirk, quirk_override);1845byt_rt5640_quirk = quirk_override;1846}18471848if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2) {1849acpi_dev_add_driver_gpios(ACPI_COMPANION(priv->codec_dev),1850byt_rt5640_hp_elitepad_1000g2_gpios);18511852priv->hsmic_detect = devm_fwnode_gpiod_get(dev, codec_dev->fwnode,1853"headset-mic-detect", GPIOD_IN,1854"headset-mic-detect");1855if (IS_ERR(priv->hsmic_detect)) {1856ret_val = dev_err_probe(dev, PTR_ERR(priv->hsmic_detect),1857"getting hsmic-detect GPIO\n");1858goto err_device;1859}1860}18611862/* Must be called before register_card, also see declaration comment. */1863ret_val = byt_rt5640_add_codec_device_props(codec_dev, priv);1864if (ret_val)1865goto err_remove_gpios;18661867log_quirks(dev);18681869if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) ||1870(byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {1871byt_rt5640_dais[dai_index].codecs->dai_name = "rt5640-aif2";1872aif = 2;1873} else {1874aif = 1;1875}18761877if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||1878(byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2))1879byt_rt5640_dais[dai_index].cpus->dai_name = "ssp0-port";18801881if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {1882priv->mclk = devm_clk_get_optional(dev, "pmc_plt_clk_3");1883if (IS_ERR(priv->mclk)) {1884ret_val = dev_err_probe(dev, PTR_ERR(priv->mclk),1885"Failed to get MCLK from pmc_plt_clk_3\n");1886goto err;1887}1888/*1889* Fall back to bit clock usage when clock is not1890* available likely due to missing dependencies.1891*/1892if (!priv->mclk)1893byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;1894}18951896if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) {1897cfg_spk = "0";1898spk_type = "none";1899} else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {1900cfg_spk = "1";1901spk_type = "mono";1902} else if (byt_rt5640_quirk & BYT_RT5640_SWAPPED_SPEAKERS) {1903cfg_spk = "swapped";1904spk_type = "swapped";1905} else {1906cfg_spk = "2";1907spk_type = "stereo";1908}19091910if (byt_rt5640_quirk & BYT_RT5640_LINEOUT) {1911if (byt_rt5640_quirk & BYT_RT5640_LINEOUT_AS_HP2)1912lineout_string = " cfg-hp2:lineout";1913else1914lineout_string = " cfg-lineout:2";1915}19161917if (byt_rt5640_quirk & BYT_RT5640_HSMIC2_ON_IN1)1918headset2_string = " cfg-hs2:in1";19191920snprintf(byt_rt5640_components, sizeof(byt_rt5640_components),1921"cfg-spk:%s cfg-mic:%s aif:%d%s%s", cfg_spk,1922map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif,1923lineout_string, headset2_string);1924byt_rt5640_card.components = byt_rt5640_components;1925#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)1926snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name),1927"bytcr-rt5640-%s-spk-%s-mic", spk_type,1928map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]);1929byt_rt5640_card.long_name = byt_rt5640_long_name;1930#endif19311932/* override platform name, if required */1933platform_name = mach->mach_params.platform;19341935ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card,1936platform_name);1937if (ret_val)1938goto err;19391940sof_parent = snd_soc_acpi_sof_parent(dev);19411942/* set card and driver name */1943if (sof_parent) {1944byt_rt5640_card.name = SOF_CARD_NAME;1945byt_rt5640_card.driver_name = SOF_DRIVER_NAME;1946} else {1947byt_rt5640_card.name = CARD_NAME;1948byt_rt5640_card.driver_name = DRIVER_NAME;1949}19501951/* set pm ops */1952if (sof_parent)1953dev->driver->pm = &snd_soc_pm_ops;19541955ret_val = devm_snd_soc_register_card(dev, &byt_rt5640_card);1956if (ret_val) {1957dev_err(dev, "devm_snd_soc_register_card failed %d\n", ret_val);1958goto err;1959}1960platform_set_drvdata(pdev, &byt_rt5640_card);1961return ret_val;19621963err:1964device_remove_software_node(priv->codec_dev);1965err_remove_gpios:1966if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)1967acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev));1968err_device:1969put_device(priv->codec_dev);1970return ret_val;1971}19721973static void snd_byt_rt5640_mc_remove(struct platform_device *pdev)1974{1975struct snd_soc_card *card = platform_get_drvdata(pdev);1976struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);19771978if (byt_rt5640_quirk & BYT_RT5640_JD_HP_ELITEP_1000G2)1979acpi_dev_remove_driver_gpios(ACPI_COMPANION(priv->codec_dev));19801981device_remove_software_node(priv->codec_dev);1982put_device(priv->codec_dev);1983}19841985static struct platform_driver snd_byt_rt5640_mc_driver = {1986.driver = {1987.name = "bytcr_rt5640",1988},1989.probe = snd_byt_rt5640_mc_probe,1990.remove = snd_byt_rt5640_mc_remove,1991};19921993module_platform_driver(snd_byt_rt5640_mc_driver);19941995MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver");1996MODULE_AUTHOR("Subhransu S. Prusty <[email protected]>");1997MODULE_LICENSE("GPL v2");1998MODULE_ALIAS("platform:bytcr_rt5640");199920002001