mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
Merge branch 'topic/rt5670' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-intel
This commit is contained in:
commit
3326302753
2 changed files with 160 additions and 41 deletions
|
@ -14,10 +14,12 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
|
@ -588,6 +590,89 @@ static int can_use_asrc(struct snd_soc_dapm_widget *source,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* rt5670_sel_asrc_clk_src - select ASRC clock source for a set of filters
|
||||
* @codec: SoC audio codec device.
|
||||
* @filter_mask: mask of filters.
|
||||
* @clk_src: clock source
|
||||
*
|
||||
* The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5670 can
|
||||
* only support standard 32fs or 64fs i2s format, ASRC should be enabled to
|
||||
* support special i2s clock format such as Intel's 100fs(100 * sampling rate).
|
||||
* ASRC function will track i2s clock and generate a corresponding system clock
|
||||
* for codec. This function provides an API to select the clock source for a
|
||||
* set of filters specified by the mask. And the codec driver will turn on ASRC
|
||||
* for these filters if ASRC is selected as their clock source.
|
||||
*/
|
||||
int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec,
|
||||
unsigned int filter_mask, unsigned int clk_src)
|
||||
{
|
||||
unsigned int asrc2_mask = 0, asrc2_value = 0;
|
||||
unsigned int asrc3_mask = 0, asrc3_value = 0;
|
||||
|
||||
if (clk_src > RT5670_CLK_SEL_SYS3)
|
||||
return -EINVAL;
|
||||
|
||||
if (filter_mask & RT5670_DA_STEREO_FILTER) {
|
||||
asrc2_mask |= RT5670_DA_STO_CLK_SEL_MASK;
|
||||
asrc2_value = (asrc2_value & ~RT5670_DA_STO_CLK_SEL_MASK)
|
||||
| (clk_src << RT5670_DA_STO_CLK_SEL_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5670_DA_MONO_L_FILTER) {
|
||||
asrc2_mask |= RT5670_DA_MONOL_CLK_SEL_MASK;
|
||||
asrc2_value = (asrc2_value & ~RT5670_DA_MONOL_CLK_SEL_MASK)
|
||||
| (clk_src << RT5670_DA_MONOL_CLK_SEL_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5670_DA_MONO_R_FILTER) {
|
||||
asrc2_mask |= RT5670_DA_MONOR_CLK_SEL_MASK;
|
||||
asrc2_value = (asrc2_value & ~RT5670_DA_MONOR_CLK_SEL_MASK)
|
||||
| (clk_src << RT5670_DA_MONOR_CLK_SEL_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5670_AD_STEREO_FILTER) {
|
||||
asrc2_mask |= RT5670_AD_STO1_CLK_SEL_MASK;
|
||||
asrc2_value = (asrc2_value & ~RT5670_AD_STO1_CLK_SEL_MASK)
|
||||
| (clk_src << RT5670_AD_STO1_CLK_SEL_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5670_AD_MONO_L_FILTER) {
|
||||
asrc3_mask |= RT5670_AD_MONOL_CLK_SEL_MASK;
|
||||
asrc3_value = (asrc3_value & ~RT5670_AD_MONOL_CLK_SEL_MASK)
|
||||
| (clk_src << RT5670_AD_MONOL_CLK_SEL_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5670_AD_MONO_R_FILTER) {
|
||||
asrc3_mask |= RT5670_AD_MONOR_CLK_SEL_MASK;
|
||||
asrc3_value = (asrc3_value & ~RT5670_AD_MONOR_CLK_SEL_MASK)
|
||||
| (clk_src << RT5670_AD_MONOR_CLK_SEL_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5670_UP_RATE_FILTER) {
|
||||
asrc3_mask |= RT5670_UP_CLK_SEL_MASK;
|
||||
asrc3_value = (asrc3_value & ~RT5670_UP_CLK_SEL_MASK)
|
||||
| (clk_src << RT5670_UP_CLK_SEL_SFT);
|
||||
}
|
||||
|
||||
if (filter_mask & RT5670_DOWN_RATE_FILTER) {
|
||||
asrc3_mask |= RT5670_DOWN_CLK_SEL_MASK;
|
||||
asrc3_value = (asrc3_value & ~RT5670_DOWN_CLK_SEL_MASK)
|
||||
| (clk_src << RT5670_DOWN_CLK_SEL_SFT);
|
||||
}
|
||||
|
||||
if (asrc2_mask)
|
||||
snd_soc_update_bits(codec, RT5670_ASRC_2,
|
||||
asrc2_mask, asrc2_value);
|
||||
|
||||
if (asrc3_mask)
|
||||
snd_soc_update_bits(codec, RT5670_ASRC_3,
|
||||
asrc3_mask, asrc3_value);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt5670_sel_asrc_clk_src);
|
||||
|
||||
/* Digital Mixer */
|
||||
static const struct snd_kcontrol_new rt5670_sto1_adc_l_mix[] = {
|
||||
SOC_DAPM_SINGLE("ADC1 Switch", RT5670_STO1_ADC_MIXER,
|
||||
|
@ -2188,6 +2273,13 @@ static int rt5670_set_dai_sysclk(struct snd_soc_dai *dai,
|
|||
if (freq == rt5670->sysclk && clk_id == rt5670->sysclk_src)
|
||||
return 0;
|
||||
|
||||
if (rt5670->pdata.jd_mode) {
|
||||
if (clk_id == RT5670_SCLK_S_PLL1)
|
||||
snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
|
||||
else
|
||||
snd_soc_dapm_disable_pin(&codec->dapm, "PLL1");
|
||||
snd_soc_dapm_sync(&codec->dapm);
|
||||
}
|
||||
switch (clk_id) {
|
||||
case RT5670_SCLK_S_MCLK:
|
||||
reg_val |= RT5670_SCLK_SRC_MCLK;
|
||||
|
@ -2549,6 +2641,17 @@ static 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[] = {
|
||||
{
|
||||
.ident = "Intel Braswell",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "Braswell CRB"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static int rt5670_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -2568,6 +2671,12 @@ 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;
|
||||
rt5670->pdata.jd_mode = 1;
|
||||
}
|
||||
|
||||
rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap);
|
||||
if (IS_ERR(rt5670->regmap)) {
|
||||
ret = PTR_ERR(rt5670->regmap);
|
||||
|
@ -2609,6 +2718,10 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
|
|||
}
|
||||
|
||||
if (rt5670->pdata.jd_mode) {
|
||||
regmap_update_bits(rt5670->regmap, RT5670_GLB_CLK,
|
||||
RT5670_SCLK_SRC_MASK, RT5670_SCLK_SRC_RCCLK);
|
||||
rt5670->sysclk = 0;
|
||||
rt5670->sysclk_src = RT5670_SCLK_S_RCCLK;
|
||||
regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1,
|
||||
RT5670_PWR_MB, RT5670_PWR_MB);
|
||||
regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG2,
|
||||
|
@ -2716,18 +2829,26 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
|
|||
|
||||
}
|
||||
|
||||
pm_runtime_enable(&i2c->dev);
|
||||
pm_request_idle(&i2c->dev);
|
||||
|
||||
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5670,
|
||||
rt5670_dai, ARRAY_SIZE(rt5670_dai));
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
pm_runtime_put(&i2c->dev);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
pm_runtime_disable(&i2c->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rt5670_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
pm_runtime_disable(&i2c->dev);
|
||||
snd_soc_unregister_codec(&i2c->dev);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1023,50 +1023,33 @@
|
|||
#define RT5670_DMIC_2_M_NOR (0x0 << 8)
|
||||
#define RT5670_DMIC_2_M_ASYN (0x1 << 8)
|
||||
|
||||
/* ASRC clock source selection (0x84, 0x85) */
|
||||
#define RT5670_CLK_SEL_SYS (0x0)
|
||||
#define RT5670_CLK_SEL_I2S1_ASRC (0x1)
|
||||
#define RT5670_CLK_SEL_I2S2_ASRC (0x2)
|
||||
#define RT5670_CLK_SEL_I2S3_ASRC (0x3)
|
||||
#define RT5670_CLK_SEL_SYS2 (0x5)
|
||||
#define RT5670_CLK_SEL_SYS3 (0x6)
|
||||
|
||||
/* ASRC Control 2 (0x84) */
|
||||
#define RT5670_MDA_L_M_MASK (0x1 << 15)
|
||||
#define RT5670_MDA_L_M_SFT 15
|
||||
#define RT5670_MDA_L_M_NOR (0x0 << 15)
|
||||
#define RT5670_MDA_L_M_ASYN (0x1 << 15)
|
||||
#define RT5670_MDA_R_M_MASK (0x1 << 14)
|
||||
#define RT5670_MDA_R_M_SFT 14
|
||||
#define RT5670_MDA_R_M_NOR (0x0 << 14)
|
||||
#define RT5670_MDA_R_M_ASYN (0x1 << 14)
|
||||
#define RT5670_MAD_L_M_MASK (0x1 << 13)
|
||||
#define RT5670_MAD_L_M_SFT 13
|
||||
#define RT5670_MAD_L_M_NOR (0x0 << 13)
|
||||
#define RT5670_MAD_L_M_ASYN (0x1 << 13)
|
||||
#define RT5670_MAD_R_M_MASK (0x1 << 12)
|
||||
#define RT5670_MAD_R_M_SFT 12
|
||||
#define RT5670_MAD_R_M_NOR (0x0 << 12)
|
||||
#define RT5670_MAD_R_M_ASYN (0x1 << 12)
|
||||
#define RT5670_ADC_M_MASK (0x1 << 11)
|
||||
#define RT5670_ADC_M_SFT 11
|
||||
#define RT5670_ADC_M_NOR (0x0 << 11)
|
||||
#define RT5670_ADC_M_ASYN (0x1 << 11)
|
||||
#define RT5670_STO_DAC_M_MASK (0x1 << 5)
|
||||
#define RT5670_STO_DAC_M_SFT 5
|
||||
#define RT5670_STO_DAC_M_NOR (0x0 << 5)
|
||||
#define RT5670_STO_DAC_M_ASYN (0x1 << 5)
|
||||
#define RT5670_I2S1_R_D_MASK (0x1 << 4)
|
||||
#define RT5670_I2S1_R_D_SFT 4
|
||||
#define RT5670_I2S1_R_D_DIS (0x0 << 4)
|
||||
#define RT5670_I2S1_R_D_EN (0x1 << 4)
|
||||
#define RT5670_I2S2_R_D_MASK (0x1 << 3)
|
||||
#define RT5670_I2S2_R_D_SFT 3
|
||||
#define RT5670_I2S2_R_D_DIS (0x0 << 3)
|
||||
#define RT5670_I2S2_R_D_EN (0x1 << 3)
|
||||
#define RT5670_PRE_SCLK_MASK (0x3)
|
||||
#define RT5670_PRE_SCLK_SFT 0
|
||||
#define RT5670_PRE_SCLK_512 (0x0)
|
||||
#define RT5670_PRE_SCLK_1024 (0x1)
|
||||
#define RT5670_PRE_SCLK_2048 (0x2)
|
||||
#define RT5670_DA_STO_CLK_SEL_MASK (0xf << 12)
|
||||
#define RT5670_DA_STO_CLK_SEL_SFT 12
|
||||
#define RT5670_DA_MONOL_CLK_SEL_MASK (0xf << 8)
|
||||
#define RT5670_DA_MONOL_CLK_SEL_SFT 8
|
||||
#define RT5670_DA_MONOR_CLK_SEL_MASK (0xf << 4)
|
||||
#define RT5670_DA_MONOR_CLK_SEL_SFT 4
|
||||
#define RT5670_AD_STO1_CLK_SEL_MASK (0xf << 0)
|
||||
#define RT5670_AD_STO1_CLK_SEL_SFT 0
|
||||
|
||||
/* ASRC Control 3 (0x85) */
|
||||
#define RT5670_I2S1_RATE_MASK (0xf << 12)
|
||||
#define RT5670_I2S1_RATE_SFT 12
|
||||
#define RT5670_I2S2_RATE_MASK (0xf << 8)
|
||||
#define RT5670_I2S2_RATE_SFT 8
|
||||
#define RT5670_UP_CLK_SEL_MASK (0xf << 12)
|
||||
#define RT5670_UP_CLK_SEL_SFT 12
|
||||
#define RT5670_DOWN_CLK_SEL_MASK (0xf << 8)
|
||||
#define RT5670_DOWN_CLK_SEL_SFT 8
|
||||
#define RT5670_AD_MONOL_CLK_SEL_MASK (0xf << 4)
|
||||
#define RT5670_AD_MONOL_CLK_SEL_SFT 4
|
||||
#define RT5670_AD_MONOR_CLK_SEL_MASK (0xf << 0)
|
||||
#define RT5670_AD_MONOR_CLK_SEL_SFT 0
|
||||
|
||||
/* ASRC Control 4 (0x89) */
|
||||
#define RT5670_I2S1_PD_MASK (0x7 << 12)
|
||||
|
@ -1983,6 +1966,21 @@ enum {
|
|||
RT5670_DMIC_DATA_GPIO5,
|
||||
};
|
||||
|
||||
/* filter mask */
|
||||
enum {
|
||||
RT5670_DA_STEREO_FILTER = 0x1,
|
||||
RT5670_DA_MONO_L_FILTER = (0x1 << 1),
|
||||
RT5670_DA_MONO_R_FILTER = (0x1 << 2),
|
||||
RT5670_AD_STEREO_FILTER = (0x1 << 3),
|
||||
RT5670_AD_MONO_L_FILTER = (0x1 << 4),
|
||||
RT5670_AD_MONO_R_FILTER = (0x1 << 5),
|
||||
RT5670_UP_RATE_FILTER = (0x1 << 6),
|
||||
RT5670_DOWN_RATE_FILTER = (0x1 << 7),
|
||||
};
|
||||
|
||||
int rt5670_sel_asrc_clk_src(struct snd_soc_codec *codec,
|
||||
unsigned int filter_mask, unsigned int clk_src);
|
||||
|
||||
struct rt5670_priv {
|
||||
struct snd_soc_codec *codec;
|
||||
struct rt5670_platform_data pdata;
|
||||
|
|
Loading…
Reference in a new issue