Re: [PATCH v2 1/2] ASoC: codec: Inno codec driver for RK3036 SoC
On Fri, Nov 06, 2015 at 04:15:37PM +0800, Shunqian Zheng wrote: > On 2015年11月06日 00:13, Mark Brown wrote: > >On Thu, Nov 05, 2015 at 05:53:13PM +0800, Shunqian Zheng wrote: > >This looks like a simple boolean control rather than an enum - it looks > >like it's just turning antipop on and off. > It is a boolean control, but it takes 2 bits -- the value of "on" is b10 and > b01 for "off". > So I try to use VALUE_ENUM. The presentation of the control to userspace needs to be a Switch, this is probably going to need you to code something custom. signature.asc Description: PGP signature
Re: [PATCH v2 1/2] ASoC: codec: Inno codec driver for RK3036 SoC
Mark, On 2015年11月06日 00:13, Mark Brown wrote: On Thu, Nov 05, 2015 at 05:53:13PM +0800, Shunqian Zheng wrote: This is basically all good, a few very minor comments below but nothing that should take any time to fix. +static const char *rk3036_codec_antipop_text[] = {"none", "work"}; +static const unsigned int rk3036_codec_antipop_values[] = {0x1, 0x2}; + +static SOC_VALUE_ENUM_DOUBLE_DECL(rk3036_codec_antipop_enum, INNO_R09, + INNO_R09_HPL_ANITPOP_SHIFT, INNO_R09_HPR_ANITPOP_SHIFT, 0x3, + rk3036_codec_antipop_text, rk3036_codec_antipop_values); This looks like a simple boolean control rather than an enum - it looks like it's just turning antipop on and off. It is a boolean control, but it takes 2 bits -- the value of "on" is b10 and b01 for "off". So I try to use VALUE_ENUM. + SOC_DOUBLE_R_RANGE_TLV("Headphone Volume", INNO_R07, INNO_R08, + INNO_HP_GAIN_SHIFT, INNO_HP_GAIN_N39DB, + INNO_HP_GAIN_0DB, 0, rk3036_codec_hp_tlv), + SOC_DOUBLE("Zero Cross Detect", INNO_R06, INNO_R06_VOUTL_CZ_SHIFT, + INNO_R06_VOUTR_CZ_SHIFT, 1, 0), This should be "Zero Cross Switch". Make change in V3. + SOC_DOUBLE("HP Mute", INNO_R09, INNO_R09_HPL_MUTE_SHIFT, + INNO_R09_HPR_MUTE_SHIFT, 1, 1), This should be "Headphone Switch". Make change in V3. +static int rk3036_codec_add_widgets(struct snd_soc_codec *codec) +{ + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + + snd_soc_add_codec_controls(codec, rk3036_codec_dapm_controls, + ARRAY_SIZE(rk3036_codec_dapm_controls)); + + snd_soc_dapm_new_controls(dapm, rk3036_codec_dapm_widgets, + ARRAY_SIZE(rk3036_codec_dapm_widgets)); + + snd_soc_dapm_add_routes(dapm, rk3036_codec_dapm_routes, + ARRAY_SIZE(rk3036_codec_dapm_routes)); Just point at the tables from the driver structure and let the core do the initialisation for you. Make change in V3. +static int rk3036_codec_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + switch (level) { + case SND_SOC_BIAS_STANDBY: + /* set a big current for capacitor charging. */ + snd_soc_write(codec, INNO_R10, INNO_R10_MAX_CUR); + /* start precharge */ + snd_soc_write(codec, INNO_R06, INNO_R06_DAC_PRECHARGE); Do we not need to wait for this to ramp? The datasheet didn't give the delay value. It works in my tests. Thank you, Shunqian -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 1/2] ASoC: codec: Inno codec driver for RK3036 SoC
LABBE, On 2015年11月05日 20:47, LABBE Corentin wrote: On Thu, Nov 05, 2015 at 05:53:13PM +0800, Shunqian Zheng wrote: From: ZhengShunQian RK3036 SoC integrated with an Inno audio codec. This driver implements the functions of it. There is not need a special machine driver, since the simple-card machine driver works perfect in this case. Signed-off-by: ZhengShunQian --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/inno_rk3036.c | 455 + sound/soc/codecs/inno_rk3036.h | 120 +++ 4 files changed, 581 insertions(+) create mode 100644 sound/soc/codecs/inno_rk3036.c create mode 100644 sound/soc/codecs/inno_rk3036.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index cfdafc4..89d789e 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -67,6 +67,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_ES8328_I2C if I2C select SND_SOC_GTM601 select SND_SOC_ICS43432 + select SND_SOC_INNO_RK3036 select SND_SOC_ISABELLE if I2C select SND_SOC_JZ4740_CODEC select SND_SOC_LM4857 if I2C @@ -471,6 +472,9 @@ config SND_SOC_GTM601 config SND_SOC_ICS43432 tristate +config SND_SOC_INNO_RK3036 + tristate "Inno codec driver for RK3036 SoC" + config SND_SOC_ISABELLE tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index f632fc4..2f6bc6c 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -60,6 +60,7 @@ snd-soc-es8328-i2c-objs := es8328-i2c.o snd-soc-es8328-spi-objs := es8328-spi.o snd-soc-gtm601-objs := gtm601.o snd-soc-ics43432-objs := ics43432.o +snd-soc-inno-rk3036-objs := inno_rk3036.o snd-soc-isabelle-objs := isabelle.o snd-soc-jz4740-codec-objs := jz4740.o snd-soc-l3-objs := l3.o @@ -255,6 +256,7 @@ obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o obj-$(CONFIG_SND_SOC_GTM601)+= snd-soc-gtm601.o obj-$(CONFIG_SND_SOC_ICS43432)+= snd-soc-ics43432.o +obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o obj-$(CONFIG_SND_SOC_ISABELLE)+= snd-soc-isabelle.o obj-$(CONFIG_SND_SOC_JZ4740_CODEC)+= snd-soc-jz4740-codec.o obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c new file mode 100644 index 000..ce68f02 --- /dev/null +++ b/sound/soc/codecs/inno_rk3036.c @@ -0,0 +1,455 @@ +/* + * Driver of Inno codec for rk3036 by Rockchip Inc. + * + * Author: Rockchip Inc. + * Author: Zheng ShunQian + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inno_rk3036.h" + +struct rk3036_codec_priv { + void __iomem *base; + struct clk *pclk; + struct regmap *regmap; + struct device *dev; +}; + +static const DECLARE_TLV_DB_MINMAX(rk3036_codec_hp_tlv, -39, 0); + +static const char *rk3036_codec_antipop_text[] = {"none", "work"}; +static const unsigned int rk3036_codec_antipop_values[] = {0x1, 0x2}; + +static SOC_VALUE_ENUM_DOUBLE_DECL(rk3036_codec_antipop_enum, INNO_R09, + INNO_R09_HPL_ANITPOP_SHIFT, INNO_R09_HPR_ANITPOP_SHIFT, 0x3, + rk3036_codec_antipop_text, rk3036_codec_antipop_values); + +static const struct snd_kcontrol_new rk3036_codec_dapm_controls[] = { + SOC_DOUBLE_R_RANGE_TLV("Headphone Volume", INNO_R07, INNO_R08, + INNO_HP_GAIN_SHIFT, INNO_HP_GAIN_N39DB, + INNO_HP_GAIN_0DB, 0, rk3036_codec_hp_tlv), + SOC_DOUBLE("Zero Cross Detect", INNO_R06, INNO_R06_VOUTL_CZ_SHIFT, + INNO_R06_VOUTR_CZ_SHIFT, 1, 0), + SOC_DOUBLE("HP Mute", INNO_R09, INNO_R09_HPL_MUTE_SHIFT, + INNO_R09_HPR_MUTE_SHIFT, 1, 1), + SOC_ENUM("Anti-pop", rk3036_codec_antipop_enum), +}; + +static const struct snd_kcontrol_new rk3036_codec_hpl_mixer_controls[] = { + SOC_DAPM_SINGLE("DAC Left Out Switch", INNO_R09, + INNO_R09_DACL_SWITCH_SHIFT, 1, 0), +}; + +static const struct snd_kcontrol_new rk3036_codec_hpr_mixer_controls[] = { + SOC_DAPM_SINGLE("DAC Right Out Switch", INNO_R09, + INNO_R09_DACR_SWITCH_SHIFT, 1, 0), +}; + +static const struct snd_kcontrol_new rk3036_codec_hpl_switch_controls[] = { + SOC_DAPM_SINGLE("HP Left Out Switch", INNO_R05, + INNO_R05_HPL_WORK_SHIFT, 1, 0), +}; + +static const struct snd_kcontrol_new rk3036_codec_hpr_switch_controls[] = { + SOC_DAPM_SINGLE("HP Right Out Switch", INNO_R05, + INNO_R05_HPR_WORK_SHIFT, 1, 0), +}; + +static const struct snd_soc_dapm_widget rk3036_codec_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY_S("DAC PWR", 1, INNO_R06, + INNO_R06_DAC_EN_SHIFT, 0, NULL, 0
Re: [PATCH v2 1/2] ASoC: codec: Inno codec driver for RK3036 SoC
On Thu, Nov 05, 2015 at 05:53:13PM +0800, Shunqian Zheng wrote: This is basically all good, a few very minor comments below but nothing that should take any time to fix. > +static const char *rk3036_codec_antipop_text[] = {"none", "work"}; > +static const unsigned int rk3036_codec_antipop_values[] = {0x1, 0x2}; > + > +static SOC_VALUE_ENUM_DOUBLE_DECL(rk3036_codec_antipop_enum, INNO_R09, > + INNO_R09_HPL_ANITPOP_SHIFT, INNO_R09_HPR_ANITPOP_SHIFT, 0x3, > + rk3036_codec_antipop_text, rk3036_codec_antipop_values); This looks like a simple boolean control rather than an enum - it looks like it's just turning antipop on and off. > + SOC_DOUBLE_R_RANGE_TLV("Headphone Volume", INNO_R07, INNO_R08, > + INNO_HP_GAIN_SHIFT, INNO_HP_GAIN_N39DB, > + INNO_HP_GAIN_0DB, 0, rk3036_codec_hp_tlv), > + SOC_DOUBLE("Zero Cross Detect", INNO_R06, INNO_R06_VOUTL_CZ_SHIFT, > + INNO_R06_VOUTR_CZ_SHIFT, 1, 0), This should be "Zero Cross Switch". > + SOC_DOUBLE("HP Mute", INNO_R09, INNO_R09_HPL_MUTE_SHIFT, > + INNO_R09_HPR_MUTE_SHIFT, 1, 1), This should be "Headphone Switch". > +static int rk3036_codec_add_widgets(struct snd_soc_codec *codec) > +{ > + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); > + > + snd_soc_add_codec_controls(codec, rk3036_codec_dapm_controls, > + ARRAY_SIZE(rk3036_codec_dapm_controls)); > + > + snd_soc_dapm_new_controls(dapm, rk3036_codec_dapm_widgets, > + ARRAY_SIZE(rk3036_codec_dapm_widgets)); > + > + snd_soc_dapm_add_routes(dapm, rk3036_codec_dapm_routes, > + ARRAY_SIZE(rk3036_codec_dapm_routes)); Just point at the tables from the driver structure and let the core do the initialisation for you. > +static int rk3036_codec_set_bias_level(struct snd_soc_codec *codec, > +enum snd_soc_bias_level level) > +{ > + switch (level) { > + case SND_SOC_BIAS_STANDBY: > + /* set a big current for capacitor charging. */ > + snd_soc_write(codec, INNO_R10, INNO_R10_MAX_CUR); > + /* start precharge */ > + snd_soc_write(codec, INNO_R06, INNO_R06_DAC_PRECHARGE); Do we not need to wait for this to ramp? signature.asc Description: PGP signature
Re: [PATCH v2 1/2] ASoC: codec: Inno codec driver for RK3036 SoC
On Thu, Nov 05, 2015 at 05:53:13PM +0800, Shunqian Zheng wrote: > From: ZhengShunQian > > RK3036 SoC integrated with an Inno audio codec. > This driver implements the functions of it. > > There is not need a special machine driver, since the > simple-card machine driver works perfect in this case. > > Signed-off-by: ZhengShunQian > --- > sound/soc/codecs/Kconfig | 4 + > sound/soc/codecs/Makefile | 2 + > sound/soc/codecs/inno_rk3036.c | 455 > + > sound/soc/codecs/inno_rk3036.h | 120 +++ > 4 files changed, 581 insertions(+) > create mode 100644 sound/soc/codecs/inno_rk3036.c > create mode 100644 sound/soc/codecs/inno_rk3036.h > > diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig > index cfdafc4..89d789e 100644 > --- a/sound/soc/codecs/Kconfig > +++ b/sound/soc/codecs/Kconfig > @@ -67,6 +67,7 @@ config SND_SOC_ALL_CODECS > select SND_SOC_ES8328_I2C if I2C > select SND_SOC_GTM601 > select SND_SOC_ICS43432 > + select SND_SOC_INNO_RK3036 > select SND_SOC_ISABELLE if I2C > select SND_SOC_JZ4740_CODEC > select SND_SOC_LM4857 if I2C > @@ -471,6 +472,9 @@ config SND_SOC_GTM601 > config SND_SOC_ICS43432 > tristate > > +config SND_SOC_INNO_RK3036 > + tristate "Inno codec driver for RK3036 SoC" > + > config SND_SOC_ISABELLE > tristate > > diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile > index f632fc4..2f6bc6c 100644 > --- a/sound/soc/codecs/Makefile > +++ b/sound/soc/codecs/Makefile > @@ -60,6 +60,7 @@ snd-soc-es8328-i2c-objs := es8328-i2c.o > snd-soc-es8328-spi-objs := es8328-spi.o > snd-soc-gtm601-objs := gtm601.o > snd-soc-ics43432-objs := ics43432.o > +snd-soc-inno-rk3036-objs := inno_rk3036.o > snd-soc-isabelle-objs := isabelle.o > snd-soc-jz4740-codec-objs := jz4740.o > snd-soc-l3-objs := l3.o > @@ -255,6 +256,7 @@ obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o > obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o > obj-$(CONFIG_SND_SOC_GTM601)+= snd-soc-gtm601.o > obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o > +obj-$(CONFIG_SND_SOC_INNO_RK3036)+= snd-soc-inno-rk3036.o > obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o > obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o > obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o > diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c > new file mode 100644 > index 000..ce68f02 > --- /dev/null > +++ b/sound/soc/codecs/inno_rk3036.c > @@ -0,0 +1,455 @@ > +/* > + * Driver of Inno codec for rk3036 by Rockchip Inc. > + * > + * Author: Rockchip Inc. > + * Author: Zheng ShunQian > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "inno_rk3036.h" > + > +struct rk3036_codec_priv { > + void __iomem *base; > + struct clk *pclk; > + struct regmap *regmap; > + struct device *dev; > +}; > + > +static const DECLARE_TLV_DB_MINMAX(rk3036_codec_hp_tlv, -39, 0); > + > +static const char *rk3036_codec_antipop_text[] = {"none", "work"}; > +static const unsigned int rk3036_codec_antipop_values[] = {0x1, 0x2}; > + > +static SOC_VALUE_ENUM_DOUBLE_DECL(rk3036_codec_antipop_enum, INNO_R09, > + INNO_R09_HPL_ANITPOP_SHIFT, INNO_R09_HPR_ANITPOP_SHIFT, 0x3, > + rk3036_codec_antipop_text, rk3036_codec_antipop_values); > + > +static const struct snd_kcontrol_new rk3036_codec_dapm_controls[] = { > + SOC_DOUBLE_R_RANGE_TLV("Headphone Volume", INNO_R07, INNO_R08, > + INNO_HP_GAIN_SHIFT, INNO_HP_GAIN_N39DB, > + INNO_HP_GAIN_0DB, 0, rk3036_codec_hp_tlv), > + SOC_DOUBLE("Zero Cross Detect", INNO_R06, INNO_R06_VOUTL_CZ_SHIFT, > + INNO_R06_VOUTR_CZ_SHIFT, 1, 0), > + SOC_DOUBLE("HP Mute", INNO_R09, INNO_R09_HPL_MUTE_SHIFT, > + INNO_R09_HPR_MUTE_SHIFT, 1, 1), > + SOC_ENUM("Anti-pop", rk3036_codec_antipop_enum), > +}; > + > +static const struct snd_kcontrol_new rk3036_codec_hpl_mixer_controls[] = { > + SOC_DAPM_SINGLE("DAC Left Out Switch", INNO_R09, > + INNO_R09_DACL_SWITCH_SHIFT, 1, 0), > +}; > + > +static const struct snd_kcontrol_new rk3036_codec_hpr_mixer_controls[] = { > + SOC_DAPM_SINGLE("DAC Right Out Switch", INNO_R09, > + INNO_R09_DACR_SWITCH_SHIFT, 1, 0), > +}; > + > +static const struct snd_kcontrol_new rk3036_codec_hpl_switch_controls[] = { > + SOC_DAPM_SINGLE("HP Left Out Switch", INNO_R05, > + INNO_R05_HPL_WORK_SHIFT, 1, 0), > +}; > + > +static const struct snd_kcontrol_new rk3036_codec_hpr_switch_controls[] = { > + SOC_DAPM_SINGLE("HP Right Out Switch", INNO_R05, > + INNO_R05_HPR_WORK_SHIFT, 1, 0), > +}; > + > +static const struct snd_soc_dapm_widget rk3036_codec_dap
[PATCH v2 1/2] ASoC: codec: Inno codec driver for RK3036 SoC
From: ZhengShunQian RK3036 SoC integrated with an Inno audio codec. This driver implements the functions of it. There is not need a special machine driver, since the simple-card machine driver works perfect in this case. Signed-off-by: ZhengShunQian --- sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/inno_rk3036.c | 455 + sound/soc/codecs/inno_rk3036.h | 120 +++ 4 files changed, 581 insertions(+) create mode 100644 sound/soc/codecs/inno_rk3036.c create mode 100644 sound/soc/codecs/inno_rk3036.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index cfdafc4..89d789e 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -67,6 +67,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_ES8328_I2C if I2C select SND_SOC_GTM601 select SND_SOC_ICS43432 + select SND_SOC_INNO_RK3036 select SND_SOC_ISABELLE if I2C select SND_SOC_JZ4740_CODEC select SND_SOC_LM4857 if I2C @@ -471,6 +472,9 @@ config SND_SOC_GTM601 config SND_SOC_ICS43432 tristate +config SND_SOC_INNO_RK3036 + tristate "Inno codec driver for RK3036 SoC" + config SND_SOC_ISABELLE tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index f632fc4..2f6bc6c 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -60,6 +60,7 @@ snd-soc-es8328-i2c-objs := es8328-i2c.o snd-soc-es8328-spi-objs := es8328-spi.o snd-soc-gtm601-objs := gtm601.o snd-soc-ics43432-objs := ics43432.o +snd-soc-inno-rk3036-objs := inno_rk3036.o snd-soc-isabelle-objs := isabelle.o snd-soc-jz4740-codec-objs := jz4740.o snd-soc-l3-objs := l3.o @@ -255,6 +256,7 @@ obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o obj-$(CONFIG_SND_SOC_GTM601)+= snd-soc-gtm601.o obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o +obj-$(CONFIG_SND_SOC_INNO_RK3036) += snd-soc-inno-rk3036.o obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o diff --git a/sound/soc/codecs/inno_rk3036.c b/sound/soc/codecs/inno_rk3036.c new file mode 100644 index 000..ce68f02 --- /dev/null +++ b/sound/soc/codecs/inno_rk3036.c @@ -0,0 +1,455 @@ +/* + * Driver of Inno codec for rk3036 by Rockchip Inc. + * + * Author: Rockchip Inc. + * Author: Zheng ShunQian + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inno_rk3036.h" + +struct rk3036_codec_priv { + void __iomem *base; + struct clk *pclk; + struct regmap *regmap; + struct device *dev; +}; + +static const DECLARE_TLV_DB_MINMAX(rk3036_codec_hp_tlv, -39, 0); + +static const char *rk3036_codec_antipop_text[] = {"none", "work"}; +static const unsigned int rk3036_codec_antipop_values[] = {0x1, 0x2}; + +static SOC_VALUE_ENUM_DOUBLE_DECL(rk3036_codec_antipop_enum, INNO_R09, + INNO_R09_HPL_ANITPOP_SHIFT, INNO_R09_HPR_ANITPOP_SHIFT, 0x3, + rk3036_codec_antipop_text, rk3036_codec_antipop_values); + +static const struct snd_kcontrol_new rk3036_codec_dapm_controls[] = { + SOC_DOUBLE_R_RANGE_TLV("Headphone Volume", INNO_R07, INNO_R08, + INNO_HP_GAIN_SHIFT, INNO_HP_GAIN_N39DB, + INNO_HP_GAIN_0DB, 0, rk3036_codec_hp_tlv), + SOC_DOUBLE("Zero Cross Detect", INNO_R06, INNO_R06_VOUTL_CZ_SHIFT, + INNO_R06_VOUTR_CZ_SHIFT, 1, 0), + SOC_DOUBLE("HP Mute", INNO_R09, INNO_R09_HPL_MUTE_SHIFT, + INNO_R09_HPR_MUTE_SHIFT, 1, 1), + SOC_ENUM("Anti-pop", rk3036_codec_antipop_enum), +}; + +static const struct snd_kcontrol_new rk3036_codec_hpl_mixer_controls[] = { + SOC_DAPM_SINGLE("DAC Left Out Switch", INNO_R09, + INNO_R09_DACL_SWITCH_SHIFT, 1, 0), +}; + +static const struct snd_kcontrol_new rk3036_codec_hpr_mixer_controls[] = { + SOC_DAPM_SINGLE("DAC Right Out Switch", INNO_R09, + INNO_R09_DACR_SWITCH_SHIFT, 1, 0), +}; + +static const struct snd_kcontrol_new rk3036_codec_hpl_switch_controls[] = { + SOC_DAPM_SINGLE("HP Left Out Switch", INNO_R05, + INNO_R05_HPL_WORK_SHIFT, 1, 0), +}; + +static const struct snd_kcontrol_new rk3036_codec_hpr_switch_controls[] = { + SOC_DAPM_SINGLE("HP Right Out Switch", INNO_R05, + INNO_R05_HPR_WORK_SHIFT, 1, 0), +}; + +static const struct snd_soc_dapm_widget rk3036_codec_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY_S("DAC PWR", 1, INNO_R06, + INNO_R06_DAC_EN_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DACL VREF", 2, INNO_R04, + INNO_R04_DACL_VREF_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S(