diff mbox series

[Artful,3/3] UBUNTU: SAUCE: ASoC: rt5670: Add support for Wyse 3040

Message ID 1508153220-3808-4-git-send-email-jesse.sung@canonical.com
State New
Headers show
Series Patches for Wyse systems | expand

Commit Message

Wen-chien Jesse Sung Oct. 16, 2017, 11:27 a.m. UTC
BugLink: https://launchpad.net/bugs/1723916

The rt5760 on Wyse 3040 requires some extra code to work.
This commit uses PCI ID to identify Wyse 3040 and does things
specific to the platform when there's a match. There should
be no impact to other systems using rt5670.

Based on a patch from realtek.

Signed-off-by: Wen-chien Jesse Sung <jesse.sung@canonical.com>
---
 sound/soc/codecs/rt5670.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
 sound/soc/codecs/rt5670.h |  2 ++
 2 files changed, 44 insertions(+), 1 deletion(-)

Comments

Seth Forshee Oct. 16, 2017, 2:50 p.m. UTC | #1
On Mon, Oct 16, 2017 at 07:27:00PM +0800, Wen-chien Jesse Sung wrote:
> @@ -2890,6 +2919,13 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
>  		rt5670->pdata.jd_mode = 2;
>  	}
>  
> +	pdev_host = pci_get_subsys(0x8086, 0x2280, 0x1028, 0x07c1, NULL);

What device do these pci ids represent exactly? I mean, no doubt they
represent something specific to the machine you're looking for, just
wondering what exactly.

This seems like a pretty hacky way to determine whether these "quirks"
are needed. Is there no more direct way to figure this out? I won't
object to this if there isn't, but I want to be convinced.

Thanks,
Seth
Wen-chien Jesse Sung Oct. 16, 2017, 3:02 p.m. UTC | #2
On Mon, Oct 16, 2017 at 10:50 PM, Seth Forshee
<seth.forshee@canonical.com> wrote:
> On Mon, Oct 16, 2017 at 07:27:00PM +0800, Wen-chien Jesse Sung wrote:
>> @@ -2890,6 +2919,13 @@ static int rt5670_i2c_probe(struct i2c_client *i2c,
>>               rt5670->pdata.jd_mode = 2;
>>       }
>>
>> +     pdev_host = pci_get_subsys(0x8086, 0x2280, 0x1028, 0x07c1, NULL);
>
> What device do these pci ids represent exactly? I mean, no doubt they
> represent something specific to the machine you're looking for, just
> wondering what exactly.

These are the PCI IDs/subsys-IDs of the host PCI bridge.

> This seems like a pretty hacky way to determine whether these "quirks"
> are needed. Is there no more direct way to figure this out? I won't
> object to this if there isn't, but I want to be convinced.

Yes I agree this is pretty hacky. Since it's an I2C device, there's no clues
like PCI subsys IDs. DMI strings may be a way to do that, but the systems
may be re-branded so that DMI IDs are not reliable in this case...

Thanks,
Jesse
diff mbox series

Patch

diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
index 054b613..1b3dc29 100644
--- a/sound/soc/codecs/rt5670.c
+++ b/sound/soc/codecs/rt5670.c
@@ -20,6 +20,7 @@ 
 #include <linux/acpi.h>
 #include <linux/spi/spi.h>
 #include <linux/dmi.h>
+#include <linux/pci.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -426,7 +427,10 @@  static int rt5670_headset_detect(struct snd_soc_codec *codec, int jack_insert)
 		snd_soc_update_bits(codec, RT5670_CJ_CTRL2,
 			RT5670_CBJ_DET_MODE | RT5670_CBJ_MN_JD,
 			RT5670_CBJ_MN_JD);
-		snd_soc_write(codec, RT5670_GPIO_CTRL2, 0x0004);
+		if (unlikely(rt5670->is_wyse3040))
+			snd_soc_write(codec, RT5670_GPIO_CTRL2, 0x0034);
+		else
+			snd_soc_write(codec, RT5670_GPIO_CTRL2, 0x0004);
 		snd_soc_update_bits(codec, RT5670_GPIO_CTRL1,
 			RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_IRQ);
 		snd_soc_update_bits(codec, RT5670_CJ_CTRL1,
@@ -1466,6 +1470,10 @@  static int rt5670_hp_event(struct snd_soc_dapm_widget *w,
 			RT5670_L_MUTE | RT5670_R_MUTE, 0);
 		msleep(80);
 		regmap_write(rt5670->regmap, RT5670_DEPOP_M1, 0x8019);
+		if (rt5670->is_wyse3040)
+			regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2,
+					   RT5670_GP2_PF_MASK | RT5670_GP2_OUT_MASK,
+					   RT5670_GP2_PF_OUT | RT5670_GP2_OUT_HI);
 		break;
 
 	case SND_SOC_DAPM_PRE_PMD:
