Commit 84400d7f authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/rt5645', 'asoc/topic/rt5651',...

Merge remote-tracking branches 'asoc/topic/rt5645', 'asoc/topic/rt5651', 'asoc/topic/rt5659', 'asoc/topic/rt5663' and 'asoc/topic/rt5670' into asoc-next
......@@ -19,6 +19,22 @@ Optional properties:
Based on the different PCB layout, add the manual offset value to
compensate the DC offset for each L and R channel, and they are different
between headphone and headset.
- "realtek,impedance_sensing_num"
The matrix row number of the impedance sensing table.
If the value is 0, it means the impedance sensing is not supported.
- "realtek,impedance_sensing_table"
The matrix rows of the impedance sensing table are consisted by impedance
minimum, impedance maximun, volume, DC offset w/o and w/ mic of each L and
R channel accordingly. Example is shown as following.
< 0 300 7 0xffd160 0xffd1c0 0xff8a10 0xff8ab0
301 65535 4 0xffe470 0xffe470 0xffb8e0 0xffb8e0>
The first and second column are defined for the impedance range. If the
detected impedance value is in the range, then the volume value of the
third column will be set to codec. In our codec design, each volume value
should compensate different DC offset to avoid the pop sound, and it is
also different between headphone and headset. In the example, the
"realtek,impedance_sensing_num" is 2. It means that there are 2 ranges of
impedance in the impedance sensing function.
Pins on the device (for linking into audio routes) for RT5663:
......
......@@ -11,11 +11,19 @@
#ifndef __LINUX_SND_RT5651_H
#define __LINUX_SND_RT5651_H
enum rt5651_jd_src {
RT5651_JD_NULL,
RT5651_JD1_1,
RT5651_JD1_2,
RT5651_JD2,
};
struct rt5651_platform_data {
/* IN2 can optionally be differential */
bool in2_diff;
bool dmic_en;
enum rt5651_jd_src jd_src;
};
#endif
......@@ -16,6 +16,9 @@ struct rt5663_platform_data {
unsigned int dc_offset_r_manual;
unsigned int dc_offset_l_manual_mic;
unsigned int dc_offset_r_manual_mic;
unsigned int impedance_sensing_num;
unsigned int *impedance_sensing_table;
};
#endif
......
......@@ -55,6 +55,8 @@ MODULE_PARM_DESC(quirk, "RT5645 pdata quirk override");
#define RT5645_HWEQ_NUM 57
#define TIME_TO_POWER_MS 400
static const struct regmap_range_cfg rt5645_ranges[] = {
{
.name = "PR",
......@@ -432,6 +434,7 @@ struct rt5645_priv {
int jack_type;
bool en_button_func;
bool hp_on;
int v_id;
};
static int rt5645_reset(struct snd_soc_codec *codec)
......@@ -2516,9 +2519,7 @@ static const struct snd_soc_dapm_route rt5645_dapm_routes[] = {
{ "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" },
......@@ -2707,6 +2708,11 @@ static const struct snd_soc_dapm_route rt5645_specific_dapm_routes[] = {
{ "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)
{
......@@ -3363,6 +3369,11 @@ static int rt5645_probe(struct snd_soc_codec *codec)
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,
......@@ -3637,14 +3648,14 @@ static const struct dmi_system_id dmi_platform_gpd_win[] = {
{}
};
static struct rt5645_platform_data general_platform_data2 = {
static const 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 struct dmi_system_id dmi_platform_asus_t100ha[] = {
static const struct dmi_system_id dmi_platform_asus_t100ha[] = {
{
.ident = "ASUS T100HAN",
.matches = {
......@@ -3655,11 +3666,11 @@ static struct dmi_system_id dmi_platform_asus_t100ha[] = {
{ }
};
static struct rt5645_platform_data minix_z83_4_platform_data = {
static const struct rt5645_platform_data minix_z83_4_platform_data = {
.jd_mode = 3,
};
static struct dmi_system_id dmi_platform_minix_z83_4[] = {
static const struct dmi_system_id dmi_platform_minix_z83_4[] = {
{
.ident = "MINIX Z83-4",
.matches = {
......@@ -3775,6 +3786,12 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
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) {
......@@ -3803,6 +3820,9 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
regmap_write(rt5645->regmap, RT5645_RESET, 0);
regmap_read(regmap, RT5645_VENDOR_ID, &val);
rt5645->v_id = val & 0xff;
ret = regmap_register_patch(rt5645->regmap, init_list,
ARRAY_SIZE(init_list));
if (ret != 0)
......
......@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
......@@ -26,10 +27,15 @@
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include <sound/jack.h>
#include "rl6231.h"
#include "rt5651.h"
#define RT5651_JD_MAP(quirk) ((quirk) & GENMASK(7, 0))
#define RT5651_IN2_DIFF BIT(16)
#define RT5651_DMIC_EN BIT(17)
#define RT5651_DEVICE_ID_VALUE 0x6281
#define RT5651_PR_RANGE_BASE (0xff + 1)
......@@ -37,6 +43,8 @@
#define RT5651_PR_BASE (RT5651_PR_RANGE_BASE + (0 * RT5651_PR_SPACING))
static unsigned long rt5651_quirk;
static const struct regmap_range_cfg rt5651_ranges[] = {
{ .name = "PR", .range_min = RT5651_PR_BASE,
.range_max = RT5651_PR_BASE + 0xb4,
......@@ -880,11 +888,14 @@ static const struct snd_soc_dapm_widget rt5651_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("PLL1", RT5651_PWR_ANLG2,
RT5651_PWR_PLL_BIT, 0, NULL, 0),
/* Input Side */
SND_SOC_DAPM_SUPPLY("JD Power", RT5651_PWR_ANLG2,
RT5651_PWM_JD_M_BIT, 0, NULL, 0),
/* micbias */
SND_SOC_DAPM_SUPPLY("LDO", RT5651_PWR_ANLG1,
RT5651_PWR_LDO_BIT, 0, NULL, 0),
SND_SOC_DAPM_MICBIAS("micbias1", RT5651_PWR_ANLG2,
RT5651_PWR_MB1_BIT, 0),
SND_SOC_DAPM_SUPPLY("micbias1", RT5651_PWR_ANLG2,
RT5651_PWR_MB1_BIT, 0, NULL, 0),
/* Input Lines */
SND_SOC_DAPM_INPUT("MIC1"),
SND_SOC_DAPM_INPUT("MIC2"),
......@@ -1528,6 +1539,8 @@ static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
static int rt5651_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
switch (level) {
case SND_SOC_BIAS_PREPARE:
if (SND_SOC_BIAS_STANDBY == snd_soc_codec_get_bias_level(codec)) {
......@@ -1556,8 +1569,13 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
snd_soc_write(codec, RT5651_PWR_DIG2, 0x0000);
snd_soc_write(codec, RT5651_PWR_VOL, 0x0000);
snd_soc_write(codec, RT5651_PWR_MIXER, 0x0000);
snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
if (rt5651->pdata.jd_src) {
snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0204);
snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0002);
} else {
snd_soc_write(codec, RT5651_PWR_ANLG1, 0x0000);
snd_soc_write(codec, RT5651_PWR_ANLG2, 0x0000);
}
break;
default:
......@@ -1570,6 +1588,7 @@ static int rt5651_set_bias_level(struct snd_soc_codec *codec,
static int rt5651_probe(struct snd_soc_codec *codec)
{
struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
rt5651->codec = codec;
......@@ -1585,6 +1604,15 @@ static int rt5651_probe(struct snd_soc_codec *codec)
snd_soc_codec_force_bias_level(codec, SND_SOC_BIAS_OFF);
if (rt5651->pdata.jd_src) {
snd_soc_dapm_force_enable_pin(dapm, "JD Power");
snd_soc_dapm_force_enable_pin(dapm, "LDO");
snd_soc_dapm_sync(dapm);
regmap_update_bits(rt5651->regmap, RT5651_MICBIAS,
0x38, 0x38);
}
return 0;
}
......@@ -1718,15 +1746,130 @@ static const struct i2c_device_id rt5651_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, rt5651_i2c_id);
static int rt5651_quirk_cb(const struct dmi_system_id *id)
{
rt5651_quirk = (unsigned long) id->driver_data;
return 1;
}
static const struct dmi_system_id rt5651_quirk_table[] = {
{
.callback = rt5651_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "KIANO"),
DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
},
.driver_data = (unsigned long *) RT5651_JD1_1,
},
{}
};
static int rt5651_parse_dt(struct rt5651_priv *rt5651, struct device_node *np)
{
rt5651->pdata.in2_diff = of_property_read_bool(np,
"realtek,in2-differential");
rt5651->pdata.dmic_en = of_property_read_bool(np,
"realtek,dmic-en");
if (of_property_read_bool(np, "realtek,in2-differential"))
rt5651_quirk |= RT5651_IN2_DIFF;
if (of_property_read_bool(np, "realtek,dmic-en"))
rt5651_quirk |= RT5651_DMIC_EN;
return 0;
}
static void rt5651_set_pdata(struct rt5651_priv *rt5651)
{
if (rt5651_quirk & RT5651_IN2_DIFF)
rt5651->pdata.in2_diff = true;
if (rt5651_quirk & RT5651_DMIC_EN)
rt5651->pdata.dmic_en = true;
if (RT5651_JD_MAP(rt5651_quirk))
rt5651->pdata.jd_src = RT5651_JD_MAP(rt5651_quirk);
}
static irqreturn_t rt5651_irq(int irq, void *data)
{
struct rt5651_priv *rt5651 = data;
queue_delayed_work(system_power_efficient_wq,
&rt5651->jack_detect_work, msecs_to_jiffies(250));
return IRQ_HANDLED;
}
static int rt5651_jack_detect(struct snd_soc_codec *codec, int jack_insert)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
int jack_type;
if (jack_insert) {
snd_soc_dapm_force_enable_pin(dapm, "LDO");
snd_soc_dapm_sync(dapm);
snd_soc_update_bits(codec, RT5651_MICBIAS,
RT5651_MIC1_OVCD_MASK |
RT5651_MIC1_OVTH_MASK |
RT5651_PWR_CLK12M_MASK |
RT5651_PWR_MB_MASK,
RT5651_MIC1_OVCD_EN |
RT5651_MIC1_OVTH_600UA |
RT5651_PWR_MB_PU |
RT5651_PWR_CLK12M_PU);
msleep(100);
if (snd_soc_read(codec, RT5651_IRQ_CTRL2) & RT5651_MB1_OC_CLR)
jack_type = SND_JACK_HEADPHONE;
else
jack_type = SND_JACK_HEADSET;
snd_soc_update_bits(codec, RT5651_IRQ_CTRL2,
RT5651_MB1_OC_CLR, 0);
} else { /* jack out */
jack_type = 0;
snd_soc_update_bits(codec, RT5651_MICBIAS,
RT5651_MIC1_OVCD_MASK,
RT5651_MIC1_OVCD_DIS);
}
return jack_type;
}
static void rt5651_jack_detect_work(struct work_struct *work)
{
struct rt5651_priv *rt5651 =
container_of(work, struct rt5651_priv, jack_detect_work.work);
int report, val = 0;
if (!rt5651->codec)
return;
switch (rt5651->pdata.jd_src) {
case RT5651_JD1_1:
val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x1000;
break;
case RT5651_JD1_2:
val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x2000;
break;
case RT5651_JD2:
val = snd_soc_read(rt5651->codec, RT5651_INT_IRQ_ST) & 0x4000;
break;
default:
break;
}
report = rt5651_jack_detect(rt5651->codec, !val);
snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
}
int rt5651_set_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *hp_jack)
{
struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
rt5651->hp_jack = hp_jack;
rt5651_irq(0, rt5651);
return 0;
}
EXPORT_SYMBOL_GPL(rt5651_set_jack_detect);
static int rt5651_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
......@@ -1746,6 +1889,10 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
rt5651->pdata = *pdata;
else if (i2c->dev.of_node)
rt5651_parse_dt(rt5651, i2c->dev.of_node);
else
dmi_check_system(rt5651_quirk_table);
rt5651_set_pdata(rt5651);
rt5651->regmap = devm_regmap_init_i2c(i2c, &rt5651_regmap);
if (IS_ERR(rt5651->regmap)) {
......@@ -1779,6 +1926,59 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
rt5651->hp_mute = 1;
if (rt5651->pdata.jd_src) {
/* IRQ output on GPIO1 */
regmap_update_bits(rt5651->regmap, RT5651_GPIO_CTRL1,
RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ);
switch (rt5651->pdata.jd_src) {
case RT5651_JD1_1:
regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
RT5651_JD_TRG_SEL_MASK,
RT5651_JD_TRG_SEL_JD1_1);
regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
RT5651_JD1_1_IRQ_EN,
RT5651_JD1_1_IRQ_EN);
break;
case RT5651_JD1_2:
regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
RT5651_JD_TRG_SEL_MASK,
RT5651_JD_TRG_SEL_JD1_2);
regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
RT5651_JD1_2_IRQ_EN,
RT5651_JD1_2_IRQ_EN);
break;
case RT5651_JD2:
regmap_update_bits(rt5651->regmap, RT5651_JD_CTRL2,
RT5651_JD_TRG_SEL_MASK,
RT5651_JD_TRG_SEL_JD2);
regmap_update_bits(rt5651->regmap, RT5651_IRQ_CTRL1,
RT5651_JD2_IRQ_EN,
RT5651_JD2_IRQ_EN);
break;
case RT5651_JD_NULL:
break;
default:
dev_warn(&i2c->dev, "Currently only JD1_1 / JD1_2 / JD2 are supported\n");
break;
}
}
INIT_DELAYED_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work);
if (i2c->irq) {
ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
rt5651_irq,
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING |
IRQF_ONESHOT, "rt5651", rt5651);
if (ret) {
dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
return ret;
}
}
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5651,
rt5651_dai, ARRAY_SIZE(rt5651_dai));
......@@ -1787,6 +1987,9 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
static int rt5651_i2c_remove(struct i2c_client *i2c)
{
struct rt5651_priv *rt5651 = i2c_get_clientdata(i2c);
cancel_delayed_work_sync(&rt5651->jack_detect_work);
snd_soc_unregister_codec(&i2c->dev);
return 0;
......
......@@ -2062,6 +2062,8 @@ struct rt5651_priv {
struct snd_soc_codec *codec;
struct rt5651_platform_data pdata;
struct regmap *regmap;
struct snd_soc_jack *hp_jack;
struct delayed_work jack_detect_work;
int sysclk;
int sysclk_src;
......@@ -2077,4 +2079,6 @@ struct rt5651_priv {
bool hp_mute;
};
int rt5651_set_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *hp_jack);
#endif /* __RT5651_H__ */
......@@ -3385,10 +3385,9 @@ static int rt5659_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return 0;
}
static int rt5659_set_dai_sysclk(struct snd_soc_dai *dai,
int clk_id, unsigned int freq, int dir)
static int rt5659_set_codec_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = dai->codec;
struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
unsigned int reg_val = 0;
......@@ -3414,20 +3413,21 @@ static int rt5659_set_dai_sysclk(struct snd_soc_dai *dai,
rt5659->sysclk = freq;
rt5659->sysclk_src = clk_id;
dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
dev_dbg(codec->dev, "Sysclk is %dHz and clock id is %d\n",
freq, clk_id);
return 0;
}
static int rt5659_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int Source,
unsigned int freq_in, unsigned int freq_out)
static int rt5659_set_codec_pll(struct snd_soc_codec *codec, int pll_id,
int source, unsigned int freq_in,
unsigned int freq_out)
{
struct snd_soc_codec *codec = dai->codec;
struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
struct rl6231_pll_code pll_code;
int ret;
if (Source == rt5659->pll_src && freq_in == rt5659->pll_in &&
if (source == rt5659->pll_src && freq_in == rt5659->pll_in &&
freq_out == rt5659->pll_out)
return 0;
......@@ -3441,7 +3441,7 @@ static int rt5659_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int Source,
return 0;
}
switch (Source) {
switch (source) {
case RT5659_PLL1_S_MCLK:
snd_soc_update_bits(codec, RT5659_GLB_CLK,
RT5659_PLL1_SRC_MASK, RT5659_PLL1_SRC_MCLK);
......@@ -3459,7 +3459,7 @@ static int rt5659_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int Source,
RT5659_PLL1_SRC_MASK, RT5659_PLL1_SRC_BCLK3);
break;
default:
dev_err(codec->dev, "Unknown PLL Source %d\n", Source);
dev_err(codec->dev, "Unknown PLL source %d\n", source);
return -EINVAL;
}
......@@ -3481,7 +3481,7 @@ static int rt5659_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int Source,
rt5659->pll_in = freq_in;
rt5659->pll_out = freq_out;
rt5659->pll_src = Source;
rt5659->pll_src = source;
return 0;
}
......@@ -3666,9 +3666,7 @@ static int rt5659_resume(struct snd_soc_codec *codec)
static const struct snd_soc_dai_ops rt5659_aif_dai_ops = {
.hw_params = rt5659_hw_params,
.set_fmt = rt5659_set_dai_fmt,
.set_sysclk = rt5659_set_dai_sysclk,
.set_tdm_slot = rt5659_set_tdm_slot,
.set_pll = rt5659_set_dai_pll,
.set_bclk_ratio = rt5659_set_bclk_ratio,
};
......@@ -3747,6 +3745,8 @@ static const struct snd_soc_codec_driver soc_codec_dev_rt5659 = {
.dapm_routes = rt5659_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(rt5659_dapm_routes),
},
.set_sysclk = rt5659_set_codec_sysclk,
.set_pll = rt5659_set_codec_pll,
};
......
This diff is collapsed.
......@@ -34,6 +34,24 @@
#include "rt5670.h"
#include "rt5670-dsp.h"
#define RT5670_DEV_GPIO BIT(0)
#define RT5670_IN2_DIFF BIT(1)
#define RT5670_DMIC_EN BIT(2)
#define RT5670_DMIC1_IN2P BIT(3)
#define RT5670_DMIC1_GPIO6 BIT(4)
#define RT5670_DMIC1_GPIO7 BIT(5)
#define RT5670_DMIC2_INR BIT(6)
#define RT5670_DMIC2_GPIO8 BIT(7)
#define RT5670_DMIC3_GPIO5 BIT(8)
#define RT5670_JD_MODE1 BIT(9)
#define RT5670_JD_MODE2 BIT(10)
#define RT5670_JD_MODE3 BIT(11)
static unsigned long rt5670_quirk;
static unsigned int quirk_override;
module_param_named(quirk, quirk_override, uint, 0444);
MODULE_PARM_DESC(quirk, "Board-specific quirk override");
#define RT5670_DEVICE_ID 0x6271
#define RT5670_PR_RANGE_BASE (0xff + 1)
......@@ -2582,6 +2600,24 @@ static int rt5670_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
return 0;
}
static int rt5670_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
{
struct snd_soc_codec *codec = dai->codec;
dev_dbg(codec->dev, "%s ratio=%d\n", __func__, ratio);
if (dai->id != RT5670_AIF1)
return 0;
if ((ratio % 50) == 0)
snd_soc_update_bits(codec, RT5670_GEN_CTRL3,
RT5670_TDM_DATA_MODE_SEL, RT5670_TDM_DATA_MODE_50FS);
else
snd_soc_update_bits(codec, RT5670_GEN_CTRL3,
RT5670_TDM_DATA_MODE_SEL, RT5670_TDM_DATA_MODE_NOR);
return 0;
}
static int rt5670_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
......@@ -2712,6 +2748,7 @@ static const struct snd_soc_dai_ops rt5670_aif_dai_ops = {
.set_fmt = rt5670_set_dai_fmt,
.set_tdm_slot = rt5670_set_tdm_slot,
.set_pll = rt5670_set_dai_pll,
.set_bclk_ratio = rt5670_set_bclk_ratio,
};
static struct snd_soc_dai_driver rt5670_dai[] = {
......@@ -2808,56 +2845,84 @@ static const struct acpi_device_id rt5670_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match);
#endif
static const struct dmi_system_id dmi_platform_intel_braswell[] = {
static int rt5670_quirk_cb(const struct dmi_system_id *id)
{
rt5670_quirk = (unsigned long)id->driver_data;
return 1;
}
static const struct dmi_system_id dmi_platform_intel_quirks[] = {
{
.callback = rt5670_quirk_cb,
.ident = "Intel Braswell",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
DMI_MATCH(DMI_BOARD_NAME, "Braswell CRB"),
},
.driver_data = (unsigned long *)(RT5670_DMIC_EN |
RT5670_DMIC1_IN2P |
RT5670_DEV_GPIO |
RT5670_JD_MODE1),
},
{
.callback = rt5670_quirk_cb,
.ident = "Dell Wyse 3040",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Wyse 3040"),
},
.driver_data = (unsigned long *)(RT5670_DMIC_EN |
RT5670_DMIC1_IN2P |
RT5670_DEV_GPIO |
RT5670_JD_MODE1),
},
{
.callback = rt5670_quirk_cb,
.ident = "Lenovo Thinkpad Tablet 10",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad 10"),
},
.driver_data = (unsigned long *)(RT5670_DMIC_EN |
RT5670_DMIC1_IN2P |
RT5670_DEV_GPIO |
RT5670_JD_MODE1),
},
{
.callback = rt5670_quirk_cb,
.ident = "Lenovo Thinkpad Tablet 10",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Tablet B"),
},
.driver_data = (unsigned long *)(RT5670_DMIC_EN |
RT5670_DMIC1_IN2P |
RT5670_DEV_GPIO |
RT5670_JD_MODE1),
},
{}
};
static const struct dmi_system_id dmi_platform_intel_bytcht_jdmode2[] = {
{
.callback = rt5670_quirk_cb,
.ident = "Lenovo Thinkpad Tablet 10",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Miix 2 10"),
},
.driver_data = (unsigned long *)(RT5670_DMIC_EN |
RT5670_DMIC1_IN2P |
RT5670_DEV_GPIO |
RT5670_JD_MODE2),
},
{}
};
static const struct dmi_system_id dmi_platform_intel_bytcht_jdmode3[] = {
{
.callback = rt5670_quirk_cb,
.ident = "Dell Venue 8 Pro 5855",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5855"),
},
.driver_data = (unsigned long *)(RT5670_DMIC_EN |
RT5670_DMIC2_INR |
RT5670_DEV_GPIO |
RT5670_JD_MODE3),
},
{}
};
......@@ -2881,21 +2946,61 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
if (pdata)
rt5670->pdata = *pdata;
if (dmi_check_system(dmi_platform_intel_braswell)) {
rt5670->pdata.dmic_en = true;
rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
dmi_check_system(dmi_platform_intel_quirks);
if (quirk_override) {
dev_info(&i2c->dev, "Overriding quirk 0x%x => 0x%x\n",
(unsigned int)rt5670_quirk, quirk_override);
rt5670_quirk = quirk_override;
}
if (rt5670_quirk & RT5670_DEV_GPIO) {
rt5670->pdata.dev_gpio = true;
rt5670->pdata.jd_mode = 1;
} else if (dmi_check_system(dmi_platform_intel_bytcht_jdmode2)) {
dev_info(&i2c->dev, "quirk dev_gpio\n");
}
if (rt5670_quirk & RT5670_IN2_DIFF) {
rt5670->pdata.in2_diff = true;
dev_info(&i2c->dev, "quirk IN2_DIFF\n");
}
if (rt5670_quirk & RT5670_DMIC_EN) {
rt5670->pdata.dmic_en = true;
dev_info(&i2c->dev, "quirk DMIC enabled\n");
}
if (rt5670_quirk & RT5670_DMIC1_IN2P) {
rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
rt5670->pdata.dev_gpio = true;
dev_info(&i2c->dev, "quirk DMIC1 on IN2P pin\n");
}
if (rt5670_quirk & RT5670_DMIC1_GPIO6) {
rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_GPIO6;
dev_info(&i2c->dev, "quirk DMIC1 on GPIO6 pin\n");
}
if (rt5670_quirk & RT5670_DMIC1_GPIO7) {
rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_GPIO7;
dev_info(&i2c->dev, "quirk DMIC1 on GPIO7 pin\n");
}
if (rt5670_quirk & RT5670_DMIC2_INR) {
rt5670->pdata.dmic2_data_pin = RT5670_DMIC_DATA_IN3N;
dev_info(&i2c->dev, "quirk DMIC2 on INR pin\n");
}
if (rt5670_quirk & RT5670_DMIC2_GPIO8) {
rt5670->pdata.dmic2_data_pin = RT5670_DMIC_DATA_GPIO8;
dev_info(&i2c->dev, "quirk DMIC2 on GPIO8 pin\n");
}
if (rt5670_quirk & RT5670_DMIC3_GPIO5) {
rt5670->pdata.dmic3_data_pin = RT5670_DMIC_DATA_GPIO5;
dev_info(&i2c->dev, "quirk DMIC3 on GPIO5 pin\n");
}
if (rt5670_quirk & RT5670_JD_MODE1) {
rt5670->pdata.jd_mode = 1;
dev_info(&i2c->dev, "quirk JD mode 1\n");
}
if (rt5670_quirk & RT5670_JD_MODE2) {
rt5670->pdata.jd_mode = 2;
} else if (dmi_check_system(dmi_platform_intel_bytcht_jdmode3)) {
rt5670->pdata.dmic_en = true;
rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
rt5670->pdata.dev_gpio = true;
dev_info(&i2c->dev, "quirk JD mode 2\n");
}
if (rt5670_quirk & RT5670_JD_MODE3) {
rt5670->pdata.jd_mode = 3;
dev_info(&i2c->dev, "quirk JD mode 3\n");
}
rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap);
......
......@@ -1816,6 +1816,10 @@
#define RT5670_ZCD_HP_DIS (0x0 << 15)
#define RT5670_ZCD_HP_EN (0x1 << 15)
/* General Control 3 (0xfc) */
#define RT5670_TDM_DATA_MODE_SEL (0x1 << 11)
#define RT5670_TDM_DATA_MODE_NOR (0x0 << 11)
#define RT5670_TDM_DATA_MODE_50FS (0x1 << 11)
/* Codec Private Register definition */
/* 3D Speaker Control (0x63) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment