static void rt5514_schedule_copy(struct rt5514_dsp *rt5514_dsp)
{
+ size_t period_bytes;
u8 buf[8];
+ if (!rt5514_dsp->substream)
+ return;
+
+ period_bytes = snd_pcm_lib_period_bytes(rt5514_dsp->substream);
rt5514_dsp->get_size = 0;
/**
rt5514_dsp->buf_size = rt5514_dsp->buf_limit - rt5514_dsp->buf_base;
+ if (rt5514_dsp->buf_size % period_bytes)
+ rt5514_dsp->buf_size = (rt5514_dsp->buf_size / period_bytes) *
+ period_bytes;
+
if (rt5514_dsp->buf_base && rt5514_dsp->buf_limit &&
rt5514_dsp->buf_rp && rt5514_dsp->buf_size)
schedule_delayed_work(&rt5514_dsp->copy_work, 0);
dev_err(&rt5514_spi->dev,
"%s Failed to reguest IRQ: %d\n", __func__,
ret);
++++ else
++++ device_init_wakeup(rt5514_dsp->dev, true);
}
return 0;
return true;
}
++ ++EXPORT_SYMBOL_GPL(rt5514_spi_burst_read);
/**
* rt5514_spi_burst_write - Write data to SPI by rt5514 address.
return ret;
}
- -- device_init_wakeup(&spi->dev, true);
- --
return 0;
}
- -- if (rt5514_dsp->substream) {
- -- rt5514_spi_burst_read(RT5514_IRQ_CTRL, (u8 *)&buf, sizeof(buf));
- -- if (buf[0] & RT5514_IRQ_STATUS_BIT)
- -- rt5514_schedule_copy(rt5514_dsp);
+ static int __maybe_unused rt5514_suspend(struct device *dev)
+ {
+ int irq = to_spi_device(dev)->irq;
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(irq);
+
+ return 0;
+ }
+
+ static int __maybe_unused rt5514_resume(struct device *dev)
+ {
+ struct snd_soc_platform *platform = snd_soc_lookup_platform(dev);
+ struct rt5514_dsp *rt5514_dsp =
+ snd_soc_platform_get_drvdata(platform);
+ int irq = to_spi_device(dev)->irq;
+ u8 buf[8];
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(irq);
+
++++ if (rt5514_dsp) {
++++ if (rt5514_dsp->substream) {
++++ rt5514_spi_burst_read(RT5514_IRQ_CTRL, (u8 *)&buf,
++++ sizeof(buf));
++++ if (buf[0] & RT5514_IRQ_STATUS_BIT)
++++ rt5514_schedule_copy(rt5514_dsp);
++++ }
+ }
+
+ return 0;
+ }
+
+ static const struct dev_pm_ops rt5514_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(rt5514_suspend, rt5514_resume)
+ };
+
static const struct of_device_id rt5514_of_match[] = {
{ .compatible = "realtek,rt5514", },
{},
static struct spi_driver rt5514_spi_driver = {
.driver = {
.name = "rt5514",
+ .pm = &rt5514_pm_ops,
.of_match_table = of_match_ptr(rt5514_of_match),
},
.probe = rt5514_spi_probe,
return 0;
}
++ ++static int rt5514_calibration(struct rt5514_priv *rt5514, bool on)
++ ++{
++ ++ if (on) {
++ ++ regmap_write(rt5514->regmap, RT5514_ANA_CTRL_PLL3, 0x0000000a);
++ ++ regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 0xf,
++ ++ 0xa);
++ ++ regmap_update_bits(rt5514->regmap, RT5514_PWR_ANA1, 0x301,
++ ++ 0x301);
++ ++ regmap_write(rt5514->regmap, RT5514_PLL3_CALIB_CTRL4,
++ ++ 0x80000000 | rt5514->pll3_cal_value);
++ ++ regmap_write(rt5514->regmap, RT5514_PLL3_CALIB_CTRL1,
++ ++ 0x8bb80800);
++ ++ regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5,
++ ++ 0xc0000000, 0x80000000);
++ ++ regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5,
++ ++ 0xc0000000, 0xc0000000);
++ ++ } else {
++ ++ regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5,
++ ++ 0xc0000000, 0x40000000);
++ ++ regmap_update_bits(rt5514->regmap, RT5514_PWR_ANA1, 0x301, 0);
++ ++ regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 0xf,
++ ++ 0x4);
++ ++ }
++ ++
++ ++ return 0;
++ ++}
++ ++
static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component);
struct snd_soc_codec *codec = rt5514->codec;
const struct firmware *fw = NULL;
++ ++ u8 buf[8];
if (ucontrol->value.integer.value[0] == rt5514->dsp_enabled)
return 0;
rt5514->dsp_enabled = ucontrol->value.integer.value[0];
if (rt5514->dsp_enabled) {
++ ++ if (rt5514->pdata.dsp_calib_clk_name &&
++ ++ !IS_ERR(rt5514->dsp_calib_clk)) {
++ ++ if (clk_set_rate(rt5514->dsp_calib_clk,
++ ++ rt5514->pdata.dsp_calib_clk_rate))
++ ++ dev_err(codec->dev,
++ ++ "Can't set rate for mclk");
++ ++
++ ++ if (clk_prepare_enable(rt5514->dsp_calib_clk))
++ ++ dev_err(codec->dev,
++ ++ "Can't enable dsp_calib_clk");
++ ++
++ ++ rt5514_calibration(rt5514, true);
++ ++
++ ++ msleep(20);
++ ++#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI)
++ ++ rt5514_spi_burst_read(RT5514_PLL3_CALIB_CTRL6 |
++ ++ RT5514_DSP_MAPPING,
++ ++ (u8 *)&buf, sizeof(buf));
++ ++#else
++ ++ dev_err(codec->dev, "There is no SPI driver for"
++ ++ " loading the firmware\n");
++ ++#endif
++ ++ rt5514->pll3_cal_value = buf[0] | buf[1] << 8 |
++ ++ buf[2] << 16 | buf[3] << 24;
++ ++
++ ++ rt5514_calibration(rt5514, false);
++ ++ clk_disable_unprepare(rt5514->dsp_calib_clk);
++ ++ }
++ ++
rt5514_enable_dsp_prepare(rt5514);
request_firmware(&fw, RT5514_FIRMWARE1, codec->dev);
/* DSP run */
regmap_write(rt5514->i2c_regmap, 0x18002f00,
0x00055148);
++ ++
++ ++ if (rt5514->pdata.dsp_calib_clk_name &&
++ ++ !IS_ERR(rt5514->dsp_calib_clk)) {
++ ++ msleep(20);
++ ++
++ ++ regmap_write(rt5514->i2c_regmap, 0x1800211c,
++ ++ rt5514->pll3_cal_value);
++ ++ regmap_write(rt5514->i2c_regmap, 0x18002124,
++ ++ 0x00220012);
++ ++ regmap_write(rt5514->i2c_regmap, 0x18002124,
++ ++ 0x80220042);
++ ++ regmap_write(rt5514->i2c_regmap, 0x18002124,
++ ++ 0xe0220042);
++ ++ }
} else {
regmap_multi_reg_write(rt5514->i2c_regmap,
rt5514_i2c_patch, ARRAY_SIZE(rt5514_i2c_patch));
SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0),
---- SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0,
++++ SND_SOC_DAPM_SUPPLY_S("DMIC CLK", 1, SND_SOC_NOPM, 0, 0,
rt5514_set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_SUPPLY("ADC CLK", RT5514_CLK_CTRL1,
static int rt5514_probe(struct snd_soc_codec *codec)
{
struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec);
++ ++ struct platform_device *pdev = container_of(codec->dev,
++ ++ struct platform_device, dev);
rt5514->mclk = devm_clk_get(codec->dev, "mclk");
if (PTR_ERR(rt5514->mclk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
++ ++ if (rt5514->pdata.dsp_calib_clk_name) {
++ ++ rt5514->dsp_calib_clk = devm_clk_get(&pdev->dev,
++ ++ rt5514->pdata.dsp_calib_clk_name);
++ ++ if (PTR_ERR(rt5514->dsp_calib_clk) == -EPROBE_DEFER)
++ ++ return -EPROBE_DEFER;
++ ++ }
++ ++
rt5514->codec = codec;
++ ++ rt5514->pll3_cal_value = 0x0078b000;
return 0;
}
{
device_property_read_u32(dev, "realtek,dmic-init-delay-ms",
&rt5514->pdata.dmic_init_delay);
++ ++ device_property_read_string(dev, "realtek,dsp-calib-clk-name",
++ ++ &rt5514->pdata.dsp_calib_clk_name);
++ ++ device_property_read_u32(dev, "realtek,dsp-calib-clk-rate",
++ ++ &rt5514->pdata.dsp_calib_clk_rate);
return 0;
}
#define RT5645_HWEQ_NUM 57
+ #define TIME_TO_POWER_MS 400
+
static const struct regmap_range_cfg rt5645_ranges[] = {
{
.name = "PR",
int jack_type;
bool en_button_func;
bool hp_on;
+ int v_id;
};
static int rt5645_reset(struct snd_soc_codec *codec)
return 0;
}
+++ +static int rt5645_set_micbias1_event(struct snd_soc_dapm_widget *w,
+++ + struct snd_kcontrol *k, int event)
+++ +{
+++ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+++ +
+++ + switch (event) {
+++ + case SND_SOC_DAPM_PRE_PMU:
+++ + snd_soc_update_bits(codec, RT5645_GEN_CTRL2,
+++ + RT5645_MICBIAS1_POW_CTRL_SEL_MASK,
+++ + RT5645_MICBIAS1_POW_CTRL_SEL_M);
+++ + break;
+++ +
+++ + case SND_SOC_DAPM_POST_PMD:
+++ + snd_soc_update_bits(codec, RT5645_GEN_CTRL2,
+++ + RT5645_MICBIAS1_POW_CTRL_SEL_MASK,
+++ + RT5645_MICBIAS1_POW_CTRL_SEL_A);
+++ + break;
+++ +
+++ + default:
+++ + return 0;
+++ + }
+++ +
+++ + return 0;
+++ +}
+++ +
+++ +static int rt5645_set_micbias2_event(struct snd_soc_dapm_widget *w,
+++ + struct snd_kcontrol *k, int event)
+++ +{
+++ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+++ +
+++ + switch (event) {
+++ + case SND_SOC_DAPM_PRE_PMU:
+++ + snd_soc_update_bits(codec, RT5645_GEN_CTRL2,
+++ + RT5645_MICBIAS2_POW_CTRL_SEL_MASK,
+++ + RT5645_MICBIAS2_POW_CTRL_SEL_M);
+++ + break;
+++ +
+++ + case SND_SOC_DAPM_POST_PMD:
+++ + snd_soc_update_bits(codec, RT5645_GEN_CTRL2,
+++ + RT5645_MICBIAS2_POW_CTRL_SEL_MASK,
+++ + RT5645_MICBIAS2_POW_CTRL_SEL_A);
+++ + break;
+++ +
+++ + default:
+++ + return 0;
+++ + }
+++ +
+++ + return 0;
+++ +}
+++ +
static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("LDO2", RT5645_PWR_MIXER,
RT5645_PWR_LDO2_BIT, 0, NULL, 0),
/* Input Side */
/* micbias */
--- - SND_SOC_DAPM_MICBIAS("micbias1", RT5645_PWR_ANLG2,
--- - RT5645_PWR_MB1_BIT, 0),
--- - SND_SOC_DAPM_MICBIAS("micbias2", RT5645_PWR_ANLG2,
--- - RT5645_PWR_MB2_BIT, 0),
+++ + SND_SOC_DAPM_SUPPLY("micbias1", RT5645_PWR_ANLG2,
+++ + RT5645_PWR_MB1_BIT, 0, rt5645_set_micbias1_event,
+++ + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+++ + SND_SOC_DAPM_SUPPLY("micbias2", RT5645_PWR_ANLG2,
+++ + RT5645_PWR_MB2_BIT, 0, rt5645_set_micbias2_event,
+++ + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
/* Input Lines */
SND_SOC_DAPM_INPUT("DMIC L1"),
SND_SOC_DAPM_INPUT("DMIC R1"),
{ "SPKVOL L", "Switch", "SPK MIXL" },
{ "SPKVOL R", "Switch", "SPK MIXR" },
- { "SPOL MIX", "DAC R1 Switch", "DAC R1" },
{ "SPOL MIX", "DAC L1 Switch", "DAC L1" },
- { "SPOL MIX", "SPKVOL R Switch", "SPKVOL R" },
{ "SPOL MIX", "SPKVOL L Switch", "SPKVOL L" },
{ "SPOR MIX", "DAC R1 Switch", "DAC R1" },
{ "SPOR MIX", "SPKVOL R Switch", "SPKVOL R" },
{ "DAC R2 Mux", "IF1 DAC", "RT5645 IF1 DAC2 R Mux" },
};
+ static const struct snd_soc_dapm_route rt5645_old_dapm_routes[] = {
+ { "SPOL MIX", "DAC R1 Switch", "DAC R1" },
+ { "SPOL MIX", "SPKVOL R Switch", "SPKVOL R" },
+ };
+
static int rt5645_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
return IRQ_HANDLED;
}
-- static void rt5645_btn_check_callback(unsigned long data)
++ static void rt5645_btn_check_callback(struct timer_list *t)
{
-- struct rt5645_priv *rt5645 = (struct rt5645_priv *)data;
++ struct rt5645_priv *rt5645 = from_timer(rt5645, t, btn_check_timer);
queue_delayed_work(system_power_efficient_wq,
&rt5645->jack_detect_work, msecs_to_jiffies(5));
snd_soc_dapm_add_routes(dapm,
rt5645_specific_dapm_routes,
ARRAY_SIZE(rt5645_specific_dapm_routes));
+ if (rt5645->v_id < 3) {
+ snd_soc_dapm_add_routes(dapm,
+ rt5645_old_dapm_routes,
+ ARRAY_SIZE(rt5645_old_dapm_routes));
+ }
break;
case CODEC_TYPE_RT5650:
snd_soc_dapm_new_controls(dapm,
snd_soc_dapm_sync(dapm);
}
+++ + if (rt5645->pdata.long_name)
+++ + codec->component.card->long_name = rt5645->pdata.long_name;
+++ +
rt5645->eq_param = devm_kzalloc(codec->dev,
RT5645_HWEQ_NUM * sizeof(struct rt5645_eq_param_s), GFP_KERNEL);
MODULE_DEVICE_TABLE(acpi, rt5645_acpi_match);
#endif
--- -static const struct rt5645_platform_data general_platform_data = {
+++ +static const struct rt5645_platform_data intel_braswell_platform_data = {
.dmic1_data_pin = RT5645_DMIC1_DISABLE,
.dmic2_data_pin = RT5645_DMIC_DATA_IN2P,
.jd_mode = 3,
};
--- -static const struct dmi_system_id dmi_platform_intel_braswell[] = {
+++ +static const struct rt5645_platform_data buddy_platform_data = {
+++ + .dmic1_data_pin = RT5645_DMIC_DATA_GPIO5,
+++ + .dmic2_data_pin = RT5645_DMIC_DATA_IN2P,
+++ + .jd_mode = 3,
+++ + .level_trigger_irq = true,
+++ +};
+++ +
+++ +static const struct rt5645_platform_data gpd_win_platform_data = {
+++ + .jd_mode = 3,
+++ + .inv_jd1_1 = true,
+++ + .long_name = "gpd-win-pocket-rt5645",
+++ + /* The GPD pocket has a diff. mic, for the win this does not matter. */
+++ + .in2_diff = true,
+++ +};
+++ +
+++ +static const struct rt5645_platform_data asus_t100ha_platform_data = {
+++ + .dmic1_data_pin = RT5645_DMIC_DATA_IN2N,
+++ + .dmic2_data_pin = RT5645_DMIC2_DISABLE,
+++ + .jd_mode = 3,
+++ + .inv_jd1_1 = true,
+++ +};
+++ +
+++ +static const struct rt5645_platform_data jd_mode3_platform_data = {
+++ + .jd_mode = 3,
+++ +};
+++ +
+++ +static const struct dmi_system_id dmi_platform_data[] = {
+++ + {
+++ + .ident = "Chrome Buddy",
+++ + .matches = {
+++ + DMI_MATCH(DMI_PRODUCT_NAME, "Buddy"),
+++ + },
+++ + .driver_data = (void *)&buddy_platform_data,
+++ + },
{
.ident = "Intel Strago",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "Strago"),
},
+++ + .driver_data = (void *)&intel_braswell_platform_data,
},
{
.ident = "Google Chrome",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
},
+++ + .driver_data = (void *)&intel_braswell_platform_data,
},
{
.ident = "Google Setzer",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "Setzer"),
},
+++ + .driver_data = (void *)&intel_braswell_platform_data,
},
{
.ident = "Microsoft Surface 3",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "Surface 3"),
},
+++ + .driver_data = (void *)&intel_braswell_platform_data,
},
--- - { }
--- -};
--- -
--- -static const struct rt5645_platform_data buddy_platform_data = {
--- - .dmic1_data_pin = RT5645_DMIC_DATA_GPIO5,
--- - .dmic2_data_pin = RT5645_DMIC_DATA_IN2P,
--- - .jd_mode = 3,
--- - .level_trigger_irq = true,
--- -};
--- -
-- -static const struct dmi_system_id dmi_platform_intel_broadwell[] = {
- static struct dmi_system_id dmi_platform_intel_broadwell[] = {
--- - {
--- - .ident = "Chrome Buddy",
--- - .matches = {
--- - DMI_MATCH(DMI_PRODUCT_NAME, "Buddy"),
--- - },
--- - },
--- - { }
--- -};
--- -
--- -static const struct rt5645_platform_data gpd_win_platform_data = {
--- - .jd_mode = 3,
--- - .inv_jd1_1 = true,
--- -};
--- -
--- -static const struct dmi_system_id dmi_platform_gpd_win[] = {
{
/*
* Match for the GPDwin which unfortunately uses somewhat
* the same default product_name. Also the GPDwin is the
* only device to have both board_ and product_name not set.
*/
--- - .ident = "GPD Win",
+++ + .ident = "GPD Win / Pocket",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_MATCH(DMI_BOARD_NAME, "Default string"),
DMI_MATCH(DMI_BOARD_SERIAL, "Default string"),
DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
},
+++ + .driver_data = (void *)&gpd_win_platform_data,
},
--- - {}
--- -};
--- -
-- -static const struct rt5645_platform_data general_platform_data2 = {
- static struct rt5645_platform_data general_platform_data2 = {
--- - .dmic1_data_pin = RT5645_DMIC_DATA_IN2N,
--- - .dmic2_data_pin = RT5645_DMIC2_DISABLE,
--- - .jd_mode = 3,
--- - .inv_jd1_1 = true,
--- -};
--- -
-- -static const struct dmi_system_id dmi_platform_asus_t100ha[] = {
- static struct dmi_system_id dmi_platform_asus_t100ha[] = {
{
.ident = "ASUS T100HAN",
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "T100HAN"),
},
+++ + .driver_data = (void *)&asus_t100ha_platform_data,
},
--- - { }
--- -};
--- -
-- -static const struct rt5645_platform_data minix_z83_4_platform_data = {
- static struct rt5645_platform_data minix_z83_4_platform_data = {
--- - .jd_mode = 3,
--- -};
--- -
-- -static const struct dmi_system_id dmi_platform_minix_z83_4[] = {
- static struct dmi_system_id dmi_platform_minix_z83_4[] = {
{
.ident = "MINIX Z83-4",
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MINIX"),
DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
},
+++ + .driver_data = (void *)&jd_mode3_platform_data,
+++ + },
+++ + {
+++ + .ident = "Teclast X80 Pro",
+++ + .matches = {
+++ + DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"),
+++ + DMI_MATCH(DMI_PRODUCT_NAME, "X80 Pro"),
+++ + },
+++ + .driver_data = (void *)&jd_mode3_platform_data,
},
{ }
};
static bool rt5645_check_dp(struct device *dev)
{
if (device_property_present(dev, "realtek,in2-differential") ||
--- - device_property_present(dev, "realtek,dmic1-data-pin") ||
--- - device_property_present(dev, "realtek,dmic2-data-pin") ||
--- - device_property_present(dev, "realtek,jd-mode"))
+++ + device_property_present(dev, "realtek,dmic1-data-pin") ||
+++ + device_property_present(dev, "realtek,dmic2-data-pin") ||
+++ + device_property_present(dev, "realtek,jd-mode"))
return true;
return false;
const struct i2c_device_id *id)
{
struct rt5645_platform_data *pdata = dev_get_platdata(&i2c->dev);
+++ + const struct dmi_system_id *dmi_data;
struct rt5645_priv *rt5645;
int ret, i;
unsigned int val;
rt5645->i2c = i2c;
i2c_set_clientdata(i2c, rt5645);
+++ + dmi_data = dmi_first_match(dmi_platform_data);
+++ + if (dmi_data) {
+++ + dev_info(&i2c->dev, "Detected %s platform\n", dmi_data->ident);
+++ + pdata = dmi_data->driver_data;
+++ + }
+++ +
if (pdata)
rt5645->pdata = *pdata;
--- - else if (dmi_check_system(dmi_platform_intel_broadwell))
--- - rt5645->pdata = buddy_platform_data;
else if (rt5645_check_dp(&i2c->dev))
rt5645_parse_dt(rt5645, &i2c->dev);
--- - else if (dmi_check_system(dmi_platform_intel_braswell))
--- - rt5645->pdata = general_platform_data;
--- - else if (dmi_check_system(dmi_platform_gpd_win))
--- - rt5645->pdata = gpd_win_platform_data;
--- - else if (dmi_check_system(dmi_platform_asus_t100ha))
--- - rt5645->pdata = general_platform_data2;
--- - else if (dmi_check_system(dmi_platform_minix_z83_4))
--- - rt5645->pdata = minix_z83_4_platform_data;
+++ + else
+++ + rt5645->pdata = jd_mode3_platform_data;
if (quirk != -1) {
rt5645->pdata.in2_diff = QUIRK_IN2_DIFF(quirk);
ret);
return ret;
}
+
+ /*
+ * Read after 400msec, as it is the interval required between
+ * read and power On.
+ */
+ msleep(TIME_TO_POWER_MS);
regmap_read(regmap, RT5645_VENDOR_ID2, &val);
switch (val) {
regmap_write(rt5645->regmap, RT5645_RESET, 0);
+ regmap_read(regmap, RT5645_VENDOR_ID, &val);
+ rt5645->v_id = val & 0xff;
+
++ + regmap_write(rt5645->regmap, RT5645_AD_DA_MIXER, 0x8080);
++ +
ret = regmap_register_patch(rt5645->regmap, init_list,
ARRAY_SIZE(init_list));
if (ret != 0)
regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
}
-- setup_timer(&rt5645->btn_check_timer,
-- rt5645_btn_check_callback, (unsigned long)rt5645);
++ timer_setup(&rt5645->btn_check_timer, rt5645_btn_check_callback, 0);
INIT_DELAYED_WORK(&rt5645->jack_detect_work, rt5645_jack_detect_work);
INIT_DELAYED_WORK(&rt5645->rcclock_work, rt5645_rcclock_work);
*/
#include <linux/module.h>
- #include <linux/acpi.h>
#include <linux/platform_device.h>
+ #include <linux/acpi.h>
+ #include <linux/clk.h>
#include <linux/dmi.h>
#include <linux/slab.h>
#include <asm/cpu_device_id.h>
#include <asm/platform_sst_audio.h>
- #include <linux/clk.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/jack.h>
+ #include <sound/soc-acpi.h>
#include "../../codecs/rt5645.h"
#include "../atom/sst-atom-controls.h"
- #include "../common/sst-acpi.h"
#define CHT_PLAT_CLK_3_HZ 19200000
#define CHT_CODEC_DAI1 "rt5645-aif1"
struct cht_mc_private {
struct snd_soc_jack jack;
struct cht_acpi_card *acpi_card;
---- char codec_name[16];
++++ char codec_name[SND_ACPI_I2C_ID_LEN];
struct clk *mclk;
};
- #define CHT_RT5645_MAP(quirk) ((quirk) & 0xff)
+ #define CHT_RT5645_MAP(quirk) ((quirk) & GENMASK(7, 0))
#define CHT_RT5645_SSP2_AIF2 BIT(16) /* default is using AIF1 */
#define CHT_RT5645_SSP0_AIF1 BIT(17)
#define CHT_RT5645_SSP0_AIF2 BIT(18)
dev_info(dev, "quirk SSP0_AIF2 enabled");
}
- static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
- {
- struct snd_soc_pcm_runtime *rtd;
-
- list_for_each_entry(rtd, &card->rtd_list, list) {
- if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI1,
- strlen(CHT_CODEC_DAI1)))
- return rtd->codec_dai;
- if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI2,
- strlen(CHT_CODEC_DAI2)))
- return rtd->codec_dai;
- }
- return NULL;
- }
-
static int platform_clock_control(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
int ret;
- codec_dai = cht_get_codec_dai(card);
+ codec_dai = snd_soc_card_get_codec_dai(card, CHT_CODEC_DAI1);
+ if (!codec_dai)
+ codec_dai = snd_soc_card_get_codec_dai(card, CHT_CODEC_DAI2);
+
if (!codec_dai) {
dev_err(card->dev, "Codec dai not found; Unable to set platform clock\n");
return -EIO;
}
if (SND_SOC_DAPM_EVENT_ON(event)) {
- if (ctx->mclk) {
- ret = clk_prepare_enable(ctx->mclk);
- if (ret < 0) {
- dev_err(card->dev,
- "could not configure MCLK state");
- return ret;
- }
+ ret = clk_prepare_enable(ctx->mclk);
+ if (ret < 0) {
+ dev_err(card->dev,
+ "could not configure MCLK state");
+ return ret;
}
} else {
/* Set codec sysclk source to its internal clock because codec PLL will
return ret;
}
- if (ctx->mclk)
- clk_disable_unprepare(ctx->mclk);
+ clk_disable_unprepare(ctx->mclk);
}
return 0;
SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Int Mic", NULL),
+++ + SND_SOC_DAPM_MIC("Int Analog Mic", NULL),
SND_SOC_DAPM_SPK("Ext Spk", NULL),
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
{"IN1N", NULL, "Headset Mic"},
{"DMIC L1", NULL, "Int Mic"},
{"DMIC R1", NULL, "Int Mic"},
+++ + {"IN2P", NULL, "Int Analog Mic"},
+++ + {"IN2N", NULL, "Int Analog Mic"},
{"Headphone", NULL, "HPOL"},
{"Headphone", NULL, "HPOR"},
{"Ext Spk", NULL, "SPOL"},
{"Headphone", NULL, "Platform Clock"},
{"Headset Mic", NULL, "Platform Clock"},
{"Int Mic", NULL, "Platform Clock"},
+++ + {"Int Analog Mic", NULL, "Platform Clock"},
+++ + {"Int Analog Mic", NULL, "micbias1"},
+++ + {"Int Analog Mic", NULL, "micbias2"},
{"Ext Spk", NULL, "Platform Clock"},
};
SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
SOC_DAPM_PIN_SWITCH("Int Mic"),
+++ + SOC_DAPM_PIN_SWITCH("Int Analog Mic"),
SOC_DAPM_PIN_SWITCH("Ext Spk"),
};
static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
{
- int ret;
- int jack_type;
- struct snd_soc_codec *codec = runtime->codec;
struct snd_soc_card *card = runtime->card;
struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card);
+ struct snd_soc_codec *codec = runtime->codec;
+ int jack_type;
+ int ret;
if ((cht_rt5645_quirk & CHT_RT5645_SSP2_AIF2) ||
(cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)) {
rt5645_set_jack_detect(codec, &ctx->jack, &ctx->jack, &ctx->jack);
- if (ctx->mclk) {
- /*
- * The firmware might enable the clock at
- * boot (this information may or may not
- * be reflected in the enable clock register).
- * To change the rate we must disable the clock
- * first to cover these cases. Due to common
- * clock framework restrictions that do not allow
- * to disable a clock that has not been enabled,
- * we need to enable the clock first.
- */
- ret = clk_prepare_enable(ctx->mclk);
- if (!ret)
- clk_disable_unprepare(ctx->mclk);
- ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
+ /*
+ * The firmware might enable the clock at
+ * boot (this information may or may not
+ * be reflected in the enable clock register).
+ * To change the rate we must disable the clock
+ * first to cover these cases. Due to common
+ * clock framework restrictions that do not allow
+ * to disable a clock that has not been enabled,
+ * we need to enable the clock first.
+ */
+ ret = clk_prepare_enable(ctx->mclk);
+ if (!ret)
+ clk_disable_unprepare(ctx->mclk);
+
+ ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
+
+ if (ret)
+ dev_err(runtime->dev, "unable to set MCLK rate\n");
- if (ret)
- dev_err(runtime->dev, "unable to set MCLK rate\n");
- }
return ret;
}
.dpcm_playback = 1,
.ops = &cht_aif1_ops,
},
- [MERR_DPCM_COMPR] = {
- .name = "Compressed Port",
- .stream_name = "Compress",
- .cpu_dai_name = "compress-cpu-dai",
- .codec_dai_name = "snd-soc-dummy-dai",
- .codec_name = "snd-soc-dummy",
- .platform_name = "sst-mfld-platform",
- },
/* CODEC<->CODEC link */
/* back ends */
{
.name = "SSP2-Codec",
- .id = 1,
+ .id = 0,
.cpu_dai_name = "ssp2-port",
.platform_name = "sst-mfld-platform",
.no_pcm = 1,
{"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650},
};
----static char cht_rt5645_codec_name[16]; /* i2c-<HID>:00 with HID being 8 chars */
++++static char cht_rt5645_codec_name[SND_ACPI_I2C_ID_LEN];
static char cht_rt5645_codec_aif_name[12]; /* = "rt5645-aif[1|2]" */
static char cht_rt5645_cpu_dai_name[10]; /* = "ssp[0|2]-port" */
static int snd_cht_mc_probe(struct platform_device *pdev)
{
- int ret_val = 0;
- int i;
- struct cht_mc_private *drv;
struct snd_soc_card *card = snd_soc_cards[0].soc_card;
- struct sst_acpi_mach *mach;
+ struct snd_soc_acpi_mach *mach;
+ struct cht_mc_private *drv;
const char *i2c_name = NULL;
- int dai_index = 0;
bool found = false;
bool is_bytcr = false;
+ int dai_index = 0;
+ int ret_val = 0;
+ int i;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC);
if (!drv)
}
/* fixup codec name based on HID */
- -- i2c_name = snd_soc_acpi_find_name_from_hid(mach->id);
- i2c_name = sst_acpi_find_name_from_hid(mach->id);
- if (i2c_name != NULL) {
++++ i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
+ if (i2c_name) {
snprintf(cht_rt5645_codec_name, sizeof(cht_rt5645_codec_name),
"%s%s", "i2c-", i2c_name);
cht_dailink[dai_index].codec_name = cht_rt5645_codec_name;
/* format specified: 2 64-bit integers */
struct acpi_buffer format = {sizeof("NN"), "NN"};
struct acpi_buffer state = {0, NULL};
- struct sst_acpi_package_context pkg_ctx;
+ struct snd_soc_acpi_package_context pkg_ctx;
bool pkg_found = false;
state.length = sizeof(chan_package);
pkg_ctx.state = &state;
pkg_ctx.data_valid = false;
- pkg_found = sst_acpi_find_package_from_hid(mach->id, &pkg_ctx);
+ pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,
+ &pkg_ctx);
if (pkg_found) {
if (chan_package.aif_value == 1) {
dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
cht_rt5645_cpu_dai_name;
}
- if (is_valleyview()) {
- drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
- if (IS_ERR(drv->mclk)) {
- dev_err(&pdev->dev,
- "Failed to get MCLK from pmc_plt_clk_3: %ld\n",
- PTR_ERR(drv->mclk));
- return PTR_ERR(drv->mclk);
- }
+ drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
+ if (IS_ERR(drv->mclk)) {
+ dev_err(&pdev->dev,
+ "Failed to get MCLK from pmc_plt_clk_3: %ld\n",
+ PTR_ERR(drv->mclk));
+ return PTR_ERR(drv->mclk);
}
snd_soc_card_set_drvdata(card, drv);