diff options
author | Binyuan Lan <lby@rock-chips.com> | 2018-01-14 00:13:15 +0800 |
---|---|---|
committer | Tao Huang <huangtao@rock-chips.com> | 2018-02-08 21:00:48 +0800 |
commit | 8c4db84a0aa89dfe0d905ae988aea13b72fd9335 (patch) | |
tree | 2bf35888431000fefcd989fb67999f6b628b16c6 | |
parent | 7a53209b74ccd0cc8dc65d0754a61e7e1bfa3322 (diff) |
ASoC: rockchip: add support for rk817 codec
Change-Id: I4fd64900d3ac0e573371af5ba47a3cb7b83a7c93
Signed-off-by: Binyuan Lan <lby@rock-chips.com>
-rw-r--r-- | Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt | 34 | ||||
-rw-r--r-- | drivers/mfd/rk808.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 6 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/codecs/rk817_codec.c | 919 | ||||
-rw-r--r-- | sound/soc/codecs/rk817_codec.h | 180 |
6 files changed, 1145 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt b/Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt new file mode 100644 index 000000000000..95f9430b1757 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rockchip,rk817-codec.txt @@ -0,0 +1,34 @@ +* Rockchip rk817 codec + +Required properties: + +- compatible: "rockchip,rk817-codec" +- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names. +- clock-names: should be "mclk". + + +Example for rk817 codec: + +rk817: pmic@20 { + compatible = "rockchip,rk817"; + reg = <0x20>; + interrupt-parent = <&gpio0>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int>; + + ........ + + rk817_codec: rk817-codec { + #sound-dai-cells = <0>; + compatible = "rockchip,rk817-codec"; + clocks = <&cru SCLK_I2S_8CH_OUT>; + clock-names = "mclk"; + pinctrl-names = "default"; + pinctrl-0 = <&i2s_8ch_mclk>; + status = "okay"; + }; + + ........ + +}; diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index fd9adae77a42..a37ebd70e334 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -767,6 +767,10 @@ static const struct mfd_cell rk817s[] = { .num_resources = ARRAY_SIZE(rk817_rtc_resources), .resources = &rk817_rtc_resources[0], }, + { + .name = "rk817-codec", + .of_compatible = "rockchip,rk817-codec", + }, }; static const struct rk808_reg_data rk817_pre_init_reg[] = { diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0f65f46ee57e..30313b9f9087 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -96,6 +96,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_RK1000 if I2C select SND_SOC_RK3228 select SND_SOC_RK3328 + select SND_SOC_RK817 if I2C select SND_SOC_RT286 if I2C select SND_SOC_RT298 if I2C select SND_SOC_RT5616 if I2C @@ -588,6 +589,11 @@ config SND_SOC_RK3328 select REGMAP_MMIO tristate "Rockchip RK3328 CODEC" +config SND_SOC_RK817 + tristate "Rockchip RK817 CODEC" + depends on MFD_RK808 + select REGMAP_I2C + config SND_SOC_RL6231 tristate default y if SND_SOC_RT5616=y diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index edf27ede08da..042a9705da12 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -94,6 +94,7 @@ snd-soc-rk1000-objs := rk1000_codec.o snd-soc-rk312x-objs := rk312x_codec.o snd-soc-rk3228-objs := rk3228_codec.o snd-soc-rk3328-objs := rk3328_codec.o +snd-soc-rk817-objs := rk817_codec.o snd-soc-rl6231-objs := rl6231.o snd-soc-rl6347a-objs := rl6347a.o snd-soc-rt286-objs := rt286.o @@ -304,6 +305,7 @@ obj-$(CONFIG_SND_SOC_RK1000) += snd-soc-rk1000.o obj-$(CONFIG_SND_SOC_RK312X) += snd-soc-rk312x.o obj-$(CONFIG_SND_SOC_RK3228) += snd-soc-rk3228.o obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o +obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c new file mode 100644 index 000000000000..c1f862966ab8 --- /dev/null +++ b/sound/soc/codecs/rk817_codec.c @@ -0,0 +1,919 @@ +/* + * Copyright (c) 2018 Rockchip Electronics Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/delay.h> +#include <linux/mfd/rk808.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <sound/core.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include "rk817_codec.h" + +static int dbg_enable; +module_param_named(dbg_level, dbg_enable, int, 0644); + +#define DBG(args...) \ + do { \ + if (dbg_enable) { \ + pr_info(args); \ + } \ + } while (0) + +/* For route */ +#define RK817_CODEC_PLAYBACK 1 +#define RK817_CODEC_CAPTURE 2 +#define RK817_CODEC_INCALL 4 +#define RK817_CODEC_ALL (RK817_CODEC_PLAYBACK |\ + RK817_CODEC_CAPTURE | RK817_CODEC_INCALL) + +/* + * DDAC L/R volume setting + * 0: 0dB + * 0x0a:-3.75dB + * 0x7d: -46dB + * 0xff: -95dB + * Step: 0.375dB + */ +#define OUT_VOLUME (0x03) + +/* + * DADC L/R volume setting + * 0: 0dB + * 0x0a:-3.75dB + * 0x7d: -46dB + * 0xff: -95dB + * Step: 0.375dB + */ +#define CAPTURE_VOLUME (0x0) + +struct rk817_codec_priv { + struct snd_soc_codec *codec; + struct regmap *regmap; + struct rk808 *rk817; + struct clk *mclk; + + unsigned int stereo_sysclk; + unsigned int rate; + + unsigned int spk_volume; + unsigned int hp_volume; + unsigned int capture_volume; + + long int playback_path; + long int capture_path; +}; + +static struct rk817_codec_priv *rk817_priv; + +static const struct reg_default rk817_reg_defaults[] = { + { RK817_CODEC_DTOP_VUCTL, 0x003 }, + { RK817_CODEC_DTOP_VUCTIME, 0x00 }, + { RK817_CODEC_DTOP_LPT_SRST, 0x00 }, + { RK817_CODEC_DTOP_DIGEN_CLKE, 0x00 }, + { RK817_CODEC_AREF_RTCFG0, 0x00 }, + { RK817_CODEC_AREF_RTCFG1, 0x06 }, + { RK817_CODEC_AADC_CFG0, 0xc8 }, + { RK817_CODEC_AADC_CFG1, 0x00 }, + { RK817_CODEC_DADC_VOLL, 0x00 }, + { RK817_CODEC_DADC_VOLR, 0x00 }, + { RK817_CODEC_DADC_SR_ACL0, 0x00 }, + { RK817_CODEC_DADC_ALC1, 0x00 }, + { RK817_CODEC_DADC_ALC2, 0x00 }, + { RK817_CODEC_DADC_NG, 0x00 }, + { RK817_CODEC_DADC_HPF, 0x00 }, + { RK817_CODEC_DADC_RVOLL, 0xff }, + { RK817_CODEC_DADC_RVOLR, 0xff }, + { RK817_CODEC_AMIC_CFG0, 0x70 }, + { RK817_CODEC_AMIC_CFG1, 0x00 }, + { RK817_CODEC_DMIC_PGA_GAIN, 0x66 }, + { RK817_CODEC_DMIC_LMT1, 0x00 }, + { RK817_CODEC_DMIC_LMT2, 0x00 }, + { RK817_CODEC_DMIC_NG1, 0x00 }, + { RK817_CODEC_DMIC_NG2, 0x00 }, + { RK817_CODEC_ADAC_CFG0, 0x00 }, + { RK817_CODEC_ADAC_CFG1, 0x07 }, + { RK817_CODEC_DDAC_POPD_DACST, 0x82 }, + { RK817_CODEC_DDAC_VOLL, 0x00 }, + { RK817_CODEC_DDAC_VOLR, 0x00 }, + { RK817_CODEC_DDAC_SR_LMT0, 0x00 }, + { RK817_CODEC_DDAC_LMT1, 0x00 }, + { RK817_CODEC_DDAC_LMT2, 0x00 }, + { RK817_CODEC_DDAC_MUTE_MIXCTL, 0xa0 }, + { RK817_CODEC_DDAC_RVOLL, 0xff }, + { RK817_CODEC_DDAC_RVOLR, 0xff }, + { RK817_CODEC_AHP_ANTI0, 0x00 }, + { RK817_CODEC_AHP_ANTI1, 0x00 }, + { RK817_CODEC_AHP_CFG0, 0xe0 }, + { RK817_CODEC_AHP_CFG1, 0x1f }, + { RK817_CODEC_AHP_CP, 0x09 }, + { RK817_CODEC_ACLASSD_CFG1, 0x69 }, + { RK817_CODEC_ACLASSD_CFG2, 0x44 }, + { RK817_CODEC_APLL_CFG0, 0x04 }, + { RK817_CODEC_APLL_CFG1, 0x00 }, + { RK817_CODEC_APLL_CFG2, 0x30 }, + { RK817_CODEC_APLL_CFG3, 0x19 }, + { RK817_CODEC_APLL_CFG4, 0x65 }, + { RK817_CODEC_APLL_CFG5, 0x01 }, + { RK817_CODEC_DI2S_CKM, 0x01 }, + { RK817_CODEC_DI2S_RSD, 0x00 }, + { RK817_CODEC_DI2S_RXCR1, 0x00 }, + { RK817_CODEC_DI2S_RXCR2, 0x17 }, + { RK817_CODEC_DI2S_RXCMD_TSD, 0x00 }, + { RK817_CODEC_DI2S_TXCR1, 0x00 }, + { RK817_CODEC_DI2S_TXCR2, 0x17 }, + { RK817_CODEC_DI2S_TXCR3_TXCMD, 0x00 }, +}; + +static bool rk817_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RK817_CODEC_DTOP_LPT_SRST: + return true; + default: + return false; + } +} + +static bool rk817_codec_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RK817_CODEC_DTOP_VUCTL: + case RK817_CODEC_DTOP_VUCTIME: + case RK817_CODEC_DTOP_LPT_SRST: + case RK817_CODEC_DTOP_DIGEN_CLKE: + case RK817_CODEC_AREF_RTCFG0: + case RK817_CODEC_AREF_RTCFG1: + case RK817_CODEC_AADC_CFG0: + case RK817_CODEC_AADC_CFG1: + case RK817_CODEC_DADC_VOLL: + case RK817_CODEC_DADC_VOLR: + case RK817_CODEC_DADC_SR_ACL0: + case RK817_CODEC_DADC_ALC1: + case RK817_CODEC_DADC_ALC2: + case RK817_CODEC_DADC_NG: + case RK817_CODEC_DADC_HPF: + case RK817_CODEC_DADC_RVOLL: + case RK817_CODEC_DADC_RVOLR: + case RK817_CODEC_AMIC_CFG0: + case RK817_CODEC_AMIC_CFG1: + case RK817_CODEC_DMIC_PGA_GAIN: + case RK817_CODEC_DMIC_LMT1: + case RK817_CODEC_DMIC_LMT2: + case RK817_CODEC_DMIC_NG1: + case RK817_CODEC_DMIC_NG2: + case RK817_CODEC_ADAC_CFG0: + case RK817_CODEC_ADAC_CFG1: + case RK817_CODEC_DDAC_POPD_DACST: + case RK817_CODEC_DDAC_VOLL: + case RK817_CODEC_DDAC_VOLR: + case RK817_CODEC_DDAC_SR_LMT0: + case RK817_CODEC_DDAC_LMT1: + case RK817_CODEC_DDAC_LMT2: + case RK817_CODEC_DDAC_MUTE_MIXCTL: + case RK817_CODEC_DDAC_RVOLL: + case RK817_CODEC_DDAC_RVOLR: + case RK817_CODEC_AHP_ANTI0: + case RK817_CODEC_AHP_ANTI1: + case RK817_CODEC_AHP_CFG0: + case RK817_CODEC_AHP_CFG1: + case RK817_CODEC_AHP_CP: + case RK817_CODEC_ACLASSD_CFG1: + case RK817_CODEC_ACLASSD_CFG2: + case RK817_CODEC_APLL_CFG0: + case RK817_CODEC_APLL_CFG1: + case RK817_CODEC_APLL_CFG2: + case RK817_CODEC_APLL_CFG3: + case RK817_CODEC_APLL_CFG4: + case RK817_CODEC_APLL_CFG5: + case RK817_CODEC_DI2S_CKM: + case RK817_CODEC_DI2S_RSD: + case RK817_CODEC_DI2S_RXCR1: + case RK817_CODEC_DI2S_RXCR2: + case RK817_CODEC_DI2S_RXCMD_TSD: + case RK817_CODEC_DI2S_TXCR1: + case RK817_CODEC_DI2S_TXCR2: + case RK817_CODEC_DI2S_TXCR3_TXCMD: + return true; + default: + return false; + } +} + +static int rk817_reset(struct snd_soc_codec *codec) +{ + snd_soc_write(codec, RK817_CODEC_DTOP_LPT_SRST, 0x40); + mdelay(10); + + return 0; +} + +static struct rk817_reg_val_typ playback_power_up_list[] = { + {RK817_CODEC_AREF_RTCFG1, 0x40}, + {RK817_CODEC_DDAC_POPD_DACST, 0x02}, + {RK817_CODEC_DDAC_SR_LMT0, 0x02}, + /*{RK817_CODEC_DTOP_DIGEN_CLKE, 0x0f},*/ + /*APLL*/ + {RK817_CODEC_APLL_CFG0, 0x04}, + {RK817_CODEC_APLL_CFG1, 0x58}, + {RK817_CODEC_APLL_CFG2, 0x2d}, + {RK817_CODEC_APLL_CFG3, 0x0c}, + {RK817_CODEC_APLL_CFG4, 0xa5}, + {RK817_CODEC_APLL_CFG5, 0x00}, + + {RK817_CODEC_DI2S_RXCMD_TSD, 0x00}, + {RK817_CODEC_DI2S_RSD, 0x00}, + {RK817_CODEC_DI2S_CKM, 0x00}, + {RK817_CODEC_DI2S_RXCR1, 0x00}, + {RK817_CODEC_DI2S_RXCMD_TSD, 0x20}, + {RK817_CODEC_DTOP_VUCTIME, 0xf4}, + + {RK817_CODEC_DDAC_VOLL, 0x0a}, + {RK817_CODEC_DDAC_VOLR, 0x0a}, +}; + +#define RK817_CODEC_PLAYBACK_POWER_UP_LIST_LEN \ + ARRAY_SIZE(playback_power_up_list) + +static struct rk817_reg_val_typ playback_power_down_list[] = { + {RK817_CODEC_DDAC_MUTE_MIXCTL, 0xa1}, + {RK817_CODEC_ADAC_CFG1, 0x0f}, + /* HP */ + {RK817_CODEC_AHP_CFG0, 0xe0}, + {RK817_CODEC_AHP_CP, 0x09}, + /* SPK */ + {RK817_CODEC_ACLASSD_CFG1, 0x69}, +}; + +#define RK817_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN \ + ARRAY_SIZE(playback_power_down_list) + +static struct rk817_reg_val_typ capture_power_up_list[] = { + {RK817_CODEC_AREF_RTCFG1, 0x40}, + {RK817_CODEC_DDAC_SR_LMT0, 0x02}, + {RK817_CODEC_DADC_SR_ACL0, 0x02}, + /*{RK817_CODEC_DTOP_DIGEN_CLKE, 0xff},*/ + {RK817_CODEC_APLL_CFG0, 0x04}, + {RK817_CODEC_APLL_CFG1, 0x58}, + {RK817_CODEC_APLL_CFG2, 0x2d}, + {RK817_CODEC_APLL_CFG3, 0x0c}, + {RK817_CODEC_APLL_CFG4, 0xa5}, + {RK817_CODEC_APLL_CFG5, 0x00}, + + {RK817_CODEC_DI2S_RXCMD_TSD, 0x00}, + {RK817_CODEC_DI2S_RSD, 0x00}, + {RK817_CODEC_DI2S_CKM, 0x00}, + {RK817_CODEC_DI2S_RXCR1, 0x00}, + {RK817_CODEC_DI2S_RXCMD_TSD, 0x20}, + {RK817_CODEC_DTOP_VUCTIME, 0xf4}, + + {RK817_CODEC_DDAC_MUTE_MIXCTL, 0x00}, + {RK817_CODEC_AADC_CFG0, 0x08}, + {RK817_CODEC_AMIC_CFG0, 0x0f}, + {RK817_CODEC_DI2S_TXCR3_TXCMD, 0x88}, + {RK817_CODEC_DDAC_POPD_DACST, 0x02}, + /* 0x29: -18db to 27db*/ + {RK817_CODEC_DMIC_PGA_GAIN, 0xaa}, +}; + +#define RK817_CODEC_CAPTURE_POWER_UP_LIST_LEN \ + ARRAY_SIZE(capture_power_up_list) + +static struct rk817_reg_val_typ capture_power_down_list[] = { + {RK817_CODEC_AADC_CFG0, 0xc8}, + {RK817_CODEC_AMIC_CFG0, 0x70}, +}; + +#define RK817_CODEC_CAPTURE_POWER_DOWN_LIST_LEN \ + ARRAY_SIZE(capture_power_down_list) + +static int rk817_codec_power_up(int type) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + struct snd_soc_codec *codec; + int i; + + codec = rk817->codec; + + dev_info(codec->dev, "%s : power up %s %s %s\n", __func__, + type & RK817_CODEC_PLAYBACK ? "playback" : "", + type & RK817_CODEC_CAPTURE ? "capture" : "", + type & RK817_CODEC_INCALL ? "incall" : ""); + + if (type & RK817_CODEC_PLAYBACK) { + snd_soc_update_bits(codec, RK817_CODEC_DTOP_DIGEN_CLKE, + DAC_DIG_CLK_MASK, DAC_DIG_CLK_EN); + for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_UP_LIST_LEN; i++) { + snd_soc_write(codec, playback_power_up_list[i].reg, + playback_power_up_list[i].value); + usleep_range(1000, 1100); + } + } + + if (type & RK817_CODEC_CAPTURE) { + snd_soc_update_bits(codec, RK817_CODEC_DTOP_DIGEN_CLKE, + ADC_DIG_CLK_MASK, ADC_DIG_CLK_EN); + for (i = 0; i < RK817_CODEC_CAPTURE_POWER_UP_LIST_LEN; i++) { + snd_soc_write(codec, capture_power_up_list[i].reg, + capture_power_up_list[i].value); + usleep_range(1000, 1100); + } + snd_soc_write(codec, RK817_CODEC_DADC_VOLL, + rk817->capture_volume); + snd_soc_write(codec, RK817_CODEC_DADC_VOLR, + rk817->capture_volume); + } + + return 0; +} + +static int rk817_codec_power_down(int type) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + struct snd_soc_codec *codec; + int i; + + codec = rk817->codec; + + dev_info(codec->dev, "%s : power down %s %s %s\n", __func__, + type & RK817_CODEC_PLAYBACK ? "playback" : "", + type & RK817_CODEC_CAPTURE ? "capture" : "", + type & RK817_CODEC_INCALL ? "incall" : ""); + + /* mute output for pop noise */ + if ((type & RK817_CODEC_PLAYBACK) || + (type & RK817_CODEC_INCALL)) { + snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, + DACMT_ENABLE, DACMT_ENABLE); + } + + if (type & RK817_CODEC_CAPTURE) { + for (i = 0; i < RK817_CODEC_CAPTURE_POWER_DOWN_LIST_LEN; i++) { + snd_soc_write(codec, capture_power_down_list[i].reg, + capture_power_down_list[i].value); + } + snd_soc_update_bits(codec, RK817_CODEC_DTOP_DIGEN_CLKE, + ADC_DIG_CLK_MASK, ADC_DIG_CLK_DIS); + } + + if (type & RK817_CODEC_PLAYBACK) { + for (i = 0; i < RK817_CODEC_PLAYBACK_POWER_DOWN_LIST_LEN; i++) { + snd_soc_write(codec, playback_power_down_list[i].reg, + playback_power_down_list[i].value); + } + snd_soc_update_bits(codec, RK817_CODEC_DTOP_DIGEN_CLKE, + DAC_DIG_CLK_MASK, DAC_DIG_CLK_DIS); + } + + if (type == RK817_CODEC_ALL) { + rk817_reset(codec); + snd_soc_write(codec, RK817_CODEC_APLL_CFG5, 0x01); + snd_soc_write(codec, RK817_CODEC_AREF_RTCFG1, 0x06); + } + + return 0; +} + +/* For tiny alsa playback/capture/voice call path */ +static const char * const rk817_playback_path_mode[] = { + "OFF", "RCV", "SPK", "HP", "HP_NO_MIC", "BT", "SPK_HP", /* 0-6 */ + "RING_SPK", "RING_HP", "RING_HP_NO_MIC", "RING_SPK_HP"}; /* 7-10 */ + +static const char * const rk817_capture_path_mode[] = { + "MIC OFF", "Main Mic", "Hands Free Mic", "BT Sco Mic"}; + +static const char * const rk817_call_path_mode[] = { + "OFF", "RCV", "SPK", "HP", "HP_NO_MIC", "BT"}; /* 0-5 */ + +static const char * const rk817_modem_input_mode[] = {"OFF", "ON"}; + +static const SOC_ENUM_SINGLE_DECL(rk817_playback_path_type, + 0, 0, rk817_playback_path_mode); + +static const SOC_ENUM_SINGLE_DECL(rk817_capture_path_type, + 0, 0, rk817_capture_path_mode); + +static const SOC_ENUM_SINGLE_DECL(rk817_call_path_type, + 0, 0, rk817_call_path_mode); + +static const SOC_ENUM_SINGLE_DECL(rk817_modem_input_type, + 0, 0, rk817_modem_input_mode); + +static int rk817_playback_path_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + + DBG("%s : playback_path %ld\n", __func__, rk817->playback_path); + + ucontrol->value.integer.value[0] = rk817->playback_path; + + return 0; +} + +static int rk817_playback_path_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + long int pre_path; + + codec->component.regmap = rk817_priv->regmap; + + if (rk817->playback_path == ucontrol->value.integer.value[0]) { + DBG("%s : playback_path is not changed!\n", + __func__); + return 0; + } + + pre_path = rk817->playback_path; + rk817->playback_path = ucontrol->value.integer.value[0]; + + DBG("%s : set playback_path %ld, pre_path %ld\n", + __func__, rk817->playback_path, pre_path); + + switch (rk817->playback_path) { + case OFF: + if (pre_path != OFF) + rk817_codec_power_down(RK817_CODEC_PLAYBACK); + break; + case RCV: + case SPK_PATH: + case RING_SPK: + if (pre_path == OFF) + rk817_codec_power_up(RK817_CODEC_PLAYBACK); + /* power on dac ibias/l/r*/ + snd_soc_write(codec, RK817_CODEC_ADAC_CFG1, + PWD_DACBIAS_ON | PWD_DACD_ON | + PWD_DACL_ON | PWD_DACR_ON); + /* CLASS D mode*/ + snd_soc_write(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, 0x10); + /* CLASS D enable*/ + snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG1, 0xa5); + /* restart CLASS D, OCPP/N*/ + snd_soc_write(codec, RK817_CODEC_ACLASSD_CFG2, 0xc4); + + snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->spk_volume); + snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->spk_volume); + break; + case HP_PATH: + case HP_NO_MIC: + case RING_HP: + case RING_HP_NO_MIC: + if (pre_path == OFF) + rk817_codec_power_up(RK817_CODEC_PLAYBACK); + /* HP_CP_EN , CP 2.3V */ + snd_soc_write(codec, RK817_CODEC_AHP_CP, 0x11); + /* power on HP two stage opamp ,HP amplitude 0db*/ + snd_soc_write(codec, RK817_CODEC_AHP_CFG0, 0x80); + /* power on dac ibias/l/r*/ + snd_soc_write(codec, RK817_CODEC_ADAC_CFG1, + PWD_DACBIAS_ON | PWD_DACD_DOWN | + PWD_DACL_ON | PWD_DACR_ON); + snd_soc_update_bits(codec, RK817_CODEC_DDAC_MUTE_MIXCTL, + DACMT_ENABLE, DACMT_DISABLE); + + snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->hp_volume); + snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->hp_volume); + break; + case BT: + break; + case SPK_HP: + case RING_SPK_HP: + if (pre_path == OFF) + rk817_codec_power_up(RK817_CODEC_PLAYBACK); + + snd_soc_write(codec, RK817_CODEC_DDAC_VOLL, rk817->hp_volume); + snd_soc_write(codec, RK817_CODEC_DDAC_VOLR, rk817->hp_volume); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int rk817_capture_path_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + + DBG("%s : capture_path %ld\n", __func__, + rk817->capture_path); + + ucontrol->value.integer.value[0] = rk817->capture_path; + + return 0; +} + +static int rk817_capture_path_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct rk817_codec_priv *rk817 = rk817_priv; + long int pre_path; + + codec->component.regmap = rk817_priv->regmap; + + if (rk817->capture_path == ucontrol->value.integer.value[0]) { + DBG("%s : capture_path is not changed!\n", + __func__); + return 0; + } + + pre_path = rk817->capture_path; + rk817->capture_path = ucontrol->value.integer.value[0]; + + DBG("%s : set capture_path %ld, pre_path %ld\n", __func__, + rk817->capture_path, pre_path); + + switch (rk817->capture_path) { + case MIC_OFF: + if (pre_path != MIC_OFF) + rk817_codec_power_down(RK817_CODEC_CAPTURE); + break; + case MAIN_MIC: + if (pre_path == MIC_OFF) + rk817_codec_power_up(RK817_CODEC_CAPTURE); + break; + case HANDS_FREE_MIC: + if (pre_path == MIC_OFF) + rk817_codec_power_up(RK817_CODEC_CAPTURE); + break; + case BT_SCO_MIC: + break; + default: + return -EINVAL; + } + + return 0; +} + +static struct snd_kcontrol_new rk817_snd_path_controls[] = { + SOC_ENUM_EXT("Playback Path", rk817_playback_path_type, + rk817_playback_path_get, rk817_playback_path_put), + + SOC_ENUM_EXT("Capture MIC Path", rk817_capture_path_type, + rk817_capture_path_get, rk817_capture_path_put), +}; + +static int rk817_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + + rk817->stereo_sysclk = freq; + + DBG("%s : MCLK = %dHz\n", __func__, rk817->stereo_sysclk); + + return 0; +} + +static int rk817_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + unsigned int i2s_mst = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + i2s_mst |= RK817_I2S_MODE_SLV; + break; + case SND_SOC_DAIFMT_CBM_CFM: + i2s_mst |= RK817_I2S_MODE_MST; + break; + default: + dev_err(codec->dev, "%s : set master mask failed!\n", + __func__); + return -EINVAL; + } + DBG("%s : i2s %s mode\n", __func__, + i2s_mst ? "master" : "slave"); + + snd_soc_update_bits(codec, RK817_CODEC_DI2S_CKM, + RK817_I2S_MODE_MASK, i2s_mst); + + return 0; +} + +static int rk817_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->codec; + struct rk817_codec_priv *rk817 = rk817_priv; + unsigned int rate = params_rate(params); + + DBG("%s : MCLK = %dHz, sample rate = %dHz\n", + __func__, rk817->stereo_sysclk, rate); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + snd_soc_write(codec, RK817_CODEC_DI2S_RXCR2, VDW_RX_16BITS); + snd_soc_write(codec, RK817_CODEC_DI2S_TXCR2, VDW_TX_16BITS); + break; + case SNDRV_PCM_FORMAT_S24_LE: + snd_soc_write(codec, RK817_CODEC_DI2S_RXCR2, VDW_RX_24BITS); + snd_soc_write(codec, RK817_CODEC_DI2S_TXCR2, VDW_TX_24BITS); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int rk817_digital_mute(struct snd_soc_dai *dai, int mute) +{ + DBG("%s immediately return for mid\n", __func__); + return 0; +} + +#define RK817_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_96000) + +#define RK817_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_96000) + +#define RK817_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_ops rk817_dai_ops = { + .hw_params = rk817_hw_params, + .set_fmt = rk817_set_dai_fmt, + .set_sysclk = rk817_set_dai_sysclk, + .digital_mute = rk817_digital_mute, +}; + +static struct snd_soc_dai_driver rk817_dai[] = { + { + .name = "rk817-hifi", + .id = RK817_HIFI, + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 2, + .channels_max = 8, + .rates = RK817_PLAYBACK_RATES, + .formats = RK817_FORMATS, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 2, + .channels_max = 2, + .rates = RK817_CAPTURE_RATES, + .formats = RK817_FORMATS, + }, + .ops = &rk817_dai_ops, + }, +}; + +static int rk817_suspend(struct snd_soc_codec *codec) +{ + rk817_codec_power_down(RK817_CODEC_ALL); + return 0; +} + +static int rk817_resume(struct snd_soc_codec *codec) +{ + return 0; +} + +static int rk817_probe(struct snd_soc_codec *codec) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + + DBG("%s\n", __func__); + + if (!rk817) { + dev_err(codec->dev, "%s : rk817 priv is NULL!\n", + __func__); + return -EINVAL; + } + codec->component.regmap = rk817_priv->regmap; + rk817->codec = codec; + rk817->playback_path = OFF; + rk817->capture_path = MIC_OFF; + + rk817_reset(codec); + + snd_soc_add_codec_controls(codec, rk817_snd_path_controls, + ARRAY_SIZE(rk817_snd_path_controls)); + return 0; +} + +/* power down chip */ +static int rk817_remove(struct snd_soc_codec *codec) +{ + struct rk817_codec_priv *rk817 = rk817_priv; + + DBG("%s\n", __func__); + + if (!rk817) { + dev_err(codec->dev, "%s : rk817_priv is NULL\n", __func__); + return 0; + } + + rk817_codec_power_down(RK817_CODEC_ALL); + mdelay(10); + + return 0; +} + +static struct snd_soc_codec_driver soc_codec_dev_rk817 = { + .probe = rk817_probe, + .remove = rk817_remove, + .suspend = rk817_suspend, + .resume = rk817_resume, +}; + +static int rk817_codec_parse_dt_property(struct device *dev, + struct rk817_codec_priv *rk817) +{ + struct device_node *node = dev->parent->of_node; + int ret; + + DBG("%s()\n", __func__); + + if (!node) { + dev_err(dev, "%s() dev->parent->of_node is NULL\n", + __func__); + return -ENODEV; + } + + node = of_get_child_by_name(dev->parent->of_node, "rk817-codec"); + if (!node) { + dev_err(dev, "%s() Can not get child: rk817-codec\n", + __func__); + return -ENODEV; + } + + ret = of_property_read_u32(node, "skp-volume", &rk817->spk_volume); + if (ret < 0) { + DBG("%s() Can not read property skp-volume\n", __func__); + rk817->spk_volume = OUT_VOLUME; + } + + ret = of_property_read_u32(node, "hp-volume", + &rk817->hp_volume); + if (ret < 0) { + DBG("%s() Can not read property hp-volume\n", + __func__); + rk817->hp_volume = OUT_VOLUME; + } + + ret = of_property_read_u32(node, "capture-volume", + &rk817->capture_volume); + if (ret < 0) { + DBG("%s() Can not read property capture-volume\n", + __func__); + rk817->capture_volume = CAPTURE_VOLUME; + } + + return 0; +} + +static const struct regmap_config rk817_codec_regmap_config = { + .name = "rk817-codec", + .reg_bits = 8, + .val_bits = 8, + .reg_stride = 1, + .max_register = 0x4f, + .cache_type = REGCACHE_NONE, + .volatile_reg = rk817_volatile_register, + .writeable_reg = rk817_codec_register, + .readable_reg = rk817_codec_register, + .reg_defaults = rk817_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(rk817_reg_defaults), +}; + +static int rk817_platform_probe(struct platform_device *pdev) +{ + struct rk808 *rk817 = dev_get_drvdata(pdev->dev.parent); + struct rk817_codec_priv *rk817_codec_data; + int ret; + + DBG("%s\n", __func__); + + if (!rk817) { + dev_err(&pdev->dev, "%s : rk817 is NULL\n", __func__); + return -EINVAL; + } + + rk817_codec_data = devm_kzalloc(&pdev->dev, + sizeof(struct rk817_codec_priv), + GFP_KERNEL); + if (!rk817_codec_data) + return -ENOMEM; + + rk817_priv = rk817_codec_data; + platform_set_drvdata(pdev, rk817_codec_data); + + ret = rk817_codec_parse_dt_property(&pdev->dev, rk817_codec_data); + if (ret < 0) { + dev_err(&pdev->dev, "%s() parse device tree property error %d\n", + __func__, ret); + goto err_; + } + + rk817_codec_data->regmap = devm_regmap_init_i2c(rk817->i2c, + &rk817_codec_regmap_config); + if (IS_ERR(rk817_codec_data->regmap)) { + ret = PTR_ERR(rk817_codec_data->regmap); + dev_err(&pdev->dev, "failed to allocate register map: %d\n", + ret); + goto err_; + } + + rk817_codec_data->mclk = devm_clk_get(&pdev->dev, "mclk"); + if (IS_ERR(rk817_codec_data->mclk)) { + dev_err(&pdev->dev, "Unable to get mclk\n"); + ret = -ENXIO; + goto err_; + } + clk_prepare_enable(rk817_codec_data->mclk); + + ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_rk817, + rk817_dai, ARRAY_SIZE(rk817_dai)); + if (ret < 0) { + dev_err(&pdev->dev, "%s() register codec error %d\n", + __func__, ret); + goto err_; + } + + return 0; +err_: + + rk817_priv = NULL; + + return ret; +} + +static int rk817_platform_remove(struct platform_device *pdev) +{ + if (!IS_ERR(rk817_priv->mclk)) + clk_disable_unprepare(rk817_priv->mclk); + + snd_soc_unregister_codec(&pdev->dev); + + rk817_priv = NULL; + + return 0; +} + +static void rk817_platform_shutdown(struct platform_device *pdev) +{ + DBG("%s\n", __func__); + + rk817_codec_power_down(RK817_CODEC_ALL); + + if (rk817_priv) + rk817_priv = NULL; +} + +static const struct of_device_id rk817_codec_dt_ids[] = { + { .compatible = "rockchip,rk817-codec" }, + {}, +}; +MODULE_DEVICE_TABLE(of, rk817_codec_dt_ids); + +static struct platform_driver rk817_codec_driver = { + .driver = { + .name = "rk817-codec", + .of_match_table = rk817_codec_dt_ids, + }, + .probe = rk817_platform_probe, + .remove = rk817_platform_remove, + .shutdown = rk817_platform_shutdown, +}; + +module_platform_driver(rk817_codec_driver); + +MODULE_DESCRIPTION("ASoC RK817 codec driver"); +MODULE_AUTHOR("binyuan <kevan.lan@rock-chips.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rk817_codec.h b/sound/soc/codecs/rk817_codec.h new file mode 100644 index 000000000000..cdf56a087308 --- /dev/null +++ b/sound/soc/codecs/rk817_codec.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2018 Rockchip Electronics Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __RK817_CODEC_H__ +#define __RK817_CODEC_H__ + +/* codec register */ +#define RK817_CODEC_BASE 0x0000 + +#define RK817_CODEC_DTOP_VUCTL (RK817_CODEC_BASE + 0x12) +#define RK817_CODEC_DTOP_VUCTIME (RK817_CODEC_BASE + 0x13) +#define RK817_CODEC_DTOP_LPT_SRST (RK817_CODEC_BASE + 0x14) +#define RK817_CODEC_DTOP_DIGEN_CLKE (RK817_CODEC_BASE + 0x15) +#define RK817_CODEC_AREF_RTCFG0 (RK817_CODEC_BASE + 0x16) +#define RK817_CODEC_AREF_RTCFG1 (RK817_CODEC_BASE + 0x17) +#define RK817_CODEC_AADC_CFG0 (RK817_CODEC_BASE + 0x18) +#define RK817_CODEC_AADC_CFG1 (RK817_CODEC_BASE + 0x19) +#define RK817_CODEC_DADC_VOLL (RK817_CODEC_BASE + 0x1a) +#define RK817_CODEC_DADC_VOLR (RK817_CODEC_BASE + 0x1b) +#define RK817_CODEC_DADC_SR_ACL0 (RK817_CODEC_BASE + 0x1e) +#define RK817_CODEC_DADC_ALC1 (RK817_CODEC_BASE + 0x1f) +#define RK817_CODEC_DADC_ALC2 (RK817_CODEC_BASE + 0x20) +#define RK817_CODEC_DADC_NG (RK817_CODEC_BASE + 0x21) +#define RK817_CODEC_DADC_HPF (RK817_CODEC_BASE + 0x22) +#define RK817_CODEC_DADC_RVOLL (RK817_CODEC_BASE + 0x23) +#define RK817_CODEC_DADC_RVOLR (RK817_CODEC_BASE + 0x24) +#define RK817_CODEC_AMIC_CFG0 (RK817_CODEC_BASE + 0x27) +#define RK817_CODEC_AMIC_CFG1 (RK817_CODEC_BASE + 0x28) +#define RK817_CODEC_DMIC_PGA_GAIN (RK817_CODEC_BASE + 0x29) +#define RK817_CODEC_DMIC_LMT1 (RK817_CODEC_BASE + 0x2a) +#define RK817_CODEC_DMIC_LMT2 (RK817_CODEC_BASE + 0x2b) +#define RK817_CODEC_DMIC_NG1 (RK817_CODEC_BASE + 0x2c) +#define RK817_CODEC_DMIC_NG2 (RK817_CODEC_BASE + 0x2d) +#define RK817_CODEC_ADAC_CFG0 (RK817_CODEC_BASE + 0x2e) +#define RK817_CODEC_ADAC_CFG1 (RK817_CODEC_BASE + 0x2f) +#define RK817_CODEC_DDAC_POPD_DACST (RK817_CODEC_BASE + 0x30) +#define RK817_CODEC_DDAC_VOLL (RK817_CODEC_BASE + 0x31) +#define RK817_CODEC_DDAC_VOLR (RK817_CODEC_BASE + 0x32) +#define RK817_CODEC_DDAC_SR_LMT0 (RK817_CODEC_BASE + 0x35) +#define RK817_CODEC_DDAC_LMT1 (RK817_CODEC_BASE + 0x36) +#define RK817_CODEC_DDAC_LMT2 (RK817_CODEC_BASE + 0x37) +#define RK817_CODEC_DDAC_MUTE_MIXCTL (RK817_CODEC_BASE + 0x38) +#define RK817_CODEC_DDAC_RVOLL (RK817_CODEC_BASE + 0x39) +#define RK817_CODEC_DDAC_RVOLR (RK817_CODEC_BASE + 0x3a) +#define RK817_CODEC_AHP_ANTI0 (RK817_CODEC_BASE + 0x3b) +#define RK817_CODEC_AHP_ANTI1 (RK817_CODEC_BASE + 0x3c) +#define RK817_CODEC_AHP_CFG0 (RK817_CODEC_BASE + 0x3d) +#define RK817_CODEC_AHP_CFG1 (RK817_CODEC_BASE + 0x3e) +#define RK817_CODEC_AHP_CP (RK817_CODEC_BASE + 0x3f) +#define RK817_CODEC_ACLASSD_CFG1 (RK817_CODEC_BASE + 0x40) +#define RK817_CODEC_ACLASSD_CFG2 (RK817_CODEC_BASE + 0x41) +#define RK817_CODEC_APLL_CFG0 (RK817_CODEC_BASE + 0x42) +#define RK817_CODEC_APLL_CFG1 (RK817_CODEC_BASE + 0x43) +#define RK817_CODEC_APLL_CFG2 (RK817_CODEC_BASE + 0x44) +#define RK817_CODEC_APLL_CFG3 (RK817_CODEC_BASE + 0x45) +#define RK817_CODEC_APLL_CFG4 (RK817_CODEC_BASE + 0x46) +#define RK817_CODEC_APLL_CFG5 (RK817_CODEC_BASE + 0x47) +#define RK817_CODEC_DI2S_CKM (RK817_CODEC_BASE + 0x48) +#define RK817_CODEC_DI2S_RSD (RK817_CODEC_BASE + 0x49) +#define RK817_CODEC_DI2S_RXCR1 (RK817_CODEC_BASE + 0x4a) +#define RK817_CODEC_DI2S_RXCR2 (RK817_CODEC_BASE + 0x4b) +#define RK817_CODEC_DI2S_RXCMD_TSD (RK817_CODEC_BASE + 0x4c) +#define RK817_CODEC_DI2S_TXCR1 (RK817_CODEC_BASE + 0x4d) +#define RK817_CODEC_DI2S_TXCR2 (RK817_CODEC_BASE + 0x4e) +#define RK817_CODEC_DI2S_TXCR3_TXCMD (RK817_CODEC_BASE + 0x4f) + +/*RK817_CODEC_DTOP_DIGEN_CLKE*/ +#define ADC_DIG_CLK_MASK (0xf << 4) +#define ADC_DIG_CLK_SFT 4 +#define ADC_DIG_CLK_DIS (0x0 << 4) +#define ADC_DIG_CLK_EN (0xf << 4) + +#define DAC_DIG_CLK_MASK (0xf << 0) +#define DAC_DIG_CLK_SFT 0 +#define DAC_DIG_CLK_DIS (0x0 << 0) +#define DAC_DIG_CLK_EN (0xf << 0) + +/*RK817_CODEC_APLL_CFG5*/ +#define PLL_PW_DOWN (0x01 << 0) +#define PLL_PW_UP (0x00 << 0) + +/*RK817_CODEC_DI2S_CKM*/ +#define SCK_EN_ENABLE (0x1 << 2) +#define SCK_EN_DISABLE (0x0 << 2) + +#define RK817_I2S_MODE_MASK (0x1 << 0) +#define RK817_I2S_MODE_SFT 0 +#define RK817_I2S_MODE_MST (0x1 << 0) +#define RK817_I2S_MODE_SLV (0x0 << 0) + +/*RK817_CODEC_DDAC_MUTE_MIXCTL*/ +#define DACMT_ENABLE (0x1 << 0) +#define DACMT_DISABLE (0x0 << 0) + +/*RK817_CODEC_DI2S_RXCR2*/ +#define VDW_RX_24BITS (0x17) +#define VDW_RX_16BITS (0x0f) +/*RK817_CODEC_DI2S_TXCR2*/ +#define VDW_TX_24BITS (0x17) +#define VDW_TX_16BITS (0x0f) + +/*RK817_CODEC_AHP_CFG1*/ +#define HP_ANTIPOP_ENABLE (0x1 << 4) +#define HP_ANTIPOP_DISABLE (0x0 << 4) + +/*RK817_CODEC_ADAC_CFG1*/ +#define PWD_DACBIAS_MASK (0x1 << 3) +#define PWD_DACBIAS_SFT 3 +#define PWD_DACBIAS_DOWN (0x1 << 3) +#define PWD_DACBIAS_ON (0x0 << 3) + +#define PWD_DACD_MASK (0x1 << 2) +#define PWD_DACD_SFT 2 +#define PWD_DACD_DOWN (0x1 << 2) +#define PWD_DACD_ON (0x0 << 2) + +#define PWD_DACL_MASK (0x1 << 1) +#define PWD_DACL_SFT 1 +#define PWD_DACL_DOWN (0x1 << 1) +#define PWD_DACL_ON (0x0 << 1) + +#define PWD_DACR_MASK (0x1 << 0) +#define PWD_DACR_SFT 0 +#define PWD_DACR_DOWN (0x1 << 0) +#define PWD_DACR_ON (0x0 << 0) + +enum { + RK817_HIFI, + RK817_VOICE, +}; + +enum { + RK817_MONO = 1, + RK817_STEREO, +}; + +enum { + OFF, + RCV, + SPK_PATH, + HP_PATH, + HP_NO_MIC, + BT, + SPK_HP, + RING_SPK, + RING_HP, + RING_HP_NO_MIC, + RING_SPK_HP, +}; + +enum { + MIC_OFF, + MAIN_MIC, + HANDS_FREE_MIC, + BT_SCO_MIC, +}; + +struct rk817_reg_val_typ { + unsigned int reg; + unsigned int value; +}; + +struct rk817_init_bit_typ { + unsigned int reg; + unsigned int power_bit; + unsigned int init_bit; +}; + +#endif /* __RK817_CODEC_H__ */ |