@@ -1500,11 +1508,16 @@  static int rt5670_bst1_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
 
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
 		snd_soc_update_bits(codec, RT5670_PWR_ANLG2,
 				    RT5670_PWR_BST1_P, RT5670_PWR_BST1_P);
+		if (rt5670->is_wyse3040)
+			regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2,
+					   RT5670_GP2_PF_MASK | RT5670_GP2_OUT_MASK,
+					   RT5670_GP2_PF_OUT | RT5670_GP2_OUT_HI);
 		break;
 
 	case SND_SOC_DAPM_PRE_PMD:
@@ -1523,11 +1536,16 @@  static int rt5670_bst2_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
 
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
 		snd_soc_update_bits(codec, RT5670_PWR_ANLG2,
 				    RT5670_PWR_BST2_P, RT5670_PWR_BST2_P);
+		if (rt5670->is_wyse3040)
+			regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2,
+					   RT5670_GP2_PF_MASK | RT5670_GP2_OUT_MASK,
+					   RT5670_GP2_PF_OUT | RT5670_GP2_OUT_HI);
 		break;
 
 	case SND_SOC_DAPM_PRE_PMD:
@@ -2550,6 +2568,7 @@  static int rt5670_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
 			unsigned int rx_mask, int slots, int slot_width)
 {
 	struct snd_soc_codec *codec = dai->codec;
+	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
 	unsigned int val = 0;
 
 	if (rx_mask || tx_mask)
@@ -2589,6 +2608,9 @@  static int rt5670_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
 
 	snd_soc_update_bits(codec, RT5670_TDM_CTRL_1, 0x7c00, val);
 
+	if (rt5670->is_wyse3040 && (rt5670->v_id >= 5))
+		snd_soc_update_bits(codec, RT5670_GEN_CTRL3, 0x0800, 0x0800);
+
 	return 0;
 }
 
@@ -2675,6 +2697,8 @@  static int rt5670_probe(struct snd_soc_codec *codec)
 			"The driver is for RT5670 RT5671 or RT5672 only\n");
 		return -ENODEV;
 	}
+	if (rt5670->is_wyse3040)
+		rt5670->v_id = snd_soc_read(codec, RT5670_VENDOR_ID) & 0xff;
 	rt5670->codec = codec;
 
 	return 0;
@@ -2694,6 +2718,10 @@  static int rt5670_suspend(struct snd_soc_codec *codec)
 {
 	struct rt5670_priv *rt5670 = snd_soc_codec_get_drvdata(codec);
 
+	if (rt5670->is_wyse3040)
+		regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2,
+				   RT5670_GP2_PF_MASK | RT5670_GP2_OUT_MASK,
+				   RT5670_GP2_PF_OUT | RT5670_GP2_OUT_LO);
 	regcache_cache_only(rt5670->regmap, true);
 	regcache_mark_dirty(rt5670->regmap);
 	return 0;
@@ -2866,6 +2894,7 @@  static int rt5670_i2c_probe(struct i2c_client *i2c,
 	struct rt5670_priv *rt5670;
 	int ret;
 	unsigned int val;
+	struct pci_dev *pdev_host;
 
 	rt5670 = devm_kzalloc(&i2c->dev,
 				sizeof(struct rt5670_priv),
@@ -2890,6 +2919,13 @@  static int rt5670_i2c_probe(struct i2c_client *i2c,
 		rt5670->pdata.jd_mode = 2;
 	}
 
+	pdev_host = pci_get_subsys(0x8086, 0x2280, 0x1028, 0x07c1, NULL);
+	if (pdev_host) {
+		rt5670->is_wyse3040 = true;
+		rt5670->pdata.dmic_en = false;
+		pci_dev_put(pdev_host);
+	}
+
 	rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap);
 	if (IS_ERR(rt5670->regmap)) {
 		ret = PTR_ERR(rt5670->regmap);
@@ -2913,6 +2949,11 @@  static int rt5670_i2c_probe(struct i2c_client *i2c,
 
 	regmap_write(rt5670->regmap, RT5670_RESET, 0);
 
+	if (rt5670->is_wyse3040)
+		regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2,
+				   RT5670_GP2_PF_MASK | RT5670_GP2_OUT_MASK,
+				   RT5670_GP2_PF_OUT | RT5670_GP2_OUT_LO);
+
 	regmap_read(rt5670->regmap, RT5670_VENDOR_ID, &val);
 	if (val >= 4)
 		regmap_write(rt5670->regmap, RT5670_GPIO_CTRL3, 0x0980);
diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h
index 5ba485c..26b6f1a 100644
--- a/sound/soc/codecs/rt5670.h
+++ b/sound/soc/codecs/rt5670.h
@@ -1997,6 +1997,8 @@  struct rt5670_priv {
 	int lrck[RT5670_AIFS];
 	int bclk[RT5670_AIFS];
 	int master[RT5670_AIFS];
+	int v_id;
+	bool is_wyse3040;
 
 	int pll_src;
 	int pll_in;