mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 20:32:04 +09:00
ASoC: codecs: support rk3528 acodec
Signed-off-by: Jason Zhu <jason.zhu@rock-chips.com> Change-Id: Ie789864edde7aec69b5906868a76f6ba60a53d7a
This commit is contained in:
@@ -161,6 +161,7 @@ config SND_SOC_ALL_CODECS
|
||||
imply SND_SOC_RK3228
|
||||
imply SND_SOC_RK3308
|
||||
imply SND_SOC_RK3328
|
||||
imply SND_SOC_RK3528
|
||||
imply SND_SOC_RK730
|
||||
imply SND_SOC_RK817
|
||||
imply SND_SOC_RT274
|
||||
@@ -1102,6 +1103,10 @@ config SND_SOC_RK3328
|
||||
tristate "Rockchip RK3328 audio CODEC"
|
||||
select REGMAP_MMIO
|
||||
|
||||
config SND_SOC_RK3528
|
||||
tristate "Rockchip RK3528 audio CODEC"
|
||||
select REGMAP_MMIO
|
||||
|
||||
config SND_SOC_RK730
|
||||
tristate "Rockchip RK730 CODEC"
|
||||
select REGMAP_I2C
|
||||
|
||||
@@ -168,6 +168,7 @@ snd-soc-rk312x-objs := rk312x_codec.o
|
||||
snd-soc-rk3228-objs := rk3228_codec.o
|
||||
snd-soc-rk3308-objs := rk3308_codec.o
|
||||
snd-soc-rk3328-objs := rk3328_codec.o
|
||||
snd-soc-rk3528-objs := rk3528_codec.o
|
||||
snd-soc-rk730-objs := rk730.o
|
||||
snd-soc-rk817-objs := rk817_codec.o
|
||||
snd-soc-rk-codec-digital-objs := rk_codec_digital.o
|
||||
@@ -493,6 +494,7 @@ obj-$(CONFIG_SND_SOC_RK312X) += snd-soc-rk312x.o
|
||||
obj-$(CONFIG_SND_SOC_RK3228) += snd-soc-rk3228.o
|
||||
obj-$(CONFIG_SND_SOC_RK3308) += snd-soc-rk3308.o
|
||||
obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o
|
||||
obj-$(CONFIG_SND_SOC_RK3528) += snd-soc-rk3528.o
|
||||
obj-$(CONFIG_SND_SOC_RK730) += snd-soc-rk730.o
|
||||
obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o
|
||||
obj-$(CONFIG_SND_SOC_RK_CODEC_DIGITAL) += snd-soc-rk-codec-digital.o
|
||||
|
||||
771
sound/soc/codecs/rk3528_codec.c
Normal file
771
sound/soc/codecs/rk3528_codec.c
Normal file
@@ -0,0 +1,771 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* rk3528_codec.c - Rockchip RK3528 SoC Codec Driver
|
||||
*
|
||||
* Copyright (C) 2022 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "rk3528_codec.h"
|
||||
|
||||
#define CODEC_DRV_NAME "rk3528-acodec"
|
||||
|
||||
struct rk3528_codec_priv {
|
||||
const struct device *plat_dev;
|
||||
struct reset_control *reset;
|
||||
struct regmap *regmap;
|
||||
struct clk *pclk;
|
||||
struct clk *mclk;
|
||||
struct gpio_desc *pa_ctl_gpio;
|
||||
struct snd_soc_component *component;
|
||||
u32 pa_ctl_delay_ms;
|
||||
};
|
||||
|
||||
static void rk3528_codec_pa_ctrl(struct rk3528_codec_priv *rk3528, bool on)
|
||||
{
|
||||
if (!rk3528->pa_ctl_gpio)
|
||||
return;
|
||||
|
||||
if (on) {
|
||||
gpiod_direction_output(rk3528->pa_ctl_gpio, on);
|
||||
msleep(rk3528->pa_ctl_delay_ms);
|
||||
} else {
|
||||
gpiod_direction_output(rk3528->pa_ctl_gpio, on);
|
||||
}
|
||||
}
|
||||
|
||||
static int rk3528_codec_reset(struct snd_soc_component *component)
|
||||
{
|
||||
struct rk3528_codec_priv *rk3528 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
reset_control_assert(rk3528->reset);
|
||||
usleep_range(10000, 11000); /* estimated value */
|
||||
reset_control_deassert(rk3528->reset);
|
||||
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_DIG00,
|
||||
ACODEC_DAC_RST_MASK |
|
||||
ACODEC_SYS_RST_MASK,
|
||||
ACODEC_DAC_RST_N |
|
||||
ACODEC_SYS_RST_N);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_DIG02,
|
||||
ACODEC_DAC_I2S_RST_MASK,
|
||||
ACODEC_DAC_I2S_RST_N);
|
||||
usleep_range(10000, 11000); /* estimated value */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_DIG00,
|
||||
ACODEC_DAC_RST_MASK |
|
||||
ACODEC_SYS_RST_MASK,
|
||||
ACODEC_DAC_RST_P |
|
||||
ACODEC_SYS_RST_P);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_DIG02,
|
||||
ACODEC_DAC_I2S_RST_MASK,
|
||||
ACODEC_DAC_I2S_RST_P);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_codec_power_on(struct rk3528_codec_priv *rk3528)
|
||||
{
|
||||
/* vendor step 0, Supply the power of the digital part and reset the audio codec. */
|
||||
/* vendor step 1 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA08,
|
||||
ACODEC_DAC_L_POP_CTRL_MASK,
|
||||
ACODEC_DAC_L_POP_CTRL_ON);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0C,
|
||||
ACODEC_DAC_R_POP_CTRL_MASK,
|
||||
ACODEC_DAC_R_POP_CTRL_ON);
|
||||
/* vendor step 2 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA01,
|
||||
ACODEC_VREF_SEL_MASK, ACODEC_VREF_SEL(0xff));
|
||||
/* vendor step 3, supply the power of the analog part */
|
||||
/* vendor step 4 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA00,
|
||||
ACODEC_VREF_MASK, ACODEC_VREF_EN);
|
||||
|
||||
/* vendor step 5, Wait until the voltage of VCM keeps stable at the AVDD/2. */
|
||||
usleep_range(20000, 22000);
|
||||
/* vendor step 6 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA01,
|
||||
ACODEC_VREF_SEL_MASK, ACODEC_VREF_SEL(2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_codec_power_off(struct rk3528_codec_priv *rk3528)
|
||||
{
|
||||
/*
|
||||
* vendor step 0. Keep the power on and disable the DAC and ADC path.
|
||||
*/
|
||||
/* vendor step 1 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA01,
|
||||
ACODEC_VREF_SEL_MASK, ACODEC_VREF_SEL(0xff));
|
||||
/* vendor step 2 */
|
||||
/* vendor step 3 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA00,
|
||||
ACODEC_VREF_MASK, ACODEC_VREF_DIS);
|
||||
/* vendor step 4. Wait until the voltage of VCM keep stable at AGND. */
|
||||
usleep_range(20000, 22000);
|
||||
/* vendor step 5, power off the analog power supply */
|
||||
/* vendor step 6, power off the digital power supply */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_codec_dac_enable(struct rk3528_codec_priv *rk3528)
|
||||
{
|
||||
/* vendor step 0, power up the codec and input the mute signal */
|
||||
/* vendor step 1 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA00,
|
||||
ACODEC_IBIAS_DAC_MASK,
|
||||
ACODEC_IBIAS_DAC_EN);
|
||||
/* vendor step 2 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA08,
|
||||
ACODEC_DAC_L_BUF_MASK,
|
||||
ACODEC_DAC_L_BUF_EN);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0C,
|
||||
ACODEC_DAC_R_BUF_MASK,
|
||||
ACODEC_DAC_R_BUF_EN);
|
||||
/* vendor step 3 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA08,
|
||||
ACODEC_DAC_L_POP_CTRL_MASK,
|
||||
ACODEC_DAC_L_POP_CTRL_ON);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0C,
|
||||
ACODEC_DAC_R_POP_CTRL_MASK,
|
||||
ACODEC_DAC_R_POP_CTRL_ON);
|
||||
/* vendor step 4 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA09,
|
||||
ACODEC_LINEOUT_L_MASK,
|
||||
ACODEC_LINEOUT_L_EN);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0D,
|
||||
ACODEC_LINEOUT_R_MASK,
|
||||
ACODEC_LINEOUT_R_EN);
|
||||
/* vendor step 5 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA09,
|
||||
ACODEC_LINEOUT_L_INIT_MASK,
|
||||
ACODEC_LINEOUT_L_INIT_WORK);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0D,
|
||||
ACODEC_LINEOUT_R_INIT_MASK,
|
||||
ACODEC_LINEOUT_R_INIT_WORK);
|
||||
/* vendor step 6 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA08,
|
||||
ACODEC_DAC_L_VREF_MASK,
|
||||
ACODEC_DAC_L_VREF_EN);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0C,
|
||||
ACODEC_DAC_R_VREF_MASK,
|
||||
ACODEC_DAC_R_VREF_EN);
|
||||
/* vendor step 7 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA08,
|
||||
ACODEC_DAC_L_CLK_MASK,
|
||||
ACODEC_DAC_L_CLK_EN);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0C,
|
||||
ACODEC_DAC_R_CLK_MASK,
|
||||
ACODEC_DAC_R_CLK_EN);
|
||||
/* vendor step 8 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA08,
|
||||
ACODEC_DAC_L_MASK,
|
||||
ACODEC_DAC_L_EN);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0C,
|
||||
ACODEC_DAC_R_MASK,
|
||||
ACODEC_DAC_R_EN);
|
||||
/* vendor step 9 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA08,
|
||||
ACODEC_DAC_L_INIT_MASK,
|
||||
ACODEC_DAC_L_WORK);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0C,
|
||||
ACODEC_DAC_R_INIT_MASK,
|
||||
ACODEC_DAC_R_WORK);
|
||||
/* vendor step 10 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA09,
|
||||
ACODEC_LINEOUT_L_MUTE_MASK,
|
||||
ACODEC_LINEOUT_L_WORK);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0D,
|
||||
ACODEC_LINEOUT_R_MUTE_MASK,
|
||||
ACODEC_LINEOUT_R_WORK);
|
||||
/* vendor step 11, select the gain */
|
||||
/* vendor step 12, play music */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_codec_dac_disable(struct rk3528_codec_priv *rk3528)
|
||||
{
|
||||
/* vendor step 0, keep the dac channel work and input the mute signal */
|
||||
/* vendor step 1, select the gain */
|
||||
/* vendor step 2 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA09,
|
||||
ACODEC_LINEOUT_L_MUTE_MASK,
|
||||
ACODEC_LINEOUT_L_MUTE);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0D,
|
||||
ACODEC_LINEOUT_R_MUTE_MASK,
|
||||
ACODEC_LINEOUT_R_MUTE);
|
||||
/* vendor step 3 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA09,
|
||||
ACODEC_LINEOUT_L_INIT_MASK,
|
||||
ACODEC_LINEOUT_L_INIT);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0D,
|
||||
ACODEC_LINEOUT_R_INIT_MASK,
|
||||
ACODEC_LINEOUT_R_INIT);
|
||||
/* vendor step 4 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA09,
|
||||
ACODEC_LINEOUT_L_MASK,
|
||||
ACODEC_LINEOUT_L_DIS);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0D,
|
||||
ACODEC_LINEOUT_R_MASK,
|
||||
ACODEC_LINEOUT_R_DIS);
|
||||
/* vendor step 5 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA08,
|
||||
ACODEC_DAC_L_MASK,
|
||||
ACODEC_DAC_L_DIS);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0C,
|
||||
ACODEC_DAC_R_MASK,
|
||||
ACODEC_DAC_R_DIS);
|
||||
/* vendor step 6 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA08,
|
||||
ACODEC_DAC_L_CLK_MASK,
|
||||
ACODEC_DAC_L_CLK_DIS);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0C,
|
||||
ACODEC_DAC_R_CLK_MASK,
|
||||
ACODEC_DAC_R_CLK_DIS);
|
||||
/* vendor step 7 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA08,
|
||||
ACODEC_DAC_L_VREF_MASK,
|
||||
ACODEC_DAC_L_VREF_DIS);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0C,
|
||||
ACODEC_DAC_R_VREF_MASK,
|
||||
ACODEC_DAC_R_VREF_DIS);
|
||||
/* vendor step 8 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA08,
|
||||
ACODEC_DAC_L_POP_CTRL_MASK,
|
||||
ACODEC_DAC_L_POP_CTRL_OFF);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0C,
|
||||
ACODEC_DAC_R_POP_CTRL_MASK,
|
||||
ACODEC_DAC_R_POP_CTRL_OFF);
|
||||
/* vendor step 9 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA08,
|
||||
ACODEC_DAC_L_BUF_MASK,
|
||||
ACODEC_DAC_L_BUF_DIS);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0C,
|
||||
ACODEC_DAC_R_BUF_MASK,
|
||||
ACODEC_DAC_R_BUF_DIS);
|
||||
/* vendor step 10 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA00,
|
||||
ACODEC_IBIAS_DAC_MASK,
|
||||
ACODEC_IBIAS_DAC_DIS);
|
||||
/* vendor step 9 */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA08,
|
||||
ACODEC_DAC_L_INIT_MASK,
|
||||
ACODEC_DAC_L_INIT);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0C,
|
||||
ACODEC_DAC_R_INIT_MASK,
|
||||
ACODEC_DAC_R_INIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_codec_dac_dig_config(struct rk3528_codec_priv *rk3528,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
unsigned int dac_aif1 = 0;
|
||||
|
||||
switch (params_format(params)) {
|
||||
case SNDRV_PCM_FORMAT_S16_LE:
|
||||
dac_aif1 |= ACODEC_DAC_I2S_16B;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||
dac_aif1 |= ACODEC_DAC_I2S_20B;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
dac_aif1 |= ACODEC_DAC_I2S_24B;
|
||||
break;
|
||||
case SNDRV_PCM_FORMAT_S32_LE:
|
||||
dac_aif1 |= ACODEC_DAC_I2S_32B;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dac_aif1 |= ACODEC_DAC_I2S_I2S;
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_DIG01,
|
||||
ACODEC_DAC_I2S_WL_MASK |
|
||||
ACODEC_DAC_I2S_FMT_MASK,
|
||||
dac_aif1);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_DIG02,
|
||||
ACODEC_DAC_I2S_RST_MASK,
|
||||
ACODEC_DAC_I2S_RST_P);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_set_dai_fmt(struct snd_soc_dai *codec_dai,
|
||||
unsigned int fmt)
|
||||
{
|
||||
struct snd_soc_component *component = codec_dai->component;
|
||||
struct rk3528_codec_priv *rk3528 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int dac_aif1 = 0, dac_aif2 = 0;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
dac_aif2 |= ACODEC_DAC_I2S_MST_FUNC_SLAVE;
|
||||
dac_aif2 |= ACODEC_DAC_I2S_MST_IO_SLAVE;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
dac_aif2 |= ACODEC_DAC_I2S_MST_FUNC_MASTER;
|
||||
dac_aif2 |= ACODEC_DAC_I2S_MST_IO_MASTER;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
dac_aif1 |= ACODEC_DAC_I2S_I2S;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
dac_aif1 |= ACODEC_DAC_I2S_LJM;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_DIG01,
|
||||
ACODEC_DAC_I2S_FMT_MASK,
|
||||
dac_aif1);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_DIG02,
|
||||
ACODEC_DAC_I2S_MST_FUNC_MASK |
|
||||
ACODEC_DAC_I2S_MST_IO_MASK,
|
||||
dac_aif2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct rk3528_codec_priv *rk3528 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
if (mute) {
|
||||
/* Mute DAC LINEOUT */
|
||||
regmap_update_bits(rk3528->regmap,
|
||||
ACODEC_ANA09,
|
||||
ACODEC_LINEOUT_L_MUTE_MASK,
|
||||
ACODEC_LINEOUT_L_MUTE);
|
||||
regmap_update_bits(rk3528->regmap,
|
||||
ACODEC_ANA0D,
|
||||
ACODEC_LINEOUT_R_MUTE_MASK,
|
||||
ACODEC_LINEOUT_R_MUTE);
|
||||
rk3528_codec_pa_ctrl(rk3528, false);
|
||||
} else {
|
||||
/* Unmute DAC LINEOUT */
|
||||
regmap_update_bits(rk3528->regmap,
|
||||
ACODEC_ANA09,
|
||||
ACODEC_LINEOUT_L_MUTE_MASK,
|
||||
ACODEC_LINEOUT_L_WORK);
|
||||
regmap_update_bits(rk3528->regmap,
|
||||
ACODEC_ANA0D,
|
||||
ACODEC_LINEOUT_R_MUTE_MASK,
|
||||
ACODEC_LINEOUT_R_WORK);
|
||||
rk3528_codec_pa_ctrl(rk3528, true);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_codec_default_gains(struct rk3528_codec_priv *rk3528)
|
||||
{
|
||||
/* Prepare DAC gains */
|
||||
/* set LINEOUT default gains */
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_DIG06,
|
||||
ACODEC_DAC_DIG_GAIN_MASK,
|
||||
ACODEC_DAC_DIG_GAIN(ACODEC_DAC_DIG_0DB));
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0B,
|
||||
ACODEC_LINEOUT_L_GAIN_MASK,
|
||||
ACODEC_DAC_LINEOUT_GAIN_0DB);
|
||||
regmap_update_bits(rk3528->regmap, ACODEC_ANA0F,
|
||||
ACODEC_LINEOUT_R_GAIN_MASK,
|
||||
ACODEC_DAC_LINEOUT_GAIN_0DB);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_codec_open_playback(struct rk3528_codec_priv *rk3528)
|
||||
{
|
||||
rk3528_codec_dac_enable(rk3528);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_codec_close_playback(struct rk3528_codec_priv *rk3528)
|
||||
{
|
||||
rk3528_codec_dac_disable(rk3528);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_codec_dlp_down(struct rk3528_codec_priv *rk3528)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_codec_dlp_up(struct rk3528_codec_priv *rk3528)
|
||||
{
|
||||
rk3528_codec_power_on(rk3528);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct rk3528_codec_priv *rk3528 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
rk3528_codec_open_playback(rk3528);
|
||||
rk3528_codec_dac_dig_config(rk3528, params);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rk3528_pcm_shutdown(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct rk3528_codec_priv *rk3528 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
rk3528_codec_close_playback(rk3528);
|
||||
|
||||
regcache_cache_only(rk3528->regmap, false);
|
||||
regcache_sync(rk3528->regmap);
|
||||
}
|
||||
|
||||
static int rk3528_codec_prepare(struct rk3528_codec_priv *rk3528)
|
||||
{
|
||||
/* Clear registers for ADC and DAC */
|
||||
rk3528_codec_close_playback(rk3528);
|
||||
rk3528_codec_default_gains(rk3528);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_set_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||
unsigned int freq, int dir)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct rk3528_codec_priv *rk3528 = snd_soc_component_get_drvdata(component);
|
||||
int ret;
|
||||
|
||||
if (!freq)
|
||||
return 0;
|
||||
|
||||
ret = clk_set_rate(rk3528->mclk, freq);
|
||||
if (ret)
|
||||
dev_err(rk3528->plat_dev, "Failed to set mclk %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops rk3528_dai_ops = {
|
||||
.hw_params = rk3528_hw_params,
|
||||
.set_fmt = rk3528_set_dai_fmt,
|
||||
.mute_stream = rk3528_mute_stream,
|
||||
.shutdown = rk3528_pcm_shutdown,
|
||||
.set_sysclk = rk3528_set_sysclk,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver rk3528_dai[] = {
|
||||
{
|
||||
.name = "rk3528-hifi",
|
||||
.id = ACODEC_HIFI,
|
||||
.playback = {
|
||||
.stream_name = "HiFi Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = SNDRV_PCM_RATE_8000_192000,
|
||||
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE |
|
||||
SNDRV_PCM_FMTBIT_S32_LE),
|
||||
},
|
||||
.ops = &rk3528_dai_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static int rk3528_codec_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct rk3528_codec_priv *rk3528 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
rk3528->component = component;
|
||||
rk3528_codec_reset(component);
|
||||
rk3528_codec_dlp_up(rk3528);
|
||||
rk3528_codec_prepare(rk3528);
|
||||
regcache_cache_only(rk3528->regmap, false);
|
||||
regcache_sync(rk3528->regmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rk3528_codec_remove(struct snd_soc_component *component)
|
||||
{
|
||||
struct rk3528_codec_priv *rk3528 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
rk3528_codec_pa_ctrl(rk3528, false);
|
||||
rk3528_codec_power_off(rk3528);
|
||||
regcache_cache_only(rk3528->regmap, false);
|
||||
regcache_sync(rk3528->regmap);
|
||||
}
|
||||
|
||||
static int rk3528_codec_suspend(struct snd_soc_component *component)
|
||||
{
|
||||
struct rk3528_codec_priv *rk3528 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
rk3528_codec_dlp_down(rk3528);
|
||||
regcache_cache_only(rk3528->regmap, true);
|
||||
clk_disable_unprepare(rk3528->mclk);
|
||||
clk_disable_unprepare(rk3528->pclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3528_codec_resume(struct snd_soc_component *component)
|
||||
{
|
||||
struct rk3528_codec_priv *rk3528 = snd_soc_component_get_drvdata(component);
|
||||
int ret = 0;
|
||||
|
||||
ret = clk_prepare_enable(rk3528->pclk);
|
||||
if (ret < 0) {
|
||||
dev_err(rk3528->plat_dev,
|
||||
"Failed to enable acodec pclk: %d\n", ret);
|
||||
goto pclk_error;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(rk3528->mclk);
|
||||
if (ret < 0) {
|
||||
dev_err(rk3528->plat_dev,
|
||||
"Failed to enable acodec mclk: %d\n", ret);
|
||||
goto mclk_error;
|
||||
}
|
||||
|
||||
regcache_cache_only(rk3528->regmap, false);
|
||||
ret = regcache_sync(rk3528->regmap);
|
||||
if (ret)
|
||||
goto reg_error;
|
||||
|
||||
rk3528_codec_dlp_up(rk3528);
|
||||
|
||||
return 0;
|
||||
reg_error:
|
||||
clk_disable_unprepare(rk3528->mclk);
|
||||
mclk_error:
|
||||
clk_disable_unprepare(rk3528->pclk);
|
||||
pclk_error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(rk3528_codec_dac_lineout_gain_tlv,
|
||||
-3900, 150, 600);
|
||||
|
||||
static const struct snd_kcontrol_new rk3528_codec_dapm_controls[] = {
|
||||
/* DAC LINEOUT */
|
||||
SOC_SINGLE_RANGE_TLV("DAC LEFT LINEOUT Volume",
|
||||
ACODEC_ANA0B,
|
||||
ACODEC_LINEOUT_L_GAIN_SHIFT,
|
||||
ACODEC_DAC_LINEOUT_GAIN_MIN,
|
||||
ACODEC_DAC_LINEOUT_GAIN_MAX,
|
||||
0, rk3528_codec_dac_lineout_gain_tlv),
|
||||
SOC_SINGLE_RANGE_TLV("DAC RIGHT LINEOUT Volume",
|
||||
ACODEC_ANA0F,
|
||||
ACODEC_LINEOUT_R_GAIN_SHIFT,
|
||||
ACODEC_DAC_LINEOUT_GAIN_MIN,
|
||||
ACODEC_DAC_LINEOUT_GAIN_MAX,
|
||||
0, rk3528_codec_dac_lineout_gain_tlv),
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver soc_codec_dev_rk3528 = {
|
||||
.probe = rk3528_codec_probe,
|
||||
.remove = rk3528_codec_remove,
|
||||
.suspend = rk3528_codec_suspend,
|
||||
.resume = rk3528_codec_resume,
|
||||
.controls = rk3528_codec_dapm_controls,
|
||||
.num_controls = ARRAY_SIZE(rk3528_codec_dapm_controls),
|
||||
};
|
||||
|
||||
/* Set the default value or reset value */
|
||||
static const struct reg_default rk3528_codec_reg_defaults[] = {
|
||||
{ ACODEC_DIG00, 0x71 },
|
||||
{ ACODEC_DIG03, 0x53 },
|
||||
{ ACODEC_DIG07, 0x03 },
|
||||
{ ACODEC_DIG08, 0xc3 },
|
||||
{ ACODEC_DIG09, 0x28 },
|
||||
{ ACODEC_DIG0A, 0x1 },
|
||||
{ ACODEC_DIG0B, 0x80 },
|
||||
{ ACODEC_DIG0D, 0xc3 },
|
||||
{ ACODEC_DIG0E, 0xc3 },
|
||||
{ ACODEC_DIG10, 0xf1 },
|
||||
{ ACODEC_DIG11, 0xf1 },
|
||||
{ ACODEC_ANA02, 0x77 },
|
||||
{ ACODEC_ANA08, 0x20 },
|
||||
{ ACODEC_ANA0A, 0x8 },
|
||||
{ ACODEC_ANA0C, 0x20 },
|
||||
{ ACODEC_ANA0E, 0x8 },
|
||||
};
|
||||
|
||||
static bool rk3528_codec_volatile_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case ACODEC_DIG00:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct regmap_config rk3528_codec_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.max_register = ACODEC_REG_MAX,
|
||||
.volatile_reg = rk3528_codec_volatile_reg,
|
||||
.reg_defaults = rk3528_codec_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(rk3528_codec_reg_defaults),
|
||||
.cache_type = REGCACHE_FLAT,
|
||||
};
|
||||
|
||||
static const struct of_device_id rk3528_codec_of_match[] = {
|
||||
{ .compatible = "rockchip,rk3528-codec", },
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, rk3528_codec_of_match);
|
||||
|
||||
static int rk3528_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct rk3528_codec_priv *rk3528;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
|
||||
rk3528 = devm_kzalloc(&pdev->dev, sizeof(*rk3528), GFP_KERNEL);
|
||||
if (!rk3528)
|
||||
return -ENOMEM;
|
||||
|
||||
rk3528->plat_dev = &pdev->dev;
|
||||
rk3528->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, "acodec");
|
||||
if (IS_ERR(rk3528->reset))
|
||||
return PTR_ERR(rk3528->reset);
|
||||
|
||||
rk3528->pa_ctl_gpio = devm_gpiod_get_optional(&pdev->dev, "pa-ctl",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(rk3528->pa_ctl_gpio)) {
|
||||
dev_err(&pdev->dev, "Unable to claim gpio pa-ctl\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (rk3528->pa_ctl_gpio)
|
||||
of_property_read_u32(np, "pa-ctl-delay-ms",
|
||||
&rk3528->pa_ctl_delay_ms);
|
||||
|
||||
dev_info(&pdev->dev, "%s pa_ctl_gpio and pa_ctl_delay_ms: %d\n",
|
||||
rk3528->pa_ctl_gpio ? "Use" : "No use",
|
||||
rk3528->pa_ctl_delay_ms);
|
||||
|
||||
/* Close external PA during startup. */
|
||||
rk3528_codec_pa_ctrl(rk3528, false);
|
||||
|
||||
rk3528->pclk = devm_clk_get(&pdev->dev, "pclk");
|
||||
if (IS_ERR(rk3528->pclk)) {
|
||||
dev_err(&pdev->dev, "Can't get acodec pclk\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rk3528->mclk = devm_clk_get(&pdev->dev, "mclk");
|
||||
if (IS_ERR(rk3528->mclk)) {
|
||||
dev_err(&pdev->dev, "Can't get acodec mclk\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(rk3528->pclk);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to enable acodec pclk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(rk3528->mclk);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to enable acodec mclk: %d\n", ret);
|
||||
goto failed_1;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(base)) {
|
||||
ret = PTR_ERR(base);
|
||||
dev_err(&pdev->dev, "Failed to ioremap resource\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
rk3528->regmap = devm_regmap_init_mmio(&pdev->dev, base,
|
||||
&rk3528_codec_regmap_config);
|
||||
if (IS_ERR(rk3528->regmap)) {
|
||||
ret = PTR_ERR(rk3528->regmap);
|
||||
dev_err(&pdev->dev, "Failed to regmap mmio\n");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, rk3528);
|
||||
ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rk3528,
|
||||
rk3528_dai, ARRAY_SIZE(rk3528_dai));
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Failed to register codec: %d\n", ret);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
failed:
|
||||
clk_disable_unprepare(rk3528->mclk);
|
||||
failed_1:
|
||||
clk_disable_unprepare(rk3528->pclk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk3528_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rk3528_codec_priv *rk3528 =
|
||||
(struct rk3528_codec_priv *)platform_get_drvdata(pdev);
|
||||
|
||||
clk_disable_unprepare(rk3528->mclk);
|
||||
clk_disable_unprepare(rk3528->pclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rk3528_codec_driver = {
|
||||
.driver = {
|
||||
.name = CODEC_DRV_NAME,
|
||||
.of_match_table = of_match_ptr(rk3528_codec_of_match),
|
||||
},
|
||||
.probe = rk3528_platform_probe,
|
||||
.remove = rk3528_platform_remove,
|
||||
};
|
||||
module_platform_driver(rk3528_codec_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC rk3528 Codec Driver");
|
||||
MODULE_AUTHOR("Jason Zhu <jason.zhu@rock-chips.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
229
sound/soc/codecs/rk3528_codec.h
Normal file
229
sound/soc/codecs/rk3528_codec.h
Normal file
@@ -0,0 +1,229 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* rk3528_codec.h - Rockchip RK3528 SoC Codec Driver
|
||||
*
|
||||
* Copyright (C) 2022 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __RK3528_CODEC_H__
|
||||
#define __RK3528_CODEC_H__
|
||||
|
||||
#define ACODEC_DIG00 0x00 /* REG 0x00 */
|
||||
#define ACODEC_DIG01 0x04 /* REG 0x01 */
|
||||
#define ACODEC_DIG02 0x08 /* REG 0x02 */
|
||||
#define ACODEC_DIG03 0x0c /* REG 0x03 */
|
||||
#define ACODEC_DIG04 0x10 /* REG 0x04 */
|
||||
#define ACODEC_DIG05 0x14 /* REG 0x05 */
|
||||
#define ACODEC_DIG06 0x18 /* REG 0x06 */
|
||||
#define ACODEC_DIG07 0x1c /* REG 0x07 */
|
||||
#define ACODEC_DIG08 0x20 /* REG 0x08 */
|
||||
#define ACODEC_DIG09 0x24 /* REG 0x09 */
|
||||
#define ACODEC_DIG0A 0x28 /* REG 0x0a */
|
||||
#define ACODEC_DIG0B 0x2c /* REG 0x0b */
|
||||
#define ACODEC_DIG0D 0x34 /* REG 0x0d */
|
||||
#define ACODEC_DIG0E 0x38 /* REG 0x0e */
|
||||
#define ACODEC_DIG10 0x40 /* REG 0x10 */
|
||||
#define ACODEC_DIG11 0x44 /* REG 0x11 */
|
||||
|
||||
#define ACODEC_ANA00 0x80 /* REG 0x20 */
|
||||
#define ACODEC_ANA01 0x84 /* REG 0x21 */
|
||||
#define ACODEC_ANA02 0x88 /* REG 0x22 */
|
||||
#define ACODEC_ANA08 0xa0 /* REG 0x28 */
|
||||
#define ACODEC_ANA09 0xa4 /* REG 0x29 */
|
||||
#define ACODEC_ANA0A 0xa8 /* REG 0x2a */
|
||||
#define ACODEC_ANA0B 0xac /* REG 0x2b */
|
||||
#define ACODEC_ANA0C 0xb0 /* REG 0x2c */
|
||||
#define ACODEC_ANA0D 0xb4 /* REG 0x2d */
|
||||
#define ACODEC_ANA0E 0xb8 /* REG 0x2e */
|
||||
#define ACODEC_ANA0F 0xbc /* REG 0x2f */
|
||||
|
||||
#define ACODEC_REG_MAX ACODEC_ANA0F
|
||||
|
||||
/* ACODEC_DIG00 */
|
||||
#define ACODEC_DAC_RST_MASK (0x1 << 4)
|
||||
#define ACODEC_DAC_RST_P (0x1 << 4)
|
||||
#define ACODEC_DAC_RST_N (0x0 << 4)
|
||||
#define ACODEC_REG_BIST_EN (0x1 << 1)
|
||||
#define ACODEC_SYS_RST_MASK (0x1 << 0)
|
||||
#define ACODEC_SYS_RST_P (0x1 << 0)
|
||||
#define ACODEC_SYS_RST_N (0x0 << 0)
|
||||
|
||||
/* ACODEC_DIG01 */
|
||||
#define ACODEC_DAC_I2S_WL_SHIFT 4
|
||||
#define ACODEC_DAC_I2S_WL_MASK (0x3 << ACODEC_DAC_I2S_WL_SHIFT)
|
||||
#define ACODEC_DAC_I2S_32B (0x3 << ACODEC_DAC_I2S_WL_SHIFT)
|
||||
#define ACODEC_DAC_I2S_24B (0x2 << ACODEC_DAC_I2S_WL_SHIFT)
|
||||
#define ACODEC_DAC_I2S_20B (0x1 << ACODEC_DAC_I2S_WL_SHIFT)
|
||||
#define ACODEC_DAC_I2S_16B (0x0 << ACODEC_DAC_I2S_WL_SHIFT)
|
||||
#define ACODEC_DAC_I2S_FMT_SHIFT 2
|
||||
#define ACODEC_DAC_I2S_FMT_MASK (0x3 << ACODEC_DAC_I2S_FMT_SHIFT)
|
||||
#define ACODEC_DAC_I2S_I2S (0x2 << ACODEC_DAC_I2S_FMT_SHIFT)
|
||||
#define ACODEC_DAC_I2S_LJM (0x1 << ACODEC_DAC_I2S_FMT_SHIFT)
|
||||
|
||||
/* ACODEC_DIG02 */
|
||||
#define ACODEC_DAC_I2S_LRP_MASK (0x1 << 7)
|
||||
#define ACODEC_DAC_I2S_LRP_REVSL (0x1 << 7)
|
||||
#define ACODEC_DAC_I2S_LRP_NORMAL (0x0 << 7)
|
||||
#define ACODEC_DAC_I2S_LR_SWAP (0x1 << 6)
|
||||
#define ACODEC_DAC_I2S_MST_FUNC_MASK (0x1 << 5)
|
||||
#define ACODEC_DAC_I2S_MST_FUNC_MASTER (0x1 << 5)
|
||||
#define ACODEC_DAC_I2S_MST_FUNC_SLAVE (0x0 << 5)
|
||||
#define ACODEC_DAC_I2S_MST_IO_MASK (0x1 << 4)
|
||||
#define ACODEC_DAC_I2S_MST_IO_MASTER (0x1 << 4)
|
||||
#define ACODEC_DAC_I2S_MST_IO_SLAVE (0x0 << 4)
|
||||
#define ACODEC_DAC_I2S_RST_MASK (0x1 << 0)
|
||||
#define ACODEC_DAC_I2S_RST_P (0x1 << 0)
|
||||
#define ACODEC_DAC_I2S_RST_N (0x0 << 0)
|
||||
|
||||
/* ACODEC_DIG03 */
|
||||
#define ACODEC_DAC_MUTE_EN (0x1 << 7)
|
||||
#define ACODEC_DAC_MUTE_SR_SHIFT 4
|
||||
#define ACODEC_DAC_MUTE_SR_MASK (0x7 << ACODEC_DAC_MUTE_SR_SHIFT)
|
||||
#define ACODEC_DAC_MUTE_SR_96K (0x7 << ACODEC_DAC_MUTE_SR_SHIFT)
|
||||
#define ACODEC_DAC_MUTE_SR_88K2 (0x6 << ACODEC_DAC_MUTE_SR_SHIFT)
|
||||
#define ACODEC_DAC_MUTE_SR_48K (0x5 << ACODEC_DAC_MUTE_SR_SHIFT)
|
||||
#define ACODEC_DAC_MUTE_SR_44K1 (0x4 << ACODEC_DAC_MUTE_SR_SHIFT)
|
||||
#define ACODEC_DAC_MUTE_SR_32K (0x3 << ACODEC_DAC_MUTE_SR_SHIFT)
|
||||
#define ACODEC_DAC_MUTE_SR_24K (0x2 << ACODEC_DAC_MUTE_SR_SHIFT)
|
||||
#define ACODEC_DAC_MUTE_SR_16K (0x1 << ACODEC_DAC_MUTE_SR_SHIFT)
|
||||
#define ACODEC_DAC_MUTE_SR_8K (0x0 << ACODEC_DAC_MUTE_SR_SHIFT)
|
||||
#define ACODEC_DA_EN (0x1 << 3)
|
||||
#define ACODEC_DITHER_EN (0x1 << 2)
|
||||
#define ACODEC_DITHER_LEVEL (0x1 << 1)
|
||||
#define ACODEC_DITHER_SIGN (0x1 << 0)
|
||||
|
||||
/* ACODEC_DIG04 */
|
||||
#define ACODEC_DAC_DEEMP_SEL_MASK 0x3
|
||||
#define ACODEC_DAC_DEEMP_48K 0x3
|
||||
#define ACODEC_DAC_DEEMP_44K1 0x2
|
||||
#define ACODEC_DAC_DEEMP_32K 0x1
|
||||
#define ACODEC_DAC_DEEMP_DIS 0x0
|
||||
|
||||
/* ACODEC_DIG05 */
|
||||
#define ACODEC_DAC_R_BIST_SEL_SHIFT 6
|
||||
#define ACODEC_DAC_R_BIST_SEL_MASK (0x3 << ACODEC_DAC_R_BIST_SEL_SHIFT)
|
||||
#define ACODEC_DAC_R_BIST_SEL_L (0x2 << ACODEC_DAC_R_BIST_SEL_SHIFT)
|
||||
#define ACODEC_DAC_R_BIST_SEL_SINE (0x1 << ACODEC_DAC_R_BIST_SEL_SHIFT)
|
||||
#define ACODEC_DAC_R_BIST_SEL_R (0x0 << ACODEC_DAC_R_BIST_SEL_SHIFT)
|
||||
#define ACODEC_DAC_R_MUTE (0x1 << 4)
|
||||
#define ACODEC_DAC_L_BIST_SEL_SHIFT 2
|
||||
#define ACODEC_DAC_L_BIST_SEL_MASK (0x3 << ACODEC_DAC_L_BIST_SEL_SHIFT)
|
||||
#define ACODEC_DAC_L_BIST_SEL_R (0x2 << ACODEC_DAC_L_BIST_SEL_SHIFT)
|
||||
#define ACODEC_DAC_L_BIST_SEL_SINE (0x1 << ACODEC_DAC_L_BIST_SEL_SHIFT)
|
||||
#define ACODEC_DAC_L_BIST_SEL_L (0x0 << ACODEC_DAC_L_BIST_SEL_SHIFT)
|
||||
#define ACODEC_DAC_J_MUTE (0x1 << 0)
|
||||
|
||||
/* ACODEC_DIG06 */
|
||||
#define ACODEC_DAC_DIG_GAIN_SHIT 0
|
||||
#define ACODEC_DAC_DIG_GAIN_MASK (0xff << ACODEC_DAC_DIG_GAIN_SHIT)
|
||||
/* 0.5dB every step , 1: -121dB, 255: 6dB */
|
||||
#define ACODEC_DAC_DIG_GAIN(x) ((x) & ACODEC_DAC_DIG_GAIN_MASK)
|
||||
#define ACODEC_DAC_DIG_0DB 0xe1
|
||||
|
||||
/* ACODEC_ANA00 */
|
||||
#define ACODEC_IBIAS_DAC_MASK (0x1 << 1)
|
||||
#define ACODEC_IBIAS_DAC_EN (0x1 << 1)
|
||||
#define ACODEC_IBIAS_DAC_DIS (0x0 << 1)
|
||||
#define ACODEC_VREF_MASK (0x1 << 0)
|
||||
#define ACODEC_VREF_EN (0x1 << 0)
|
||||
#define ACODEC_VREF_DIS (0x0 << 0)
|
||||
|
||||
/* ACODEC_ANA01 */
|
||||
#define ACODEC_VREF_SEL_SHIFT 0
|
||||
/* Bit 0 is I0, bit 1 is 2 * I0 ... bit 7 is 128 * I0 */
|
||||
#define ACODEC_VREF_SEL_MASK (0xff << ACODEC_VREF_SEL_SHIFT)
|
||||
#define ACODEC_VREF_SEL(x) ((x) & ACODEC_VREF_SEL_MASK)
|
||||
|
||||
/* ACODEC_ANA02 */
|
||||
#define ACODEC_IBIAS_DAC_SEL_SHIFT 0
|
||||
/* Ibias_DAC = I0 * (BIT[3]*8+BIT[2]*4+BIT[1]*2+BIT[0]+1) */
|
||||
#define ACODEC_IBIAS_DAC_SEL (0xf << ACODEC_IBIAS_DAC_SEL_SHIFT)
|
||||
|
||||
/* ACODEC_ANA08 */
|
||||
#define ACODEC_DAC_L_POP_CTRL_SHIFT 5
|
||||
#define ACODEC_DAC_L_POP_CTRL_MASK (0x3 << ACODEC_DAC_L_POP_CTRL_SHIFT)
|
||||
#define ACODEC_DAC_L_POP_CTRL_ON (0x1 << ACODEC_DAC_L_POP_CTRL_SHIFT)
|
||||
#define ACODEC_DAC_L_POP_CTRL_OFF (0x0 << ACODEC_DAC_L_POP_CTRL_SHIFT)
|
||||
#define ACODEC_DAC_L_INIT_MASK (0x1 << 4)
|
||||
#define ACODEC_DAC_L_WORK (0x1 << 4)
|
||||
#define ACODEC_DAC_L_INIT (0x0 << 4)
|
||||
#define ACODEC_DAC_L_VREF_MASK (0x1 << 3)
|
||||
#define ACODEC_DAC_L_VREF_EN (0x1 << 3)
|
||||
#define ACODEC_DAC_L_VREF_DIS (0x0 << 3)
|
||||
#define ACODEC_DAC_L_BUF_MASK (0x1 << 2)
|
||||
#define ACODEC_DAC_L_BUF_EN (0x1 << 2)
|
||||
#define ACODEC_DAC_L_BUF_DIS (0x0 << 2)
|
||||
#define ACODEC_DAC_L_CLK_MASK (0x1 << 1)
|
||||
#define ACODEC_DAC_L_CLK_EN (0x1 << 1)
|
||||
#define ACODEC_DAC_L_CLK_DIS (0x0 << 1)
|
||||
#define ACODEC_DAC_L_MASK (0x1 << 0)
|
||||
#define ACODEC_DAC_L_EN (0x1 << 0)
|
||||
#define ACODEC_DAC_L_DIS (0x0 << 0)
|
||||
|
||||
/* ACODEC_ANA09 */
|
||||
#define ACODEC_LINEOUT_L_MUTE_MASK (0x1 << 5)
|
||||
#define ACODEC_LINEOUT_L_WORK (0x1 << 5)
|
||||
#define ACODEC_LINEOUT_L_MUTE (0x0 << 5)
|
||||
#define ACODEC_LINEOUT_L_INIT_MASK (0x1 << 4)
|
||||
#define ACODEC_LINEOUT_L_INIT_WORK (0x1 << 4)
|
||||
#define ACODEC_LINEOUT_L_INIT (0x0 << 4)
|
||||
#define ACODEC_LINEOUT_L_MASK (0x1 << 0)
|
||||
#define ACODEC_LINEOUT_L_EN (0x1 << 0)
|
||||
#define ACODEC_LINEOUT_L_DIS (0x0 << 0)
|
||||
|
||||
/* ACODEC_ANA0A */
|
||||
#define ACODEC_LINEOUT_L_SEL_SHIFT 0
|
||||
#define ACODEC_LINEOUT_L_SEL_MASK (0xf << ACODEC_LINEOUT_L_SEL_SHIFT)
|
||||
|
||||
/* ACODEC_ANA0B */
|
||||
#define ACODEC_LINEOUT_L_GAIN_SHIFT 0
|
||||
/* 1.5dB every step. 0: -39dB, 0x1f: 0dB */
|
||||
#define ACODEC_LINEOUT_L_GAIN_MASK (0x1f << ACODEC_LINEOUT_L_GAIN_SHIFT)
|
||||
|
||||
/* ACODEC_ANA0C */
|
||||
#define ACODEC_DAC_R_POP_CTRL_SHIFT 5
|
||||
#define ACODEC_DAC_R_POP_CTRL_MASK (0x3 << ACODEC_DAC_R_POP_CTRL_SHIFT)
|
||||
#define ACODEC_DAC_R_POP_CTRL_ON (0x1 << ACODEC_DAC_R_POP_CTRL_SHIFT)
|
||||
#define ACODEC_DAC_R_POP_CTRL_OFF (0x0 << ACODEC_DAC_R_POP_CTRL_SHIFT)
|
||||
#define ACODEC_DAC_R_INIT_MASK (0x1 << 4)
|
||||
#define ACODEC_DAC_R_WORK (0x1 << 4)
|
||||
#define ACODEC_DAC_R_INIT (0x0 << 4)
|
||||
#define ACODEC_DAC_R_VREF_MASK (0x1 << 3)
|
||||
#define ACODEC_DAC_R_VREF_EN (0x1 << 3)
|
||||
#define ACODEC_DAC_R_VREF_DIS (0x0 << 3)
|
||||
#define ACODEC_DAC_R_BUF_MASK (0x1 << 2)
|
||||
#define ACODEC_DAC_R_BUF_EN (0x1 << 2)
|
||||
#define ACODEC_DAC_R_BUF_DIS (0x0 << 2)
|
||||
#define ACODEC_DAC_R_CLK_MASK (0x1 << 1)
|
||||
#define ACODEC_DAC_R_CLK_EN (0x1 << 1)
|
||||
#define ACODEC_DAC_R_CLK_DIS (0x0 << 1)
|
||||
#define ACODEC_DAC_R_MASK (0x1 << 0)
|
||||
#define ACODEC_DAC_R_EN (0x1 << 0)
|
||||
#define ACODEC_DAC_R_DIS (0x0 << 0)
|
||||
|
||||
/* ACODEC_ANA0D */
|
||||
#define ACODEC_LINEOUT_R_MUTE_MASK (0x1 << 5)
|
||||
#define ACODEC_LINEOUT_R_WORK (0x1 << 5)
|
||||
#define ACODEC_LINEOUT_R_MUTE (0x0 << 5)
|
||||
#define ACODEC_LINEOUT_R_INIT_MASK (0x1 << 4)
|
||||
#define ACODEC_LINEOUT_R_INIT_WORK (0x1 << 4)
|
||||
#define ACODEC_LINEOUT_R_INIT (0x0 << 4)
|
||||
#define ACODEC_LINEOUT_R_MASK (0x1 << 0)
|
||||
#define ACODEC_LINEOUT_R_EN (0x1 << 0)
|
||||
#define ACODEC_LINEOUT_R_DIS (0x0 << 0)
|
||||
|
||||
/* ACODEC_ANA0E */
|
||||
#define ACODEC_LINEOUT_R_SEL_SHIFT 0
|
||||
#define ACODEC_LINEOUT_R_SEL_MASK (0xf << ACODEC_LINEOUT_L_SEL_SHIFT)
|
||||
|
||||
/* ACODEC_ANA0F */
|
||||
#define ACODEC_LINEOUT_R_GAIN_SHIFT 0
|
||||
/* 1.5dB every step. 0: -39dB, 0x1f: 0dB */
|
||||
#define ACODEC_LINEOUT_R_GAIN_MASK (0x1f << ACODEC_LINEOUT_L_GAIN_SHIFT)
|
||||
|
||||
#define ACODEC_DAC_LINEOUT_GAIN_MAX 0x1e
|
||||
#define ACODEC_DAC_LINEOUT_GAIN_MIN 0
|
||||
#define ACODEC_HIFI 0x0
|
||||
#define ACODEC_DAC_LINEOUT_GAIN_0DB 0x1a
|
||||
|
||||
#endif /* __RK3528_CODEC_H__ */
|
||||
Reference in New Issue
Block a user