Commit 096388b7 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'asoc/topic/rt5659', 'asoc/topic/rt5660',...

Merge remote-tracking branches 'asoc/topic/rt5659', 'asoc/topic/rt5660', 'asoc/topic/rt5677' and 'asoc/topic/samsung' into asoc-next
......@@ -12,6 +12,9 @@ Required properties:
Optional properties:
- clocks: The phandle of the master clock to the CODEC
- clock-names: Should be "mclk"
- realtek,in1-differential
- realtek,in3-differential
- realtek,in4-differential
......
RT5660 audio CODEC
This device supports I2C only.
Required properties:
- compatible : "realtek,rt5660".
- reg : The I2C address of the device.
Optional properties:
- clocks: The phandle of the master clock to the CODEC
- clock-names: Should be "mclk"
- realtek,in1-differential
- realtek,in3-differential
Boolean. Indicate MIC1/3 input are differential, rather than single-ended.
- realtek,poweroff-in-suspend
Boolean. If the codec will be powered off in suspend, the resume should be
added delay time for waiting codec power ready.
- realtek,dmic1-data-pin
0: dmic1 is not used
1: using GPIO2 pin as dmic1 data pin
2: using IN1P pin as dmic1 data pin
Pins on the device (for linking into audio routes) for RT5660:
* DMIC L1
* DMIC R1
* IN1P
* IN1N
* IN2P
* IN3P
* IN3N
* SPO
* LOUTL
* LOUTR
Example:
rt5660 {
compatible = "realtek,rt5660";
reg = <0x1c>;
};
RT5663/RT5668 audio CODEC
This device supports I2C only.
Required properties:
- compatible : One of "realtek,rt5663" or "realtek,rt5668".
- reg : The I2C address of the device.
- interrupts : The CODEC's interrupt output.
Optional properties:
Pins on the device (for linking into audio routes) for RT5663/RT5668:
* IN1P
* IN1N
* IN2P
* IN2N
* HPOL
* HPOR
Example:
codec: rt5663@12 {
compatible = "realtek,rt5663";
reg = <0x12>;
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
};
......@@ -497,9 +497,28 @@ static struct i2c_board_info mini2440_i2c_devs[] __initdata = {
},
};
static struct uda134x_platform_data s3c24xx_uda134x = {
.l3 = {
.gpio_clk = S3C2410_GPB(4),
.gpio_data = S3C2410_GPB(3),
.gpio_mode = S3C2410_GPB(2),
.use_gpios = 1,
.data_hold = 1,
.data_setup = 1,
.clock_high = 1,
.mode_hold = 1,
.mode = 1,
.mode_setup = 1,
},
.model = UDA134X_UDA1341,
};
static struct platform_device uda1340_codec = {
.name = "uda134x-codec",
.id = -1,
.dev = {
.platform_data = &s3c24xx_uda134x,
},
};
static struct platform_device *mini2440_devices[] __initdata = {
......
......@@ -2,9 +2,15 @@
#define _L3_H_ 1
struct l3_pins {
void (*setdat)(int);
void (*setclk)(int);
void (*setmode)(int);
void (*setdat)(struct l3_pins *, int);
void (*setclk)(struct l3_pins *, int);
void (*setmode)(struct l3_pins *, int);
int gpio_data;
int gpio_clk;
int gpio_mode;
int use_gpios;
int data_hold;
int data_setup;
int clock_high;
......@@ -13,6 +19,9 @@ struct l3_pins {
int mode_setup;
};
struct device;
int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len);
int l3_set_gpio_ops(struct device *dev, struct l3_pins *adap);
#endif
/*
* linux/sound/rt5660.h -- Platform data for RT5660
*
* Copyright 2016 Realtek Semiconductor Corp.
* Author: Oder Chiou <oder_chiou@realtek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __LINUX_SND_RT5660_H
#define __LINUX_SND_RT5660_H
enum rt5660_dmic1_data_pin {
RT5660_DMIC1_NULL,
RT5660_DMIC1_DATA_GPIO2,
RT5660_DMIC1_DATA_IN1P,
};
struct rt5660_platform_data {
/* IN1 & IN3 can optionally be differential */
bool in1_diff;
bool in3_diff;
bool use_ldo2;
bool poweroff_codec_in_suspend;
enum rt5660_dmic1_data_pin dmic1_data_pin;
};
#endif
......@@ -7,7 +7,6 @@ struct s3c24xx_uda134x_platform_data {
int l3_clk;
int l3_mode;
int l3_data;
void (*power) (int);
int model;
};
......
......@@ -113,6 +113,8 @@ config SND_SOC_ALL_CODECS
select SND_SOC_RT5645 if I2C
select SND_SOC_RT5651 if I2C
select SND_SOC_RT5659 if I2C
select SND_SOC_RT5660 if I2C
select SND_SOC_RT5663 if I2C
select SND_SOC_RT5670 if I2C
select SND_SOC_RT5677 if I2C && SPI_MASTER
select SND_SOC_SGTL5000 if I2C
......@@ -646,6 +648,8 @@ config SND_SOC_RL6231
default y if SND_SOC_RT5645=y
default y if SND_SOC_RT5651=y
default y if SND_SOC_RT5659=y
default y if SND_SOC_RT5660=y
default y if SND_SOC_RT5663=y
default y if SND_SOC_RT5670=y
default y if SND_SOC_RT5677=y
default m if SND_SOC_RT5514=m
......@@ -654,6 +658,8 @@ config SND_SOC_RL6231
default m if SND_SOC_RT5645=m
default m if SND_SOC_RT5651=m
default m if SND_SOC_RT5659=m
default m if SND_SOC_RT5660=m
default m if SND_SOC_RT5663=m
default m if SND_SOC_RT5670=m
default m if SND_SOC_RT5677=m
......@@ -666,6 +672,7 @@ config SND_SOC_RL6347A
config SND_SOC_RT286
tristate
select SND_SOC_RT5663
depends on I2C
config SND_SOC_RT298
......@@ -698,6 +705,12 @@ config SND_SOC_RT5651
config SND_SOC_RT5659
tristate
config SND_SOC_RT5660
tristate
config SND_SOC_RT5663
tristate
config SND_SOC_RT5670
tristate
......
......@@ -113,6 +113,8 @@ snd-soc-rt5640-objs := rt5640.o
snd-soc-rt5645-objs := rt5645.o
snd-soc-rt5651-objs := rt5651.o
snd-soc-rt5659-objs := rt5659.o
snd-soc-rt5660-objs := rt5660.o
snd-soc-rt5663-objs := rt5663.o
snd-soc-rt5670-objs := rt5670.o
snd-soc-rt5677-objs := rt5677.o
snd-soc-rt5677-spi-objs := rt5677-spi.o
......@@ -335,6 +337,8 @@ obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o
obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o
obj-$(CONFIG_SND_SOC_RT5659) += snd-soc-rt5659.o
obj-$(CONFIG_SND_SOC_RT5660) += snd-soc-rt5660.o
obj-$(CONFIG_SND_SOC_RT5663) += snd-soc-rt5663.o
obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o
obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o
obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o
......
......@@ -20,6 +20,8 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <sound/l3.h>
......@@ -32,11 +34,11 @@ static void sendbyte(struct l3_pins *adap, unsigned int byte)
int i;
for (i = 0; i < 8; i++) {
adap->setclk(0);
adap->setclk(adap, 0);
udelay(adap->data_hold);
adap->setdat(byte & 1);
adap->setdat(adap, byte & 1);
udelay(adap->data_setup);
adap->setclk(1);
adap->setclk(adap, 1);
udelay(adap->clock_high);
byte >>= 1;
}
......@@ -55,10 +57,10 @@ static void sendbytes(struct l3_pins *adap, const u8 *buf,
for (i = 0; i < len; i++) {
if (i) {
udelay(adap->mode_hold);
adap->setmode(0);
adap->setmode(adap, 0);
udelay(adap->mode);
}
adap->setmode(1);
adap->setmode(adap, 1);
udelay(adap->mode_setup);
sendbyte(adap, buf[i]);
}
......@@ -66,26 +68,71 @@ static void sendbytes(struct l3_pins *adap, const u8 *buf,
int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len)
{
adap->setclk(1);
adap->setdat(1);
adap->setmode(1);
adap->setclk(adap, 1);
adap->setdat(adap, 1);
adap->setmode(adap, 1);
udelay(adap->mode);
adap->setmode(0);
adap->setmode(adap, 0);
udelay(adap->mode_setup);
sendbyte(adap, addr);
udelay(adap->mode_hold);
sendbytes(adap, data, len);
adap->setclk(1);
adap->setdat(1);
adap->setmode(0);
adap->setclk(adap, 1);
adap->setdat(adap, 1);
adap->setmode(adap, 0);
return len;
}
EXPORT_SYMBOL_GPL(l3_write);
static void l3_set_clk(struct l3_pins *adap, int val)
{
gpio_set_value(adap->gpio_clk, val);
}
static void l3_set_data(struct l3_pins *adap, int val)
{
gpio_set_value(adap->gpio_data, val);
}
static void l3_set_mode(struct l3_pins *adap, int val)
{
gpio_set_value(adap->gpio_mode, val);
}
int l3_set_gpio_ops(struct device *dev, struct l3_pins *adap)
{
int ret;
if (!adap->use_gpios)
return -EINVAL;
ret = devm_gpio_request_one(dev, adap->gpio_data,
GPIOF_OUT_INIT_LOW, "l3_data");
if (ret < 0)
return ret;
adap->setdat = l3_set_data;
ret = devm_gpio_request_one(dev, adap->gpio_clk,
GPIOF_OUT_INIT_LOW, "l3_clk");
if (ret < 0)
return ret;
adap->setclk = l3_set_clk;
ret = devm_gpio_request_one(dev, adap->gpio_mode,
GPIOF_OUT_INIT_LOW, "l3_mode");
if (ret < 0)
return ret;
adap->setmode = l3_set_mode;
return 0;
}
EXPORT_SYMBOL_GPL(l3_set_gpio_ops);
MODULE_DESCRIPTION("L3 bit-banging driver");
MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");
MODULE_LICENSE("GPL");
......@@ -9,6 +9,7 @@
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
......@@ -3565,7 +3566,9 @@ static int rt5659_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
static int rt5659_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
int ret;
switch (level) {
case SND_SOC_BIAS_PREPARE:
......@@ -3582,6 +3585,17 @@ static int rt5659_set_bias_level(struct snd_soc_codec *codec,
RT5659_PWR_FV1 | RT5659_PWR_FV2);
break;
case SND_SOC_BIAS_STANDBY:
if (dapm->bias_level == SND_SOC_BIAS_OFF) {
ret = clk_prepare_enable(rt5659->mclk);
if (ret) {
dev_err(codec->dev,
"failed to enable MCLK: %d\n", ret);
return ret;
}
}
break;
case SND_SOC_BIAS_OFF:
regmap_update_bits(rt5659->regmap, RT5659_PWR_DIG_1,
RT5659_PWR_LDO, 0);
......@@ -3591,6 +3605,7 @@ static int rt5659_set_bias_level(struct snd_soc_codec *codec,
RT5659_PWR_MB | RT5659_PWR_VREF2);
regmap_update_bits(rt5659->regmap, RT5659_DIG_MISC,
RT5659_DIG_GATE_CTRL, 0);
clk_disable_unprepare(rt5659->mclk);
break;
default:
......@@ -4022,6 +4037,15 @@ static int rt5659_i2c_probe(struct i2c_client *i2c,
regmap_write(rt5659->regmap, RT5659_RESET, 0);
/* Check if MCLK provided */
rt5659->mclk = devm_clk_get(&i2c->dev, "mclk");
if (IS_ERR(rt5659->mclk)) {
if (PTR_ERR(rt5659->mclk) != -ENOENT)
return PTR_ERR(rt5659->mclk);
/* Otherwise mark the mclk pointer to NULL */
rt5659->mclk = NULL;
}
rt5659_calibrate(rt5659);
/* line in diff mode*/
......@@ -4165,6 +4189,9 @@ static int rt5659_i2c_probe(struct i2c_client *i2c,
if (ret)
dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
/* Enable IRQ output for GPIO1 pin any way */
regmap_update_bits(rt5659->regmap, RT5659_GPIO_CTRL_1,
RT5659_GP1_PIN_MASK, RT5659_GP1_PIN_IRQ);
}
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5659,
......
......@@ -180,9 +180,9 @@
#define RT5659_IRQ_CTRL_1 0x00b6
#define RT5659_IRQ_CTRL_2 0x00b7
#define RT5659_IRQ_CTRL_3 0x00b8
#define RT5659_IRQ_CTRL_4 0x00b9
#define RT5659_IRQ_CTRL_5 0x00ba
#define RT5659_IRQ_CTRL_6 0x00bb
#define RT5659_IRQ_CTRL_4 0x00ba
#define RT5659_IRQ_CTRL_5 0x00bb
#define RT5659_IRQ_CTRL_6 0x00bc
#define RT5659_INT_ST_1 0x00be
#define RT5659_INT_ST_2 0x00bf
#define RT5659_GPIO_CTRL_1 0x00c0
......@@ -1796,6 +1796,7 @@ struct rt5659_priv {
struct gpio_desc *gpiod_reset;
struct snd_soc_jack *hs_jack;
struct delayed_work jack_detect_work;
struct clk *mclk;
int sysclk;
int sysclk_src;
......
/*
* rt5660.c -- RT5660 ALSA SoC audio codec driver
*
* Copyright 2016 Realtek Semiconductor Corp.
* Author: Oder Chiou <oder_chiou@realtek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/acpi.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include "rl6231.h"
#include "rt5660.h"
#define RT5660_DEVICE_ID 0x6338
#define RT5660_PR_RANGE_BASE (0xff + 1)
#define RT5660_PR_SPACING 0x100
#define RT5660_PR_BASE (RT5660_PR_RANGE_BASE + (0 * RT5660_PR_SPACING))
static const struct regmap_range_cfg rt5660_ranges[] = {
{ .name = "PR", .range_min = RT5660_PR_BASE,
.range_max = RT5660_PR_BASE + 0xf3,
.selector_reg = RT5660_PRIV_INDEX,
.selector_mask = 0xff,
.selector_shift = 0x0,
.window_start = RT5660_PRIV_DATA,
.window_len = 0x1, },
};
static const struct reg_sequence rt5660_patch[] = {
{ RT5660_ALC_PGA_CTRL2, 0x44c3 },
{ RT5660_PR_BASE + 0x3d, 0x2600 },
};
static const struct reg_default rt5660_reg[] = {
{ 0x00, 0x0000 },
{ 0x01, 0xc800 },
{ 0x02, 0xc8c8 },
{ 0x0d, 0x1010 },
{ 0x0e, 0x1010 },
{ 0x19, 0xafaf },
{ 0x1c, 0x2f2f },
{ 0x1e, 0x0000 },
{ 0x27, 0x6060 },
{ 0x29, 0x8080 },
{ 0x2a, 0x4242 },
{ 0x2f, 0x0000 },
{ 0x3b, 0x0000 },
{ 0x3c, 0x007f },
{ 0x3d, 0x0000 },
{ 0x3e, 0x007f },
{ 0x45, 0xe000 },
{ 0x46, 0x003e },
{ 0x48, 0xf800 },
{ 0x4a, 0x0004 },
{ 0x4d, 0x0000 },
{ 0x4e, 0x0000 },
{ 0x4f, 0x01ff },
{ 0x50, 0x0000 },
{ 0x51, 0x0000 },
{ 0x52, 0x01ff },
{ 0x61, 0x0000 },
{ 0x62, 0x0000 },
{ 0x63, 0x00c0 },
{ 0x64, 0x0000 },
{ 0x65, 0x0000 },
{ 0x66, 0x0000 },
{ 0x70, 0x8000 },
{ 0x73, 0x7000 },
{ 0x74, 0x3c00 },
{ 0x75, 0x2800 },
{ 0x80, 0x0000 },
{ 0x81, 0x0000 },
{ 0x82, 0x0000 },
{ 0x8c, 0x0228 },
{ 0x8d, 0xa000 },
{ 0x8e, 0x0000 },
{ 0x92, 0x0000 },
{ 0x93, 0x3000 },
{ 0xa1, 0x0059 },
{ 0xa2, 0x0001 },
{ 0xa3, 0x5c80 },
{ 0xa4, 0x0146 },
{ 0xa5, 0x1f1f },
{ 0xa6, 0x78c6 },
{ 0xa7, 0xe5ec },
{ 0xa8, 0xba61 },
{ 0xa9, 0x3c78 },
{ 0xaa, 0x8ae2 },
{ 0xab, 0xe5ec },
{ 0xac, 0xc600 },
{ 0xad, 0xba61 },
{ 0xae, 0x17ed },
{ 0xb0, 0x2080 },
{ 0xb1, 0x0000 },
{ 0xb3, 0x001f },
{ 0xb4, 0x020c },
{ 0xb5, 0x1f00 },
{ 0xb6, 0x0000 },
{ 0xb7, 0x4000 },
{ 0xbb, 0x0000 },
{ 0xbd, 0x0000 },
{ 0xbe, 0x0000 },
{ 0xbf, 0x0100 },
{ 0xc0, 0x0000 },
{ 0xc2, 0x0000 },
{ 0xd3, 0xa220 },
{ 0xd9, 0x0809 },
{ 0xda, 0x0000 },
{ 0xe0, 0x8000 },
{ 0xe1, 0x0200 },
{ 0xe2, 0x8000 },
{ 0xe3, 0x0200 },
{ 0xe4, 0x0f20 },
{ 0xe5, 0x001f },
{ 0xe6, 0x020c },
{ 0xe7, 0x1f00 },
{ 0xe8, 0x0000 },
{ 0xe9, 0x4000 },
{ 0xea, 0x00a6 },
{ 0xeb, 0x04c3 },
{ 0xec, 0x27c8 },
{ 0xed, 0x7418 },
{ 0xee, 0xbf50 },
{ 0xef, 0x0045 },
{ 0xf0, 0x0007 },
{ 0xfa, 0x0000 },
{ 0xfd, 0x0000 },
{ 0xfe, 0x10ec },
{ 0xff, 0x6338 },
};
static bool rt5660_volatile_register(struct device *dev, unsigned int reg)
{
int i;
for (i = 0; i < ARRAY_SIZE(rt5660_ranges); i++)
if ((reg >= rt5660_ranges[i].window_start &&
reg <= rt5660_ranges[i].window_start +
rt5660_ranges[i].window_len) ||
(reg >= rt5660_ranges[i].range_min &&
reg <= rt5660_ranges[i].range_max))
return true;
switch (reg) {
case RT5660_RESET:
case RT5660_PRIV_DATA:
case RT5660_EQ_CTRL1:
case RT5660_IRQ_CTRL2:
case RT5660_INT_IRQ_ST:
case RT5660_VENDOR_ID:
case RT5660_VENDOR_ID1:
case RT5660_VENDOR_ID2:
return true;
default:
return false;
}
}
static bool rt5660_readable_register(struct device *dev, unsigned int reg)
{
int i;
for (i = 0; i < ARRAY_SIZE(rt5660_ranges); i++)
if ((reg >= rt5660_ranges[i].window_start &&
reg <= rt5660_ranges[i].window_start +
rt5660_ranges[i].window_len) ||
(reg >= rt5660_ranges[i].range_min &&
reg <= rt5660_ranges[i].range_max))
return true;
switch (reg) {
case RT5660_RESET:
case RT5660_SPK_VOL:
case RT5660_LOUT_VOL:
case RT5660_IN1_IN2:
case RT5660_IN3_IN4:
case RT5660_DAC1_DIG_VOL:
case RT5660_STO1_ADC_DIG_VOL:
case RT5660_ADC_BST_VOL1:
case RT5660_STO1_ADC_MIXER:
case RT5660_AD_DA_MIXER:
case RT5660_STO_DAC_MIXER:
case RT5660_DIG_INF1_DATA:
case RT5660_REC_L1_MIXER:
case RT5660_REC_L2_MIXER:
case RT5660_REC_R1_MIXER:
case RT5660_REC_R2_MIXER:
case RT5660_LOUT_MIXER:
case RT5660_SPK_MIXER:
case RT5660_SPO_MIXER:
case RT5660_SPO_CLSD_RATIO:
case RT5660_OUT_L_GAIN1:
case RT5660_OUT_L_GAIN2:
case RT5660_OUT_L1_MIXER:
case RT5660_OUT_R_GAIN1:
case RT5660_OUT_R_GAIN2:
case RT5660_OUT_R1_MIXER:
case RT5660_PWR_DIG1:
case RT5660_PWR_DIG2:
case RT5660_PWR_ANLG1:
case RT5660_PWR_ANLG2:
case RT5660_PWR_MIXER:
case RT5660_PWR_VOL:
case RT5660_PRIV_INDEX:
case RT5660_PRIV_DATA:
case RT5660_I2S1_SDP:
case RT5660_ADDA_CLK1:
case RT5660_ADDA_CLK2:
case RT5660_DMIC_CTRL1:
case RT5660_GLB_CLK:
case RT5660_PLL_CTRL1:
case RT5660_PLL_CTRL2:
case RT5660_CLSD_AMP_OC_CTRL:
case RT5660_CLSD_AMP_CTRL:
case RT5660_LOUT_AMP_CTRL:
case RT5660_SPK_AMP_SPKVDD:
case RT5660_MICBIAS:
case RT5660_CLSD_OUT_CTRL1:
case RT5660_CLSD_OUT_CTRL2:
case RT5660_DIPOLE_MIC_CTRL1:
case RT5660_DIPOLE_MIC_CTRL2:
case RT5660_DIPOLE_MIC_CTRL3:
case RT5660_DIPOLE_MIC_CTRL4:
case RT5660_DIPOLE_MIC_CTRL5:
case RT5660_DIPOLE_MIC_CTRL6:
case RT5660_DIPOLE_MIC_CTRL7:
case RT5660_DIPOLE_MIC_CTRL8:
case RT5660_DIPOLE_MIC_CTRL9:
case RT5660_DIPOLE_MIC_CTRL10:
case RT5660_DIPOLE_MIC_CTRL11:
case RT5660_DIPOLE_MIC_CTRL12:
case RT5660_EQ_CTRL1:
case RT5660_EQ_CTRL2:
case RT5660_DRC_AGC_CTRL1:
case RT5660_DRC_AGC_CTRL2:
case RT5660_DRC_AGC_CTRL3:
case RT5660_DRC_AGC_CTRL4:
case RT5660_DRC_AGC_CTRL5:
case RT5660_JD_CTRL:
case RT5660_IRQ_CTRL1:
case RT5660_IRQ_CTRL2:
case RT5660_INT_IRQ_ST:
case RT5660_GPIO_CTRL1:
case RT5660_GPIO_CTRL2:
case RT5660_WIND_FILTER_CTRL1:
case RT5660_SV_ZCD1:
case RT5660_SV_ZCD2:
case RT5660_DRC1_LM_CTRL1:
case RT5660_DRC1_LM_CTRL2:
case RT5660_DRC2_LM_CTRL1:
case RT5660_DRC2_LM_CTRL2:
case RT5660_MULTI_DRC_CTRL:
case RT5660_DRC2_CTRL1:
case RT5660_DRC2_CTRL2:
case RT5660_DRC2_CTRL3:
case RT5660_DRC2_CTRL4:
case RT5660_DRC2_CTRL5:
case RT5660_ALC_PGA_CTRL1:
case RT5660_ALC_PGA_CTRL2:
case RT5660_ALC_PGA_CTRL3:
case RT5660_ALC_PGA_CTRL4:
case RT5660_ALC_PGA_CTRL5:
case RT5660_ALC_PGA_CTRL6:
case RT5660_ALC_PGA_CTRL7:
case RT5660_GEN_CTRL1:
case RT5660_GEN_CTRL2:
case RT5660_GEN_CTRL3:
case RT5660_VENDOR_ID:
case RT5660_VENDOR_ID1:
case RT5660_VENDOR_ID2:
return true;
default:
return false;
}
}
static const DECLARE_TLV_DB_SCALE(rt5660_out_vol_tlv, -4650, 150, 0);
static const DECLARE_TLV_DB_SCALE(rt5660_dac_vol_tlv, -6525, 75, 0);
static const DECLARE_TLV_DB_SCALE(rt5660_adc_vol_tlv, -1725, 75, 0);
static const DECLARE_TLV_DB_SCALE(rt5660_adc_bst_tlv, 0, 1200, 0);
static const DECLARE_TLV_DB_SCALE(rt5660_bst_tlv, -1200, 75, 0);
static const struct snd_kcontrol_new rt5660_snd_controls[] = {
/* Speaker Output Volume */
SOC_SINGLE("Speaker Playback Switch", RT5660_SPK_VOL, RT5660_L_MUTE_SFT,
1, 1),
SOC_SINGLE_TLV("Speaker Playback Volume", RT5660_SPK_VOL,
RT5660_L_VOL_SFT, 39, 1, rt5660_out_vol_tlv),
/* OUTPUT Control */
SOC_DOUBLE("OUT Playback Switch", RT5660_LOUT_VOL, RT5660_L_MUTE_SFT,
RT5660_R_MUTE_SFT, 1, 1),
SOC_DOUBLE_TLV("OUT Playback Volume", RT5660_LOUT_VOL, RT5660_L_VOL_SFT,
RT5660_R_VOL_SFT, 39, 1, rt5660_out_vol_tlv),
/* DAC Digital Volume */
SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5660_DAC1_DIG_VOL,
RT5660_DAC_L1_VOL_SFT, RT5660_DAC_R1_VOL_SFT, 87, 0,
rt5660_dac_vol_tlv),
/* IN1/IN2/IN3 Control */
SOC_SINGLE_TLV("IN1 Boost Volume", RT5660_IN1_IN2, RT5660_BST_SFT1, 69,
0, rt5660_bst_tlv),
SOC_SINGLE_TLV("IN2 Boost Volume", RT5660_IN1_IN2, RT5660_BST_SFT2, 69,
0, rt5660_bst_tlv),
SOC_SINGLE_TLV("IN3 Boost Volume", RT5660_IN3_IN4, RT5660_BST_SFT3, 69,
0, rt5660_bst_tlv),
/* ADC Digital Volume Control */
SOC_DOUBLE("ADC Capture Switch", RT5660_STO1_ADC_DIG_VOL,
RT5660_L_MUTE_SFT, RT5660_R_MUTE_SFT, 1, 1),
SOC_DOUBLE_TLV("ADC Capture Volume", RT5660_STO1_ADC_DIG_VOL,
RT5660_ADC_L_VOL_SFT, RT5660_ADC_R_VOL_SFT, 63, 0,
rt5660_adc_vol_tlv),
/* ADC Boost Volume Control */
SOC_DOUBLE_TLV("STO1 ADC Boost Gain Volume", RT5660_ADC_BST_VOL1,
RT5660_STO1_ADC_L_BST_SFT, RT5660_STO1_ADC_R_BST_SFT, 3, 0,
rt5660_adc_bst_tlv),
};
/**
* rt5660_set_dmic_clk - Set parameter of dmic.
*
* @w: DAPM widget.
* @kcontrol: The kcontrol of this widget.
* @event: Event id.
*
*/
static int rt5660_set_dmic_clk(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 rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec);
int idx, rate;
rate = rt5660->sysclk / rl6231_get_pre_div(rt5660->regmap,
RT5660_ADDA_CLK1, RT5660_I2S_PD1_SFT);
idx = rl6231_calc_dmic_clk(rate);
if (idx < 0)
dev_err(codec->dev, "Failed to set DMIC clock\n");
else
snd_soc_update_bits(codec, RT5660_DMIC_CTRL1,
RT5660_DMIC_CLK_MASK, idx << RT5660_DMIC_CLK_SFT);
return idx;
}
static int rt5660_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
unsigned int val;
val = snd_soc_read(codec, RT5660_GLB_CLK);
val &= RT5660_SCLK_SRC_MASK;
if (val == RT5660_SCLK_SRC_PLL1)
return 1;
else
return 0;
}
/* Digital Mixer */
static const struct snd_kcontrol_new rt5660_sto1_adc_l_mix[] = {
SOC_DAPM_SINGLE("ADC1 Switch", RT5660_STO1_ADC_MIXER,
RT5660_M_ADC_L1_SFT, 1, 1),
SOC_DAPM_SINGLE("ADC2 Switch", RT5660_STO1_ADC_MIXER,
RT5660_M_ADC_L2_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5660_sto1_adc_r_mix[] = {
SOC_DAPM_SINGLE("ADC1 Switch", RT5660_STO1_ADC_MIXER,
RT5660_M_ADC_R1_SFT, 1, 1),
SOC_DAPM_SINGLE("ADC2 Switch", RT5660_STO1_ADC_MIXER,
RT5660_M_ADC_R2_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5660_dac_l_mix[] = {
SOC_DAPM_SINGLE("Stereo ADC Switch", RT5660_AD_DA_MIXER,
RT5660_M_ADCMIX_L_SFT, 1, 1),
SOC_DAPM_SINGLE("DAC1 Switch", RT5660_AD_DA_MIXER,
RT5660_M_DAC1_L_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5660_dac_r_mix[] = {
SOC_DAPM_SINGLE("Stereo ADC Switch", RT5660_AD_DA_MIXER,
RT5660_M_ADCMIX_R_SFT, 1, 1),
SOC_DAPM_SINGLE("DAC1 Switch", RT5660_AD_DA_MIXER,
RT5660_M_DAC1_R_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5660_sto_dac_l_mix[] = {
SOC_DAPM_SINGLE("DAC L1 Switch", RT5660_STO_DAC_MIXER,
RT5660_M_DAC_L1_SFT, 1, 1),
SOC_DAPM_SINGLE("DAC R1 Switch", RT5660_STO_DAC_MIXER,
RT5660_M_DAC_R1_STO_L_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5660_sto_dac_r_mix[] = {
SOC_DAPM_SINGLE("DAC R1 Switch", RT5660_STO_DAC_MIXER,
RT5660_M_DAC_R1_SFT, 1, 1),
SOC_DAPM_SINGLE("DAC L1 Switch", RT5660_STO_DAC_MIXER,
RT5660_M_DAC_L1_STO_R_SFT, 1, 1),
};
/* Analog Input Mixer */
static const struct snd_kcontrol_new rt5660_rec_l_mix[] = {
SOC_DAPM_SINGLE("BST3 Switch", RT5660_REC_L2_MIXER,
RT5660_M_BST3_RM_L_SFT, 1, 1),
SOC_DAPM_SINGLE("BST2 Switch", RT5660_REC_L2_MIXER,
RT5660_M_BST2_RM_L_SFT, 1, 1),
SOC_DAPM_SINGLE("BST1 Switch", RT5660_REC_L2_MIXER,
RT5660_M_BST1_RM_L_SFT, 1, 1),
SOC_DAPM_SINGLE("OUT MIXL Switch", RT5660_REC_L2_MIXER,
RT5660_M_OM_L_RM_L_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5660_rec_r_mix[] = {
SOC_DAPM_SINGLE("BST3 Switch", RT5660_REC_R2_MIXER,
RT5660_M_BST3_RM_R_SFT, 1, 1),
SOC_DAPM_SINGLE("BST2 Switch", RT5660_REC_R2_MIXER,
RT5660_M_BST2_RM_R_SFT, 1, 1),
SOC_DAPM_SINGLE("BST1 Switch", RT5660_REC_R2_MIXER,
RT5660_M_BST1_RM_R_SFT, 1, 1),
SOC_DAPM_SINGLE("OUT MIXR Switch", RT5660_REC_R2_MIXER,
RT5660_M_OM_R_RM_R_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5660_spk_mix[] = {
SOC_DAPM_SINGLE("BST3 Switch", RT5660_SPK_MIXER,
RT5660_M_BST3_SM_SFT, 1, 1),
SOC_DAPM_SINGLE("BST1 Switch", RT5660_SPK_MIXER,
RT5660_M_BST1_SM_SFT, 1, 1),
SOC_DAPM_SINGLE("DACL Switch", RT5660_SPK_MIXER,
RT5660_M_DACL_SM_SFT, 1, 1),
SOC_DAPM_SINGLE("DACR Switch", RT5660_SPK_MIXER,
RT5660_M_DACR_SM_SFT, 1, 1),
SOC_DAPM_SINGLE("OUTMIXL Switch", RT5660_SPK_MIXER,
RT5660_M_OM_L_SM_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5660_out_l_mix[] = {
SOC_DAPM_SINGLE("BST3 Switch", RT5660_OUT_L1_MIXER,
RT5660_M_BST3_OM_L_SFT, 1, 1),
SOC_DAPM_SINGLE("BST2 Switch", RT5660_OUT_L1_MIXER,
RT5660_M_BST2_OM_L_SFT, 1, 1),
SOC_DAPM_SINGLE("BST1 Switch", RT5660_OUT_L1_MIXER,
RT5660_M_BST1_OM_L_SFT, 1, 1),
SOC_DAPM_SINGLE("RECMIXL Switch", RT5660_OUT_L1_MIXER,
RT5660_M_RM_L_OM_L_SFT, 1, 1),
SOC_DAPM_SINGLE("DACR Switch", RT5660_OUT_L1_MIXER,
RT5660_M_DAC_R_OM_L_SFT, 1, 1),
SOC_DAPM_SINGLE("DACL Switch", RT5660_OUT_L1_MIXER,
RT5660_M_DAC_L_OM_L_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5660_out_r_mix[] = {
SOC_DAPM_SINGLE("BST2 Switch", RT5660_OUT_R1_MIXER,
RT5660_M_BST2_OM_R_SFT, 1, 1),
SOC_DAPM_SINGLE("BST1 Switch", RT5660_OUT_R1_MIXER,
RT5660_M_BST1_OM_R_SFT, 1, 1),
SOC_DAPM_SINGLE("RECMIXR Switch", RT5660_OUT_R1_MIXER,
RT5660_M_RM_R_OM_R_SFT, 1, 1),
SOC_DAPM_SINGLE("DACR Switch", RT5660_OUT_R1_MIXER,
RT5660_M_DAC_R_OM_R_SFT, 1, 1),
SOC_DAPM_SINGLE("DACL Switch", RT5660_OUT_R1_MIXER,
RT5660_M_DAC_L_OM_R_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5660_spo_mix[] = {
SOC_DAPM_SINGLE("DACR Switch", RT5660_SPO_MIXER,
RT5660_M_DAC_R_SPM_SFT, 1, 1),
SOC_DAPM_SINGLE("DACL Switch", RT5660_SPO_MIXER,
RT5660_M_DAC_L_SPM_SFT, 1, 1),
SOC_DAPM_SINGLE("SPKVOL Switch", RT5660_SPO_MIXER,
RT5660_M_SV_SPM_SFT, 1, 1),
SOC_DAPM_SINGLE("BST1 Switch", RT5660_SPO_MIXER,
RT5660_M_BST1_SPM_SFT, 1, 1),
};
static const struct snd_kcontrol_new rt5660_lout_mix[] = {
SOC_DAPM_SINGLE("DAC Switch", RT5660_LOUT_MIXER,
RT5660_M_DAC1_LM_SFT, 1, 1),
SOC_DAPM_SINGLE("OUTMIX Switch", RT5660_LOUT_MIXER,
RT5660_M_LOVOL_LM_SFT, 1, 1),
};
static const struct snd_kcontrol_new spk_vol_control =
SOC_DAPM_SINGLE("Switch", RT5660_SPK_VOL,
RT5660_VOL_L_SFT, 1, 1);
static const struct snd_kcontrol_new lout_l_vol_control =
SOC_DAPM_SINGLE("Switch", RT5660_LOUT_VOL,
RT5660_VOL_L_SFT, 1, 1);
static const struct snd_kcontrol_new lout_r_vol_control =
SOC_DAPM_SINGLE("Switch", RT5660_LOUT_VOL,
RT5660_VOL_R_SFT, 1, 1);
/* Interface data select */
static const char * const rt5660_data_select[] = {
"L/R", "R/L", "L/L", "R/R"
};
static const SOC_ENUM_SINGLE_DECL(rt5660_if1_dac_enum,
RT5660_DIG_INF1_DATA, RT5660_IF1_DAC_IN_SFT, rt5660_data_select);
static const SOC_ENUM_SINGLE_DECL(rt5660_if1_adc_enum,
RT5660_DIG_INF1_DATA, RT5660_IF1_ADC_IN_SFT, rt5660_data_select);
static const struct snd_kcontrol_new rt5660_if1_dac_swap_mux =
SOC_DAPM_ENUM("IF1 DAC Swap Source", rt5660_if1_dac_enum);
static const struct snd_kcontrol_new rt5660_if1_adc_swap_mux =
SOC_DAPM_ENUM("IF1 ADC Swap Source", rt5660_if1_adc_enum);
static int rt5660_lout_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);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
snd_soc_update_bits(codec, RT5660_LOUT_AMP_CTRL,
RT5660_LOUT_CO_MASK | RT5660_LOUT_CB_MASK,
RT5660_LOUT_CO_EN | RT5660_LOUT_CB_PU);
break;
case SND_SOC_DAPM_PRE_PMD:
snd_soc_update_bits(codec, RT5660_LOUT_AMP_CTRL,
RT5660_LOUT_CO_MASK | RT5660_LOUT_CB_MASK,
RT5660_LOUT_CO_DIS | RT5660_LOUT_CB_PD);
break;
default:
return 0;
}
return 0;
}
static const struct snd_soc_dapm_widget rt5660_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("LDO2", RT5660_PWR_ANLG1,
RT5660_PWR_LDO2_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("PLL1", RT5660_PWR_ANLG2,
RT5660_PWR_PLL_BIT, 0, NULL, 0),
/* MICBIAS */
SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5660_PWR_ANLG2,
RT5660_PWR_MB1_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS2", RT5660_PWR_ANLG2,
RT5660_PWR_MB2_BIT, 0, NULL, 0),
/* Input Side */
/* Input Lines */
SND_SOC_DAPM_INPUT("DMIC L1"),
SND_SOC_DAPM_INPUT("DMIC R1"),
SND_SOC_DAPM_INPUT("IN1P"),
SND_SOC_DAPM_INPUT("IN1N"),
SND_SOC_DAPM_INPUT("IN2P"),
SND_SOC_DAPM_INPUT("IN3P"),
SND_SOC_DAPM_INPUT("IN3N"),
SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0,
rt5660_set_dmic_clk, SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_SUPPLY("DMIC Power", RT5660_DMIC_CTRL1,
RT5660_DMIC_1_EN_SFT, 0, NULL, 0),
/* Boost */
SND_SOC_DAPM_PGA("BST1", RT5660_PWR_ANLG2, RT5660_PWR_BST1_BIT, 0,
NULL, 0),
SND_SOC_DAPM_PGA("BST2", RT5660_PWR_ANLG2, RT5660_PWR_BST2_BIT, 0,
NULL, 0),
SND_SOC_DAPM_PGA("BST3", RT5660_PWR_ANLG2, RT5660_PWR_BST3_BIT, 0,
NULL, 0),
/* REC Mixer */
SND_SOC_DAPM_MIXER("RECMIXL", RT5660_PWR_MIXER, RT5660_PWR_RM_L_BIT,
0, rt5660_rec_l_mix, ARRAY_SIZE(rt5660_rec_l_mix)),
SND_SOC_DAPM_MIXER("RECMIXR", RT5660_PWR_MIXER, RT5660_PWR_RM_R_BIT,
0, rt5660_rec_r_mix, ARRAY_SIZE(rt5660_rec_r_mix)),
/* ADCs */
SND_SOC_DAPM_ADC("ADC L", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_ADC("ADC R", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_SUPPLY("ADC L power", RT5660_PWR_DIG1,
RT5660_PWR_ADC_L_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC R power", RT5660_PWR_DIG1,
RT5660_PWR_ADC_R_BIT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC clock", RT5660_PR_BASE + RT5660_CHOP_DAC_ADC,
12, 0, NULL, 0),
/* ADC Mixer */
SND_SOC_DAPM_SUPPLY("adc stereo1 filter", RT5660_PWR_DIG2,
RT5660_PWR_ADC_S1F_BIT, 0, NULL, 0),
SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0,
rt5660_sto1_adc_l_mix, ARRAY_SIZE(rt5660_sto1_adc_l_mix)),
SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0,
rt5660_sto1_adc_r_mix, ARRAY_SIZE(rt5660_sto1_adc_r_mix)),
/* ADC */
SND_SOC_DAPM_ADC("Stereo1 ADC MIXL", NULL, RT5660_STO1_ADC_DIG_VOL,
RT5660_L_MUTE_SFT, 1),
SND_SOC_DAPM_ADC("Stereo1 ADC MIXR", NULL, RT5660_STO1_ADC_DIG_VOL,
RT5660_R_MUTE_SFT, 1),
/* Digital Interface */
SND_SOC_DAPM_SUPPLY("I2S1", RT5660_PWR_DIG1, RT5660_PWR_I2S1_BIT, 0,
NULL, 0),
SND_SOC_DAPM_PGA("IF1 DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF1 DAC L", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF1 DAC R", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MUX("IF1 DAC Swap Mux", SND_SOC_NOPM, 0, 0,
&rt5660_if1_dac_swap_mux),
SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MUX("IF1 ADC Swap Mux", SND_SOC_NOPM, 0, 0,
&rt5660_if1_adc_swap_mux),
/* Audio Interface */
SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
/* Output Side */
/* DAC mixer before sound effect */
SND_SOC_DAPM_MIXER("DAC1 MIXL", SND_SOC_NOPM, 0, 0, rt5660_dac_l_mix,
ARRAY_SIZE(rt5660_dac_l_mix)),
SND_SOC_DAPM_MIXER("DAC1 MIXR", SND_SOC_NOPM, 0, 0, rt5660_dac_r_mix,
ARRAY_SIZE(rt5660_dac_r_mix)),
/* DAC Mixer */
SND_SOC_DAPM_SUPPLY("dac stereo1 filter", RT5660_PWR_DIG2,
RT5660_PWR_DAC_S1F_BIT, 0, NULL, 0),
SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
rt5660_sto_dac_l_mix, ARRAY_SIZE(rt5660_sto_dac_l_mix)),
SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0,
rt5660_sto_dac_r_mix, ARRAY_SIZE(rt5660_sto_dac_r_mix)),
/* DACs */
SND_SOC_DAPM_DAC("DAC L1", NULL, RT5660_PWR_DIG1,
RT5660_PWR_DAC_L1_BIT, 0),
SND_SOC_DAPM_DAC("DAC R1", NULL, RT5660_PWR_DIG1,
RT5660_PWR_DAC_R1_BIT, 0),
/* OUT Mixer */
SND_SOC_DAPM_MIXER("SPK MIX", RT5660_PWR_MIXER, RT5660_PWR_SM_BIT,
0, rt5660_spk_mix, ARRAY_SIZE(rt5660_spk_mix)),
SND_SOC_DAPM_MIXER("OUT MIXL", RT5660_PWR_MIXER, RT5660_PWR_OM_L_BIT,
0, rt5660_out_l_mix, ARRAY_SIZE(rt5660_out_l_mix)),
SND_SOC_DAPM_MIXER("OUT MIXR", RT5660_PWR_MIXER, RT5660_PWR_OM_R_BIT,
0, rt5660_out_r_mix, ARRAY_SIZE(rt5660_out_r_mix)),
/* Output Volume */
SND_SOC_DAPM_SWITCH("SPKVOL", RT5660_PWR_VOL,
RT5660_PWR_SV_BIT, 0, &spk_vol_control),
SND_SOC_DAPM_PGA("DAC 1", SND_SOC_NOPM,
0, 0, NULL, 0),
SND_SOC_DAPM_PGA("LOUTVOL", SND_SOC_NOPM,
0, 0, NULL, 0),
SND_SOC_DAPM_SWITCH("LOUTVOL L", SND_SOC_NOPM,
RT5660_PWR_LV_L_BIT, 0, &lout_l_vol_control),
SND_SOC_DAPM_SWITCH("LOUTVOL R", SND_SOC_NOPM,
RT5660_PWR_LV_R_BIT, 0, &lout_r_vol_control),
/* HPO/LOUT/Mono Mixer */
SND_SOC_DAPM_MIXER("SPO MIX", SND_SOC_NOPM, 0,
0, rt5660_spo_mix, ARRAY_SIZE(rt5660_spo_mix)),
SND_SOC_DAPM_MIXER("LOUT MIX", SND_SOC_NOPM, 0, 0,
rt5660_lout_mix, ARRAY_SIZE(rt5660_lout_mix)),
SND_SOC_DAPM_SUPPLY("VREF HP", RT5660_GEN_CTRL1,
RT5660_PWR_VREF_HP_SFT, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("LOUT amp", 1, RT5660_PWR_ANLG1,
RT5660_PWR_HA_BIT, 0, rt5660_lout_event,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_S("SPK amp", 1, RT5660_PWR_DIG1,
RT5660_PWR_CLS_D_BIT, 0, NULL, 0),
/* Output Lines */
SND_SOC_DAPM_OUTPUT("LOUTL"),
SND_SOC_DAPM_OUTPUT("LOUTR"),
SND_SOC_DAPM_OUTPUT("SPO"),
};
static const struct snd_soc_dapm_route rt5660_dapm_routes[] = {
{ "MICBIAS1", NULL, "LDO2" },
{ "MICBIAS2", NULL, "LDO2" },
{ "BST1", NULL, "IN1P" },
{ "BST1", NULL, "IN1N" },
{ "BST2", NULL, "IN2P" },
{ "BST3", NULL, "IN3P" },
{ "BST3", NULL, "IN3N" },
{ "RECMIXL", "BST3 Switch", "BST3" },
{ "RECMIXL", "BST2 Switch", "BST2" },
{ "RECMIXL", "BST1 Switch", "BST1" },
{ "RECMIXL", "OUT MIXL Switch", "OUT MIXL" },
{ "RECMIXR", "BST3 Switch", "BST3" },
{ "RECMIXR", "BST2 Switch", "BST2" },
{ "RECMIXR", "BST1 Switch", "BST1" },
{ "RECMIXR", "OUT MIXR Switch", "OUT MIXR" },
{ "ADC L", NULL, "RECMIXL" },
{ "ADC L", NULL, "ADC L power" },
{ "ADC L", NULL, "ADC clock" },
{ "ADC R", NULL, "RECMIXR" },
{ "ADC R", NULL, "ADC R power" },
{ "ADC R", NULL, "ADC clock" },
{"DMIC L1", NULL, "DMIC CLK"},
{"DMIC L1", NULL, "DMIC Power"},
{"DMIC R1", NULL, "DMIC CLK"},
{"DMIC R1", NULL, "DMIC Power"},
{ "Sto1 ADC MIXL", "ADC1 Switch", "ADC L" },
{ "Sto1 ADC MIXL", "ADC2 Switch", "DMIC L1" },
{ "Sto1 ADC MIXR", "ADC1 Switch", "ADC R" },
{ "Sto1 ADC MIXR", "ADC2 Switch", "DMIC R1" },
{ "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" },
{ "Stereo1 ADC MIXL", NULL, "adc stereo1 filter" },
{ "adc stereo1 filter", NULL, "PLL1", rt5660_is_sys_clk_from_pll },
{ "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" },
{ "Stereo1 ADC MIXR", NULL, "adc stereo1 filter" },
{ "adc stereo1 filter", NULL, "PLL1", rt5660_is_sys_clk_from_pll },
{ "IF1 ADC", NULL, "Stereo1 ADC MIXL" },
{ "IF1 ADC", NULL, "Stereo1 ADC MIXR" },
{ "IF1 ADC", NULL, "I2S1" },
{ "IF1 ADC Swap Mux", "L/R", "IF1 ADC" },
{ "IF1 ADC Swap Mux", "R/L", "IF1 ADC" },
{ "IF1 ADC Swap Mux", "L/L", "IF1 ADC" },
{ "IF1 ADC Swap Mux", "R/R", "IF1 ADC" },
{ "AIF1TX", NULL, "IF1 ADC Swap Mux" },
{ "IF1 DAC", NULL, "AIF1RX" },
{ "IF1 DAC", NULL, "I2S1" },
{ "IF1 DAC Swap Mux", "L/R", "IF1 DAC" },
{ "IF1 DAC Swap Mux", "R/L", "IF1 DAC" },
{ "IF1 DAC Swap Mux", "L/L", "IF1 DAC" },
{ "IF1 DAC Swap Mux", "R/R", "IF1 DAC" },
{ "IF1 DAC L", NULL, "IF1 DAC Swap Mux" },
{ "IF1 DAC R", NULL, "IF1 DAC Swap Mux" },
{ "DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL" },
{ "DAC1 MIXL", "DAC1 Switch", "IF1 DAC L" },
{ "DAC1 MIXR", "Stereo ADC Switch", "Stereo1 ADC MIXR" },
{ "DAC1 MIXR", "DAC1 Switch", "IF1 DAC R" },
{ "Stereo DAC MIXL", "DAC L1 Switch", "DAC1 MIXL" },
{ "Stereo DAC MIXL", "DAC R1 Switch", "DAC1 MIXR" },
{ "Stereo DAC MIXL", NULL, "dac stereo1 filter" },
{ "dac stereo1 filter", NULL, "PLL1", rt5660_is_sys_clk_from_pll },
{ "Stereo DAC MIXR", "DAC R1 Switch", "DAC1 MIXR" },
{ "Stereo DAC MIXR", "DAC L1 Switch", "DAC1 MIXL" },
{ "Stereo DAC MIXR", NULL, "dac stereo1 filter" },
{ "dac stereo1 filter", NULL, "PLL1", rt5660_is_sys_clk_from_pll },
{ "DAC L1", NULL, "Stereo DAC MIXL" },
{ "DAC R1", NULL, "Stereo DAC MIXR" },
{ "SPK MIX", "BST3 Switch", "BST3" },
{ "SPK MIX", "BST1 Switch", "BST1" },
{ "SPK MIX", "DACL Switch", "DAC L1" },
{ "SPK MIX", "DACR Switch", "DAC R1" },
{ "SPK MIX", "OUTMIXL Switch", "OUT MIXL" },
{ "OUT MIXL", "BST3 Switch", "BST3" },
{ "OUT MIXL", "BST2 Switch", "BST2" },
{ "OUT MIXL", "BST1 Switch", "BST1" },
{ "OUT MIXL", "RECMIXL Switch", "RECMIXL" },
{ "OUT MIXL", "DACR Switch", "DAC R1" },
{ "OUT MIXL", "DACL Switch", "DAC L1" },
{ "OUT MIXR", "BST2 Switch", "BST2" },
{ "OUT MIXR", "BST1 Switch", "BST1" },
{ "OUT MIXR", "RECMIXR Switch", "RECMIXR" },
{ "OUT MIXR", "DACR Switch", "DAC R1" },
{ "OUT MIXR", "DACL Switch", "DAC L1" },
{ "SPO MIX", "DACR Switch", "DAC R1" },
{ "SPO MIX", "DACL Switch", "DAC L1" },
{ "SPO MIX", "SPKVOL Switch", "SPKVOL" },
{ "SPO MIX", "BST1 Switch", "BST1" },
{ "SPKVOL", "Switch", "SPK MIX" },
{ "LOUTVOL L", "Switch", "OUT MIXL" },
{ "LOUTVOL R", "Switch", "OUT MIXR" },
{ "LOUTVOL", NULL, "LOUTVOL L" },
{ "LOUTVOL", NULL, "LOUTVOL R" },
{ "DAC 1", NULL, "DAC L1" },
{ "DAC 1", NULL, "DAC R1" },
{ "LOUT MIX", "DAC Switch", "DAC 1" },
{ "LOUT MIX", "OUTMIX Switch", "LOUTVOL" },
{ "LOUT amp", NULL, "LOUT MIX" },
{ "LOUT amp", NULL, "VREF HP" },
{ "LOUTL", NULL, "LOUT amp" },
{ "LOUTR", NULL, "LOUT amp" },
{ "SPK amp", NULL, "SPO MIX" },
{ "SPO", NULL, "SPK amp" },
};
static int rt5660_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec);
unsigned int val_len = 0, val_clk, mask_clk;
int pre_div, bclk_ms, frame_size;
rt5660->lrck[dai->id] = params_rate(params);
pre_div = rl6231_get_clk_info(rt5660->sysclk, rt5660->lrck[dai->id]);
if (pre_div < 0) {
dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n",
rt5660->lrck[dai->id], dai->id);
return -EINVAL;
}
frame_size = snd_soc_params_to_frame_size(params);
if (frame_size < 0) {
dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size);
return frame_size;
}
if (frame_size > 32)
bclk_ms = 1;
else
bclk_ms = 0;
rt5660->bclk[dai->id] = rt5660->lrck[dai->id] * (32 << bclk_ms);
dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n",
rt5660->bclk[dai->id], rt5660->lrck[dai->id]);
dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n",
bclk_ms, pre_div, dai->id);
switch (params_width(params)) {
case 16:
break;
case 20:
val_len |= RT5660_I2S_DL_20;
break;
case 24:
val_len |= RT5660_I2S_DL_24;
break;
case 8:
val_len |= RT5660_I2S_DL_8;
break;
default:
return -EINVAL;
}
switch (dai->id) {
case RT5660_AIF1:
mask_clk = RT5660_I2S_BCLK_MS1_MASK | RT5660_I2S_PD1_MASK;
val_clk = bclk_ms << RT5660_I2S_BCLK_MS1_SFT |
pre_div << RT5660_I2S_PD1_SFT;
snd_soc_update_bits(codec, RT5660_I2S1_SDP, RT5660_I2S_DL_MASK,
val_len);
snd_soc_update_bits(codec, RT5660_ADDA_CLK1, mask_clk, val_clk);
break;
default:
dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id);
return -EINVAL;
}
return 0;
}
static int rt5660_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_codec *codec = dai->codec;
struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec);
unsigned int reg_val = 0;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
rt5660->master[dai->id] = 1;
break;
case SND_SOC_DAIFMT_CBS_CFS:
reg_val |= RT5660_I2S_MS_S;
rt5660->master[dai->id] = 0;
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
case SND_SOC_DAIFMT_IB_NF:
reg_val |= RT5660_I2S_BP_INV;
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
break;
case SND_SOC_DAIFMT_LEFT_J:
reg_val |= RT5660_I2S_DF_LEFT;
break;
case SND_SOC_DAIFMT_DSP_A:
reg_val |= RT5660_I2S_DF_PCM_A;
break;
case SND_SOC_DAIFMT_DSP_B:
reg_val |= RT5660_I2S_DF_PCM_B;
break;
default:
return -EINVAL;
}
switch (dai->id) {
case RT5660_AIF1:
snd_soc_update_bits(codec, RT5660_I2S1_SDP,
RT5660_I2S_MS_MASK | RT5660_I2S_BP_MASK |
RT5660_I2S_DF_MASK, reg_val);
break;
default:
dev_err(codec->dev, "Invalid dai->id: %d\n", dai->id);
return -EINVAL;
}
return 0;
}
static int rt5660_set_dai_sysclk(struct snd_soc_dai *dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = dai->codec;
struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec);
unsigned int reg_val = 0;
if (freq == rt5660->sysclk && clk_id == rt5660->sysclk_src)
return 0;
switch (clk_id) {
case RT5660_SCLK_S_MCLK:
reg_val |= RT5660_SCLK_SRC_MCLK;
break;
case RT5660_SCLK_S_PLL1:
reg_val |= RT5660_SCLK_SRC_PLL1;
break;
case RT5660_SCLK_S_RCCLK:
reg_val |= RT5660_SCLK_SRC_RCCLK;
break;
default:
dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
return -EINVAL;
}
snd_soc_update_bits(codec, RT5660_GLB_CLK, RT5660_SCLK_SRC_MASK,
reg_val);
rt5660->sysclk = freq;
rt5660->sysclk_src = clk_id;
dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id);
return 0;
}
static int rt5660_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
unsigned int freq_in, unsigned int freq_out)
{
struct snd_soc_codec *codec = dai->codec;
struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec);
struct rl6231_pll_code pll_code;
int ret;
if (source == rt5660->pll_src && freq_in == rt5660->pll_in &&
freq_out == rt5660->pll_out)
return 0;
if (!freq_in || !freq_out) {
dev_dbg(codec->dev, "PLL disabled\n");
rt5660->pll_in = 0;
rt5660->pll_out = 0;
snd_soc_update_bits(codec, RT5660_GLB_CLK,
RT5660_SCLK_SRC_MASK, RT5660_SCLK_SRC_MCLK);
return 0;
}
switch (source) {
case RT5660_PLL1_S_MCLK:
snd_soc_update_bits(codec, RT5660_GLB_CLK,
RT5660_PLL1_SRC_MASK, RT5660_PLL1_SRC_MCLK);
break;
case RT5660_PLL1_S_BCLK:
snd_soc_update_bits(codec, RT5660_GLB_CLK,
RT5660_PLL1_SRC_MASK, RT5660_PLL1_SRC_BCLK1);
break;
default:
dev_err(codec->dev, "Unknown PLL source %d\n", source);
return -EINVAL;
}
ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
if (ret < 0) {
dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
return ret;
}
dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n",
pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
pll_code.n_code, pll_code.k_code);
snd_soc_write(codec, RT5660_PLL_CTRL1,
pll_code.n_code << RT5660_PLL_N_SFT | pll_code.k_code);
snd_soc_write(codec, RT5660_PLL_CTRL2,
(pll_code.m_bp ? 0 : pll_code.m_code) << RT5660_PLL_M_SFT |
pll_code.m_bp << RT5660_PLL_M_BP_SFT);
rt5660->pll_in = freq_in;
rt5660->pll_out = freq_out;
rt5660->pll_src = source;
return 0;
}
static int rt5660_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec);
int ret;
switch (level) {
case SND_SOC_BIAS_ON:
break;
case SND_SOC_BIAS_PREPARE:
snd_soc_update_bits(codec, RT5660_GEN_CTRL1,
RT5660_DIG_GATE_CTRL, RT5660_DIG_GATE_CTRL);
if (IS_ERR(rt5660->mclk))
break;
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) {
clk_disable_unprepare(rt5660->mclk);
} else {
ret = clk_prepare_enable(rt5660->mclk);
if (ret)
return ret;
}
break;
case SND_SOC_BIAS_STANDBY:
if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
snd_soc_update_bits(codec, RT5660_PWR_ANLG1,
RT5660_PWR_VREF1 | RT5660_PWR_MB |
RT5660_PWR_BG | RT5660_PWR_VREF2,
RT5660_PWR_VREF1 | RT5660_PWR_MB |
RT5660_PWR_BG | RT5660_PWR_VREF2);
usleep_range(10000, 15000);
snd_soc_update_bits(codec, RT5660_PWR_ANLG1,
RT5660_PWR_FV1 | RT5660_PWR_FV2,
RT5660_PWR_FV1 | RT5660_PWR_FV2);
}
break;
case SND_SOC_BIAS_OFF:
snd_soc_update_bits(codec, RT5660_GEN_CTRL1,
RT5660_DIG_GATE_CTRL, 0);
break;
default:
break;
}
return 0;
}
static int rt5660_probe(struct snd_soc_codec *codec)
{
struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec);
rt5660->codec = codec;
return 0;
}
static int rt5660_remove(struct snd_soc_codec *codec)
{
return snd_soc_write(codec, RT5660_RESET, 0);
}
#ifdef CONFIG_PM
static int rt5660_suspend(struct snd_soc_codec *codec)
{
struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec);
regcache_cache_only(rt5660->regmap, true);
regcache_mark_dirty(rt5660->regmap);
return 0;
}
static int rt5660_resume(struct snd_soc_codec *codec)
{
struct rt5660_priv *rt5660 = snd_soc_codec_get_drvdata(codec);
if (rt5660->pdata.poweroff_codec_in_suspend)
usleep_range(350000, 400000);
regcache_cache_only(rt5660->regmap, false);
regcache_sync(rt5660->regmap);
return 0;
}
#else
#define rt5660_suspend NULL
#define rt5660_resume NULL
#endif
#define RT5660_STEREO_RATES SNDRV_PCM_RATE_8000_192000
#define RT5660_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
static const struct snd_soc_dai_ops rt5660_aif_dai_ops = {
.hw_params = rt5660_hw_params,
.set_fmt = rt5660_set_dai_fmt,
.set_sysclk = rt5660_set_dai_sysclk,
.set_pll = rt5660_set_dai_pll,
};
static struct snd_soc_dai_driver rt5660_dai[] = {
{
.name = "rt5660-aif1",
.id = RT5660_AIF1,
.playback = {
.stream_name = "AIF1 Playback",
.channels_min = 1,
.channels_max = 2,
.rates = RT5660_STEREO_RATES,
.formats = RT5660_FORMATS,
},
.capture = {
.stream_name = "AIF1 Capture",
.channels_min = 1,
.channels_max = 2,
.rates = RT5660_STEREO_RATES,
.formats = RT5660_FORMATS,
},
.ops = &rt5660_aif_dai_ops,
},
};
static struct snd_soc_codec_driver soc_codec_dev_rt5660 = {
.probe = rt5660_probe,
.remove = rt5660_remove,
.suspend = rt5660_suspend,
.resume = rt5660_resume,
.set_bias_level = rt5660_set_bias_level,
.idle_bias_off = true,
.component_driver = {
.controls = rt5660_snd_controls,
.num_controls = ARRAY_SIZE(rt5660_snd_controls),
.dapm_widgets = rt5660_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(rt5660_dapm_widgets),
.dapm_routes = rt5660_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(rt5660_dapm_routes),
},
};
static const struct regmap_config rt5660_regmap = {
.reg_bits = 8,
.val_bits = 16,
.use_single_rw = true,
.max_register = RT5660_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5660_ranges) *
RT5660_PR_SPACING),
.volatile_reg = rt5660_volatile_register,
.readable_reg = rt5660_readable_register,
.cache_type = REGCACHE_RBTREE,
.reg_defaults = rt5660_reg,
.num_reg_defaults = ARRAY_SIZE(rt5660_reg),
.ranges = rt5660_ranges,
.num_ranges = ARRAY_SIZE(rt5660_ranges),
};
static const struct i2c_device_id rt5660_i2c_id[] = {
{ "rt5660", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5660_i2c_id);
static const struct of_device_id rt5660_of_match[] = {
{ .compatible = "realtek,rt5660", },
{},
};
MODULE_DEVICE_TABLE(of, rt5660_of_match);
static const struct acpi_device_id rt5660_acpi_match[] = {
{ "10EC5660", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, rt5660_acpi_match);
static int rt5660_parse_dt(struct rt5660_priv *rt5660, struct device *dev)
{
rt5660->pdata.in1_diff = device_property_read_bool(dev,
"realtek,in1-differential");
rt5660->pdata.in3_diff = device_property_read_bool(dev,
"realtek,in3-differential");
rt5660->pdata.poweroff_codec_in_suspend = device_property_read_bool(dev,
"realtek,poweroff-in-suspend");
device_property_read_u32(dev, "realtek,dmic1-data-pin",
&rt5660->pdata.dmic1_data_pin);
return 0;
}
static int rt5660_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct rt5660_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct rt5660_priv *rt5660;
int ret;
unsigned int val;
rt5660 = devm_kzalloc(&i2c->dev, sizeof(struct rt5660_priv),
GFP_KERNEL);
if (rt5660 == NULL)
return -ENOMEM;
/* Check if MCLK provided */
rt5660->mclk = devm_clk_get(&i2c->dev, "mclk");
if (PTR_ERR(rt5660->mclk) == -EPROBE_DEFER)
return -EPROBE_DEFER;
i2c_set_clientdata(i2c, rt5660);
if (pdata)
rt5660->pdata = *pdata;
else if (i2c->dev.of_node)
rt5660_parse_dt(rt5660, &i2c->dev);
rt5660->regmap = devm_regmap_init_i2c(i2c, &rt5660_regmap);
if (IS_ERR(rt5660->regmap)) {
ret = PTR_ERR(rt5660->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
return ret;
}
regmap_read(rt5660->regmap, RT5660_VENDOR_ID2, &val);
if (val != RT5660_DEVICE_ID) {
dev_err(&i2c->dev,
"Device with ID register %#x is not rt5660\n", val);
return -ENODEV;
}
regmap_write(rt5660->regmap, RT5660_RESET, 0);
ret = regmap_register_patch(rt5660->regmap, rt5660_patch,
ARRAY_SIZE(rt5660_patch));
if (ret != 0)
dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret);
if (rt5660->pdata.dmic1_data_pin) {
regmap_update_bits(rt5660->regmap, RT5660_GPIO_CTRL1,
RT5660_GP1_PIN_MASK, RT5660_GP1_PIN_DMIC1_SCL);
if (rt5660->pdata.dmic1_data_pin == RT5660_DMIC1_DATA_GPIO2)
regmap_update_bits(rt5660->regmap, RT5660_DMIC_CTRL1,
RT5660_SEL_DMIC_DATA_MASK,
RT5660_SEL_DMIC_DATA_GPIO2);
else if (rt5660->pdata.dmic1_data_pin == RT5660_DMIC1_DATA_IN1P)
regmap_update_bits(rt5660->regmap, RT5660_DMIC_CTRL1,
RT5660_SEL_DMIC_DATA_MASK,
RT5660_SEL_DMIC_DATA_IN1P);
}
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5660,
rt5660_dai, ARRAY_SIZE(rt5660_dai));
}
static int rt5660_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
return 0;
}
static struct i2c_driver rt5660_i2c_driver = {
.driver = {
.name = "rt5660",
.acpi_match_table = ACPI_PTR(rt5660_acpi_match),
.of_match_table = of_match_ptr(rt5660_of_match),
},
.probe = rt5660_i2c_probe,
.remove = rt5660_i2c_remove,
.id_table = rt5660_i2c_id,
};
module_i2c_driver(rt5660_i2c_driver);
MODULE_DESCRIPTION("ASoC RT5660 driver");
MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
MODULE_LICENSE("GPL v2");
/*
* rt5660.h -- RT5660 ALSA SoC audio driver
*
* Copyright 2016 Realtek Semiconductor Corp.
* Author: Oder Chiou <oder_chiou@realtek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _RT5660_H
#define _RT5660_H
#include <linux/clk.h>
#include <sound/rt5660.h>
/* Info */
#define RT5660_RESET 0x00
#define RT5660_VENDOR_ID 0xfd
#define RT5660_VENDOR_ID1 0xfe
#define RT5660_VENDOR_ID2 0xff
/* I/O - Output */
#define RT5660_SPK_VOL 0x01
#define RT5660_LOUT_VOL 0x02
/* I/O - Input */
#define RT5660_IN1_IN2 0x0d
#define RT5660_IN3_IN4 0x0e
/* I/O - ADC/DAC/DMIC */
#define RT5660_DAC1_DIG_VOL 0x19
#define RT5660_STO1_ADC_DIG_VOL 0x1c
#define RT5660_ADC_BST_VOL1 0x1e
/* Mixer - D-D */
#define RT5660_STO1_ADC_MIXER 0x27
#define RT5660_AD_DA_MIXER 0x29
#define RT5660_STO_DAC_MIXER 0x2a
#define RT5660_DIG_INF1_DATA 0x2f
/* Mixer - ADC */
#define RT5660_REC_L1_MIXER 0x3b
#define RT5660_REC_L2_MIXER 0x3c
#define RT5660_REC_R1_MIXER 0x3d
#define RT5660_REC_R2_MIXER 0x3e
/* Mixer - DAC */
#define RT5660_LOUT_MIXER 0x45
#define RT5660_SPK_MIXER 0x46
#define RT5660_SPO_MIXER 0x48
#define RT5660_SPO_CLSD_RATIO 0x4a
#define RT5660_OUT_L_GAIN1 0x4d
#define RT5660_OUT_L_GAIN2 0x4e
#define RT5660_OUT_L1_MIXER 0x4f
#define RT5660_OUT_R_GAIN1 0x50
#define RT5660_OUT_R_GAIN2 0x51
#define RT5660_OUT_R1_MIXER 0x52
/* Power */
#define RT5660_PWR_DIG1 0x61
#define RT5660_PWR_DIG2 0x62
#define RT5660_PWR_ANLG1 0x63
#define RT5660_PWR_ANLG2 0x64
#define RT5660_PWR_MIXER 0x65
#define RT5660_PWR_VOL 0x66
/* Private Register Control */
#define RT5660_PRIV_INDEX 0x6a
#define RT5660_PRIV_DATA 0x6c
/* Format - ADC/DAC */
#define RT5660_I2S1_SDP 0x70
#define RT5660_ADDA_CLK1 0x73
#define RT5660_ADDA_CLK2 0x74
#define RT5660_DMIC_CTRL1 0x75
/* Function - Analog */
#define RT5660_GLB_CLK 0x80
#define RT5660_PLL_CTRL1 0x81
#define RT5660_PLL_CTRL2 0x82
#define RT5660_CLSD_AMP_OC_CTRL 0x8c
#define RT5660_CLSD_AMP_CTRL 0x8d
#define RT5660_LOUT_AMP_CTRL 0x8e
#define RT5660_SPK_AMP_SPKVDD 0x92
#define RT5660_MICBIAS 0x93
#define RT5660_CLSD_OUT_CTRL1 0xa1
#define RT5660_CLSD_OUT_CTRL2 0xa2
#define RT5660_DIPOLE_MIC_CTRL1 0xa3
#define RT5660_DIPOLE_MIC_CTRL2 0xa4
#define RT5660_DIPOLE_MIC_CTRL3 0xa5
#define RT5660_DIPOLE_MIC_CTRL4 0xa6
#define RT5660_DIPOLE_MIC_CTRL5 0xa7
#define RT5660_DIPOLE_MIC_CTRL6 0xa8
#define RT5660_DIPOLE_MIC_CTRL7 0xa9
#define RT5660_DIPOLE_MIC_CTRL8 0xaa
#define RT5660_DIPOLE_MIC_CTRL9 0xab
#define RT5660_DIPOLE_MIC_CTRL10 0xac
#define RT5660_DIPOLE_MIC_CTRL11 0xad
#define RT5660_DIPOLE_MIC_CTRL12 0xae
/* Function - Digital */
#define RT5660_EQ_CTRL1 0xb0
#define RT5660_EQ_CTRL2 0xb1
#define RT5660_DRC_AGC_CTRL1 0xb3
#define RT5660_DRC_AGC_CTRL2 0xb4
#define RT5660_DRC_AGC_CTRL3 0xb5
#define RT5660_DRC_AGC_CTRL4 0xb6
#define RT5660_DRC_AGC_CTRL5 0xb7
#define RT5660_JD_CTRL 0xbb
#define RT5660_IRQ_CTRL1 0xbd
#define RT5660_IRQ_CTRL2 0xbe
#define RT5660_INT_IRQ_ST 0xbf
#define RT5660_GPIO_CTRL1 0xc0
#define RT5660_GPIO_CTRL2 0xc2
#define RT5660_WIND_FILTER_CTRL1 0xd3
#define RT5660_SV_ZCD1 0xd9
#define RT5660_SV_ZCD2 0xda
#define RT5660_DRC1_LM_CTRL1 0xe0
#define RT5660_DRC1_LM_CTRL2 0xe1
#define RT5660_DRC2_LM_CTRL1 0xe2
#define RT5660_DRC2_LM_CTRL2 0xe3
#define RT5660_MULTI_DRC_CTRL 0xe4
#define RT5660_DRC2_CTRL1 0xe5
#define RT5660_DRC2_CTRL2 0xe6
#define RT5660_DRC2_CTRL3 0xe7
#define RT5660_DRC2_CTRL4 0xe8
#define RT5660_DRC2_CTRL5 0xe9
#define RT5660_ALC_PGA_CTRL1 0xea
#define RT5660_ALC_PGA_CTRL2 0xeb
#define RT5660_ALC_PGA_CTRL3 0xec
#define RT5660_ALC_PGA_CTRL4 0xed
#define RT5660_ALC_PGA_CTRL5 0xee
#define RT5660_ALC_PGA_CTRL6 0xef
#define RT5660_ALC_PGA_CTRL7 0xf0
/* General Control */
#define RT5660_GEN_CTRL1 0xfa
#define RT5660_GEN_CTRL2 0xfb
#define RT5660_GEN_CTRL3 0xfc
/* Index of Codec Private Register definition */
#define RT5660_CHOP_DAC_ADC 0x3d
/* Global Definition */
#define RT5660_L_MUTE (0x1 << 15)
#define RT5660_L_MUTE_SFT 15
#define RT5660_VOL_L_MUTE (0x1 << 14)
#define RT5660_VOL_L_SFT 14
#define RT5660_R_MUTE (0x1 << 7)
#define RT5660_R_MUTE_SFT 7
#define RT5660_VOL_R_MUTE (0x1 << 6)
#define RT5660_VOL_R_SFT 6
#define RT5660_L_VOL_MASK (0x3f << 8)
#define RT5660_L_VOL_SFT 8
#define RT5660_R_VOL_MASK (0x3f)
#define RT5660_R_VOL_SFT 0
/* IN1 and IN2 Control (0x0d) */
#define RT5660_IN_DF1 (0x1 << 15)
#define RT5660_IN_SFT1 15
#define RT5660_BST_MASK1 (0x7f << 8)
#define RT5660_BST_SFT1 8
#define RT5660_IN_DF2 (0x1 << 7)
#define RT5660_IN_SFT2 7
#define RT5660_BST_MASK2 (0x7f << 0)
#define RT5660_BST_SFT2 0
/* IN3 and IN4 Control (0x0e) */
#define RT5660_IN_DF3 (0x1 << 15)
#define RT5660_IN_SFT3 15
#define RT5660_BST_MASK3 (0x7f << 8)
#define RT5660_BST_SFT3 8
#define RT5660_IN_DF4 (0x1 << 7)
#define RT5660_IN_SFT4 7
#define RT5660_BST_MASK4 (0x7f << 0)
#define RT5660_BST_SFT4 0
/* DAC1 Digital Volume (0x19) */
#define RT5660_DAC_L1_VOL_MASK (0x7f << 9)
#define RT5660_DAC_L1_VOL_SFT 9
#define RT5660_DAC_R1_VOL_MASK (0x7f << 1)
#define RT5660_DAC_R1_VOL_SFT 1
/* ADC Digital Volume Control (0x1c) */
#define RT5660_ADC_L_VOL_MASK (0x3f << 9)
#define RT5660_ADC_L_VOL_SFT 9
#define RT5660_ADC_R_VOL_MASK (0x3f << 1)
#define RT5660_ADC_R_VOL_SFT 1
/* ADC Boost Volume Control (0x1e) */
#define RT5660_STO1_ADC_L_BST_MASK (0x3 << 14)
#define RT5660_STO1_ADC_L_BST_SFT 14
#define RT5660_STO1_ADC_R_BST_MASK (0x3 << 12)
#define RT5660_STO1_ADC_R_BST_SFT 12
/* Stereo ADC Mixer Control (0x27) */
#define RT5660_M_ADC_L1 (0x1 << 14)
#define RT5660_M_ADC_L1_SFT 14
#define RT5660_M_ADC_L2 (0x1 << 13)
#define RT5660_M_ADC_L2_SFT 13
#define RT5660_M_ADC_R1 (0x1 << 6)
#define RT5660_M_ADC_R1_SFT 6
#define RT5660_M_ADC_R2 (0x1 << 5)
#define RT5660_M_ADC_R2_SFT 5
/* ADC Mixer to DAC Mixer Control (0x29) */
#define RT5660_M_ADCMIX_L (0x1 << 15)
#define RT5660_M_ADCMIX_L_SFT 15
#define RT5660_M_DAC1_L (0x1 << 14)
#define RT5660_M_DAC1_L_SFT 14
#define RT5660_M_ADCMIX_R (0x1 << 7)
#define RT5660_M_ADCMIX_R_SFT 7
#define RT5660_M_DAC1_R (0x1 << 6)
#define RT5660_M_DAC1_R_SFT 6
/* Stereo DAC Mixer Control (0x2a) */
#define RT5660_M_DAC_L1 (0x1 << 14)
#define RT5660_M_DAC_L1_SFT 14
#define RT5660_DAC_L1_STO_L_VOL_MASK (0x1 << 13)
#define RT5660_DAC_L1_STO_L_VOL_SFT 13
#define RT5660_M_DAC_R1_STO_L (0x1 << 9)
#define RT5660_M_DAC_R1_STO_L_SFT 9
#define RT5660_DAC_R1_STO_L_VOL_MASK (0x1 << 8)
#define RT5660_DAC_R1_STO_L_VOL_SFT 8
#define RT5660_M_DAC_R1 (0x1 << 6)
#define RT5660_M_DAC_R1_SFT 6
#define RT5660_DAC_R1_STO_R_VOL_MASK (0x1 << 5)
#define RT5660_DAC_R1_STO_R_VOL_SFT 5
#define RT5660_M_DAC_L1_STO_R (0x1 << 1)
#define RT5660_M_DAC_L1_STO_R_SFT 1
#define RT5660_DAC_L1_STO_R_VOL_MASK (0x1)
#define RT5660_DAC_L1_STO_R_VOL_SFT 0
/* Digital Interface Data Control (0x2f) */
#define RT5660_IF1_DAC_IN_SEL (0x3 << 14)
#define RT5660_IF1_DAC_IN_SFT 14
#define RT5660_IF1_ADC_IN_SEL (0x3 << 12)
#define RT5660_IF1_ADC_IN_SFT 12
/* REC Left Mixer Control 1 (0x3b) */
#define RT5660_G_BST3_RM_L_MASK (0x7 << 4)
#define RT5660_G_BST3_RM_L_SFT 4
#define RT5660_G_BST2_RM_L_MASK (0x7 << 1)
#define RT5660_G_BST2_RM_L_SFT 1
/* REC Left Mixer Control 2 (0x3c) */
#define RT5660_G_BST1_RM_L_MASK (0x7 << 13)
#define RT5660_G_BST1_RM_L_SFT 13
#define RT5660_G_OM_L_RM_L_MASK (0x7 << 10)
#define RT5660_G_OM_L_RM_L_SFT 10
#define RT5660_M_BST3_RM_L (0x1 << 3)
#define RT5660_M_BST3_RM_L_SFT 3
#define RT5660_M_BST2_RM_L (0x1 << 2)
#define RT5660_M_BST2_RM_L_SFT 2
#define RT5660_M_BST1_RM_L (0x1 << 1)
#define RT5660_M_BST1_RM_L_SFT 1
#define RT5660_M_OM_L_RM_L (0x1)
#define RT5660_M_OM_L_RM_L_SFT 0
/* REC Right Mixer Control 1 (0x3d) */
#define RT5660_G_BST3_RM_R_MASK (0x7 << 4)
#define RT5660_G_BST3_RM_R_SFT 4
#define RT5660_G_BST2_RM_R_MASK (0x7 << 1)
#define RT5660_G_BST2_RM_R_SFT 1
/* REC Right Mixer Control 2 (0x3e) */
#define RT5660_G_BST1_RM_R_MASK (0x7 << 13)
#define RT5660_G_BST1_RM_R_SFT 13
#define RT5660_G_OM_R_RM_R_MASK (0x7 << 10)
#define RT5660_G_OM_R_RM_R_SFT 10
#define RT5660_M_BST3_RM_R (0x1 << 3)
#define RT5660_M_BST3_RM_R_SFT 3
#define RT5660_M_BST2_RM_R (0x1 << 2)
#define RT5660_M_BST2_RM_R_SFT 2
#define RT5660_M_BST1_RM_R (0x1 << 1)
#define RT5660_M_BST1_RM_R_SFT 1
#define RT5660_M_OM_R_RM_R (0x1)
#define RT5660_M_OM_R_RM_R_SFT 0
/* LOUTMIX Control (0x45) */
#define RT5660_M_DAC1_LM (0x1 << 14)
#define RT5660_M_DAC1_LM_SFT 14
#define RT5660_M_LOVOL_M (0x1 << 13)
#define RT5660_M_LOVOL_LM_SFT 13
/* SPK Mixer Control (0x46) */
#define RT5660_G_BST3_SM_MASK (0x3 << 14)
#define RT5660_G_BST3_SM_SFT 14
#define RT5660_G_BST1_SM_MASK (0x3 << 12)
#define RT5660_G_BST1_SM_SFT 12
#define RT5660_G_DACl_SM_MASK (0x3 << 10)
#define RT5660_G_DACl_SM_SFT 10
#define RT5660_G_DACR_SM_MASK (0x3 << 8)
#define RT5660_G_DACR_SM_SFT 8
#define RT5660_G_OM_L_SM_MASK (0x3 << 6)
#define RT5660_G_OM_L_SM_SFT 6
#define RT5660_M_DACR_SM (0x1 << 5)
#define RT5660_M_DACR_SM_SFT 5
#define RT5660_M_BST1_SM (0x1 << 4)
#define RT5660_M_BST1_SM_SFT 4
#define RT5660_M_BST3_SM (0x1 << 3)
#define RT5660_M_BST3_SM_SFT 3
#define RT5660_M_DACL_SM (0x1 << 2)
#define RT5660_M_DACL_SM_SFT 2
#define RT5660_M_OM_L_SM (0x1 << 1)
#define RT5660_M_OM_L_SM_SFT 1
/* SPOMIX Control (0x48) */
#define RT5660_M_DAC_R_SPM (0x1 << 14)
#define RT5660_M_DAC_R_SPM_SFT 14
#define RT5660_M_DAC_L_SPM (0x1 << 13)
#define RT5660_M_DAC_L_SPM_SFT 13
#define RT5660_M_SV_SPM (0x1 << 12)
#define RT5660_M_SV_SPM_SFT 12
#define RT5660_M_BST1_SPM (0x1 << 11)
#define RT5660_M_BST1_SPM_SFT 11
/* Output Left Mixer Control 1 (0x4d) */
#define RT5660_G_BST3_OM_L_MASK (0x7 << 13)
#define RT5660_G_BST3_OM_L_SFT 13
#define RT5660_G_BST2_OM_L_MASK (0x7 << 10)
#define RT5660_G_BST2_OM_L_SFT 10
#define RT5660_G_BST1_OM_L_MASK (0x7 << 7)
#define RT5660_G_BST1_OM_L_SFT 7
#define RT5660_G_RM_L_OM_L_MASK (0x7 << 1)
#define RT5660_G_RM_L_OM_L_SFT 1
/* Output Left Mixer Control 2 (0x4e) */
#define RT5660_G_DAC_R1_OM_L_MASK (0x7 << 10)
#define RT5660_G_DAC_R1_OM_L_SFT 10
#define RT5660_G_DAC_L1_OM_L_MASK (0x7 << 7)
#define RT5660_G_DAC_L1_OM_L_SFT 7
/* Output Left Mixer Control 3 (0x4f) */
#define RT5660_M_BST3_OM_L (0x1 << 5)
#define RT5660_M_BST3_OM_L_SFT 5
#define RT5660_M_BST2_OM_L (0x1 << 4)
#define RT5660_M_BST2_OM_L_SFT 4
#define RT5660_M_BST1_OM_L (0x1 << 3)
#define RT5660_M_BST1_OM_L_SFT 3
#define RT5660_M_RM_L_OM_L (0x1 << 2)
#define RT5660_M_RM_L_OM_L_SFT 2
#define RT5660_M_DAC_R_OM_L (0x1 << 1)
#define RT5660_M_DAC_R_OM_L_SFT 1
#define RT5660_M_DAC_L_OM_L (0x1)
#define RT5660_M_DAC_L_OM_L_SFT 0
/* Output Right Mixer Control 1 (0x50) */
#define RT5660_G_BST2_OM_R_MASK (0x7 << 10)
#define RT5660_G_BST2_OM_R_SFT 10
#define RT5660_G_BST1_OM_R_MASK (0x7 << 7)
#define RT5660_G_BST1_OM_R_SFT 7
#define RT5660_G_RM_R_OM_R_MASK (0x7 << 1)
#define RT5660_G_RM_R_OM_R_SFT 1
/* Output Right Mixer Control 2 (0x51) */
#define RT5660_G_DAC_L_OM_R_MASK (0x7 << 10)
#define RT5660_G_DAC_L_OM_R_SFT 10
#define RT5660_G_DAC_R_OM_R_MASK (0x7 << 7)
#define RT5660_G_DAC_R_OM_R_SFT 7
/* Output Right Mixer Control 3 (0x52) */
#define RT5660_M_BST2_OM_R (0x1 << 4)
#define RT5660_M_BST2_OM_R_SFT 4
#define RT5660_M_BST1_OM_R (0x1 << 3)
#define RT5660_M_BST1_OM_R_SFT 3
#define RT5660_M_RM_R_OM_R (0x1 << 2)
#define RT5660_M_RM_R_OM_R_SFT 2
#define RT5660_M_DAC_L_OM_R (0x1 << 1)
#define RT5660_M_DAC_L_OM_R_SFT 1
#define RT5660_M_DAC_R_OM_R (0x1)
#define RT5660_M_DAC_R_OM_R_SFT 0
/* Power Management for Digital 1 (0x61) */
#define RT5660_PWR_I2S1 (0x1 << 15)
#define RT5660_PWR_I2S1_BIT 15
#define RT5660_PWR_DAC_L1 (0x1 << 12)
#define RT5660_PWR_DAC_L1_BIT 12
#define RT5660_PWR_DAC_R1 (0x1 << 11)
#define RT5660_PWR_DAC_R1_BIT 11
#define RT5660_PWR_ADC_L (0x1 << 2)
#define RT5660_PWR_ADC_L_BIT 2
#define RT5660_PWR_ADC_R (0x1 << 1)
#define RT5660_PWR_ADC_R_BIT 1
#define RT5660_PWR_CLS_D (0x1)
#define RT5660_PWR_CLS_D_BIT 0
/* Power Management for Digital 2 (0x62) */
#define RT5660_PWR_ADC_S1F (0x1 << 15)
#define RT5660_PWR_ADC_S1F_BIT 15
#define RT5660_PWR_DAC_S1F (0x1 << 11)
#define RT5660_PWR_DAC_S1F_BIT 11
/* Power Management for Analog 1 (0x63) */
#define RT5660_PWR_VREF1 (0x1 << 15)
#define RT5660_PWR_VREF1_BIT 15
#define RT5660_PWR_FV1 (0x1 << 14)
#define RT5660_PWR_FV1_BIT 14
#define RT5660_PWR_MB (0x1 << 13)
#define RT5660_PWR_MB_BIT 13
#define RT5660_PWR_BG (0x1 << 11)
#define RT5660_PWR_BG_BIT 11
#define RT5660_PWR_HP_L (0x1 << 7)
#define RT5660_PWR_HP_L_BIT 7
#define RT5660_PWR_HP_R (0x1 << 6)
#define RT5660_PWR_HP_R_BIT 6
#define RT5660_PWR_HA (0x1 << 5)
#define RT5660_PWR_HA_BIT 5
#define RT5660_PWR_VREF2 (0x1 << 4)
#define RT5660_PWR_VREF2_BIT 4
#define RT5660_PWR_FV2 (0x1 << 3)
#define RT5660_PWR_FV2_BIT 3
#define RT5660_PWR_LDO2 (0x1 << 2)
#define RT5660_PWR_LDO2_BIT 2
/* Power Management for Analog 2 (0x64) */
#define RT5660_PWR_BST1 (0x1 << 15)
#define RT5660_PWR_BST1_BIT 15
#define RT5660_PWR_BST2 (0x1 << 14)
#define RT5660_PWR_BST2_BIT 14
#define RT5660_PWR_BST3 (0x1 << 13)
#define RT5660_PWR_BST3_BIT 13
#define RT5660_PWR_MB1 (0x1 << 11)
#define RT5660_PWR_MB1_BIT 11
#define RT5660_PWR_MB2 (0x1 << 10)
#define RT5660_PWR_MB2_BIT 10
#define RT5660_PWR_PLL (0x1 << 9)
#define RT5660_PWR_PLL_BIT 9
/* Power Management for Mixer (0x65) */
#define RT5660_PWR_OM_L (0x1 << 15)
#define RT5660_PWR_OM_L_BIT 15
#define RT5660_PWR_OM_R (0x1 << 14)
#define RT5660_PWR_OM_R_BIT 14
#define RT5660_PWR_SM (0x1 << 13)
#define RT5660_PWR_SM_BIT 13
#define RT5660_PWR_RM_L (0x1 << 11)
#define RT5660_PWR_RM_L_BIT 11
#define RT5660_PWR_RM_R (0x1 << 10)
#define RT5660_PWR_RM_R_BIT 10
/* Power Management for Volume (0x66) */
#define RT5660_PWR_SV (0x1 << 15)
#define RT5660_PWR_SV_BIT 15
#define RT5660_PWR_LV_L (0x1 << 11)
#define RT5660_PWR_LV_L_BIT 11
#define RT5660_PWR_LV_R (0x1 << 10)
#define RT5660_PWR_LV_R_BIT 10
/* I2S1 Audio Serial Data Port Control (0x70) */
#define RT5660_I2S_MS_MASK (0x1 << 15)
#define RT5660_I2S_MS_SFT 15
#define RT5660_I2S_MS_M (0x0 << 15)
#define RT5660_I2S_MS_S (0x1 << 15)
#define RT5660_I2S_O_CP_MASK (0x3 << 10)
#define RT5660_I2S_O_CP_SFT 10
#define RT5660_I2S_O_CP_OFF (0x0 << 10)
#define RT5660_I2S_O_CP_U_LAW (0x1 << 10)
#define RT5660_I2S_O_CP_A_LAW (0x2 << 10)
#define RT5660_I2S_I_CP_MASK (0x3 << 8)
#define RT5660_I2S_I_CP_SFT 8
#define RT5660_I2S_I_CP_OFF (0x0 << 8)
#define RT5660_I2S_I_CP_U_LAW (0x1 << 8)
#define RT5660_I2S_I_CP_A_LAW (0x2 << 8)
#define RT5660_I2S_BP_MASK (0x1 << 7)
#define RT5660_I2S_BP_SFT 7
#define RT5660_I2S_BP_NOR (0x0 << 7)
#define RT5660_I2S_BP_INV (0x1 << 7)
#define RT5660_I2S_DL_MASK (0x3 << 2)
#define RT5660_I2S_DL_SFT 2
#define RT5660_I2S_DL_16 (0x0 << 2)
#define RT5660_I2S_DL_20 (0x1 << 2)
#define RT5660_I2S_DL_24 (0x2 << 2)
#define RT5660_I2S_DL_8 (0x3 << 2)
#define RT5660_I2S_DF_MASK (0x3)
#define RT5660_I2S_DF_SFT 0
#define RT5660_I2S_DF_I2S (0x0)
#define RT5660_I2S_DF_LEFT (0x1)
#define RT5660_I2S_DF_PCM_A (0x2)
#define RT5660_I2S_DF_PCM_B (0x3)
/* ADC/DAC Clock Control 1 (0x73) */
#define RT5660_I2S_BCLK_MS1_MASK (0x1 << 15)
#define RT5660_I2S_BCLK_MS1_SFT 15
#define RT5660_I2S_BCLK_MS1_32 (0x0 << 15)
#define RT5660_I2S_BCLK_MS1_64 (0x1 << 15)
#define RT5660_I2S_PD1_MASK (0x7 << 12)
#define RT5660_I2S_PD1_SFT 12
#define RT5660_I2S_PD1_1 (0x0 << 12)
#define RT5660_I2S_PD1_2 (0x1 << 12)
#define RT5660_I2S_PD1_3 (0x2 << 12)
#define RT5660_I2S_PD1_4 (0x3 << 12)
#define RT5660_I2S_PD1_6 (0x4 << 12)
#define RT5660_I2S_PD1_8 (0x5 << 12)
#define RT5660_I2S_PD1_12 (0x6 << 12)
#define RT5660_I2S_PD1_16 (0x7 << 12)
#define RT5660_DAC_OSR_MASK (0x3 << 2)
#define RT5660_DAC_OSR_SFT 2
#define RT5660_DAC_OSR_128 (0x0 << 2)
#define RT5660_DAC_OSR_64 (0x1 << 2)
#define RT5660_DAC_OSR_32 (0x2 << 2)
#define RT5660_DAC_OSR_16 (0x3 << 2)
#define RT5660_ADC_OSR_MASK (0x3)
#define RT5660_ADC_OSR_SFT 0
#define RT5660_ADC_OSR_128 (0x0)
#define RT5660_ADC_OSR_64 (0x1)
#define RT5660_ADC_OSR_32 (0x2)
#define RT5660_ADC_OSR_16 (0x3)
/* ADC/DAC Clock Control 2 (0x74) */
#define RT5660_RESET_ADF (0x1 << 13)
#define RT5660_RESET_ADF_SFT 13
#define RT5660_RESET_DAF (0x1 << 12)
#define RT5660_RESET_DAF_SFT 12
#define RT5660_DAHPF_EN (0x1 << 11)
#define RT5660_DAHPF_EN_SFT 11
#define RT5660_ADHPF_EN (0x1 << 10)
#define RT5660_ADHPF_EN_SFT 10
/* Digital Microphone Control (0x75) */
#define RT5660_DMIC_1_EN_MASK (0x1 << 15)
#define RT5660_DMIC_1_EN_SFT 15
#define RT5660_DMIC_1_DIS (0x0 << 15)
#define RT5660_DMIC_1_EN (0x1 << 15)
#define RT5660_DMIC_1L_LH_MASK (0x1 << 13)
#define RT5660_DMIC_1L_LH_SFT 13
#define RT5660_DMIC_1L_LH_RISING (0x0 << 13)
#define RT5660_DMIC_1L_LH_FALLING (0x1 << 13)
#define RT5660_DMIC_1R_LH_MASK (0x1 << 12)
#define RT5660_DMIC_1R_LH_SFT 12
#define RT5660_DMIC_1R_LH_RISING (0x0 << 12)
#define RT5660_DMIC_1R_LH_FALLING (0x1 << 12)
#define RT5660_SEL_DMIC_DATA_MASK (0x1 << 11)
#define RT5660_SEL_DMIC_DATA_SFT 11
#define RT5660_SEL_DMIC_DATA_GPIO2 (0x0 << 11)
#define RT5660_SEL_DMIC_DATA_IN1P (0x1 << 11)
#define RT5660_DMIC_CLK_MASK (0x7 << 5)
#define RT5660_DMIC_CLK_SFT 5
/* Global Clock Control (0x80) */
#define RT5660_SCLK_SRC_MASK (0x3 << 14)
#define RT5660_SCLK_SRC_SFT 14
#define RT5660_SCLK_SRC_MCLK (0x0 << 14)
#define RT5660_SCLK_SRC_PLL1 (0x1 << 14)
#define RT5660_SCLK_SRC_RCCLK (0x2 << 14)
#define RT5660_PLL1_SRC_MASK (0x3 << 12)
#define RT5660_PLL1_SRC_SFT 12
#define RT5660_PLL1_SRC_MCLK (0x0 << 12)
#define RT5660_PLL1_SRC_BCLK1 (0x1 << 12)
#define RT5660_PLL1_SRC_RCCLK (0x2 << 12)
#define RT5660_PLL1_PD_MASK (0x1 << 3)
#define RT5660_PLL1_PD_SFT 3
#define RT5660_PLL1_PD_1 (0x0 << 3)
#define RT5660_PLL1_PD_2 (0x1 << 3)
#define RT5660_PLL_INP_MAX 40000000
#define RT5660_PLL_INP_MIN 256000
/* PLL M/N/K Code Control 1 (0x81) */
#define RT5660_PLL_N_MAX 0x1ff
#define RT5660_PLL_N_MASK (RT5660_PLL_N_MAX << 7)
#define RT5660_PLL_N_SFT 7
#define RT5660_PLL_K_MAX 0x1f
#define RT5660_PLL_K_MASK (RT5660_PLL_K_MAX)
#define RT5660_PLL_K_SFT 0
/* PLL M/N/K Code Control 2 (0x82) */
#define RT5660_PLL_M_MAX 0xf
#define RT5660_PLL_M_MASK (RT5660_PLL_M_MAX << 12)
#define RT5660_PLL_M_SFT 12
#define RT5660_PLL_M_BP (0x1 << 11)
#define RT5660_PLL_M_BP_SFT 11
/* Class D Over Current Control (0x8c) */
#define RT5660_CLSD_OC_MASK (0x1 << 9)
#define RT5660_CLSD_OC_SFT 9
#define RT5660_CLSD_OC_PU (0x0 << 9)
#define RT5660_CLSD_OC_PD (0x1 << 9)
#define RT5660_AUTO_PD_MASK (0x1 << 8)
#define RT5660_AUTO_PD_SFT 8
#define RT5660_AUTO_PD_DIS (0x0 << 8)
#define RT5660_AUTO_PD_EN (0x1 << 8)
#define RT5660_CLSD_OC_TH_MASK (0x3f)
#define RT5660_CLSD_OC_TH_SFT 0
/* Class D Output Control (0x8d) */
#define RT5660_CLSD_RATIO_MASK (0xf << 12)
#define RT5660_CLSD_RATIO_SFT 12
/* Lout Amp Control 1 (0x8e) */
#define RT5660_LOUT_CO_MASK (0x1 << 4)
#define RT5660_LOUT_CO_SFT 4
#define RT5660_LOUT_CO_DIS (0x0 << 4)
#define RT5660_LOUT_CO_EN (0x1 << 4)
#define RT5660_LOUT_CB_MASK (0x1)
#define RT5660_LOUT_CB_SFT 0
#define RT5660_LOUT_CB_PD (0x0)
#define RT5660_LOUT_CB_PU (0x1)
/* SPKVDD detection control (0x92) */
#define RT5660_SPKVDD_DET_MASK (0x1 << 15)
#define RT5660_SPKVDD_DET_SFT 15
#define RT5660_SPKVDD_DET_DIS (0x0 << 15)
#define RT5660_SPKVDD_DET_EN (0x1 << 15)
#define RT5660_SPK_AG_MASK (0x1 << 14)
#define RT5660_SPK_AG_SFT 14
#define RT5660_SPK_AG_DIS (0x0 << 14)
#define RT5660_SPK_AG_EN (0x1 << 14)
/* Micbias Control (0x93) */
#define RT5660_MIC1_BS_MASK (0x1 << 15)
#define RT5660_MIC1_BS_SFT 15
#define RT5660_MIC1_BS_9AV (0x0 << 15)
#define RT5660_MIC1_BS_75AV (0x1 << 15)
#define RT5660_MIC2_BS_MASK (0x1 << 14)
#define RT5660_MIC2_BS_SFT 14
#define RT5660_MIC2_BS_9AV (0x0 << 14)
#define RT5660_MIC2_BS_75AV (0x1 << 14)
#define RT5660_MIC1_OVCD_MASK (0x1 << 11)
#define RT5660_MIC1_OVCD_SFT 11
#define RT5660_MIC1_OVCD_DIS (0x0 << 11)
#define RT5660_MIC1_OVCD_EN (0x1 << 11)
#define RT5660_MIC1_OVTH_MASK (0x3 << 9)
#define RT5660_MIC1_OVTH_SFT 9
#define RT5660_MIC1_OVTH_600UA (0x0 << 9)
#define RT5660_MIC1_OVTH_1500UA (0x1 << 9)
#define RT5660_MIC1_OVTH_2000UA (0x2 << 9)
#define RT5660_MIC2_OVCD_MASK (0x1 << 8)
#define RT5660_MIC2_OVCD_SFT 8
#define RT5660_MIC2_OVCD_DIS (0x0 << 8)
#define RT5660_MIC2_OVCD_EN (0x1 << 8)
#define RT5660_MIC2_OVTH_MASK (0x3 << 6)
#define RT5660_MIC2_OVTH_SFT 6
#define RT5660_MIC2_OVTH_600UA (0x0 << 6)
#define RT5660_MIC2_OVTH_1500UA (0x1 << 6)
#define RT5660_MIC2_OVTH_2000UA (0x2 << 6)
#define RT5660_PWR_CLK25M_MASK (0x1 << 4)
#define RT5660_PWR_CLK25M_SFT 4
#define RT5660_PWR_CLK25M_PD (0x0 << 4)
#define RT5660_PWR_CLK25M_PU (0x1 << 4)
/* EQ Control 1 (0xb0) */
#define RT5660_EQ_SRC_MASK (0x1 << 15)
#define RT5660_EQ_SRC_SFT 15
#define RT5660_EQ_SRC_DAC (0x0 << 15)
#define RT5660_EQ_SRC_ADC (0x1 << 15)
#define RT5660_EQ_UPD (0x1 << 14)
#define RT5660_EQ_UPD_BIT 14
/* Jack Detect Control (0xbb) */
#define RT5660_JD_MASK (0x3 << 14)
#define RT5660_JD_SFT 14
#define RT5660_JD_DIS (0x0 << 14)
#define RT5660_JD_GPIO1 (0x1 << 14)
#define RT5660_JD_GPIO2 (0x2 << 14)
#define RT5660_JD_LOUT_MASK (0x1 << 11)
#define RT5660_JD_LOUT_SFT 11
#define RT5660_JD_LOUT_DIS (0x0 << 11)
#define RT5660_JD_LOUT_EN (0x1 << 11)
#define RT5660_JD_LOUT_TRG_MASK (0x1 << 10)
#define RT5660_JD_LOUT_TRG_SFT 10
#define RT5660_JD_LOUT_TRG_LO (0x0 << 10)
#define RT5660_JD_LOUT_TRG_HI (0x1 << 10)
#define RT5660_JD_SPO_MASK (0x1 << 9)
#define RT5660_JD_SPO_SFT 9
#define RT5660_JD_SPO_DIS (0x0 << 9)
#define RT5660_JD_SPO_EN (0x1 << 9)
#define RT5660_JD_SPO_TRG_MASK (0x1 << 8)
#define RT5660_JD_SPO_TRG_SFT 8
#define RT5660_JD_SPO_TRG_LO (0x0 << 8)
#define RT5660_JD_SPO_TRG_HI (0x1 << 8)
/* IRQ Control 1 (0xbd) */
#define RT5660_IRQ_JD_MASK (0x1 << 15)
#define RT5660_IRQ_JD_SFT 15
#define RT5660_IRQ_JD_BP (0x0 << 15)
#define RT5660_IRQ_JD_NOR (0x1 << 15)
#define RT5660_IRQ_OT_MASK (0x1 << 14)
#define RT5660_IRQ_OT_SFT 14
#define RT5660_IRQ_OT_BP (0x0 << 14)
#define RT5660_IRQ_OT_NOR (0x1 << 14)
#define RT5660_JD_STKY_MASK (0x1 << 13)
#define RT5660_JD_STKY_SFT 13
#define RT5660_JD_STKY_DIS (0x0 << 13)
#define RT5660_JD_STKY_EN (0x1 << 13)
#define RT5660_OT_STKY_MASK (0x1 << 12)
#define RT5660_OT_STKY_SFT 12
#define RT5660_OT_STKY_DIS (0x0 << 12)
#define RT5660_OT_STKY_EN (0x1 << 12)
#define RT5660_JD_P_MASK (0x1 << 11)
#define RT5660_JD_P_SFT 11
#define RT5660_JD_P_NOR (0x0 << 11)
#define RT5660_JD_P_INV (0x1 << 11)
#define RT5660_OT_P_MASK (0x1 << 10)
#define RT5660_OT_P_SFT 10
#define RT5660_OT_P_NOR (0x0 << 10)
#define RT5660_OT_P_INV (0x1 << 10)
/* IRQ Control 2 (0xbe) */
#define RT5660_IRQ_MB1_OC_MASK (0x1 << 15)
#define RT5660_IRQ_MB1_OC_SFT 15
#define RT5660_IRQ_MB1_OC_BP (0x0 << 15)
#define RT5660_IRQ_MB1_OC_NOR (0x1 << 15)
#define RT5660_IRQ_MB2_OC_MASK (0x1 << 14)
#define RT5660_IRQ_MB2_OC_SFT 14
#define RT5660_IRQ_MB2_OC_BP (0x0 << 14)
#define RT5660_IRQ_MB2_OC_NOR (0x1 << 14)
#define RT5660_MB1_OC_STKY_MASK (0x1 << 11)
#define RT5660_MB1_OC_STKY_SFT 11
#define RT5660_MB1_OC_STKY_DIS (0x0 << 11)
#define RT5660_MB1_OC_STKY_EN (0x1 << 11)
#define RT5660_MB2_OC_STKY_MASK (0x1 << 10)
#define RT5660_MB2_OC_STKY_SFT 10
#define RT5660_MB2_OC_STKY_DIS (0x0 << 10)
#define RT5660_MB2_OC_STKY_EN (0x1 << 10)
#define RT5660_MB1_OC_P_MASK (0x1 << 7)
#define RT5660_MB1_OC_P_SFT 7
#define RT5660_MB1_OC_P_NOR (0x0 << 7)
#define RT5660_MB1_OC_P_INV (0x1 << 7)
#define RT5660_MB2_OC_P_MASK (0x1 << 6)
#define RT5660_MB2_OC_P_SFT 6
#define RT5660_MB2_OC_P_NOR (0x0 << 6)
#define RT5660_MB2_OC_P_INV (0x1 << 6)
#define RT5660_MB1_OC_CLR (0x1 << 3)
#define RT5660_MB1_OC_CLR_SFT 3
#define RT5660_MB2_OC_CLR (0x1 << 2)
#define RT5660_MB2_OC_CLR_SFT 2
/* GPIO Control 1 (0xc0) */
#define RT5660_GP2_PIN_MASK (0x1 << 14)
#define RT5660_GP2_PIN_SFT 14
#define RT5660_GP2_PIN_GPIO2 (0x0 << 14)
#define RT5660_GP2_PIN_DMIC1_SDA (0x1 << 14)
#define RT5660_GP1_PIN_MASK (0x3 << 12)
#define RT5660_GP1_PIN_SFT 12
#define RT5660_GP1_PIN_GPIO1 (0x0 << 12)
#define RT5660_GP1_PIN_DMIC1_SCL (0x1 << 12)
#define RT5660_GP1_PIN_IRQ (0x2 << 12)
#define RT5660_GPIO_M_MASK (0x1 << 9)
#define RT5660_GPIO_M_SFT 9
#define RT5660_GPIO_M_FLT (0x0 << 9)
#define RT5660_GPIO_M_PH (0x1 << 9)
/* GPIO Control 3 (0xc2) */
#define RT5660_GP2_PF_MASK (0x1 << 5)
#define RT5660_GP2_PF_SFT 5
#define RT5660_GP2_PF_IN (0x0 << 5)
#define RT5660_GP2_PF_OUT (0x1 << 5)
#define RT5660_GP2_OUT_MASK (0x1 << 4)
#define RT5660_GP2_OUT_SFT 4
#define RT5660_GP2_OUT_LO (0x0 << 4)
#define RT5660_GP2_OUT_HI (0x1 << 4)
#define RT5660_GP2_P_MASK (0x1 << 3)
#define RT5660_GP2_P_SFT 3
#define RT5660_GP2_P_NOR (0x0 << 3)
#define RT5660_GP2_P_INV (0x1 << 3)
#define RT5660_GP1_PF_MASK (0x1 << 2)
#define RT5660_GP1_PF_SFT 2
#define RT5660_GP1_PF_IN (0x0 << 2)
#define RT5660_GP1_PF_OUT (0x1 << 2)
#define RT5660_GP1_OUT_MASK (0x1 << 1)
#define RT5660_GP1_OUT_SFT 1
#define RT5660_GP1_OUT_LO (0x0 << 1)
#define RT5660_GP1_OUT_HI (0x1 << 1)
#define RT5660_GP1_P_MASK (0x1)
#define RT5660_GP1_P_SFT 0
#define RT5660_GP1_P_NOR (0x0)
#define RT5660_GP1_P_INV (0x1)
/* Soft volume and zero cross control 1 (0xd9) */
#define RT5660_SV_MASK (0x1 << 15)
#define RT5660_SV_SFT 15
#define RT5660_SV_DIS (0x0 << 15)
#define RT5660_SV_EN (0x1 << 15)
#define RT5660_SPO_SV_MASK (0x1 << 14)
#define RT5660_SPO_SV_SFT 14
#define RT5660_SPO_SV_DIS (0x0 << 14)
#define RT5660_SPO_SV_EN (0x1 << 14)
#define RT5660_OUT_SV_MASK (0x1 << 12)
#define RT5660_OUT_SV_SFT 12
#define RT5660_OUT_SV_DIS (0x0 << 12)
#define RT5660_OUT_SV_EN (0x1 << 12)
#define RT5660_ZCD_DIG_MASK (0x1 << 11)
#define RT5660_ZCD_DIG_SFT 11
#define RT5660_ZCD_DIG_DIS (0x0 << 11)
#define RT5660_ZCD_DIG_EN (0x1 << 11)
#define RT5660_ZCD_MASK (0x1 << 10)
#define RT5660_ZCD_SFT 10
#define RT5660_ZCD_PD (0x0 << 10)
#define RT5660_ZCD_PU (0x1 << 10)
#define RT5660_SV_DLY_MASK (0xf)
#define RT5660_SV_DLY_SFT 0
/* Soft volume and zero cross control 2 (0xda) */
#define RT5660_ZCD_SPO_MASK (0x1 << 15)
#define RT5660_ZCD_SPO_SFT 15
#define RT5660_ZCD_SPO_DIS (0x0 << 15)
#define RT5660_ZCD_SPO_EN (0x1 << 15)
#define RT5660_ZCD_OMR_MASK (0x1 << 8)
#define RT5660_ZCD_OMR_SFT 8
#define RT5660_ZCD_OMR_DIS (0x0 << 8)
#define RT5660_ZCD_OMR_EN (0x1 << 8)
#define RT5660_ZCD_OML_MASK (0x1 << 7)
#define RT5660_ZCD_OML_SFT 7
#define RT5660_ZCD_OML_DIS (0x0 << 7)
#define RT5660_ZCD_OML_EN (0x1 << 7)
#define RT5660_ZCD_SPM_MASK (0x1 << 6)
#define RT5660_ZCD_SPM_SFT 6
#define RT5660_ZCD_SPM_DIS (0x0 << 6)
#define RT5660_ZCD_SPM_EN (0x1 << 6)
#define RT5660_ZCD_RMR_MASK (0x1 << 5)
#define RT5660_ZCD_RMR_SFT 5
#define RT5660_ZCD_RMR_DIS (0x0 << 5)
#define RT5660_ZCD_RMR_EN (0x1 << 5)
#define RT5660_ZCD_RML_MASK (0x1 << 4)
#define RT5660_ZCD_RML_SFT 4
#define RT5660_ZCD_RML_DIS (0x0 << 4)
#define RT5660_ZCD_RML_EN (0x1 << 4)
/* General Control 1 (0xfa) */
#define RT5660_PWR_VREF_HP (0x1 << 11)
#define RT5660_PWR_VREF_HP_SFT 11
#define RT5660_DIG_GATE_CTRL (0x1)
#define RT5660_DIG_GATE_CTRL_SFT 0
/* System Clock Source */
#define RT5660_SCLK_S_MCLK 0
#define RT5660_SCLK_S_PLL1 1
#define RT5660_SCLK_S_RCCLK 2
/* PLL1 Source */
#define RT5660_PLL1_S_MCLK 0
#define RT5660_PLL1_S_BCLK 1
enum {
RT5660_AIF1,
RT5660_AIFS,
};
struct rt5660_priv {
struct snd_soc_codec *codec;
struct rt5660_platform_data pdata;
struct regmap *regmap;
struct clk *mclk;
int sysclk;
int sysclk_src;
int lrck[RT5660_AIFS];
int bclk[RT5660_AIFS];
int master[RT5660_AIFS];
int pll_src;
int pll_in;
int pll_out;
};
#endif
/*
* rt5663.c -- RT5668/RT5663 ALSA SoC audio codec driver
*
* Copyright 2016 Realtek Semiconductor Corp.
* Author: Jack Yu <jack.yu@realtek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/acpi.h>
#include <linux/workqueue.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/jack.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include "rt5663.h"
#include "rl6231.h"
#define RT5668_DEVICE_ID 0x6451
#define RT5663_DEVICE_ID 0x6406
enum {
CODEC_TYPE_RT5668,
CODEC_TYPE_RT5663,
};
struct rt5663_priv {
struct snd_soc_codec *codec;
struct regmap *regmap;
struct delayed_work jack_detect_work;
struct snd_soc_jack *hs_jack;
struct timer_list btn_check_timer;
int codec_type;
int sysclk;
int sysclk_src;
int lrck;
int pll_src;
int pll_in;
int pll_out;
int jack_type;
};
static const struct reg_default rt5668_reg[] = {
{ 0x0000, 0x0000 },
{ 0x0001, 0xc8c8 },
{ 0x0002, 0x8080 },
{ 0x0003, 0x8000 },
{ 0x0004, 0xc80a },
{ 0x0005, 0x0000 },
{ 0x0006, 0x0000 },
{ 0x0007, 0x0000 },
{ 0x000a, 0x0000 },
{ 0x000b, 0x0000 },
{ 0x000c, 0x0000 },
{ 0x000d, 0x0000 },
{ 0x000f, 0x0808 },
{ 0x0010, 0x4000 },
{ 0x0011, 0x0000 },
{ 0x0012, 0x1404 },
{ 0x0013, 0x1000 },
{ 0x0014, 0xa00a },
{ 0x0015, 0x0404 },
{ 0x0016, 0x0404 },
{ 0x0017, 0x0011 },
{ 0x0018, 0xafaf },
{ 0x0019, 0xafaf },
{ 0x001a, 0xafaf },
{ 0x001b, 0x0011 },
{ 0x001c, 0x2f2f },
{ 0x001d, 0x2f2f },
{ 0x001e, 0x2f2f },
{ 0x001f, 0x0000 },
{ 0x0020, 0x0000 },
{ 0x0021, 0x0000 },
{ 0x0022, 0x5757 },
{ 0x0023, 0x0039 },
{ 0x0024, 0x000b },
{ 0x0026, 0xc0c0 },
{ 0x0027, 0xc0c0 },
{ 0x0028, 0xc0c0 },
{ 0x0029, 0x8080 },
{ 0x002a, 0xaaaa },
{ 0x002b, 0xaaaa },
{ 0x002c, 0xaba8 },
{ 0x002d, 0x0000 },
{ 0x002e, 0x0000 },
{ 0x002f, 0x0000 },
{ 0x0030, 0x0000 },
{ 0x0031, 0x5000 },
{ 0x0032, 0x0000 },
{ 0x0033, 0x0000 },
{ 0x0034, 0x0000 },
{ 0x0035, 0x0000 },
{ 0x003a, 0x0000 },
{ 0x003b, 0x0000 },
{ 0x003c, 0x00ff },
{ 0x003d, 0x0000 },
{ 0x003e, 0x00ff },
{ 0x003f, 0x0000 },
{ 0x0040, 0x0000 },
{ 0x0041, 0x00ff },
{ 0x0042, 0x0000 },
{ 0x0043, 0x00ff },
{ 0x0044, 0x0c0c },
{ 0x0049, 0xc00b },
{ 0x004a, 0x0000 },
{ 0x004b, 0x031f },
{ 0x004d, 0x0000 },
{ 0x004e, 0x001f },
{ 0x004f, 0x0000 },
{ 0x0050, 0x001f },
{ 0x0052, 0xf000 },
{ 0x0061, 0x0000 },
{ 0x0062, 0x0000 },
{ 0x0063, 0x003e },
{ 0x0064, 0x0000 },
{ 0x0065, 0x0000 },
{ 0x0066, 0x003f },
{ 0x0067, 0x0000 },
{ 0x006b, 0x0000 },
{ 0x006d, 0xff00 },
{ 0x006e, 0x2808 },
{ 0x006f, 0x000a },
{ 0x0070, 0x8000 },
{ 0x0071, 0x8000 },
{ 0x0072, 0x8000 },
{ 0x0073, 0x7000 },
{ 0x0074, 0x7770 },
{ 0x0075, 0x0002 },
{ 0x0076, 0x0001 },
{ 0x0078, 0x00f0 },
{ 0x0079, 0x0000 },
{ 0x007a, 0x0000 },
{ 0x007b, 0x0000 },
{ 0x007c, 0x0000 },
{ 0x007d, 0x0123 },
{ 0x007e, 0x4500 },
{ 0x007f, 0x8003 },
{ 0x0080, 0x0000 },
{ 0x0081, 0x0000 },
{ 0x0082, 0x0000 },
{ 0x0083, 0x0000 },
{ 0x0084, 0x0000 },
{ 0x0085, 0x0000 },
{ 0x0086, 0x0008 },
{ 0x0087, 0x0000 },
{ 0x0088, 0x0000 },
{ 0x0089, 0x0000 },
{ 0x008a, 0x0000 },
{ 0x008b, 0x0000 },
{ 0x008c, 0x0003 },
{ 0x008e, 0x0060 },
{ 0x008f, 0x1000 },
{ 0x0091, 0x0c26 },
{ 0x0092, 0x0073 },
{ 0x0093, 0x0000 },
{ 0x0094, 0x0080 },
{ 0x0098, 0x0000 },
{ 0x0099, 0x0000 },
{ 0x009a, 0x0007 },
{ 0x009f, 0x0000 },
{ 0x00a0, 0x0000 },
{ 0x00a1, 0x0002 },
{ 0x00a2, 0x0001 },
{ 0x00a3, 0x0002 },
{ 0x00a4, 0x0001 },
{ 0x00ae, 0x2040 },
{ 0x00af, 0x0000 },
{ 0x00b6, 0x0000 },
{ 0x00b7, 0x0000 },
{ 0x00b8, 0x0000 },
{ 0x00b9, 0x0000 },
{ 0x00ba, 0x0002 },
{ 0x00bb, 0x0000 },
{ 0x00be, 0x0000 },
{ 0x00c0, 0x0000 },
{ 0x00c1, 0x0aaa },
{ 0x00c2, 0xaa80 },
{ 0x00c3, 0x0003 },
{ 0x00c4, 0x0000 },
{ 0x00d0, 0x0000 },
{ 0x00d1, 0x2244 },
{ 0x00d2, 0x0000 },
{ 0x00d3, 0x3300 },
{ 0x00d4, 0x2200 },
{ 0x00d9, 0x0809 },
{ 0x00da, 0x0000 },
{ 0x00db, 0x0008 },
{ 0x00dc, 0x00c0 },
{ 0x00dd, 0x6724 },
{ 0x00de, 0x3131 },
{ 0x00df, 0x0008 },
{ 0x00e0, 0x4000 },
{ 0x00e1, 0x3131 },
{ 0x00e2, 0x600c },
{ 0x00ea, 0xb320 },
{ 0x00eb, 0x0000 },
{ 0x00ec, 0xb300 },
{ 0x00ed, 0x0000 },
{ 0x00ee, 0xb320 },
{ 0x00ef, 0x0000 },
{ 0x00f0, 0x0201 },
{ 0x00f1, 0x0ddd },
{ 0x00f2, 0x0ddd },
{ 0x00f6, 0x0000 },
{ 0x00f7, 0x0000 },
{ 0x00f8, 0x0000 },
{ 0x00fa, 0x0000 },
{ 0x00fb, 0x0000 },
{ 0x00fc, 0x0000 },
{ 0x00fd, 0x0000 },
{ 0x00fe, 0x10ec },
{ 0x00ff, 0x6451 },
{ 0x0100, 0xaaaa },
{ 0x0101, 0x000a },
{ 0x010a, 0xaaaa },
{ 0x010b, 0xa0a0 },
{ 0x010c, 0xaeae },
{ 0x010d, 0xaaaa },
{ 0x010e, 0xaaaa },
{ 0x010f, 0xaaaa },
{ 0x0110, 0xe002 },
{ 0x0111, 0xa602 },
{ 0x0112, 0xaaaa },
{ 0x0113, 0x2000 },
{ 0x0117, 0x0f00 },
{ 0x0125, 0x0420 },
{ 0x0132, 0x0000 },
{ 0x0133, 0x0000 },
{ 0x0136, 0x5555 },
{ 0x0137, 0x5540 },
{ 0x0138, 0x3700 },
{ 0x0139, 0x79a1 },
{ 0x013a, 0x2020 },
{ 0x013b, 0x2020 },
{ 0x013c, 0x2005 },
{ 0x013f, 0x0000 },
{ 0x0145, 0x0002 },
{ 0x0146, 0x0000 },
{ 0x0147, 0x0000 },
{ 0x0148, 0x0000 },
{ 0x0160, 0x4ec0 },
{ 0x0161, 0x0080 },
{ 0x0162, 0x0200 },
{ 0x0163, 0x0800 },
{ 0x0164, 0x0000 },
{ 0x0165, 0x0000 },
{ 0x0166, 0x0000 },
{ 0x0167, 0x000f },
{ 0x0168, 0x000f },
{ 0x0170, 0x4e80 },
{ 0x0171, 0x0080 },
{ 0x0172, 0x0200 },
{ 0x0173, 0x0800 },
{ 0x0174, 0x00ff },
{ 0x0175, 0x0000 },
{ 0x0190, 0x4131 },
{ 0x0191, 0x4131 },
{ 0x0192, 0x4131 },
{ 0x0193, 0x4131 },
{ 0x0194, 0x0000 },
{ 0x0195, 0x0000 },
{ 0x0196, 0x0000 },
{ 0x0197, 0x0000 },
{ 0x0198, 0x0000 },
{ 0x0199, 0x0000 },
{ 0x01a0, 0x1e64 },
{ 0x01a1, 0x06a3 },
{ 0x01a2, 0x0000 },
{ 0x01a3, 0x0000 },
{ 0x01a4, 0x0000 },
{ 0x01a5, 0x0000 },
{ 0x01a6, 0x0000 },
{ 0x01a7, 0x0000 },
{ 0x01a8, 0x0000 },
{ 0x01a9, 0x0000 },
{ 0x01aa, 0x0000 },
{ 0x01ab, 0x0000 },
{ 0x01b5, 0x0000 },
{ 0x01b6, 0x01c3 },
{ 0x01b7, 0x02a0 },
{ 0x01b8, 0x03e9 },
{ 0x01b9, 0x1389 },
{ 0x01ba, 0xc351 },
{ 0x01bb, 0x0009 },
{ 0x01bc, 0x0018 },
{ 0x01bd, 0x002a },
{ 0x01be, 0x004c },
{ 0x01bf, 0x0097 },
{ 0x01c0, 0x433d },
{ 0x01c1, 0x0000 },
{ 0x01c2, 0x0000 },
{ 0x01c3, 0x0000 },
{ 0x01c4, 0x0000 },
{ 0x01c5, 0x0000 },
{ 0x01c6, 0x0000 },
{ 0x01c7, 0x0000 },
{ 0x01c8, 0x40af },
{ 0x01c9, 0x0702 },
{ 0x01ca, 0x0000 },
{ 0x01cb, 0x0000 },
{ 0x01cc, 0x5757 },
{ 0x01cd, 0x5757 },
{ 0x01ce, 0x5757 },
{ 0x01cf, 0x5757 },
{ 0x01d0, 0x5757 },
{ 0x01d1, 0x5757 },
{ 0x01d2, 0x5757 },
{ 0x01d3, 0x5757 },
{ 0x01d4, 0x5757 },
{ 0x01d5, 0x5757 },
{ 0x01d6, 0x003c },
{ 0x01da, 0x0000 },
{ 0x01db, 0x0000 },
{ 0x01dc, 0x0000 },
{ 0x01de, 0x7c00 },
{ 0x01df, 0x0320 },
{ 0x01e0, 0x06a1 },
{ 0x01e1, 0x0000 },
{ 0x01e2, 0x0000 },
{ 0x01e3, 0x0000 },
{ 0x01e4, 0x0000 },
{ 0x01e5, 0x0000 },
{ 0x01e6, 0x0001 },
{ 0x01e7, 0x0000 },
{ 0x01e8, 0x0000 },
{ 0x01ea, 0x0000 },
{ 0x01eb, 0x0000 },
{ 0x01ec, 0x0000 },
{ 0x01ed, 0x0000 },
{ 0x01ee, 0x0000 },
{ 0x01ef, 0x0000 },
{ 0x01f0, 0x0000 },
{ 0x01f1, 0x0000 },
{ 0x01f2, 0x0000 },
{ 0x01f3, 0x0000 },
{ 0x01f4, 0x0000 },
{ 0x0200, 0x0000 },
{ 0x0201, 0x0000 },
{ 0x0202, 0x0000 },
{ 0x0203, 0x0000 },
{ 0x0204, 0x0000 },
{ 0x0205, 0x0000 },
{ 0x0206, 0x0000 },
{ 0x0207, 0x0000 },
{ 0x0208, 0x0000 },
{ 0x0210, 0x60b1 },
{ 0x0211, 0xa000 },
{ 0x0212, 0x024c },
{ 0x0213, 0xf7ff },
{ 0x0214, 0x024c },
{ 0x0215, 0x0102 },
{ 0x0216, 0x00a3 },
{ 0x0217, 0x0048 },
{ 0x0218, 0x92c0 },
{ 0x0219, 0x0000 },
{ 0x021a, 0x00c8 },
{ 0x021b, 0x0020 },
{ 0x02fa, 0x0000 },
{ 0x02fb, 0x0000 },
{ 0x02fc, 0x0000 },
{ 0x02ff, 0x0110 },
{ 0x0300, 0x001f },
{ 0x0301, 0x032c },
{ 0x0302, 0x5f21 },
{ 0x0303, 0x4000 },
{ 0x0304, 0x4000 },
{ 0x0305, 0x06d5 },
{ 0x0306, 0x8000 },
{ 0x0307, 0x0700 },
{ 0x0310, 0x4560 },
{ 0x0311, 0xa4a8 },
{ 0x0312, 0x7418 },
{ 0x0313, 0x0000 },
{ 0x0314, 0x0006 },
{ 0x0315, 0xffff },
{ 0x0316, 0xc400 },
{ 0x0317, 0x0000 },
{ 0x0330, 0x00a6 },
{ 0x0331, 0x04c3 },
{ 0x0332, 0x27c8 },
{ 0x0333, 0xbf50 },
{ 0x0334, 0x0045 },
{ 0x0335, 0x0007 },
{ 0x0336, 0x7418 },
{ 0x0337, 0x0501 },
{ 0x0338, 0x0000 },
{ 0x0339, 0x0010 },
{ 0x033a, 0x1010 },
{ 0x03c0, 0x7e00 },
{ 0x03c1, 0x8000 },
{ 0x03c2, 0x8000 },
{ 0x03c3, 0x8000 },
{ 0x03c4, 0x8000 },
{ 0x03c5, 0x8000 },
{ 0x03c6, 0x8000 },
{ 0x03c7, 0x8000 },
{ 0x03c8, 0x8000 },
{ 0x03c9, 0x8000 },
{ 0x03ca, 0x8000 },
{ 0x03cb, 0x8000 },
{ 0x03cc, 0x8000 },
{ 0x03d0, 0x0000 },
{ 0x03d1, 0x0000 },
{ 0x03d2, 0x0000 },
{ 0x03d3, 0x0000 },
{ 0x03d4, 0x2000 },
{ 0x03d5, 0x2000 },
{ 0x03d6, 0x0000 },
{ 0x03d7, 0x0000 },
{ 0x03d8, 0x2000 },
{ 0x03d9, 0x2000 },
{ 0x03da, 0x2000 },
{ 0x03db, 0x2000 },
{ 0x03dc, 0x0000 },
{ 0x03dd, 0x0000 },
{ 0x03de, 0x0000 },
{ 0x03df, 0x2000 },
{ 0x03e0, 0x0000 },
{ 0x03e1, 0x0000 },
{ 0x03e2, 0x0000 },
{ 0x03e3, 0x0000 },
{ 0x03e4, 0x0000 },
{ 0x03e5, 0x0000 },
{ 0x03e6, 0x0000 },
{ 0x03e7, 0x0000 },
{ 0x03e8, 0x0000 },
{ 0x03e9, 0x0000 },
{ 0x03ea, 0x0000 },
{ 0x03eb, 0x0000 },
{ 0x03ec, 0x0000 },
{ 0x03ed, 0x0000 },
{ 0x03ee, 0x0000 },
{ 0x03ef, 0x0000 },
{ 0x03f0, 0x0800 },
{ 0x03f1, 0x0800 },
{ 0x03f2, 0x0800 },
{ 0x03f3, 0x0800 },
{ 0x03fe, 0x0000 },
{ 0x03ff, 0x0000 },
{ 0x07f0, 0x0000 },
{ 0x07fa, 0x0000 },
};
static const struct reg_default rt5663_reg[] = {
{ 0x0000, 0x0000 },
{ 0x0002, 0x0008 },
{ 0x0005, 0x1000 },
{ 0x0006, 0x1000 },
{ 0x000a, 0x0000 },
{ 0x0010, 0x000f },
{ 0x0015, 0x42c1 },
{ 0x0016, 0x0000 },
{ 0x0018, 0x000b },
{ 0x0019, 0xafaf },
{ 0x001c, 0x2f2f },
{ 0x001f, 0x0000 },
{ 0x0022, 0x5757 },
{ 0x0023, 0x0039 },
{ 0x0026, 0xc0c0 },
{ 0x0029, 0x8080 },
{ 0x002a, 0xa0a0 },
{ 0x002c, 0x000c },
{ 0x002d, 0x0000 },
{ 0x0040, 0x0808 },
{ 0x0061, 0x0000 },
{ 0x0062, 0x0000 },
{ 0x0063, 0x003e },
{ 0x0064, 0x0000 },
{ 0x0065, 0x0000 },
{ 0x0066, 0x0000 },
{ 0x006b, 0x0000 },
{ 0x006e, 0x0000 },
{ 0x006f, 0x0000 },
{ 0x0070, 0x8020 },
{ 0x0073, 0x1000 },
{ 0x0074, 0xe400 },
{ 0x0075, 0x0002 },
{ 0x0076, 0x0001 },
{ 0x0077, 0x00f0 },
{ 0x0078, 0x0000 },
{ 0x0079, 0x0000 },
{ 0x007a, 0x0123 },
{ 0x007b, 0x8003 },
{ 0x0080, 0x0000 },
{ 0x0081, 0x0000 },
{ 0x0082, 0x0000 },
{ 0x0083, 0x0000 },
{ 0x0084, 0x0000 },
{ 0x0086, 0x0008 },
{ 0x0087, 0x0000 },
{ 0x008a, 0x0000 },
{ 0x008b, 0x0000 },
{ 0x008c, 0x0003 },
{ 0x008e, 0x0004 },
{ 0x008f, 0x1000 },
{ 0x0090, 0x0646 },
{ 0x0091, 0x0e3e },
{ 0x0092, 0x1071 },
{ 0x0093, 0x0000 },
{ 0x0094, 0x0080 },
{ 0x0097, 0x0000 },
{ 0x0098, 0x0000 },
{ 0x009a, 0x0000 },
{ 0x009f, 0x0000 },
{ 0x00ae, 0x2000 },
{ 0x00af, 0x0000 },
{ 0x00b6, 0x0000 },
{ 0x00b7, 0x0000 },
{ 0x00b8, 0x0000 },
{ 0x00ba, 0x0000 },
{ 0x00bb, 0x0000 },
{ 0x00be, 0x0000 },
{ 0x00bf, 0x0000 },
{ 0x00c0, 0x0000 },
{ 0x00c1, 0x0000 },
{ 0x00c5, 0x0000 },
{ 0x00cb, 0xa02f },
{ 0x00cc, 0x0000 },
{ 0x00cd, 0x0e02 },
{ 0x00d9, 0x08f9 },
{ 0x00db, 0x0008 },
{ 0x00dc, 0x00c0 },
{ 0x00dd, 0x6724 },
{ 0x00de, 0x3131 },
{ 0x00df, 0x0008 },
{ 0x00e0, 0x4000 },
{ 0x00e1, 0x3131 },
{ 0x00e2, 0x0043 },
{ 0x00e4, 0x400b },
{ 0x00e5, 0x8031 },
{ 0x00e6, 0x3080 },
{ 0x00e7, 0x4100 },
{ 0x00e8, 0x1400 },
{ 0x00e9, 0xe00a },
{ 0x00ea, 0x0404 },
{ 0x00eb, 0x0404 },
{ 0x00ec, 0xb320 },
{ 0x00ed, 0x0000 },
{ 0x00f4, 0x0000 },
{ 0x00f6, 0x0000 },
{ 0x00f8, 0x0000 },
{ 0x00fa, 0x8000 },
{ 0x00fd, 0x0001 },
{ 0x00fe, 0x10ec },
{ 0x00ff, 0x6406 },
{ 0x0100, 0xa0a0 },
{ 0x0108, 0x4444 },
{ 0x0109, 0x4444 },
{ 0x010a, 0xaaaa },
{ 0x010b, 0x00a0 },
{ 0x010c, 0x8aaa },
{ 0x010d, 0xaaaa },
{ 0x010e, 0x2aaa },
{ 0x010f, 0x002a },
{ 0x0110, 0xa0a4 },
{ 0x0111, 0x4602 },
{ 0x0112, 0x0101 },
{ 0x0113, 0x2000 },
{ 0x0114, 0x0000 },
{ 0x0116, 0x0000 },
{ 0x0117, 0x0f00 },
{ 0x0118, 0x0006 },
{ 0x0125, 0x2224 },
{ 0x0126, 0x5550 },
{ 0x0127, 0x0400 },
{ 0x0128, 0x7711 },
{ 0x0132, 0x0004 },
{ 0x0137, 0x5441 },
{ 0x0139, 0x79a1 },
{ 0x013a, 0x30c0 },
{ 0x013b, 0x2000 },
{ 0x013c, 0x2005 },
{ 0x013d, 0x30c0 },
{ 0x013e, 0x0000 },
{ 0x0140, 0x3700 },
{ 0x0141, 0x1f00 },
{ 0x0144, 0x0000 },
{ 0x0145, 0x0002 },
{ 0x0146, 0x0000 },
{ 0x0160, 0x0e80 },
{ 0x0161, 0x0020 },
{ 0x0162, 0x0080 },
{ 0x0163, 0x0800 },
{ 0x0164, 0x0000 },
{ 0x0165, 0x0000 },
{ 0x0166, 0x0000 },
{ 0x0167, 0x1417 },
{ 0x0168, 0x0017 },
{ 0x0169, 0x0017 },
{ 0x0180, 0x2000 },
{ 0x0181, 0x0000 },
{ 0x0182, 0x0000 },
{ 0x0183, 0x2000 },
{ 0x0184, 0x0000 },
{ 0x0185, 0x0000 },
{ 0x01b0, 0x4b30 },
{ 0x01b1, 0x0000 },
{ 0x01b2, 0xd870 },
{ 0x01b3, 0x0000 },
{ 0x01b4, 0x0030 },
{ 0x01b5, 0x5757 },
{ 0x01b6, 0x5757 },
{ 0x01b7, 0x5757 },
{ 0x01b8, 0x5757 },
{ 0x01c0, 0x433d },
{ 0x01c1, 0x0540 },
{ 0x01c2, 0x0000 },
{ 0x01c3, 0x0000 },
{ 0x01c4, 0x0000 },
{ 0x01c5, 0x0009 },
{ 0x01c6, 0x0018 },
{ 0x01c7, 0x002a },
{ 0x01c8, 0x004c },
{ 0x01c9, 0x0097 },
{ 0x01ca, 0x01c3 },
{ 0x01cb, 0x03e9 },
{ 0x01cc, 0x1389 },
{ 0x01cd, 0xc351 },
{ 0x01ce, 0x0000 },
{ 0x01cf, 0x0000 },
{ 0x01d0, 0x0000 },
{ 0x01d1, 0x0000 },
{ 0x01d2, 0x0000 },
{ 0x01d3, 0x003c },
{ 0x01d4, 0x5757 },
{ 0x01d5, 0x5757 },
{ 0x01d6, 0x5757 },
{ 0x01d7, 0x5757 },
{ 0x01d8, 0x5757 },
{ 0x01d9, 0x5757 },
{ 0x01da, 0x0000 },
{ 0x01db, 0x0000 },
{ 0x01dd, 0x0009 },
{ 0x01de, 0x7f00 },
{ 0x01df, 0x00c8 },
{ 0x01e0, 0x0691 },
{ 0x01e1, 0x0000 },
{ 0x01e2, 0x0000 },
{ 0x01e3, 0x0000 },
{ 0x01e4, 0x0000 },
{ 0x01e5, 0x0040 },
{ 0x01e6, 0x0000 },
{ 0x01e7, 0x0000 },
{ 0x01e8, 0x0000 },
{ 0x01ea, 0x0000 },
{ 0x01eb, 0x0000 },
{ 0x01ec, 0x0000 },
{ 0x01ed, 0x0000 },
{ 0x01ee, 0x0000 },
{ 0x01ef, 0x0000 },
{ 0x01f0, 0x0000 },
{ 0x01f1, 0x0000 },
{ 0x01f2, 0x0000 },
{ 0x0200, 0x0000 },
{ 0x0201, 0x2244 },
{ 0x0202, 0xaaaa },
{ 0x0250, 0x8010 },
{ 0x0251, 0x0000 },
{ 0x0252, 0x028a },
{ 0x02fa, 0x0000 },
{ 0x02fb, 0x0000 },
{ 0x02fc, 0x0000 },
{ 0x0300, 0x0000 },
{ 0x03d0, 0x0000 },
{ 0x03d1, 0x0000 },
{ 0x03d2, 0x0000 },
{ 0x03d3, 0x0000 },
{ 0x03d4, 0x2000 },
{ 0x03d5, 0x2000 },
{ 0x03d6, 0x0000 },
{ 0x03d7, 0x0000 },
{ 0x03d8, 0x2000 },
{ 0x03d9, 0x2000 },
{ 0x03da, 0x2000 },
{ 0x03db, 0x2000 },
{ 0x03dc, 0x0000 },
{ 0x03dd, 0x0000 },
{ 0x03de, 0x0000 },
{ 0x03df, 0x2000 },
{ 0x03e0, 0x0000 },
{ 0x03e1, 0x0000 },
{ 0x03e2, 0x0000 },
{ 0x03e3, 0x0000 },
{ 0x03e4, 0x0000 },
{ 0x03e5, 0x0000 },
{ 0x03e6, 0x0000 },
{ 0x03e7, 0x0000 },
{ 0x03e8, 0x0000 },
{ 0x03e9, 0x0000 },
{ 0x03ea, 0x0000 },
{ 0x03eb, 0x0000 },
{ 0x03ec, 0x0000 },
{ 0x03ed, 0x0000 },
{ 0x03ee, 0x0000 },
{ 0x03ef, 0x0000 },
{ 0x03f0, 0x0800 },
{ 0x03f1, 0x0800 },
{ 0x03f2, 0x0800 },
{ 0x03f3, 0x0800 },
};
static bool rt5663_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT5663_RESET:
case RT5663_SIL_DET_CTL:
case RT5663_HP_IMP_GAIN_2:
case RT5663_AD_DA_MIXER:
case RT5663_FRAC_DIV_2:
case RT5663_MICBIAS_1:
case RT5663_ASRC_11_2:
case RT5663_ADC_EQ_1:
case RT5663_INT_ST_1:
case RT5663_INT_ST_2:
case RT5663_GPIO_STA:
case RT5663_SIN_GEN_1:
case RT5663_IL_CMD_1:
case RT5663_IL_CMD_5:
case RT5663_IL_CMD_PWRSAV1:
case RT5663_EM_JACK_TYPE_1:
case RT5663_EM_JACK_TYPE_2:
case RT5663_EM_JACK_TYPE_3:
case RT5663_JD_CTRL2:
case RT5663_VENDOR_ID:
case RT5663_VENDOR_ID_1:
case RT5663_VENDOR_ID_2:
case RT5663_PLL_INT_REG:
case RT5663_SOFT_RAMP:
case RT5663_STO_DRE_1:
case RT5663_STO_DRE_5:
case RT5663_STO_DRE_6:
case RT5663_STO_DRE_7:
case RT5663_MIC_DECRO_1:
case RT5663_MIC_DECRO_4:
case RT5663_HP_IMP_SEN_1:
case RT5663_HP_IMP_SEN_3:
case RT5663_HP_IMP_SEN_4:
case RT5663_HP_IMP_SEN_5:
case RT5663_HP_CALIB_1_1:
case RT5663_HP_CALIB_9:
case RT5663_HP_CALIB_ST1:
case RT5663_HP_CALIB_ST2:
case RT5663_HP_CALIB_ST3:
case RT5663_HP_CALIB_ST4:
case RT5663_HP_CALIB_ST5:
case RT5663_HP_CALIB_ST6:
case RT5663_HP_CALIB_ST7:
case RT5663_HP_CALIB_ST8:
case RT5663_HP_CALIB_ST9:
case RT5663_ANA_JD:
return true;
default:
return false;
}
}
static bool rt5663_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT5663_RESET:
case RT5663_HP_OUT_EN:
case RT5663_HP_LCH_DRE:
case RT5663_HP_RCH_DRE:
case RT5663_CALIB_BST:
case RT5663_RECMIX:
case RT5663_SIL_DET_CTL:
case RT5663_PWR_SAV_SILDET:
case RT5663_SIDETONE_CTL:
case RT5663_STO1_DAC_DIG_VOL:
case RT5663_STO1_ADC_DIG_VOL:
case RT5663_STO1_BOOST:
case RT5663_HP_IMP_GAIN_1:
case RT5663_HP_IMP_GAIN_2:
case RT5663_STO1_ADC_MIXER:
case RT5663_AD_DA_MIXER:
case RT5663_STO_DAC_MIXER:
case RT5663_DIG_SIDE_MIXER:
case RT5663_BYPASS_STO_DAC:
case RT5663_CALIB_REC_MIX:
case RT5663_PWR_DIG_1:
case RT5663_PWR_DIG_2:
case RT5663_PWR_ANLG_1:
case RT5663_PWR_ANLG_2:
case RT5663_PWR_ANLG_3:
case RT5663_PWR_MIXER:
case RT5663_SIG_CLK_DET:
case RT5663_PRE_DIV_GATING_1:
case RT5663_PRE_DIV_GATING_2:
case RT5663_I2S1_SDP:
case RT5663_ADDA_CLK_1:
case RT5663_ADDA_RST:
case RT5663_FRAC_DIV_1:
case RT5663_FRAC_DIV_2:
case RT5663_TDM_1:
case RT5663_TDM_2:
case RT5663_TDM_3:
case RT5663_TDM_4:
case RT5663_TDM_5:
case RT5663_GLB_CLK:
case RT5663_PLL_1:
case RT5663_PLL_2:
case RT5663_ASRC_1:
case RT5663_ASRC_2:
case RT5663_ASRC_4:
case RT5663_DUMMY_REG:
case RT5663_ASRC_8:
case RT5663_ASRC_9:
case RT5663_ASRC_11:
case RT5663_DEPOP_1:
case RT5663_DEPOP_2:
case RT5663_DEPOP_3:
case RT5663_HP_CHARGE_PUMP_1:
case RT5663_HP_CHARGE_PUMP_2:
case RT5663_MICBIAS_1:
case RT5663_RC_CLK:
case RT5663_ASRC_11_2:
case RT5663_DUMMY_REG_2:
case RT5663_REC_PATH_GAIN:
case RT5663_AUTO_1MRC_CLK:
case RT5663_ADC_EQ_1:
case RT5663_ADC_EQ_2:
case RT5663_IRQ_1:
case RT5663_IRQ_2:
case RT5663_IRQ_3:
case RT5663_IRQ_4:
case RT5663_IRQ_5:
case RT5663_INT_ST_1:
case RT5663_INT_ST_2:
case RT5663_GPIO_1:
case RT5663_GPIO_2:
case RT5663_GPIO_STA:
case RT5663_SIN_GEN_1:
case RT5663_SIN_GEN_2:
case RT5663_SIN_GEN_3:
case RT5663_SOF_VOL_ZC1:
case RT5663_IL_CMD_1:
case RT5663_IL_CMD_2:
case RT5663_IL_CMD_3:
case RT5663_IL_CMD_4:
case RT5663_IL_CMD_5:
case RT5663_IL_CMD_6:
case RT5663_IL_CMD_7:
case RT5663_IL_CMD_8:
case RT5663_IL_CMD_PWRSAV1:
case RT5663_IL_CMD_PWRSAV2:
case RT5663_EM_JACK_TYPE_1:
case RT5663_EM_JACK_TYPE_2:
case RT5663_EM_JACK_TYPE_3:
case RT5663_EM_JACK_TYPE_4:
case RT5663_EM_JACK_TYPE_5:
case RT5663_EM_JACK_TYPE_6:
case RT5663_STO1_HPF_ADJ1:
case RT5663_STO1_HPF_ADJ2:
case RT5663_FAST_OFF_MICBIAS:
case RT5663_JD_CTRL1:
case RT5663_JD_CTRL2:
case RT5663_DIG_MISC:
case RT5663_VENDOR_ID:
case RT5663_VENDOR_ID_1:
case RT5663_VENDOR_ID_2:
case RT5663_DIG_VOL_ZCD:
case RT5663_ANA_BIAS_CUR_1:
case RT5663_ANA_BIAS_CUR_2:
case RT5663_ANA_BIAS_CUR_3:
case RT5663_ANA_BIAS_CUR_4:
case RT5663_ANA_BIAS_CUR_5:
case RT5663_ANA_BIAS_CUR_6:
case RT5663_BIAS_CUR_5:
case RT5663_BIAS_CUR_6:
case RT5663_BIAS_CUR_7:
case RT5663_BIAS_CUR_8:
case RT5663_DACREF_LDO:
case RT5663_DUMMY_REG_3:
case RT5663_BIAS_CUR_9:
case RT5663_DUMMY_REG_4:
case RT5663_VREFADJ_OP:
case RT5663_VREF_RECMIX:
case RT5663_CHARGE_PUMP_1:
case RT5663_CHARGE_PUMP_1_2:
case RT5663_CHARGE_PUMP_1_3:
case RT5663_CHARGE_PUMP_2:
case RT5663_DIG_IN_PIN1:
case RT5663_PAD_DRV_CTL:
case RT5663_PLL_INT_REG:
case RT5663_CHOP_DAC_L:
case RT5663_CHOP_ADC:
case RT5663_CALIB_ADC:
case RT5663_CHOP_DAC_R:
case RT5663_DUMMY_CTL_DACLR:
case RT5663_DUMMY_REG_5:
case RT5663_SOFT_RAMP:
case RT5663_TEST_MODE_1:
case RT5663_TEST_MODE_2:
case RT5663_TEST_MODE_3:
case RT5663_STO_DRE_1:
case RT5663_STO_DRE_2:
case RT5663_STO_DRE_3:
case RT5663_STO_DRE_4:
case RT5663_STO_DRE_5:
case RT5663_STO_DRE_6:
case RT5663_STO_DRE_7:
case RT5663_STO_DRE_8:
case RT5663_STO_DRE_9:
case RT5663_STO_DRE_10:
case RT5663_MIC_DECRO_1:
case RT5663_MIC_DECRO_2:
case RT5663_MIC_DECRO_3:
case RT5663_MIC_DECRO_4:
case RT5663_MIC_DECRO_5:
case RT5663_MIC_DECRO_6:
case RT5663_HP_DECRO_1:
case RT5663_HP_DECRO_2:
case RT5663_HP_DECRO_3:
case RT5663_HP_DECRO_4:
case RT5663_HP_DECOUP:
case RT5663_HP_IMP_SEN_MAP8:
case RT5663_HP_IMP_SEN_MAP9:
case RT5663_HP_IMP_SEN_MAP10:
case RT5663_HP_IMP_SEN_MAP11:
case RT5663_HP_IMP_SEN_1:
case RT5663_HP_IMP_SEN_2:
case RT5663_HP_IMP_SEN_3:
case RT5663_HP_IMP_SEN_4:
case RT5663_HP_IMP_SEN_5:
case RT5663_HP_IMP_SEN_6:
case RT5663_HP_IMP_SEN_7:
case RT5663_HP_IMP_SEN_8:
case RT5663_HP_IMP_SEN_9:
case RT5663_HP_IMP_SEN_10:
case RT5663_HP_IMP_SEN_11:
case RT5663_HP_IMP_SEN_12:
case RT5663_HP_IMP_SEN_13:
case RT5663_HP_IMP_SEN_14:
case RT5663_HP_IMP_SEN_15:
case RT5663_HP_IMP_SEN_16:
case RT5663_HP_IMP_SEN_17:
case RT5663_HP_IMP_SEN_18:
case RT5663_HP_IMP_SEN_19:
case RT5663_HP_IMPSEN_DIG5:
case RT5663_HP_IMPSEN_MAP1:
case RT5663_HP_IMPSEN_MAP2:
case RT5663_HP_IMPSEN_MAP3:
case RT5663_HP_IMPSEN_MAP4:
case RT5663_HP_IMPSEN_MAP5:
case RT5663_HP_IMPSEN_MAP7:
case RT5663_HP_LOGIC_1:
case RT5663_HP_LOGIC_2:
case RT5663_HP_CALIB_1:
case RT5663_HP_CALIB_1_1:
case RT5663_HP_CALIB_2:
case RT5663_HP_CALIB_3:
case RT5663_HP_CALIB_4:
case RT5663_HP_CALIB_5:
case RT5663_HP_CALIB_5_1:
case RT5663_HP_CALIB_6:
case RT5663_HP_CALIB_7:
case RT5663_HP_CALIB_9:
case RT5663_HP_CALIB_10:
case RT5663_HP_CALIB_11:
case RT5663_HP_CALIB_ST1:
case RT5663_HP_CALIB_ST2:
case RT5663_HP_CALIB_ST3:
case RT5663_HP_CALIB_ST4:
case RT5663_HP_CALIB_ST5:
case RT5663_HP_CALIB_ST6:
case RT5663_HP_CALIB_ST7:
case RT5663_HP_CALIB_ST8:
case RT5663_HP_CALIB_ST9:
case RT5663_HP_AMP_DET:
case RT5663_DUMMY_REG_6:
case RT5663_HP_BIAS:
case RT5663_CBJ_1:
case RT5663_CBJ_2:
case RT5663_CBJ_3:
case RT5663_DUMMY_1:
case RT5663_DUMMY_2:
case RT5663_DUMMY_3:
case RT5663_ANA_JD:
case RT5663_ADC_LCH_LPF1_A1:
case RT5663_ADC_RCH_LPF1_A1:
case RT5663_ADC_LCH_LPF1_H0:
case RT5663_ADC_RCH_LPF1_H0:
case RT5663_ADC_LCH_BPF1_A1:
case RT5663_ADC_RCH_BPF1_A1:
case RT5663_ADC_LCH_BPF1_A2:
case RT5663_ADC_RCH_BPF1_A2:
case RT5663_ADC_LCH_BPF1_H0:
case RT5663_ADC_RCH_BPF1_H0:
case RT5663_ADC_LCH_BPF2_A1:
case RT5663_ADC_RCH_BPF2_A1:
case RT5663_ADC_LCH_BPF2_A2:
case RT5663_ADC_RCH_BPF2_A2:
case RT5663_ADC_LCH_BPF2_H0:
case RT5663_ADC_RCH_BPF2_H0:
case RT5663_ADC_LCH_BPF3_A1:
case RT5663_ADC_RCH_BPF3_A1:
case RT5663_ADC_LCH_BPF3_A2:
case RT5663_ADC_RCH_BPF3_A2:
case RT5663_ADC_LCH_BPF3_H0:
case RT5663_ADC_RCH_BPF3_H0:
case RT5663_ADC_LCH_BPF4_A1:
case RT5663_ADC_RCH_BPF4_A1:
case RT5663_ADC_LCH_BPF4_A2:
case RT5663_ADC_RCH_BPF4_A2:
case RT5663_ADC_LCH_BPF4_H0:
case RT5663_ADC_RCH_BPF4_H0:
case RT5663_ADC_LCH_HPF1_A1:
case RT5663_ADC_RCH_HPF1_A1:
case RT5663_ADC_LCH_HPF1_H0:
case RT5663_ADC_RCH_HPF1_H0:
case RT5663_ADC_EQ_PRE_VOL_L:
case RT5663_ADC_EQ_PRE_VOL_R:
case RT5663_ADC_EQ_POST_VOL_L:
case RT5663_ADC_EQ_POST_VOL_R:
return true;
default:
return false;
}
}
static bool rt5668_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT5663_RESET:
case RT5668_CBJ_TYPE_2:
case RT5668_PDM_OUT_CTL:
case RT5668_PDM_I2C_DATA_CTL1:
case RT5668_PDM_I2C_DATA_CTL4:
case RT5668_ALC_BK_GAIN:
case RT5663_PLL_2:
case RT5663_MICBIAS_1:
case RT5663_ADC_EQ_1:
case RT5663_INT_ST_1:
case RT5668_GPIO_STA:
case RT5663_IL_CMD_1:
case RT5663_IL_CMD_5:
case RT5668_A_JD_CTRL:
case RT5663_JD_CTRL2:
case RT5663_VENDOR_ID:
case RT5663_VENDOR_ID_1:
case RT5663_VENDOR_ID_2:
case RT5663_STO_DRE_1:
case RT5663_STO_DRE_5:
case RT5663_STO_DRE_6:
case RT5663_STO_DRE_7:
case RT5668_MONO_DYNA_6:
case RT5668_STO1_SIL_DET:
case RT5668_MONOL_SIL_DET:
case RT5668_MONOR_SIL_DET:
case RT5668_STO2_DAC_SIL:
case RT5668_MONO_AMP_CAL_ST1:
case RT5668_MONO_AMP_CAL_ST2:
case RT5668_MONO_AMP_CAL_ST3:
case RT5668_MONO_AMP_CAL_ST4:
case RT5663_HP_IMP_SEN_2:
case RT5663_HP_IMP_SEN_3:
case RT5663_HP_IMP_SEN_4:
case RT5663_HP_IMP_SEN_10:
case RT5663_HP_CALIB_1:
case RT5663_HP_CALIB_10:
case RT5663_HP_CALIB_ST1:
case RT5663_HP_CALIB_ST4:
case RT5663_HP_CALIB_ST5:
case RT5663_HP_CALIB_ST6:
case RT5663_HP_CALIB_ST7:
case RT5663_HP_CALIB_ST8:
case RT5663_HP_CALIB_ST9:
case RT5668_HP_CALIB_ST10:
case RT5668_HP_CALIB_ST11:
return true;
default:
return false;
}
}
static bool rt5668_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case RT5668_LOUT_CTRL:
case RT5668_HP_AMP_2:
case RT5668_MONO_OUT:
case RT5668_MONO_GAIN:
case RT5668_AEC_BST:
case RT5668_IN1_IN2:
case RT5668_IN3_IN4:
case RT5668_INL1_INR1:
case RT5668_CBJ_TYPE_2:
case RT5668_CBJ_TYPE_3:
case RT5668_CBJ_TYPE_4:
case RT5668_CBJ_TYPE_5:
case RT5668_CBJ_TYPE_8:
case RT5668_DAC3_DIG_VOL:
case RT5668_DAC3_CTRL:
case RT5668_MONO_ADC_DIG_VOL:
case RT5668_STO2_ADC_DIG_VOL:
case RT5668_MONO_ADC_BST_GAIN:
case RT5668_STO2_ADC_BST_GAIN:
case RT5668_SIDETONE_CTRL:
case RT5668_MONO1_ADC_MIXER:
case RT5668_STO2_ADC_MIXER:
case RT5668_MONO_DAC_MIXER:
case RT5668_DAC2_SRC_CTRL:
case RT5668_IF_3_4_DATA_CTL:
case RT5668_IF_5_DATA_CTL:
case RT5668_PDM_OUT_CTL:
case RT5668_PDM_I2C_DATA_CTL1:
case RT5668_PDM_I2C_DATA_CTL2:
case RT5668_PDM_I2C_DATA_CTL3:
case RT5668_PDM_I2C_DATA_CTL4:
case RT5668_RECMIX1_NEW:
case RT5668_RECMIX1L_0:
case RT5668_RECMIX1L:
case RT5668_RECMIX1R_0:
case RT5668_RECMIX1R:
case RT5668_RECMIX2_NEW:
case RT5668_RECMIX2_L_2:
case RT5668_RECMIX2_R:
case RT5668_RECMIX2_R_2:
case RT5668_CALIB_REC_LR:
case RT5668_ALC_BK_GAIN:
case RT5668_MONOMIX_GAIN:
case RT5668_MONOMIX_IN_GAIN:
case RT5668_OUT_MIXL_GAIN:
case RT5668_OUT_LMIX_IN_GAIN:
case RT5668_OUT_RMIX_IN_GAIN:
case RT5668_OUT_RMIX_IN_GAIN1:
case RT5668_LOUT_MIXER_CTRL:
case RT5668_PWR_VOL:
case RT5668_ADCDAC_RST:
case RT5668_I2S34_SDP:
case RT5668_I2S5_SDP:
case RT5668_TDM_5:
case RT5668_TDM_6:
case RT5668_TDM_7:
case RT5668_TDM_8:
case RT5668_ASRC_3:
case RT5668_ASRC_6:
case RT5668_ASRC_7:
case RT5668_PLL_TRK_13:
case RT5668_I2S_M_CLK_CTL:
case RT5668_FDIV_I2S34_M_CLK:
case RT5668_FDIV_I2S34_M_CLK2:
case RT5668_FDIV_I2S5_M_CLK:
case RT5668_FDIV_I2S5_M_CLK2:
case RT5668_IRQ_4:
case RT5668_GPIO_3:
case RT5668_GPIO_4:
case RT5668_GPIO_STA:
case RT5668_HP_AMP_DET1:
case RT5668_HP_AMP_DET2:
case RT5668_HP_AMP_DET3:
case RT5668_MID_BD_HP_AMP:
case RT5668_LOW_BD_HP_AMP:
case RT5668_SOF_VOL_ZC2:
case RT5668_ADC_STO2_ADJ1:
case RT5668_ADC_STO2_ADJ2:
case RT5668_A_JD_CTRL:
case RT5668_JD1_TRES_CTRL:
case RT5668_JD2_TRES_CTRL:
case RT5668_JD_CTRL2:
case RT5668_DUM_REG_2:
case RT5668_DUM_REG_3:
case RT5663_VENDOR_ID:
case RT5663_VENDOR_ID_1:
case RT5663_VENDOR_ID_2:
case RT5668_DACADC_DIG_VOL2:
case RT5668_DIG_IN_PIN2:
case RT5668_PAD_DRV_CTL1:
case RT5668_SOF_RAM_DEPOP:
case RT5668_VOL_TEST:
case RT5668_TEST_MODE_3:
case RT5668_TEST_MODE_4:
case RT5663_STO_DRE_9:
case RT5668_MONO_DYNA_1:
case RT5668_MONO_DYNA_2:
case RT5668_MONO_DYNA_3:
case RT5668_MONO_DYNA_4:
case RT5668_MONO_DYNA_5:
case RT5668_MONO_DYNA_6:
case RT5668_STO1_SIL_DET:
case RT5668_MONOL_SIL_DET:
case RT5668_MONOR_SIL_DET:
case RT5668_STO2_DAC_SIL:
case RT5668_PWR_SAV_CTL1:
case RT5668_PWR_SAV_CTL2:
case RT5668_PWR_SAV_CTL3:
case RT5668_PWR_SAV_CTL4:
case RT5668_PWR_SAV_CTL5:
case RT5668_PWR_SAV_CTL6:
case RT5668_MONO_AMP_CAL1:
case RT5668_MONO_AMP_CAL2:
case RT5668_MONO_AMP_CAL3:
case RT5668_MONO_AMP_CAL4:
case RT5668_MONO_AMP_CAL5:
case RT5668_MONO_AMP_CAL6:
case RT5668_MONO_AMP_CAL7:
case RT5668_MONO_AMP_CAL_ST1:
case RT5668_MONO_AMP_CAL_ST2:
case RT5668_MONO_AMP_CAL_ST3:
case RT5668_MONO_AMP_CAL_ST4:
case RT5668_MONO_AMP_CAL_ST5:
case RT5668_HP_IMP_SEN_13:
case RT5668_HP_IMP_SEN_14:
case RT5668_HP_IMP_SEN_6:
case RT5668_HP_IMP_SEN_7:
case RT5668_HP_IMP_SEN_8:
case RT5668_HP_IMP_SEN_9:
case RT5668_HP_IMP_SEN_10:
case RT5668_HP_LOGIC_3:
case RT5668_HP_CALIB_ST10:
case RT5668_HP_CALIB_ST11:
case RT5668_PRO_REG_TBL_4:
case RT5668_PRO_REG_TBL_5:
case RT5668_PRO_REG_TBL_6:
case RT5668_PRO_REG_TBL_7:
case RT5668_PRO_REG_TBL_8:
case RT5668_PRO_REG_TBL_9:
case RT5668_SAR_ADC_INL_1:
case RT5668_SAR_ADC_INL_2:
case RT5668_SAR_ADC_INL_3:
case RT5668_SAR_ADC_INL_4:
case RT5668_SAR_ADC_INL_5:
case RT5668_SAR_ADC_INL_6:
case RT5668_SAR_ADC_INL_7:
case RT5668_SAR_ADC_INL_8:
case RT5668_SAR_ADC_INL_9:
case RT5668_SAR_ADC_INL_10:
case RT5668_SAR_ADC_INL_11:
case RT5668_SAR_ADC_INL_12:
case RT5668_DRC_CTRL_1:
case RT5668_DRC1_CTRL_2:
case RT5668_DRC1_CTRL_3:
case RT5668_DRC1_CTRL_4:
case RT5668_DRC1_CTRL_5:
case RT5668_DRC1_CTRL_6:
case RT5668_DRC1_HD_CTRL_1:
case RT5668_DRC1_HD_CTRL_2:
case RT5668_DRC1_PRI_REG_1:
case RT5668_DRC1_PRI_REG_2:
case RT5668_DRC1_PRI_REG_3:
case RT5668_DRC1_PRI_REG_4:
case RT5668_DRC1_PRI_REG_5:
case RT5668_DRC1_PRI_REG_6:
case RT5668_DRC1_PRI_REG_7:
case RT5668_DRC1_PRI_REG_8:
case RT5668_ALC_PGA_CTL_1:
case RT5668_ALC_PGA_CTL_2:
case RT5668_ALC_PGA_CTL_3:
case RT5668_ALC_PGA_CTL_4:
case RT5668_ALC_PGA_CTL_5:
case RT5668_ALC_PGA_CTL_6:
case RT5668_ALC_PGA_CTL_7:
case RT5668_ALC_PGA_CTL_8:
case RT5668_ALC_PGA_REG_1:
case RT5668_ALC_PGA_REG_2:
case RT5668_ALC_PGA_REG_3:
case RT5668_ADC_EQ_RECOV_1:
case RT5668_ADC_EQ_RECOV_2:
case RT5668_ADC_EQ_RECOV_3:
case RT5668_ADC_EQ_RECOV_4:
case RT5668_ADC_EQ_RECOV_5:
case RT5668_ADC_EQ_RECOV_6:
case RT5668_ADC_EQ_RECOV_7:
case RT5668_ADC_EQ_RECOV_8:
case RT5668_ADC_EQ_RECOV_9:
case RT5668_ADC_EQ_RECOV_10:
case RT5668_ADC_EQ_RECOV_11:
case RT5668_ADC_EQ_RECOV_12:
case RT5668_ADC_EQ_RECOV_13:
case RT5668_VID_HIDDEN:
case RT5668_VID_CUSTOMER:
case RT5668_SCAN_MODE:
case RT5668_I2C_BYPA:
return true;
case RT5663_TDM_1:
case RT5663_DEPOP_3:
case RT5663_ASRC_11_2:
case RT5663_INT_ST_2:
case RT5663_GPIO_STA:
case RT5663_SIN_GEN_1:
case RT5663_SIN_GEN_2:
case RT5663_SIN_GEN_3:
case RT5663_IL_CMD_PWRSAV1:
case RT5663_IL_CMD_PWRSAV2:
case RT5663_EM_JACK_TYPE_1:
case RT5663_EM_JACK_TYPE_2:
case RT5663_EM_JACK_TYPE_3:
case RT5663_EM_JACK_TYPE_4:
case RT5663_FAST_OFF_MICBIAS:
case RT5663_ANA_BIAS_CUR_1:
case RT5663_ANA_BIAS_CUR_2:
case RT5663_BIAS_CUR_9:
case RT5663_DUMMY_REG_4:
case RT5663_VREF_RECMIX:
case RT5663_CHARGE_PUMP_1_2:
case RT5663_CHARGE_PUMP_1_3:
case RT5663_CHARGE_PUMP_2:
case RT5663_CHOP_DAC_R:
case RT5663_DUMMY_CTL_DACLR:
case RT5663_DUMMY_REG_5:
case RT5663_SOFT_RAMP:
case RT5663_TEST_MODE_1:
case RT5663_STO_DRE_10:
case RT5663_MIC_DECRO_1:
case RT5663_MIC_DECRO_2:
case RT5663_MIC_DECRO_3:
case RT5663_MIC_DECRO_4:
case RT5663_MIC_DECRO_5:
case RT5663_MIC_DECRO_6:
case RT5663_HP_DECRO_1:
case RT5663_HP_DECRO_2:
case RT5663_HP_DECRO_3:
case RT5663_HP_DECRO_4:
case RT5663_HP_DECOUP:
case RT5663_HP_IMPSEN_MAP4:
case RT5663_HP_IMPSEN_MAP5:
case RT5663_HP_IMPSEN_MAP7:
case RT5663_HP_CALIB_1:
case RT5663_CBJ_1:
case RT5663_CBJ_2:
case RT5663_CBJ_3:
return false;
default:
return rt5663_readable_register(dev, reg);
}
}
static const DECLARE_TLV_DB_SCALE(rt5663_hp_vol_tlv, -2400, 150, 0);
static const DECLARE_TLV_DB_SCALE(rt5668_hp_vol_tlv, -2250, 150, 0);
static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0);
static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0);
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */
static const DECLARE_TLV_DB_RANGE(in_bst_tlv,
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0)
);
/* Interface data select */
static const char * const rt5663_if1_adc_data_select[] = {
"L/R", "R/L", "L/L", "R/R"
};
static SOC_ENUM_SINGLE_DECL(rt5663_if1_adc_enum, RT5663_TDM_2,
RT5663_DATA_SWAP_ADCDAT1_SHIFT, rt5663_if1_adc_data_select);
static void rt5663_enable_push_button_irq(struct snd_soc_codec *codec,
bool enable)
{
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
if (enable) {
snd_soc_update_bits(codec, RT5663_IL_CMD_6,
RT5668_EN_4BTN_INL_MASK, RT5668_EN_4BTN_INL_EN);
/* reset in-line command */
snd_soc_update_bits(codec, RT5663_IL_CMD_6,
RT5668_RESET_4BTN_INL_MASK,
RT5668_RESET_4BTN_INL_RESET);
snd_soc_update_bits(codec, RT5663_IL_CMD_6,
RT5668_RESET_4BTN_INL_MASK,
RT5668_RESET_4BTN_INL_NOR);
switch (rt5663->codec_type) {
case CODEC_TYPE_RT5668:
snd_soc_update_bits(codec, RT5663_IRQ_3,
RT5668_EN_IRQ_INLINE_MASK,
RT5668_EN_IRQ_INLINE_NOR);
break;
case CODEC_TYPE_RT5663:
snd_soc_update_bits(codec, RT5663_IRQ_2,
RT5663_EN_IRQ_INLINE_MASK,
RT5663_EN_IRQ_INLINE_NOR);
break;
default:
dev_err(codec->dev, "Unknown CODEC_TYPE\n");
}
} else {
switch (rt5663->codec_type) {
case CODEC_TYPE_RT5668:
snd_soc_update_bits(codec, RT5663_IRQ_3,
RT5668_EN_IRQ_INLINE_MASK,
RT5668_EN_IRQ_INLINE_BYP);
break;
case CODEC_TYPE_RT5663:
snd_soc_update_bits(codec, RT5663_IRQ_2,
RT5663_EN_IRQ_INLINE_MASK,
RT5663_EN_IRQ_INLINE_BYP);
break;
default:
dev_err(codec->dev, "Unknown CODEC_TYPE\n");
}
snd_soc_update_bits(codec, RT5663_IL_CMD_6,
RT5668_EN_4BTN_INL_MASK, RT5668_EN_4BTN_INL_DIS);
/* reset in-line command */
snd_soc_update_bits(codec, RT5663_IL_CMD_6,
RT5668_RESET_4BTN_INL_MASK,
RT5668_RESET_4BTN_INL_RESET);
snd_soc_update_bits(codec, RT5663_IL_CMD_6,
RT5668_RESET_4BTN_INL_MASK,
RT5668_RESET_4BTN_INL_NOR);
}
}
/**
* rt5668_jack_detect - Detect headset.
* @codec: SoC audio codec device.
* @jack_insert: Jack insert or not.
*
* Detect whether is headset or not when jack inserted.
*
* Returns detect status.
*/
static int rt5668_jack_detect(struct snd_soc_codec *codec, int jack_insert)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct rt5663_priv *rt5668 = snd_soc_codec_get_drvdata(codec);
int val, i = 0, sleep_time[5] = {300, 150, 100, 50, 30};
dev_dbg(codec->dev, "%s jack_insert:%d\n", __func__, jack_insert);
if (jack_insert) {
snd_soc_write(codec, RT5668_CBJ_TYPE_2, 0x8040);
snd_soc_write(codec, RT5668_CBJ_TYPE_3, 0x1484);
snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1");
snd_soc_dapm_force_enable_pin(dapm, "MICBIAS2");
snd_soc_dapm_force_enable_pin(dapm, "Mic Det Power");
snd_soc_dapm_force_enable_pin(dapm, "CBJ Power");
snd_soc_dapm_sync(dapm);
snd_soc_update_bits(codec, RT5663_RC_CLK,
RT5668_DIG_1M_CLK_MASK, RT5668_DIG_1M_CLK_EN);
snd_soc_update_bits(codec, RT5663_RECMIX, 0x8, 0x8);
while (i < 5) {
msleep(sleep_time[i]);
val = snd_soc_read(codec, RT5668_CBJ_TYPE_2) & 0x0003;
if (val == 0x1 || val == 0x2 || val == 0x3)
break;
dev_dbg(codec->dev, "%s: MX-0011 val=%x sleep %d\n",
__func__, val, sleep_time[i]);
i++;
}
dev_dbg(codec->dev, "%s val = %d\n", __func__, val);
switch (val) {
case 1:
case 2:
rt5668->jack_type = SND_JACK_HEADSET;
rt5663_enable_push_button_irq(codec, true);
break;
default:
snd_soc_dapm_disable_pin(dapm, "MICBIAS1");
snd_soc_dapm_disable_pin(dapm, "MICBIAS2");
snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
snd_soc_dapm_disable_pin(dapm, "CBJ Power");
snd_soc_dapm_sync(dapm);
rt5668->jack_type = SND_JACK_HEADPHONE;
break;
}
} else {
snd_soc_update_bits(codec, RT5663_RECMIX, 0x8, 0x0);
if (rt5668->jack_type == SND_JACK_HEADSET) {
rt5663_enable_push_button_irq(codec, false);
snd_soc_dapm_disable_pin(dapm, "MICBIAS1");
snd_soc_dapm_disable_pin(dapm, "MICBIAS2");
snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
snd_soc_dapm_disable_pin(dapm, "CBJ Power");
snd_soc_dapm_sync(dapm);
}
rt5668->jack_type = 0;
}
dev_dbg(codec->dev, "jack_type = %d\n", rt5668->jack_type);
return rt5668->jack_type;
}
/**
* rt5663_jack_detect - Detect headset.
* @codec: SoC audio codec device.
* @jack_insert: Jack insert or not.
*
* Detect whether is headset or not when jack inserted.
*
* Returns detect status.
*/
static int rt5663_jack_detect(struct snd_soc_codec *codec, int jack_insert)
{
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
int val, i = 0, sleep_time[5] = {300, 150, 100, 50, 30};
dev_dbg(codec->dev, "%s jack_insert:%d\n", __func__, jack_insert);
if (jack_insert) {
snd_soc_update_bits(codec, RT5663_DIG_MISC,
RT5668_DIG_GATE_CTRL_MASK, RT5668_DIG_GATE_CTRL_EN);
snd_soc_update_bits(codec, RT5663_HP_CHARGE_PUMP_1,
RT5663_SI_HP_MASK | RT5668_OSW_HP_L_MASK |
RT5668_OSW_HP_R_MASK, RT5663_SI_HP_EN |
RT5668_OSW_HP_L_DIS | RT5668_OSW_HP_R_DIS);
snd_soc_update_bits(codec, RT5663_DUMMY_1,
RT5663_EMB_CLK_MASK | RT5663_HPA_CPL_BIAS_MASK |
RT5663_HPA_CPR_BIAS_MASK, RT5663_EMB_CLK_EN |
RT5663_HPA_CPL_BIAS_1 | RT5663_HPA_CPR_BIAS_1);
snd_soc_update_bits(codec, RT5663_CBJ_1,
RT5663_INBUF_CBJ_BST1_MASK | RT5663_CBJ_SENSE_BST1_MASK,
RT5663_INBUF_CBJ_BST1_ON | RT5663_CBJ_SENSE_BST1_L);
snd_soc_update_bits(codec, RT5663_IL_CMD_2,
RT5663_PWR_MIC_DET_MASK, RT5663_PWR_MIC_DET_ON);
/* BST1 power on for JD */
snd_soc_update_bits(codec, RT5663_PWR_ANLG_2,
RT5668_PWR_BST1_MASK, RT5668_PWR_BST1_ON);
snd_soc_update_bits(codec, RT5663_EM_JACK_TYPE_1,
RT5663_CBJ_DET_MASK | RT5663_EXT_JD_MASK |
RT5663_POL_EXT_JD_MASK, RT5663_CBJ_DET_EN |
RT5663_EXT_JD_EN | RT5663_POL_EXT_JD_EN);
snd_soc_update_bits(codec, RT5663_PWR_ANLG_1,
RT5668_PWR_MB_MASK | RT5668_LDO1_DVO_MASK |
RT5668_AMP_HP_MASK, RT5668_PWR_MB |
RT5668_LDO1_DVO_0_9V | RT5668_AMP_HP_3X);
snd_soc_update_bits(codec, RT5663_AUTO_1MRC_CLK,
RT5668_IRQ_POW_SAV_MASK, RT5668_IRQ_POW_SAV_EN);
snd_soc_update_bits(codec, RT5663_IRQ_1,
RT5663_EN_IRQ_JD1_MASK, RT5663_EN_IRQ_JD1_EN);
while (i < 5) {
msleep(sleep_time[i]);
val = snd_soc_read(codec, RT5663_EM_JACK_TYPE_2) &
0x0003;
i++;
if (val == 0x1 || val == 0x2 || val == 0x3)
break;
dev_dbg(codec->dev, "%s: MX-00e7 val=%x sleep %d\n",
__func__, val, sleep_time[i]);
}
dev_dbg(codec->dev, "%s val = %d\n", __func__, val);
switch (val) {
case 1:
case 2:
rt5663->jack_type = SND_JACK_HEADSET;
rt5663_enable_push_button_irq(codec, true);
break;
default:
rt5663->jack_type = SND_JACK_HEADPHONE;
break;
}
} else {
if (rt5663->jack_type == SND_JACK_HEADSET)
rt5663_enable_push_button_irq(codec, false);
rt5663->jack_type = 0;
}
dev_dbg(codec->dev, "jack_type = %d\n", rt5663->jack_type);
return rt5663->jack_type;
}
static int rt5663_button_detect(struct snd_soc_codec *codec)
{
int btn_type, val;
val = snd_soc_read(codec, RT5663_IL_CMD_5);
dev_dbg(codec->dev, "%s: val=0x%x\n", __func__, val);
btn_type = val & 0xfff0;
snd_soc_write(codec, RT5663_IL_CMD_5, val);
return btn_type;
}
static irqreturn_t rt5663_irq(int irq, void *data)
{
struct rt5663_priv *rt5663 = data;
dev_dbg(rt5663->codec->dev, "%s IRQ queue work\n", __func__);
queue_delayed_work(system_wq, &rt5663->jack_detect_work,
msecs_to_jiffies(250));
return IRQ_HANDLED;
}
int rt5663_set_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *hs_jack)
{
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
rt5663->hs_jack = hs_jack;
rt5663_irq(0, rt5663);
return 0;
}
EXPORT_SYMBOL_GPL(rt5663_set_jack_detect);
static bool rt5663_check_jd_status(struct snd_soc_codec *codec)
{
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
int val = snd_soc_read(codec, RT5663_INT_ST_1);
dev_dbg(codec->dev, "%s val=%x\n", __func__, val);
/* JD1 */
switch (rt5663->codec_type) {
case CODEC_TYPE_RT5668:
return !(val & 0x2000);
case CODEC_TYPE_RT5663:
return !(val & 0x1000);
default:
dev_err(codec->dev, "Unknown CODEC_TYPE\n");
}
return false;
}
static void rt5663_jack_detect_work(struct work_struct *work)
{
struct rt5663_priv *rt5663 =
container_of(work, struct rt5663_priv, jack_detect_work.work);
struct snd_soc_codec *codec = rt5663->codec;
int btn_type, report = 0;
if (!codec)
return;
if (rt5663_check_jd_status(codec)) {
/* jack in */
if (rt5663->jack_type == 0) {
/* jack was out, report jack type */
switch (rt5663->codec_type) {
case CODEC_TYPE_RT5668:
report = rt5668_jack_detect(rt5663->codec, 1);
break;
case CODEC_TYPE_RT5663:
report = rt5663_jack_detect(rt5663->codec, 1);
break;
default:
dev_err(codec->dev, "Unknown CODEC_TYPE\n");
}
} else {
/* jack is already in, report button event */
report = SND_JACK_HEADSET;
btn_type = rt5663_button_detect(rt5663->codec);
/**
* rt5663 can report three kinds of button behavior,
* one click, double click and hold. However,
* currently we will report button pressed/released
* event. So all the three button behaviors are
* treated as button pressed.
*/
switch (btn_type) {
case 0x8000:
case 0x4000:
case 0x2000:
report |= SND_JACK_BTN_0;
break;
case 0x1000:
case 0x0800:
case 0x0400:
report |= SND_JACK_BTN_1;
break;
case 0x0200:
case 0x0100:
case 0x0080:
report |= SND_JACK_BTN_2;
break;
case 0x0040:
case 0x0020:
case 0x0010:
report |= SND_JACK_BTN_3;
break;
case 0x0000: /* unpressed */
break;
default:
btn_type = 0;
dev_err(rt5663->codec->dev,
"Unexpected button code 0x%04x\n",
btn_type);
break;
}
/* button release or spurious interrput*/
if (btn_type == 0)
report = rt5663->jack_type;
}
} else {
/* jack out */
switch (rt5663->codec_type) {
case CODEC_TYPE_RT5668:
report = rt5668_jack_detect(rt5663->codec, 0);
break;
case CODEC_TYPE_RT5663:
report = rt5663_jack_detect(rt5663->codec, 0);
break;
default:
dev_err(codec->dev, "Unknown CODEC_TYPE\n");
}
}
dev_dbg(codec->dev, "%s jack report: 0x%04x\n", __func__, report);
snd_soc_jack_report(rt5663->hs_jack, report, SND_JACK_HEADSET |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3);
}
static const struct snd_kcontrol_new rt5663_snd_controls[] = {
/* DAC Digital Volume */
SOC_DOUBLE_TLV("DAC Playback Volume", RT5663_STO1_DAC_DIG_VOL,
RT5668_DAC_L1_VOL_SHIFT + 1, RT5668_DAC_R1_VOL_SHIFT + 1,
87, 0, dac_vol_tlv),
/* ADC Digital Volume Control */
SOC_DOUBLE("ADC Capture Switch", RT5663_STO1_ADC_DIG_VOL,
RT5668_ADC_L_MUTE_SHIFT, RT5668_ADC_R_MUTE_SHIFT, 1, 1),
SOC_DOUBLE_TLV("ADC Capture Volume", RT5663_STO1_ADC_DIG_VOL,
RT5668_ADC_L_VOL_SHIFT + 1, RT5668_ADC_R_VOL_SHIFT + 1,
63, 0, adc_vol_tlv),
};
static const struct snd_kcontrol_new rt5668_specific_controls[] = {
/* Headphone Output Volume */
SOC_DOUBLE_R_TLV("Headphone Playback Volume", RT5663_HP_LCH_DRE,
RT5663_HP_RCH_DRE, RT5668_GAIN_HP_SHIFT, 15, 1,
rt5668_hp_vol_tlv),
/* Mic Boost Volume */
SOC_SINGLE_TLV("IN1 Capture Volume", RT5668_AEC_BST,
RT5668_GAIN_CBJ_SHIFT, 8, 0, in_bst_tlv),
};
static const struct snd_kcontrol_new rt5663_specific_controls[] = {
/* Headphone Output Volume */
SOC_DOUBLE_R_TLV("Headphone Playback Volume", RT5663_STO_DRE_9,
RT5663_STO_DRE_10, RT5663_DRE_GAIN_HP_SHIFT, 23, 1,
rt5663_hp_vol_tlv),
/* Mic Boost Volume*/
SOC_SINGLE_TLV("IN1 Capture Volume", RT5663_CBJ_2,
RT5663_GAIN_BST1_SHIFT, 8, 0, in_bst_tlv),
/* Data Swap for Slot0/1 in ADCDAT1 */
SOC_ENUM("IF1 ADC Data Swap", rt5663_if1_adc_enum),
};
static int rt5663_is_sys_clk_from_pll(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_widget *sink)
{
unsigned int val;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
val = snd_soc_read(codec, RT5663_GLB_CLK);
val &= RT5663_SCLK_SRC_MASK;
if (val == RT5663_SCLK_SRC_PLL1)
return 1;
else
return 0;
}
static int rt5663_is_using_asrc(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_widget *sink)
{
unsigned int reg, shift, val;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
if (rt5663->codec_type == CODEC_TYPE_RT5668) {
switch (w->shift) {
case RT5668_ADC_STO1_ASRC_SHIFT:
reg = RT5668_ASRC_3;
shift = RT5668_AD_STO1_TRACK_SHIFT;
break;
case RT5668_DAC_STO1_ASRC_SHIFT:
reg = RT5663_ASRC_2;
shift = RT5668_DA_STO1_TRACK_SHIFT;
break;
default:
return 0;
}
} else {
switch (w->shift) {
case RT5663_ADC_STO1_ASRC_SHIFT:
reg = RT5663_ASRC_2;
shift = RT5663_AD_STO1_TRACK_SHIFT;
break;
case RT5663_DAC_STO1_ASRC_SHIFT:
reg = RT5663_ASRC_2;
shift = RT5663_DA_STO1_TRACK_SHIFT;
break;
default:
return 0;
}
}
val = (snd_soc_read(codec, reg) >> shift) & 0x7;
if (val)
return 1;
return 0;
}
static int rt5663_i2s_use_asrc(struct snd_soc_dapm_widget *source,
struct snd_soc_dapm_widget *sink)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
int da_asrc_en, ad_asrc_en;
da_asrc_en = (snd_soc_read(codec, RT5663_ASRC_2) &
RT5663_DA_STO1_TRACK_MASK) ? 1 : 0;
switch (rt5663->codec_type) {
case CODEC_TYPE_RT5668:
ad_asrc_en = (snd_soc_read(codec, RT5668_ASRC_3) &
RT5668_AD_STO1_TRACK_MASK) ? 1 : 0;
break;
case CODEC_TYPE_RT5663:
ad_asrc_en = (snd_soc_read(codec, RT5663_ASRC_2) &
RT5663_AD_STO1_TRACK_MASK) ? 1 : 0;
break;
default:
dev_err(codec->dev, "Unknown CODEC_TYPE\n");
return 1;
}
if (da_asrc_en || ad_asrc_en)
if (rt5663->sysclk > rt5663->lrck * 384)
return 1;
dev_err(codec->dev, "sysclk < 384 x fs, disable i2s asrc\n");
return 0;
}
/**
* rt5663_sel_asrc_clk_src - select ASRC clock source for a set of filters
* @codec: SoC audio codec device.
* @filter_mask: mask of filters.
* @clk_src: clock source
*
* The ASRC function is for asynchronous MCLK and LRCK. Also, since RT5668 can
* only support standard 32fs or 64fs i2s format, ASRC should be enabled to
* support special i2s clock format such as Intel's 100fs(100 * sampling rate).
* ASRC function will track i2s clock and generate a corresponding system clock
* for codec. This function provides an API to select the clock source for a
* set of filters specified by the mask. And the codec driver will turn on ASRC
* for these filters if ASRC is selected as their clock source.
*/
int rt5663_sel_asrc_clk_src(struct snd_soc_codec *codec,
unsigned int filter_mask, unsigned int clk_src)
{
struct rt5663_priv *rt5668 = snd_soc_codec_get_drvdata(codec);
unsigned int asrc2_mask = 0;
unsigned int asrc2_value = 0;
unsigned int asrc3_mask = 0;
unsigned int asrc3_value = 0;
switch (clk_src) {
case RT5663_CLK_SEL_SYS:
case RT5663_CLK_SEL_I2S1_ASRC:
break;
default:
return -EINVAL;
}
if (filter_mask & RT5663_DA_STEREO_FILTER) {
asrc2_mask |= RT5668_DA_STO1_TRACK_MASK;
asrc2_value |= clk_src << RT5668_DA_STO1_TRACK_SHIFT;
}
if (filter_mask & RT5663_AD_STEREO_FILTER) {
switch (rt5668->codec_type) {
case CODEC_TYPE_RT5668:
asrc3_mask |= RT5668_AD_STO1_TRACK_MASK;
asrc3_value |= clk_src << RT5668_AD_STO1_TRACK_SHIFT;
break;
case CODEC_TYPE_RT5663:
asrc2_mask |= RT5663_AD_STO1_TRACK_MASK;
asrc2_value |= clk_src << RT5663_AD_STO1_TRACK_SHIFT;
break;
default:
dev_err(codec->dev, "Unknown CODEC_TYPE\n");
}
}
if (asrc2_mask)
snd_soc_update_bits(codec, RT5663_ASRC_2, asrc2_mask,
asrc2_value);
if (asrc3_mask)
snd_soc_update_bits(codec, RT5668_ASRC_3, asrc3_mask,
asrc3_value);
return 0;
}
EXPORT_SYMBOL_GPL(rt5663_sel_asrc_clk_src);
/* Analog Mixer */
static const struct snd_kcontrol_new rt5668_recmix1l[] = {
SOC_DAPM_SINGLE("BST2 Switch", RT5668_RECMIX1L,
RT5668_RECMIX1L_BST2_SHIFT, 1, 1),
SOC_DAPM_SINGLE("BST1 CBJ Switch", RT5668_RECMIX1L,
RT5668_RECMIX1L_BST1_CBJ_SHIFT, 1, 1),
};
static const struct snd_kcontrol_new rt5668_recmix1r[] = {
SOC_DAPM_SINGLE("BST2 Switch", RT5668_RECMIX1R,
RT5668_RECMIX1R_BST2_SHIFT, 1, 1),
};
/* Digital Mixer */
static const struct snd_kcontrol_new rt5663_sto1_adc_l_mix[] = {
SOC_DAPM_SINGLE("ADC1 Switch", RT5663_STO1_ADC_MIXER,
RT5668_M_STO1_ADC_L1_SHIFT, 1, 1),
SOC_DAPM_SINGLE("ADC2 Switch", RT5663_STO1_ADC_MIXER,
RT5668_M_STO1_ADC_L2_SHIFT, 1, 1),
};
static const struct snd_kcontrol_new rt5668_sto1_adc_r_mix[] = {
SOC_DAPM_SINGLE("ADC1 Switch", RT5663_STO1_ADC_MIXER,
RT5668_M_STO1_ADC_R1_SHIFT, 1, 1),
SOC_DAPM_SINGLE("ADC2 Switch", RT5663_STO1_ADC_MIXER,
RT5668_M_STO1_ADC_R2_SHIFT, 1, 1),
};
static const struct snd_kcontrol_new rt5663_adda_l_mix[] = {
SOC_DAPM_SINGLE("ADC L Switch", RT5663_AD_DA_MIXER,
RT5668_M_ADCMIX_L_SHIFT, 1, 1),
SOC_DAPM_SINGLE("DAC L Switch", RT5663_AD_DA_MIXER,
RT5668_M_DAC1_L_SHIFT, 1, 1),
};
static const struct snd_kcontrol_new rt5663_adda_r_mix[] = {
SOC_DAPM_SINGLE("ADC R Switch", RT5663_AD_DA_MIXER,
RT5668_M_ADCMIX_R_SHIFT, 1, 1),
SOC_DAPM_SINGLE("DAC R Switch", RT5663_AD_DA_MIXER,
RT5668_M_DAC1_R_SHIFT, 1, 1),
};
static const struct snd_kcontrol_new rt5663_sto1_dac_l_mix[] = {
SOC_DAPM_SINGLE("DAC L Switch", RT5663_STO_DAC_MIXER,
RT5668_M_DAC_L1_STO_L_SHIFT, 1, 1),
SOC_DAPM_SINGLE("DAC R Switch", RT5663_STO_DAC_MIXER,
RT5668_M_DAC_R1_STO_L_SHIFT, 1, 1),
};
static const struct snd_kcontrol_new rt5663_sto1_dac_r_mix[] = {
SOC_DAPM_SINGLE("DAC L Switch", RT5663_STO_DAC_MIXER,
RT5668_M_DAC_L1_STO_R_SHIFT, 1, 1),
SOC_DAPM_SINGLE("DAC R Switch", RT5663_STO_DAC_MIXER,
RT5668_M_DAC_R1_STO_R_SHIFT, 1, 1),
};
/* Out Switch */
static const struct snd_kcontrol_new rt5668_hpo_switch =
SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5668_HP_AMP_2,
RT5668_EN_DAC_HPO_SHIFT, 1, 0);
/* Stereo ADC source */
static const char * const rt5668_sto1_adc_src[] = {
"ADC L", "ADC R"
};
static SOC_ENUM_SINGLE_DECL(rt5668_sto1_adcl_enum, RT5663_STO1_ADC_MIXER,
RT5668_STO1_ADC_L_SRC_SHIFT, rt5668_sto1_adc_src);
static const struct snd_kcontrol_new rt5668_sto1_adcl_mux =
SOC_DAPM_ENUM("STO1 ADC L Mux", rt5668_sto1_adcl_enum);
static SOC_ENUM_SINGLE_DECL(rt5668_sto1_adcr_enum, RT5663_STO1_ADC_MIXER,
RT5668_STO1_ADC_R_SRC_SHIFT, rt5668_sto1_adc_src);
static const struct snd_kcontrol_new rt5668_sto1_adcr_mux =
SOC_DAPM_ENUM("STO1 ADC R Mux", rt5668_sto1_adcr_enum);
/* RT5663: Analog DACL1 input source */
static const char * const rt5663_alg_dacl_src[] = {
"DAC L", "STO DAC MIXL"
};
static SOC_ENUM_SINGLE_DECL(rt5663_alg_dacl_enum, RT5663_BYPASS_STO_DAC,
RT5663_DACL1_SRC_SHIFT, rt5663_alg_dacl_src);
static const struct snd_kcontrol_new rt5663_alg_dacl_mux =
SOC_DAPM_ENUM("DAC L Mux", rt5663_alg_dacl_enum);
/* RT5663: Analog DACR1 input source */
static const char * const rt5663_alg_dacr_src[] = {
"DAC R", "STO DAC MIXR"
};
static SOC_ENUM_SINGLE_DECL(rt5663_alg_dacr_enum, RT5663_BYPASS_STO_DAC,
RT5663_DACR1_SRC_SHIFT, rt5663_alg_dacr_src);
static const struct snd_kcontrol_new rt5663_alg_dacr_mux =
SOC_DAPM_ENUM("DAC R Mux", rt5663_alg_dacr_enum);
static int rt5663_hp_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 rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
if (rt5663->codec_type == CODEC_TYPE_RT5668) {
snd_soc_update_bits(codec, RT5663_HP_CHARGE_PUMP_1,
RT5668_SEL_PM_HP_SHIFT, RT5668_SEL_PM_HP_HIGH);
snd_soc_update_bits(codec, RT5663_HP_LOGIC_2,
RT5668_HP_SIG_SRC1_MASK,
RT5668_HP_SIG_SRC1_SILENCE);
} else {
snd_soc_write(codec, RT5663_DEPOP_2, 0x3003);
snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x000b,
0x000b);
snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x0030,
0x0030);
snd_soc_update_bits(codec, RT5663_HP_CHARGE_PUMP_1,
RT5668_OVCD_HP_MASK, RT5668_OVCD_HP_DIS);
snd_soc_write(codec, RT5663_HP_CHARGE_PUMP_2, 0x1371);
snd_soc_write(codec, RT5663_HP_BIAS, 0xabba);
snd_soc_write(codec, RT5663_CHARGE_PUMP_1, 0x2224);
snd_soc_write(codec, RT5663_ANA_BIAS_CUR_1, 0x7766);
snd_soc_write(codec, RT5663_HP_BIAS, 0xafaa);
snd_soc_write(codec, RT5663_CHARGE_PUMP_2, 0x7777);
snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x3000,
0x3000);
}
break;
case SND_SOC_DAPM_PRE_PMD:
if (rt5663->codec_type == CODEC_TYPE_RT5668) {
snd_soc_update_bits(codec, RT5663_HP_LOGIC_2,
RT5668_HP_SIG_SRC1_MASK,
RT5668_HP_SIG_SRC1_REG);
} else {
snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x3000, 0x0);
snd_soc_update_bits(codec, RT5663_HP_CHARGE_PUMP_1,
RT5668_OVCD_HP_MASK, RT5668_OVCD_HP_EN);
snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x0030, 0x0);
snd_soc_update_bits(codec, RT5663_DEPOP_1, 0x000b,
0x000b);
}
break;
default:
return 0;
}
return 0;
}
static int rt5668_bst2_power(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
snd_soc_update_bits(codec, RT5663_PWR_ANLG_2,
RT5668_PWR_BST2_MASK | RT5668_PWR_BST2_OP_MASK,
RT5668_PWR_BST2 | RT5668_PWR_BST2_OP);
break;
case SND_SOC_DAPM_PRE_PMD:
snd_soc_update_bits(codec, RT5663_PWR_ANLG_2,
RT5668_PWR_BST2_MASK | RT5668_PWR_BST2_OP_MASK, 0);
break;
default:
return 0;
}
return 0;
}
static int rt5663_pre_div_power(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
snd_soc_write(codec, RT5663_PRE_DIV_GATING_1, 0xff00);
snd_soc_write(codec, RT5663_PRE_DIV_GATING_2, 0xfffc);
break;
case SND_SOC_DAPM_PRE_PMD:
snd_soc_write(codec, RT5663_PRE_DIV_GATING_1, 0x0000);
snd_soc_write(codec, RT5663_PRE_DIV_GATING_2, 0x0000);
break;
default:
return 0;
}
return 0;
}
static const struct snd_soc_dapm_widget rt5663_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("PLL", RT5663_PWR_ANLG_3, RT5668_PWR_PLL_SHIFT, 0,
NULL, 0),
/* micbias */
SND_SOC_DAPM_MICBIAS("MICBIAS1", RT5663_PWR_ANLG_2,
RT5668_PWR_MB1_SHIFT, 0),
SND_SOC_DAPM_MICBIAS("MICBIAS2", RT5663_PWR_ANLG_2,
RT5668_PWR_MB2_SHIFT, 0),
/* Input Lines */
SND_SOC_DAPM_INPUT("IN1P"),
SND_SOC_DAPM_INPUT("IN1N"),
/* REC Mixer Power */
SND_SOC_DAPM_SUPPLY("RECMIX1L Power", RT5663_PWR_ANLG_2,
RT5668_PWR_RECMIX1_SHIFT, 0, NULL, 0),
/* ADCs */
SND_SOC_DAPM_ADC("ADC L", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_SUPPLY("ADC L Power", RT5663_PWR_DIG_1,
RT5668_PWR_ADC_L1_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC Clock", RT5663_CHOP_ADC,
RT5668_CKGEN_ADCC_SHIFT, 0, NULL, 0),
/* ADC Mixer */
SND_SOC_DAPM_MIXER("STO1 ADC MIXL", SND_SOC_NOPM,
0, 0, rt5663_sto1_adc_l_mix,
ARRAY_SIZE(rt5663_sto1_adc_l_mix)),
/* ADC Filter Power */
SND_SOC_DAPM_SUPPLY("STO1 ADC Filter", RT5663_PWR_DIG_2,
RT5668_PWR_ADC_S1F_SHIFT, 0, NULL, 0),
/* Digital Interface */
SND_SOC_DAPM_SUPPLY("I2S", RT5663_PWR_DIG_1, RT5668_PWR_I2S1_SHIFT, 0,
NULL, 0),
SND_SOC_DAPM_PGA("IF DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF1 ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF ADC", SND_SOC_NOPM, 0, 0, NULL, 0),
/* Audio Interface */
SND_SOC_DAPM_AIF_IN("AIFRX", "AIF Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("AIFTX", "AIF Capture", 0, SND_SOC_NOPM, 0, 0),
/* DAC mixer before sound effect */
SND_SOC_DAPM_MIXER("ADDA MIXL", SND_SOC_NOPM, 0, 0, rt5663_adda_l_mix,
ARRAY_SIZE(rt5663_adda_l_mix)),
SND_SOC_DAPM_MIXER("ADDA MIXR", SND_SOC_NOPM, 0, 0, rt5663_adda_r_mix,
ARRAY_SIZE(rt5663_adda_r_mix)),
SND_SOC_DAPM_PGA("DAC L1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("DAC R1", SND_SOC_NOPM, 0, 0, NULL, 0),
/* DAC Mixer */
SND_SOC_DAPM_SUPPLY("STO1 DAC Filter", RT5663_PWR_DIG_2,
RT5668_PWR_DAC_S1F_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_MIXER("STO1 DAC MIXL", SND_SOC_NOPM, 0, 0,
rt5663_sto1_dac_l_mix, ARRAY_SIZE(rt5663_sto1_dac_l_mix)),
SND_SOC_DAPM_MIXER("STO1 DAC MIXR", SND_SOC_NOPM, 0, 0,
rt5663_sto1_dac_r_mix, ARRAY_SIZE(rt5663_sto1_dac_r_mix)),
/* DACs */
SND_SOC_DAPM_SUPPLY("STO1 DAC L Power", RT5663_PWR_DIG_1,
RT5668_PWR_DAC_L1_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("STO1 DAC R Power", RT5663_PWR_DIG_1,
RT5668_PWR_DAC_R1_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_DAC("DAC L", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_DAC("DAC R", NULL, SND_SOC_NOPM, 0, 0),
/* Headphone*/
SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, rt5663_hp_event,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
/* Output Lines */
SND_SOC_DAPM_OUTPUT("HPOL"),
SND_SOC_DAPM_OUTPUT("HPOR"),
};
static const struct snd_soc_dapm_widget rt5668_specific_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("LDO2", RT5663_PWR_ANLG_3,
RT5668_PWR_LDO2_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Mic Det Power", RT5668_PWR_VOL,
RT5668_PWR_MIC_DET_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("LDO DAC", RT5663_PWR_DIG_1,
RT5668_PWR_LDO_DACREF_SHIFT, 0, NULL, 0),
/* ASRC */
SND_SOC_DAPM_SUPPLY("I2S ASRC", RT5663_ASRC_1,
RT5668_I2S1_ASRC_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DAC ASRC", RT5663_ASRC_1,
RT5668_DAC_STO1_ASRC_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC ASRC", RT5663_ASRC_1,
RT5668_ADC_STO1_ASRC_SHIFT, 0, NULL, 0),
/* Input Lines */
SND_SOC_DAPM_INPUT("IN2P"),
SND_SOC_DAPM_INPUT("IN2N"),
/* Boost */
SND_SOC_DAPM_PGA("BST1 CBJ", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("CBJ Power", RT5663_PWR_ANLG_3,
RT5668_PWR_CBJ_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PGA("BST2", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("BST2 Power", SND_SOC_NOPM, 0, 0,
rt5668_bst2_power, SND_SOC_DAPM_PRE_PMD |
SND_SOC_DAPM_POST_PMU),
/* REC Mixer */
SND_SOC_DAPM_MIXER("RECMIX1L", SND_SOC_NOPM, 0, 0, rt5668_recmix1l,
ARRAY_SIZE(rt5668_recmix1l)),
SND_SOC_DAPM_MIXER("RECMIX1R", SND_SOC_NOPM, 0, 0, rt5668_recmix1r,
ARRAY_SIZE(rt5668_recmix1r)),
SND_SOC_DAPM_SUPPLY("RECMIX1R Power", RT5663_PWR_ANLG_2,
RT5668_PWR_RECMIX2_SHIFT, 0, NULL, 0),
/* ADC */
SND_SOC_DAPM_ADC("ADC R", NULL, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_SUPPLY("ADC R Power", RT5663_PWR_DIG_1,
RT5668_PWR_ADC_R1_SHIFT, 0, NULL, 0),
/* ADC Mux */
SND_SOC_DAPM_PGA("STO1 ADC L1", RT5663_STO1_ADC_MIXER,
RT5668_STO1_ADC_L1_SRC_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PGA("STO1 ADC R1", RT5663_STO1_ADC_MIXER,
RT5668_STO1_ADC_R1_SRC_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_PGA("STO1 ADC L2", RT5663_STO1_ADC_MIXER,
RT5668_STO1_ADC_L2_SRC_SHIFT, 1, NULL, 0),
SND_SOC_DAPM_PGA("STO1 ADC R2", RT5663_STO1_ADC_MIXER,
RT5668_STO1_ADC_R2_SRC_SHIFT, 1, NULL, 0),
SND_SOC_DAPM_MUX("STO1 ADC L Mux", SND_SOC_NOPM, 0, 0,
&rt5668_sto1_adcl_mux),
SND_SOC_DAPM_MUX("STO1 ADC R Mux", SND_SOC_NOPM, 0, 0,
&rt5668_sto1_adcr_mux),
/* ADC Mix */
SND_SOC_DAPM_MIXER("STO1 ADC MIXR", SND_SOC_NOPM, 0, 0,
rt5668_sto1_adc_r_mix, ARRAY_SIZE(rt5668_sto1_adc_r_mix)),
/* Analog DAC Clock */
SND_SOC_DAPM_SUPPLY("DAC Clock", RT5663_CHOP_DAC_L,
RT5668_CKGEN_DAC1_SHIFT, 0, NULL, 0),
/* Headphone out */
SND_SOC_DAPM_SWITCH("HPO Playback", SND_SOC_NOPM, 0, 0,
&rt5668_hpo_switch),
};
static const struct snd_soc_dapm_widget rt5663_specific_dapm_widgets[] = {
/* System Clock Pre Divider Gating */
SND_SOC_DAPM_SUPPLY("Pre Div Power", SND_SOC_NOPM, 0, 0,
rt5663_pre_div_power, SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD),
/* LDO */
SND_SOC_DAPM_SUPPLY("LDO ADC", RT5663_PWR_DIG_1,
RT5668_PWR_LDO_DACREF_SHIFT, 0, NULL, 0),
/* ASRC */
SND_SOC_DAPM_SUPPLY("I2S ASRC", RT5663_ASRC_1,
RT5663_I2S1_ASRC_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DAC ASRC", RT5663_ASRC_1,
RT5663_DAC_STO1_ASRC_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC ASRC", RT5663_ASRC_1,
RT5663_ADC_STO1_ASRC_SHIFT, 0, NULL, 0),
/* Boost */
SND_SOC_DAPM_PGA("BST1", SND_SOC_NOPM, 0, 0, NULL, 0),
/* STO ADC */
SND_SOC_DAPM_PGA("STO1 ADC L1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("STO1 ADC L2", SND_SOC_NOPM, 0, 0, NULL, 0),
/* Analog DAC source */
SND_SOC_DAPM_MUX("DAC L Mux", SND_SOC_NOPM, 0, 0, &rt5663_alg_dacl_mux),
SND_SOC_DAPM_MUX("DAC R Mux", SND_SOC_NOPM, 0, 0, &rt5663_alg_dacr_mux),
};
static const struct snd_soc_dapm_route rt5663_dapm_routes[] = {
/* PLL */
{ "I2S", NULL, "PLL", rt5663_is_sys_clk_from_pll },
/* ASRC */
{ "STO1 ADC Filter", NULL, "ADC ASRC", rt5663_is_using_asrc },
{ "STO1 DAC Filter", NULL, "DAC ASRC", rt5663_is_using_asrc },
{ "I2S", NULL, "I2S ASRC", rt5663_i2s_use_asrc },
{ "ADC L", NULL, "ADC L Power" },
{ "ADC L", NULL, "ADC Clock" },
{ "STO1 ADC L2", NULL, "STO1 DAC MIXL" },
{ "STO1 ADC MIXL", "ADC1 Switch", "STO1 ADC L1" },
{ "STO1 ADC MIXL", "ADC2 Switch", "STO1 ADC L2" },
{ "STO1 ADC MIXL", NULL, "STO1 ADC Filter" },
{ "IF1 ADC1", NULL, "STO1 ADC MIXL" },
{ "IF ADC", NULL, "IF1 ADC1" },
{ "AIFTX", NULL, "IF ADC" },
{ "AIFTX", NULL, "I2S" },
{ "AIFRX", NULL, "I2S" },
{ "IF DAC", NULL, "AIFRX" },
{ "IF1 DAC1 L", NULL, "IF DAC" },
{ "IF1 DAC1 R", NULL, "IF DAC" },
{ "ADDA MIXL", "ADC L Switch", "STO1 ADC MIXL" },
{ "ADDA MIXL", "DAC L Switch", "IF1 DAC1 L" },
{ "ADDA MIXL", NULL, "STO1 DAC Filter" },
{ "ADDA MIXL", NULL, "STO1 DAC L Power" },
{ "ADDA MIXR", "DAC R Switch", "IF1 DAC1 R" },
{ "ADDA MIXR", NULL, "STO1 DAC Filter" },
{ "ADDA MIXR", NULL, "STO1 DAC R Power" },
{ "DAC L1", NULL, "ADDA MIXL" },
{ "DAC R1", NULL, "ADDA MIXR" },
{ "STO1 DAC MIXL", "DAC L Switch", "DAC L1" },
{ "STO1 DAC MIXL", "DAC R Switch", "DAC R1" },
{ "STO1 DAC MIXL", NULL, "STO1 DAC L Power" },
{ "STO1 DAC MIXL", NULL, "STO1 DAC Filter" },
{ "STO1 DAC MIXR", "DAC R Switch", "DAC R1" },
{ "STO1 DAC MIXR", "DAC L Switch", "DAC L1" },
{ "STO1 DAC MIXR", NULL, "STO1 DAC R Power" },
{ "STO1 DAC MIXR", NULL, "STO1 DAC Filter" },
{ "HP Amp", NULL, "DAC L" },
{ "HP Amp", NULL, "DAC R" },
};
static const struct snd_soc_dapm_route rt5668_specific_dapm_routes[] = {
{ "MICBIAS1", NULL, "LDO2" },
{ "MICBIAS2", NULL, "LDO2" },
{ "BST1 CBJ", NULL, "IN1P" },
{ "BST1 CBJ", NULL, "IN1N" },
{ "BST1 CBJ", NULL, "CBJ Power" },
{ "BST2", NULL, "IN2P" },
{ "BST2", NULL, "IN2N" },
{ "BST2", NULL, "BST2 Power" },
{ "RECMIX1L", "BST2 Switch", "BST2" },
{ "RECMIX1L", "BST1 CBJ Switch", "BST1 CBJ" },
{ "RECMIX1L", NULL, "RECMIX1L Power" },
{ "RECMIX1R", "BST2 Switch", "BST2" },
{ "RECMIX1R", NULL, "RECMIX1R Power" },
{ "ADC L", NULL, "RECMIX1L" },
{ "ADC R", NULL, "RECMIX1R" },
{ "ADC R", NULL, "ADC R Power" },
{ "ADC R", NULL, "ADC Clock" },
{ "STO1 ADC L Mux", "ADC L", "ADC L" },
{ "STO1 ADC L Mux", "ADC R", "ADC R" },
{ "STO1 ADC L1", NULL, "STO1 ADC L Mux" },
{ "STO1 ADC R Mux", "ADC L", "ADC L" },
{ "STO1 ADC R Mux", "ADC R", "ADC R" },
{ "STO1 ADC R1", NULL, "STO1 ADC R Mux" },
{ "STO1 ADC R2", NULL, "STO1 DAC MIXR" },
{ "STO1 ADC MIXR", "ADC1 Switch", "STO1 ADC R1" },
{ "STO1 ADC MIXR", "ADC2 Switch", "STO1 ADC R2" },
{ "STO1 ADC MIXR", NULL, "STO1 ADC Filter" },
{ "IF1 ADC1", NULL, "STO1 ADC MIXR" },
{ "ADDA MIXR", "ADC R Switch", "STO1 ADC MIXR" },
{ "DAC L", NULL, "STO1 DAC MIXL" },
{ "DAC L", NULL, "LDO DAC" },
{ "DAC L", NULL, "DAC Clock" },
{ "DAC R", NULL, "STO1 DAC MIXR" },
{ "DAC R", NULL, "LDO DAC" },
{ "DAC R", NULL, "DAC Clock" },
{ "HPO Playback", "Switch", "HP Amp" },
{ "HPOL", NULL, "HPO Playback" },
{ "HPOR", NULL, "HPO Playback" },
};
static const struct snd_soc_dapm_route rt5663_specific_dapm_routes[] = {
{ "I2S", NULL, "Pre Div Power" },
{ "BST1", NULL, "IN1P" },
{ "BST1", NULL, "IN1N" },
{ "BST1", NULL, "RECMIX1L Power" },
{ "ADC L", NULL, "BST1" },
{ "STO1 ADC L1", NULL, "ADC L" },
{ "DAC L Mux", "DAC L", "DAC L1" },
{ "DAC L Mux", "STO DAC MIXL", "STO1 DAC MIXL" },
{ "DAC R Mux", "DAC R", "DAC R1"},
{ "DAC R Mux", "STO DAC MIXR", "STO1 DAC MIXR" },
{ "DAC L", NULL, "DAC L Mux" },
{ "DAC R", NULL, "DAC R Mux" },
{ "HPOL", NULL, "HP Amp" },
{ "HPOR", NULL, "HP Amp" },
};
static int rt5663_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
unsigned int val_len = 0;
int pre_div;
rt5663->lrck = params_rate(params);
dev_dbg(dai->dev, "bclk is %dHz and sysclk is %dHz\n",
rt5663->lrck, rt5663->sysclk);
pre_div = rl6231_get_clk_info(rt5663->sysclk, rt5663->lrck);
if (pre_div < 0) {
dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n",
rt5663->lrck, dai->id);
return -EINVAL;
}
dev_dbg(dai->dev, "pre_div is %d for iis %d\n", pre_div, dai->id);
switch (params_width(params)) {
case 8:
val_len = RT5668_I2S_DL_8;
break;
case 16:
val_len = RT5668_I2S_DL_16;
break;
case 20:
val_len = RT5668_I2S_DL_20;
break;
case 24:
val_len = RT5668_I2S_DL_24;
break;
default:
return -EINVAL;
}
snd_soc_update_bits(codec, RT5663_I2S1_SDP,
RT5668_I2S_DL_MASK, val_len);
snd_soc_update_bits(codec, RT5663_ADDA_CLK_1,
RT5668_I2S_PD1_MASK, pre_div << RT5668_I2S_PD1_SHIFT);
return 0;
}
static int rt5663_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_codec *codec = dai->codec;
unsigned int reg_val = 0;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
break;
case SND_SOC_DAIFMT_CBS_CFS:
reg_val |= RT5668_I2S_MS_S;
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
case SND_SOC_DAIFMT_IB_NF:
reg_val |= RT5668_I2S_BP_INV;
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
break;
case SND_SOC_DAIFMT_LEFT_J:
reg_val |= RT5668_I2S_DF_LEFT;
break;
case SND_SOC_DAIFMT_DSP_A:
reg_val |= RT5668_I2S_DF_PCM_A;
break;
case SND_SOC_DAIFMT_DSP_B:
reg_val |= RT5668_I2S_DF_PCM_B;
break;
default:
return -EINVAL;
}
snd_soc_update_bits(codec, RT5663_I2S1_SDP, RT5668_I2S_MS_MASK |
RT5668_I2S_BP_MASK | RT5668_I2S_DF_MASK, reg_val);
return 0;
}
static int rt5663_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
unsigned int freq, int dir)
{
struct snd_soc_codec *codec = dai->codec;
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
unsigned int reg_val = 0;
if (freq == rt5663->sysclk && clk_id == rt5663->sysclk_src)
return 0;
switch (clk_id) {
case RT5663_SCLK_S_MCLK:
reg_val |= RT5663_SCLK_SRC_MCLK;
break;
case RT5663_SCLK_S_PLL1:
reg_val |= RT5663_SCLK_SRC_PLL1;
break;
case RT5663_SCLK_S_RCCLK:
reg_val |= RT5663_SCLK_SRC_RCCLK;
break;
default:
dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id);
return -EINVAL;
}
snd_soc_update_bits(codec, RT5663_GLB_CLK, RT5668_SCLK_SRC_MASK,
reg_val);
rt5663->sysclk = freq;
rt5663->sysclk_src = clk_id;
dev_dbg(codec->dev, "Sysclk is %dHz and clock id is %d\n",
freq, clk_id);
return 0;
}
static int rt5663_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
unsigned int freq_in, unsigned int freq_out)
{
struct snd_soc_codec *codec = dai->codec;
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
struct rl6231_pll_code pll_code;
int ret;
int mask, shift, val;
if (source == rt5663->pll_src && freq_in == rt5663->pll_in &&
freq_out == rt5663->pll_out)
return 0;
if (!freq_in || !freq_out) {
dev_dbg(codec->dev, "PLL disabled\n");
rt5663->pll_in = 0;
rt5663->pll_out = 0;
snd_soc_update_bits(codec, RT5663_GLB_CLK,
RT5663_SCLK_SRC_MASK, RT5663_SCLK_SRC_MCLK);
return 0;
}
switch (rt5663->codec_type) {
case CODEC_TYPE_RT5668:
mask = RT5668_PLL1_SRC_MASK;
shift = RT5668_PLL1_SRC_SHIFT;
break;
case CODEC_TYPE_RT5663:
mask = RT5663_PLL1_SRC_MASK;
shift = RT5663_PLL1_SRC_SHIFT;
break;
default:
dev_err(codec->dev, "Unknown CODEC_TYPE\n");
return -EINVAL;
}
switch (source) {
case RT5663_PLL1_S_MCLK:
val = 0x0;
break;
case RT5663_PLL1_S_BCLK1:
val = 0x1;
break;
default:
dev_err(codec->dev, "Unknown PLL source %d\n", source);
return -EINVAL;
}
snd_soc_update_bits(codec, RT5663_GLB_CLK, mask, (val << shift));
ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
if (ret < 0) {
dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
return ret;
}
dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n", pll_code.m_bp,
(pll_code.m_bp ? 0 : pll_code.m_code), pll_code.n_code,
pll_code.k_code);
snd_soc_write(codec, RT5663_PLL_1,
pll_code.n_code << RT5668_PLL_N_SHIFT | pll_code.k_code);
snd_soc_write(codec, RT5663_PLL_2,
(pll_code.m_bp ? 0 : pll_code.m_code) << RT5668_PLL_M_SHIFT |
pll_code.m_bp << RT5668_PLL_M_BP_SHIFT);
rt5663->pll_in = freq_in;
rt5663->pll_out = freq_out;
rt5663->pll_src = source;
return 0;
}
static int rt5663_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 rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
unsigned int val = 0, reg;
if (rx_mask || tx_mask)
val |= RT5668_TDM_MODE_TDM;
switch (slots) {
case 4:
val |= RT5668_TDM_IN_CH_4;
val |= RT5668_TDM_OUT_CH_4;
break;
case 6:
val |= RT5668_TDM_IN_CH_6;
val |= RT5668_TDM_OUT_CH_6;
break;
case 8:
val |= RT5668_TDM_IN_CH_8;
val |= RT5668_TDM_OUT_CH_8;
break;
case 2:
break;
default:
return -EINVAL;
}
switch (slot_width) {
case 20:
val |= RT5668_TDM_IN_LEN_20;
val |= RT5668_TDM_OUT_LEN_20;
break;
case 24:
val |= RT5668_TDM_IN_LEN_24;
val |= RT5668_TDM_OUT_LEN_24;
break;
case 32:
val |= RT5668_TDM_IN_LEN_32;
val |= RT5668_TDM_OUT_LEN_32;
break;
case 16:
break;
default:
return -EINVAL;
}
switch (rt5663->codec_type) {
case CODEC_TYPE_RT5668:
reg = RT5663_TDM_2;
break;
case CODEC_TYPE_RT5663:
reg = RT5663_TDM_1;
break;
default:
dev_err(codec->dev, "Unknown CODEC_TYPE\n");
return -EINVAL;
}
snd_soc_update_bits(codec, reg, RT5668_TDM_MODE_MASK |
RT5668_TDM_IN_CH_MASK | RT5668_TDM_OUT_CH_MASK |
RT5668_TDM_IN_LEN_MASK | RT5668_TDM_OUT_LEN_MASK, val);
return 0;
}
static int rt5663_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
{
struct snd_soc_codec *codec = dai->codec;
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
unsigned int reg;
dev_dbg(codec->dev, "%s ratio = %d\n", __func__, ratio);
if (rt5663->codec_type == CODEC_TYPE_RT5668)
reg = RT5668_TDM_8;
else
reg = RT5663_TDM_5;
switch (ratio) {
case 32:
snd_soc_update_bits(codec, reg,
RT5663_TDM_LENGTN_MASK,
RT5663_TDM_LENGTN_16);
break;
case 40:
snd_soc_update_bits(codec, reg,
RT5663_TDM_LENGTN_MASK,
RT5663_TDM_LENGTN_20);
break;
case 48:
snd_soc_update_bits(codec, reg,
RT5663_TDM_LENGTN_MASK,
RT5663_TDM_LENGTN_24);
break;
case 64:
snd_soc_update_bits(codec, reg,
RT5663_TDM_LENGTN_MASK,
RT5663_TDM_LENGTN_32);
break;
default:
dev_err(codec->dev, "Invalid ratio!\n");
return -EINVAL;
}
return 0;
}
static int rt5663_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
switch (level) {
case SND_SOC_BIAS_ON:
snd_soc_update_bits(codec, RT5663_PWR_ANLG_1,
RT5668_PWR_FV1_MASK | RT5668_PWR_FV2_MASK,
RT5668_PWR_FV1 | RT5668_PWR_FV2);
break;
case SND_SOC_BIAS_PREPARE:
if (rt5663->codec_type == CODEC_TYPE_RT5668) {
snd_soc_update_bits(codec, RT5663_DIG_MISC,
RT5668_DIG_GATE_CTRL_MASK,
RT5668_DIG_GATE_CTRL_EN);
snd_soc_update_bits(codec, RT5663_SIG_CLK_DET,
RT5668_EN_ANA_CLK_DET_MASK |
RT5668_PWR_CLK_DET_MASK,
RT5668_EN_ANA_CLK_DET_AUTO |
RT5668_PWR_CLK_DET_EN);
}
break;
case SND_SOC_BIAS_STANDBY:
if (rt5663->codec_type == CODEC_TYPE_RT5668)
snd_soc_update_bits(codec, RT5663_DIG_MISC,
RT5668_DIG_GATE_CTRL_MASK,
RT5668_DIG_GATE_CTRL_DIS);
snd_soc_update_bits(codec, RT5663_PWR_ANLG_1,
RT5668_PWR_VREF1_MASK | RT5668_PWR_VREF2_MASK |
RT5668_PWR_FV1_MASK | RT5668_PWR_FV2_MASK |
RT5668_PWR_MB_MASK, RT5668_PWR_VREF1 |
RT5668_PWR_VREF2 | RT5668_PWR_MB);
usleep_range(10000, 10005);
if (rt5663->codec_type == CODEC_TYPE_RT5668) {
snd_soc_update_bits(codec, RT5663_SIG_CLK_DET,
RT5668_EN_ANA_CLK_DET_MASK |
RT5668_PWR_CLK_DET_MASK,
RT5668_EN_ANA_CLK_DET_DIS |
RT5668_PWR_CLK_DET_DIS);
}
break;
case SND_SOC_BIAS_OFF:
snd_soc_update_bits(codec, RT5663_PWR_ANLG_1,
RT5668_PWR_VREF1_MASK | RT5668_PWR_VREF2_MASK |
RT5668_PWR_FV1 | RT5668_PWR_FV2, 0x0);
break;
default:
break;
}
return 0;
}
static int rt5663_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
rt5663->codec = codec;
switch (rt5663->codec_type) {
case CODEC_TYPE_RT5668:
snd_soc_dapm_new_controls(dapm,
rt5668_specific_dapm_widgets,
ARRAY_SIZE(rt5668_specific_dapm_widgets));
snd_soc_dapm_add_routes(dapm,
rt5668_specific_dapm_routes,
ARRAY_SIZE(rt5668_specific_dapm_routes));
snd_soc_add_codec_controls(codec, rt5668_specific_controls,
ARRAY_SIZE(rt5668_specific_controls));
break;
case CODEC_TYPE_RT5663:
snd_soc_dapm_new_controls(dapm,
rt5663_specific_dapm_widgets,
ARRAY_SIZE(rt5663_specific_dapm_widgets));
snd_soc_dapm_add_routes(dapm,
rt5663_specific_dapm_routes,
ARRAY_SIZE(rt5663_specific_dapm_routes));
snd_soc_add_codec_controls(codec, rt5663_specific_controls,
ARRAY_SIZE(rt5663_specific_controls));
break;
}
return 0;
}
static int rt5663_remove(struct snd_soc_codec *codec)
{
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
regmap_write(rt5663->regmap, RT5663_RESET, 0);
return 0;
}
#ifdef CONFIG_PM
static int rt5663_suspend(struct snd_soc_codec *codec)
{
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
regcache_cache_only(rt5663->regmap, true);
regcache_mark_dirty(rt5663->regmap);
return 0;
}
static int rt5663_resume(struct snd_soc_codec *codec)
{
struct rt5663_priv *rt5663 = snd_soc_codec_get_drvdata(codec);
regcache_cache_only(rt5663->regmap, false);
regcache_sync(rt5663->regmap);
return 0;
}
#else
#define rt5663_suspend NULL
#define rt5663_resume NULL
#endif
#define RT5663_STEREO_RATES SNDRV_PCM_RATE_8000_192000
#define RT5663_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
static struct snd_soc_dai_ops rt5663_aif_dai_ops = {
.hw_params = rt5663_hw_params,
.set_fmt = rt5663_set_dai_fmt,
.set_sysclk = rt5663_set_dai_sysclk,
.set_pll = rt5663_set_dai_pll,
.set_tdm_slot = rt5663_set_tdm_slot,
.set_bclk_ratio = rt5663_set_bclk_ratio,
};
static struct snd_soc_dai_driver rt5663_dai[] = {
{
.name = "rt5663-aif",
.id = RT5663_AIF,
.playback = {
.stream_name = "AIF Playback",
.channels_min = 1,
.channels_max = 2,
.rates = RT5663_STEREO_RATES,
.formats = RT5663_FORMATS,
},
.capture = {
.stream_name = "AIF Capture",
.channels_min = 1,
.channels_max = 2,
.rates = RT5663_STEREO_RATES,
.formats = RT5663_FORMATS,
},
.ops = &rt5663_aif_dai_ops,
},
};
static struct snd_soc_codec_driver soc_codec_dev_rt5663 = {
.probe = rt5663_probe,
.remove = rt5663_remove,
.suspend = rt5663_suspend,
.resume = rt5663_resume,
.set_bias_level = rt5663_set_bias_level,
.idle_bias_off = true,
.component_driver = {
.controls = rt5663_snd_controls,
.num_controls = ARRAY_SIZE(rt5663_snd_controls),
.dapm_widgets = rt5663_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(rt5663_dapm_widgets),
.dapm_routes = rt5663_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(rt5663_dapm_routes),
}
};
static const struct regmap_config rt5668_regmap = {
.reg_bits = 16,
.val_bits = 16,
.use_single_rw = true,
.max_register = 0x07fa,
.volatile_reg = rt5668_volatile_register,
.readable_reg = rt5668_readable_register,
.cache_type = REGCACHE_RBTREE,
.reg_defaults = rt5668_reg,
.num_reg_defaults = ARRAY_SIZE(rt5668_reg),
};
static const struct regmap_config rt5663_regmap = {
.reg_bits = 16,
.val_bits = 16,
.use_single_rw = true,
.max_register = 0x03f3,
.volatile_reg = rt5663_volatile_register,
.readable_reg = rt5663_readable_register,
.cache_type = REGCACHE_RBTREE,
.reg_defaults = rt5663_reg,
.num_reg_defaults = ARRAY_SIZE(rt5663_reg),
};
static const struct regmap_config temp_regmap = {
.name = "nocache",
.reg_bits = 16,
.val_bits = 16,
.use_single_rw = true,
.max_register = 0x03f3,
.cache_type = REGCACHE_NONE,
};
static const struct i2c_device_id rt5663_i2c_id[] = {
{ "rt5668", 0 },
{ "rt5663", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, rt5663_i2c_id);
#if defined(CONFIG_OF)
static const struct of_device_id rt5663_of_match[] = {
{ .compatible = "realtek,rt5668", },
{ .compatible = "realtek,rt5663", },
{},
};
MODULE_DEVICE_TABLE(of, rt5663_of_match);
#endif
#ifdef CONFIG_ACPI
static struct acpi_device_id rt5663_acpi_match[] = {
{ "10EC5668", 0},
{ "10EC5663", 0},
{},
};
MODULE_DEVICE_TABLE(acpi, rt5663_acpi_match);
#endif
static void rt5668_calibrate(struct rt5663_priv *rt5668)
{
regmap_write(rt5668->regmap, RT5663_BIAS_CUR_8, 0xa402);
regmap_write(rt5668->regmap, RT5663_PWR_DIG_1, 0x0100);
regmap_write(rt5668->regmap, RT5663_RECMIX, 0x4040);
regmap_write(rt5668->regmap, RT5663_DIG_MISC, 0x0001);
regmap_write(rt5668->regmap, RT5663_RC_CLK, 0x0380);
regmap_write(rt5668->regmap, RT5663_GLB_CLK, 0x8000);
regmap_write(rt5668->regmap, RT5663_ADDA_CLK_1, 0x1000);
regmap_write(rt5668->regmap, RT5663_CHOP_DAC_L, 0x3030);
regmap_write(rt5668->regmap, RT5663_CALIB_ADC, 0x3c05);
regmap_write(rt5668->regmap, RT5663_PWR_ANLG_1, 0xa23e);
msleep(40);
regmap_write(rt5668->regmap, RT5663_PWR_ANLG_1, 0xf23e);
regmap_write(rt5668->regmap, RT5663_HP_CALIB_2, 0x0321);
regmap_write(rt5668->regmap, RT5663_HP_CALIB_1, 0xfc00);
msleep(500);
}
static void rt5663_calibrate(struct rt5663_priv *rt5668)
{
int value, count;
regmap_write(rt5668->regmap, RT5663_RC_CLK, 0x0280);
regmap_write(rt5668->regmap, RT5663_GLB_CLK, 0x8000);
regmap_write(rt5668->regmap, RT5663_DIG_MISC, 0x8001);
regmap_write(rt5668->regmap, RT5663_VREF_RECMIX, 0x0032);
regmap_write(rt5668->regmap, RT5663_PWR_ANLG_1, 0xa2be);
msleep(20);
regmap_write(rt5668->regmap, RT5663_PWR_ANLG_1, 0xf2be);
regmap_write(rt5668->regmap, RT5663_PWR_DIG_2, 0x8400);
regmap_write(rt5668->regmap, RT5663_CHOP_ADC, 0x3000);
regmap_write(rt5668->regmap, RT5663_DEPOP_1, 0x003b);
regmap_write(rt5668->regmap, RT5663_PWR_DIG_1, 0x8df8);
regmap_write(rt5668->regmap, RT5663_PWR_ANLG_2, 0x0003);
regmap_write(rt5668->regmap, RT5663_PWR_ANLG_3, 0x018c);
regmap_write(rt5668->regmap, RT5663_ADDA_CLK_1, 0x1111);
regmap_write(rt5668->regmap, RT5663_PRE_DIV_GATING_1, 0xffff);
regmap_write(rt5668->regmap, RT5663_PRE_DIV_GATING_2, 0xffff);
regmap_write(rt5668->regmap, RT5663_DEPOP_2, 0x3003);
regmap_write(rt5668->regmap, RT5663_DEPOP_1, 0x003b);
regmap_write(rt5668->regmap, RT5663_HP_CHARGE_PUMP_1, 0x1e32);
regmap_write(rt5668->regmap, RT5663_HP_CHARGE_PUMP_2, 0x1371);
regmap_write(rt5668->regmap, RT5663_DACREF_LDO, 0x3b0b);
regmap_write(rt5668->regmap, RT5663_STO_DAC_MIXER, 0x2080);
regmap_write(rt5668->regmap, RT5663_BYPASS_STO_DAC, 0x000c);
regmap_write(rt5668->regmap, RT5663_HP_BIAS, 0xabba);
regmap_write(rt5668->regmap, RT5663_CHARGE_PUMP_1, 0x2224);
regmap_write(rt5668->regmap, RT5663_HP_OUT_EN, 0x8088);
regmap_write(rt5668->regmap, RT5663_STO_DRE_9, 0x0017);
regmap_write(rt5668->regmap, RT5663_STO_DRE_10, 0x0017);
regmap_write(rt5668->regmap, RT5663_STO1_ADC_MIXER, 0x4040);
regmap_write(rt5668->regmap, RT5663_RECMIX, 0x0005);
regmap_write(rt5668->regmap, RT5663_ADDA_RST, 0xc000);
regmap_write(rt5668->regmap, RT5663_STO1_HPF_ADJ1, 0x3320);
regmap_write(rt5668->regmap, RT5663_HP_CALIB_2, 0x00c9);
regmap_write(rt5668->regmap, RT5663_DUMMY_1, 0x004c);
regmap_write(rt5668->regmap, RT5663_ANA_BIAS_CUR_1, 0x7766);
regmap_write(rt5668->regmap, RT5663_BIAS_CUR_8, 0x4702);
msleep(200);
regmap_write(rt5668->regmap, RT5663_HP_CALIB_1, 0x0069);
regmap_write(rt5668->regmap, RT5663_HP_CALIB_3, 0x06c2);
regmap_write(rt5668->regmap, RT5663_HP_CALIB_1_1, 0x7b00);
regmap_write(rt5668->regmap, RT5663_HP_CALIB_1_1, 0xfb00);
count = 0;
while (true) {
regmap_read(rt5668->regmap, RT5663_HP_CALIB_1_1, &value);
if (value & 0x8000)
usleep_range(10000, 10005);
else
break;
if (count > 200)
return;
count++;
}
}
static int rt5663_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct rt5663_priv *rt5663;
int ret;
unsigned int val;
struct regmap *regmap;
rt5663 = devm_kzalloc(&i2c->dev, sizeof(struct rt5663_priv),
GFP_KERNEL);
if (rt5663 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, rt5663);
regmap = devm_regmap_init_i2c(i2c, &temp_regmap);
if (IS_ERR(regmap)) {
ret = PTR_ERR(regmap);
dev_err(&i2c->dev, "Failed to allocate temp register map: %d\n",
ret);
return ret;
}
regmap_read(regmap, RT5663_VENDOR_ID_2, &val);
switch (val) {
case RT5668_DEVICE_ID:
rt5663->regmap = devm_regmap_init_i2c(i2c, &rt5668_regmap);
rt5663->codec_type = CODEC_TYPE_RT5668;
break;
case RT5663_DEVICE_ID:
rt5663->regmap = devm_regmap_init_i2c(i2c, &rt5663_regmap);
rt5663->codec_type = CODEC_TYPE_RT5663;
break;
default:
dev_err(&i2c->dev,
"Device with ID register %#x is not rt5663 or rt5668\n",
val);
return -ENODEV;
}
if (IS_ERR(rt5663->regmap)) {
ret = PTR_ERR(rt5663->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
return ret;
}
/* reset and calibrate */
regmap_write(rt5663->regmap, RT5663_RESET, 0);
regcache_cache_bypass(rt5663->regmap, true);
switch (rt5663->codec_type) {
case CODEC_TYPE_RT5668:
rt5668_calibrate(rt5663);
break;
case CODEC_TYPE_RT5663:
rt5663_calibrate(rt5663);
break;
default:
dev_err(&i2c->dev, "%s:Unknown codec type\n", __func__);
}
regcache_cache_bypass(rt5663->regmap, false);
regmap_write(rt5663->regmap, RT5663_RESET, 0);
dev_dbg(&i2c->dev, "calibrate done\n");
/* GPIO1 as IRQ */
regmap_update_bits(rt5663->regmap, RT5663_GPIO_1, RT5668_GP1_PIN_MASK,
RT5668_GP1_PIN_IRQ);
/* 4btn inline command debounce */
regmap_update_bits(rt5663->regmap, RT5663_IL_CMD_5,
RT5668_4BTN_CLK_DEB_MASK, RT5668_4BTN_CLK_DEB_65MS);
switch (rt5663->codec_type) {
case CODEC_TYPE_RT5668:
regmap_write(rt5663->regmap, RT5663_BIAS_CUR_8, 0xa402);
/* JD1 */
regmap_update_bits(rt5663->regmap, RT5663_AUTO_1MRC_CLK,
RT5668_IRQ_POW_SAV_MASK | RT5668_IRQ_POW_SAV_JD1_MASK,
RT5668_IRQ_POW_SAV_EN | RT5668_IRQ_POW_SAV_JD1_EN);
regmap_update_bits(rt5663->regmap, RT5663_PWR_ANLG_2,
RT5668_PWR_JD1_MASK, RT5668_PWR_JD1);
regmap_update_bits(rt5663->regmap, RT5663_IRQ_1,
RT5668_EN_CB_JD_MASK, RT5668_EN_CB_JD_EN);
regmap_update_bits(rt5663->regmap, RT5663_HP_LOGIC_2,
RT5668_HP_SIG_SRC1_MASK, RT5668_HP_SIG_SRC1_REG);
regmap_update_bits(rt5663->regmap, RT5663_RECMIX,
RT5668_VREF_BIAS_MASK | RT5668_CBJ_DET_MASK |
RT5668_DET_TYPE_MASK, RT5668_VREF_BIAS_REG |
RT5668_CBJ_DET_EN | RT5668_DET_TYPE_QFN);
/* Set GPIO4 and GPIO8 as input for combo jack */
regmap_update_bits(rt5663->regmap, RT5663_GPIO_2,
RT5668_GP4_PIN_CONF_MASK, RT5668_GP4_PIN_CONF_INPUT);
regmap_update_bits(rt5663->regmap, RT5668_GPIO_3,
RT5668_GP8_PIN_CONF_MASK, RT5668_GP8_PIN_CONF_INPUT);
regmap_update_bits(rt5663->regmap, RT5663_PWR_ANLG_1,
RT5668_LDO1_DVO_MASK | RT5668_AMP_HP_MASK,
RT5668_LDO1_DVO_0_9V | RT5668_AMP_HP_3X);
break;
case CODEC_TYPE_RT5663:
regmap_write(rt5663->regmap, RT5663_VREF_RECMIX, 0x0032);
regmap_write(rt5663->regmap, RT5663_PWR_ANLG_1, 0xa2be);
msleep(20);
regmap_write(rt5663->regmap, RT5663_PWR_ANLG_1, 0xf2be);
regmap_update_bits(rt5663->regmap, RT5663_GPIO_2,
RT5663_GP1_PIN_CONF_MASK, RT5663_GP1_PIN_CONF_OUTPUT);
/* DACREF LDO control */
regmap_update_bits(rt5663->regmap, RT5663_DACREF_LDO, 0x3e0e,
0x3a0a);
regmap_update_bits(rt5663->regmap, RT5663_RECMIX,
RT5663_RECMIX1_BST1_MASK, RT5663_RECMIX1_BST1_ON);
regmap_update_bits(rt5663->regmap, RT5663_TDM_2,
RT5663_DATA_SWAP_ADCDAT1_MASK,
RT5663_DATA_SWAP_ADCDAT1_LL);
break;
default:
dev_err(&i2c->dev, "%s:Unknown codec type\n", __func__);
}
INIT_DELAYED_WORK(&rt5663->jack_detect_work, rt5663_jack_detect_work);
if (i2c->irq) {
ret = request_irq(i2c->irq, rt5663_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
| IRQF_ONESHOT, "rt5663", rt5663);
if (ret)
dev_err(&i2c->dev, "%s Failed to reguest IRQ: %d\n",
__func__, ret);
}
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5663,
rt5663_dai, ARRAY_SIZE(rt5663_dai));
if (ret) {
if (i2c->irq)
free_irq(i2c->irq, rt5663);
}
return ret;
}
static int rt5663_i2c_remove(struct i2c_client *i2c)
{
struct rt5663_priv *rt5663 = i2c_get_clientdata(i2c);
if (i2c->irq)
free_irq(i2c->irq, rt5663);
snd_soc_unregister_codec(&i2c->dev);
return 0;
}
static void rt5663_i2c_shutdown(struct i2c_client *client)
{
struct rt5663_priv *rt5663 = i2c_get_clientdata(client);
regmap_write(rt5663->regmap, RT5663_RESET, 0);
}
static struct i2c_driver rt5663_i2c_driver = {
.driver = {
.name = "rt5663",
.acpi_match_table = ACPI_PTR(rt5663_acpi_match),
.of_match_table = of_match_ptr(rt5663_of_match),
},
.probe = rt5663_i2c_probe,
.remove = rt5663_i2c_remove,
.shutdown = rt5663_i2c_shutdown,
.id_table = rt5663_i2c_id,
};
module_i2c_driver(rt5663_i2c_driver);
MODULE_DESCRIPTION("ASoC RT5663 driver");
MODULE_AUTHOR("Jack Yu <jack.yu@realtek.com>");
MODULE_LICENSE("GPL v2");
/*
* rt5663.h -- RT5663 ALSA SoC audio driver
*
* Copyright 2016 Realtek Microelectronics
* Author: Jack Yu <jack.yu@realtek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __RT5663_H__
#define __RT5663_H__
/* Info */
#define RT5663_RESET 0x0000
#define RT5663_VENDOR_ID 0x00fd
#define RT5663_VENDOR_ID_1 0x00fe
#define RT5663_VENDOR_ID_2 0x00ff
#define RT5668_LOUT_CTRL 0x0001
#define RT5668_HP_AMP_2 0x0003
#define RT5668_MONO_OUT 0x0004
#define RT5668_MONO_GAIN 0x0007
#define RT5668_AEC_BST 0x000b
#define RT5668_IN1_IN2 0x000c
#define RT5668_IN3_IN4 0x000d
#define RT5668_INL1_INR1 0x000f
#define RT5668_CBJ_TYPE_2 0x0011
#define RT5668_CBJ_TYPE_3 0x0012
#define RT5668_CBJ_TYPE_4 0x0013
#define RT5668_CBJ_TYPE_5 0x0014
#define RT5668_CBJ_TYPE_8 0x0017
/* I/O - ADC/DAC/DMIC */
#define RT5668_DAC3_DIG_VOL 0x001a
#define RT5668_DAC3_CTRL 0x001b
#define RT5668_MONO_ADC_DIG_VOL 0x001d
#define RT5668_STO2_ADC_DIG_VOL 0x001e
#define RT5668_MONO_ADC_BST_GAIN 0x0020
#define RT5668_STO2_ADC_BST_GAIN 0x0021
#define RT5668_SIDETONE_CTRL 0x0024
/* Mixer - D-D */
#define RT5668_MONO1_ADC_MIXER 0x0027
#define RT5668_STO2_ADC_MIXER 0x0028
#define RT5668_MONO_DAC_MIXER 0x002b
#define RT5668_DAC2_SRC_CTRL 0x002e
#define RT5668_IF_3_4_DATA_CTL 0x002f
#define RT5668_IF_5_DATA_CTL 0x0030
#define RT5668_PDM_OUT_CTL 0x0031
#define RT5668_PDM_I2C_DATA_CTL1 0x0032
#define RT5668_PDM_I2C_DATA_CTL2 0x0033
#define RT5668_PDM_I2C_DATA_CTL3 0x0034
#define RT5668_PDM_I2C_DATA_CTL4 0x0035
/*Mixer - Analog*/
#define RT5668_RECMIX1_NEW 0x003a
#define RT5668_RECMIX1L_0 0x003b
#define RT5668_RECMIX1L 0x003c
#define RT5668_RECMIX1R_0 0x003d
#define RT5668_RECMIX1R 0x003e
#define RT5668_RECMIX2_NEW 0x003f
#define RT5668_RECMIX2_L_2 0x0041
#define RT5668_RECMIX2_R 0x0042
#define RT5668_RECMIX2_R_2 0x0043
#define RT5668_CALIB_REC_LR 0x0044
#define RT5668_ALC_BK_GAIN 0x0049
#define RT5668_MONOMIX_GAIN 0x004a
#define RT5668_MONOMIX_IN_GAIN 0x004b
#define RT5668_OUT_MIXL_GAIN 0x004d
#define RT5668_OUT_LMIX_IN_GAIN 0x004e
#define RT5668_OUT_RMIX_IN_GAIN 0x004f
#define RT5668_OUT_RMIX_IN_GAIN1 0x0050
#define RT5668_LOUT_MIXER_CTRL 0x0052
/* Power */
#define RT5668_PWR_VOL 0x0067
#define RT5668_ADCDAC_RST 0x006d
/* Format - ADC/DAC */
#define RT5668_I2S34_SDP 0x0071
#define RT5668_I2S5_SDP 0x0072
/* Format - TDM Control */
#define RT5668_TDM_5 0x007c
#define RT5668_TDM_6 0x007d
#define RT5668_TDM_7 0x007e
#define RT5668_TDM_8 0x007f
/* Function - Analog */
#define RT5668_ASRC_3 0x0085
#define RT5668_ASRC_6 0x0088
#define RT5668_ASRC_7 0x0089
#define RT5668_PLL_TRK_13 0x0099
#define RT5668_I2S_M_CLK_CTL 0x00a0
#define RT5668_FDIV_I2S34_M_CLK 0x00a1
#define RT5668_FDIV_I2S34_M_CLK2 0x00a2
#define RT5668_FDIV_I2S5_M_CLK 0x00a3
#define RT5668_FDIV_I2S5_M_CLK2 0x00a4
/* Function - Digital */
#define RT5668_IRQ_4 0x00b9
#define RT5668_GPIO_3 0x00c2
#define RT5668_GPIO_4 0x00c3
#define RT5668_GPIO_STA 0x00c4
#define RT5668_HP_AMP_DET1 0x00d0
#define RT5668_HP_AMP_DET2 0x00d1
#define RT5668_HP_AMP_DET3 0x00d2
#define RT5668_MID_BD_HP_AMP 0x00d3
#define RT5668_LOW_BD_HP_AMP 0x00d4
#define RT5668_SOF_VOL_ZC2 0x00da
#define RT5668_ADC_STO2_ADJ1 0x00ee
#define RT5668_ADC_STO2_ADJ2 0x00ef
/* General Control */
#define RT5668_A_JD_CTRL 0x00f0
#define RT5668_JD1_TRES_CTRL 0x00f1
#define RT5668_JD2_TRES_CTRL 0x00f2
#define RT5668_JD_CTRL2 0x00f7
#define RT5668_DUM_REG_2 0x00fb
#define RT5668_DUM_REG_3 0x00fc
#define RT5668_DACADC_DIG_VOL2 0x0101
#define RT5668_DIG_IN_PIN2 0x0133
#define RT5668_PAD_DRV_CTL1 0x0136
#define RT5668_SOF_RAM_DEPOP 0x0138
#define RT5668_VOL_TEST 0x013f
#define RT5668_TEST_MODE_3 0x0147
#define RT5668_TEST_MODE_4 0x0148
#define RT5668_MONO_DYNA_1 0x0170
#define RT5668_MONO_DYNA_2 0x0171
#define RT5668_MONO_DYNA_3 0x0172
#define RT5668_MONO_DYNA_4 0x0173
#define RT5668_MONO_DYNA_5 0x0174
#define RT5668_MONO_DYNA_6 0x0175
#define RT5668_STO1_SIL_DET 0x0190
#define RT5668_MONOL_SIL_DET 0x0191
#define RT5668_MONOR_SIL_DET 0x0192
#define RT5668_STO2_DAC_SIL 0x0193
#define RT5668_PWR_SAV_CTL1 0x0194
#define RT5668_PWR_SAV_CTL2 0x0195
#define RT5668_PWR_SAV_CTL3 0x0196
#define RT5668_PWR_SAV_CTL4 0x0197
#define RT5668_PWR_SAV_CTL5 0x0198
#define RT5668_PWR_SAV_CTL6 0x0199
#define RT5668_MONO_AMP_CAL1 0x01a0
#define RT5668_MONO_AMP_CAL2 0x01a1
#define RT5668_MONO_AMP_CAL3 0x01a2
#define RT5668_MONO_AMP_CAL4 0x01a3
#define RT5668_MONO_AMP_CAL5 0x01a4
#define RT5668_MONO_AMP_CAL6 0x01a5
#define RT5668_MONO_AMP_CAL7 0x01a6
#define RT5668_MONO_AMP_CAL_ST1 0x01a7
#define RT5668_MONO_AMP_CAL_ST2 0x01a8
#define RT5668_MONO_AMP_CAL_ST3 0x01a9
#define RT5668_MONO_AMP_CAL_ST4 0x01aa
#define RT5668_MONO_AMP_CAL_ST5 0x01ab
#define RT5668_HP_IMP_SEN_13 0x01b9
#define RT5668_HP_IMP_SEN_14 0x01ba
#define RT5668_HP_IMP_SEN_6 0x01bb
#define RT5668_HP_IMP_SEN_7 0x01bc
#define RT5668_HP_IMP_SEN_8 0x01bd
#define RT5668_HP_IMP_SEN_9 0x01be
#define RT5668_HP_IMP_SEN_10 0x01bf
#define RT5668_HP_LOGIC_3 0x01dc
#define RT5668_HP_CALIB_ST10 0x01f3
#define RT5668_HP_CALIB_ST11 0x01f4
#define RT5668_PRO_REG_TBL_4 0x0203
#define RT5668_PRO_REG_TBL_5 0x0204
#define RT5668_PRO_REG_TBL_6 0x0205
#define RT5668_PRO_REG_TBL_7 0x0206
#define RT5668_PRO_REG_TBL_8 0x0207
#define RT5668_PRO_REG_TBL_9 0x0208
#define RT5668_SAR_ADC_INL_1 0x0210
#define RT5668_SAR_ADC_INL_2 0x0211
#define RT5668_SAR_ADC_INL_3 0x0212
#define RT5668_SAR_ADC_INL_4 0x0213
#define RT5668_SAR_ADC_INL_5 0x0214
#define RT5668_SAR_ADC_INL_6 0x0215
#define RT5668_SAR_ADC_INL_7 0x0216
#define RT5668_SAR_ADC_INL_8 0x0217
#define RT5668_SAR_ADC_INL_9 0x0218
#define RT5668_SAR_ADC_INL_10 0x0219
#define RT5668_SAR_ADC_INL_11 0x021a
#define RT5668_SAR_ADC_INL_12 0x021b
#define RT5668_DRC_CTRL_1 0x02ff
#define RT5668_DRC1_CTRL_2 0x0301
#define RT5668_DRC1_CTRL_3 0x0302
#define RT5668_DRC1_CTRL_4 0x0303
#define RT5668_DRC1_CTRL_5 0x0304
#define RT5668_DRC1_CTRL_6 0x0305
#define RT5668_DRC1_HD_CTRL_1 0x0306
#define RT5668_DRC1_HD_CTRL_2 0x0307
#define RT5668_DRC1_PRI_REG_1 0x0310
#define RT5668_DRC1_PRI_REG_2 0x0311
#define RT5668_DRC1_PRI_REG_3 0x0312
#define RT5668_DRC1_PRI_REG_4 0x0313
#define RT5668_DRC1_PRI_REG_5 0x0314
#define RT5668_DRC1_PRI_REG_6 0x0315
#define RT5668_DRC1_PRI_REG_7 0x0316
#define RT5668_DRC1_PRI_REG_8 0x0317
#define RT5668_ALC_PGA_CTL_1 0x0330
#define RT5668_ALC_PGA_CTL_2 0x0331
#define RT5668_ALC_PGA_CTL_3 0x0332
#define RT5668_ALC_PGA_CTL_4 0x0333
#define RT5668_ALC_PGA_CTL_5 0x0334
#define RT5668_ALC_PGA_CTL_6 0x0335
#define RT5668_ALC_PGA_CTL_7 0x0336
#define RT5668_ALC_PGA_CTL_8 0x0337
#define RT5668_ALC_PGA_REG_1 0x0338
#define RT5668_ALC_PGA_REG_2 0x0339
#define RT5668_ALC_PGA_REG_3 0x033a
#define RT5668_ADC_EQ_RECOV_1 0x03c0
#define RT5668_ADC_EQ_RECOV_2 0x03c1
#define RT5668_ADC_EQ_RECOV_3 0x03c2
#define RT5668_ADC_EQ_RECOV_4 0x03c3
#define RT5668_ADC_EQ_RECOV_5 0x03c4
#define RT5668_ADC_EQ_RECOV_6 0x03c5
#define RT5668_ADC_EQ_RECOV_7 0x03c6
#define RT5668_ADC_EQ_RECOV_8 0x03c7
#define RT5668_ADC_EQ_RECOV_9 0x03c8
#define RT5668_ADC_EQ_RECOV_10 0x03c9
#define RT5668_ADC_EQ_RECOV_11 0x03ca
#define RT5668_ADC_EQ_RECOV_12 0x03cb
#define RT5668_ADC_EQ_RECOV_13 0x03cc
#define RT5668_VID_HIDDEN 0x03fe
#define RT5668_VID_CUSTOMER 0x03ff
#define RT5668_SCAN_MODE 0x07f0
#define RT5668_I2C_BYPA 0x07fa
/* Headphone Amp Control 2 (0x0003) */
#define RT5668_EN_DAC_HPO_MASK (0x1 << 14)
#define RT5668_EN_DAC_HPO_SHIFT 14
#define RT5668_EN_DAC_HPO_DIS (0x0 << 14)
#define RT5668_EN_DAC_HPO_EN (0x1 << 14)
/*Headphone Amp L/R Analog Gain and Digital NG2 Gain Control (0x0005 0x0006)*/
#define RT5668_GAIN_HP (0x1f << 8)
#define RT5668_GAIN_HP_SHIFT 8
/* AEC BST Control (0x000b) */
#define RT5668_GAIN_CBJ_MASK (0xf << 8)
#define RT5668_GAIN_CBJ_SHIFT 8
/* IN1 Control / MIC GND REF (0x000c) */
#define RT5668_IN1_DF_MASK (0x1 << 15)
#define RT5668_IN1_DF_SHIFT 15
/* Combo Jack and Type Detection Control 1 (0x0010) */
#define RT5668_CBJ_DET_MASK (0x1 << 15)
#define RT5668_CBJ_DET_SHIFT 15
#define RT5668_CBJ_DET_DIS (0x0 << 15)
#define RT5668_CBJ_DET_EN (0x1 << 15)
#define RT5668_DET_TYPE_MASK (0x1 << 12)
#define RT5668_DET_TYPE_SHIFT 12
#define RT5668_DET_TYPE_WLCSP (0x0 << 12)
#define RT5668_DET_TYPE_QFN (0x1 << 12)
#define RT5668_VREF_BIAS_MASK (0x1 << 6)
#define RT5668_VREF_BIAS_SHIFT 6
#define RT5668_VREF_BIAS_FSM (0x0 << 6)
#define RT5668_VREF_BIAS_REG (0x1 << 6)
/* REC Left Mixer Control 2 (0x003c) */
#define RT5668_RECMIX1L_BST1_CBJ (0x1 << 7)
#define RT5668_RECMIX1L_BST1_CBJ_SHIFT 7
#define RT5668_RECMIX1L_BST2 (0x1 << 4)
#define RT5668_RECMIX1L_BST2_SHIFT 4
/* REC Right Mixer Control 2 (0x003e) */
#define RT5668_RECMIX1R_BST2 (0x1 << 4)
#define RT5668_RECMIX1R_BST2_SHIFT 4
/* DAC1 Digital Volume (0x0019) */
#define RT5668_DAC_L1_VOL_MASK (0xff << 8)
#define RT5668_DAC_L1_VOL_SHIFT 8
#define RT5668_DAC_R1_VOL_MASK (0xff)
#define RT5668_DAC_R1_VOL_SHIFT 0
/* ADC Digital Volume Control (0x001c) */
#define RT5668_ADC_L_MUTE_MASK (0x1 << 15)
#define RT5668_ADC_L_MUTE_SHIFT 15
#define RT5668_ADC_L_VOL_MASK (0x7f << 8)
#define RT5668_ADC_L_VOL_SHIFT 8
#define RT5668_ADC_R_MUTE_MASK (0x1 << 7)
#define RT5668_ADC_R_MUTE_SHIFT 7
#define RT5668_ADC_R_VOL_MASK (0x7f)
#define RT5668_ADC_R_VOL_SHIFT 0
/* Stereo ADC Mixer Control (0x0026) */
#define RT5668_M_STO1_ADC_L1 (0x1 << 15)
#define RT5668_M_STO1_ADC_L1_SHIFT 15
#define RT5668_M_STO1_ADC_L2 (0x1 << 14)
#define RT5668_M_STO1_ADC_L2_SHIFT 14
#define RT5668_STO1_ADC_L1_SRC (0x1 << 13)
#define RT5668_STO1_ADC_L1_SRC_SHIFT 13
#define RT5668_STO1_ADC_L2_SRC (0x1 << 12)
#define RT5668_STO1_ADC_L2_SRC_SHIFT 12
#define RT5668_STO1_ADC_L_SRC (0x3 << 10)
#define RT5668_STO1_ADC_L_SRC_SHIFT 10
#define RT5668_M_STO1_ADC_R1 (0x1 << 7)
#define RT5668_M_STO1_ADC_R1_SHIFT 7
#define RT5668_M_STO1_ADC_R2 (0x1 << 6)
#define RT5668_M_STO1_ADC_R2_SHIFT 6
#define RT5668_STO1_ADC_R1_SRC (0x1 << 5)
#define RT5668_STO1_ADC_R1_SRC_SHIFT 5
#define RT5668_STO1_ADC_R2_SRC (0x1 << 4)
#define RT5668_STO1_ADC_R2_SRC_SHIFT 4
#define RT5668_STO1_ADC_R_SRC (0x3 << 2)
#define RT5668_STO1_ADC_R_SRC_SHIFT 2
/* ADC Mixer to DAC Mixer Control (0x0029) */
#define RT5668_M_ADCMIX_L (0x1 << 15)
#define RT5668_M_ADCMIX_L_SHIFT 15
#define RT5668_M_DAC1_L (0x1 << 14)
#define RT5668_M_DAC1_L_SHIFT 14
#define RT5668_M_ADCMIX_R (0x1 << 7)
#define RT5668_M_ADCMIX_R_SHIFT 7
#define RT5668_M_DAC1_R (0x1 << 6)
#define RT5668_M_DAC1_R_SHIFT 6
/* Stereo DAC Mixer Control (0x002a) */
#define RT5668_M_DAC_L1_STO_L (0x1 << 15)
#define RT5668_M_DAC_L1_STO_L_SHIFT 15
#define RT5668_M_DAC_R1_STO_L (0x1 << 13)
#define RT5668_M_DAC_R1_STO_L_SHIFT 13
#define RT5668_M_DAC_L1_STO_R (0x1 << 7)
#define RT5668_M_DAC_L1_STO_R_SHIFT 7
#define RT5668_M_DAC_R1_STO_R (0x1 << 5)
#define RT5668_M_DAC_R1_STO_R_SHIFT 5
/* Power Management for Digital 1 (0x0061) */
#define RT5668_PWR_I2S1 (0x1 << 15)
#define RT5668_PWR_I2S1_SHIFT 15
#define RT5668_PWR_DAC_L1 (0x1 << 11)
#define RT5668_PWR_DAC_L1_SHIFT 11
#define RT5668_PWR_DAC_R1 (0x1 << 10)
#define RT5668_PWR_DAC_R1_SHIFT 10
#define RT5668_PWR_LDO_DACREF_MASK (0x1 << 8)
#define RT5668_PWR_LDO_DACREF_SHIFT 8
#define RT5668_PWR_LDO_DACREF_ON (0x1 << 8)
#define RT5668_PWR_LDO_DACREF_DOWN (0x0 << 8)
#define RT5668_PWR_LDO_SHIFT 8
#define RT5668_PWR_ADC_L1 (0x1 << 4)
#define RT5668_PWR_ADC_L1_SHIFT 4
#define RT5668_PWR_ADC_R1 (0x1 << 3)
#define RT5668_PWR_ADC_R1_SHIFT 3
/* Power Management for Digital 2 (0x0062) */
#define RT5668_PWR_ADC_S1F (0x1 << 15)
#define RT5668_PWR_ADC_S1F_SHIFT 15
#define RT5668_PWR_DAC_S1F (0x1 << 10)
#define RT5668_PWR_DAC_S1F_SHIFT 10
/* Power Management for Analog 1 (0x0063) */
#define RT5668_PWR_VREF1 (0x1 << 15)
#define RT5668_PWR_VREF1_MASK (0x1 << 15)
#define RT5668_PWR_VREF1_SHIFT 15
#define RT5668_PWR_FV1 (0x1 << 14)
#define RT5668_PWR_FV1_MASK (0x1 << 14)
#define RT5668_PWR_FV1_SHIFT 14
#define RT5668_PWR_VREF2 (0x1 << 13)
#define RT5668_PWR_VREF2_MASK (0x1 << 13)
#define RT5668_PWR_VREF2_SHIFT 13
#define RT5668_PWR_FV2 (0x1 << 12)
#define RT5668_PWR_FV2_MASK (0x1 << 12)
#define RT5668_PWR_FV2_SHIFT 12
#define RT5668_PWR_MB (0x1 << 9)
#define RT5668_PWR_MB_MASK (0x1 << 9)
#define RT5668_PWR_MB_SHIFT 9
#define RT5668_AMP_HP_MASK (0x3 << 2)
#define RT5668_AMP_HP_SHIFT 2
#define RT5668_AMP_HP_1X (0x0 << 2)
#define RT5668_AMP_HP_3X (0x1 << 2)
#define RT5668_AMP_HP_5X (0x3 << 2)
#define RT5668_LDO1_DVO_MASK (0x3)
#define RT5668_LDO1_DVO_SHIFT 0
#define RT5668_LDO1_DVO_0_9V (0x0)
#define RT5668_LDO1_DVO_1_0V (0x1)
#define RT5668_LDO1_DVO_1_2V (0x2)
#define RT5668_LDO1_DVO_1_4V (0x3)
/* Power Management for Analog 2 (0x0064) */
#define RT5668_PWR_BST1 (0x1 << 15)
#define RT5668_PWR_BST1_MASK (0x1 << 15)
#define RT5668_PWR_BST1_SHIFT 15
#define RT5668_PWR_BST1_OFF (0x0 << 15)
#define RT5668_PWR_BST1_ON (0x1 << 15)
#define RT5668_PWR_BST2 (0x1 << 14)
#define RT5668_PWR_BST2_MASK (0x1 << 14)
#define RT5668_PWR_BST2_SHIFT 14
#define RT5668_PWR_MB1 (0x1 << 11)
#define RT5668_PWR_MB1_SHIFT 11
#define RT5668_PWR_MB2 (0x1 << 10)
#define RT5668_PWR_MB2_SHIFT 10
#define RT5668_PWR_BST2_OP (0x1 << 6)
#define RT5668_PWR_BST2_OP_MASK (0x1 << 6)
#define RT5668_PWR_BST2_OP_SHIFT 6
#define RT5668_PWR_JD1 (0x1 << 3)
#define RT5668_PWR_JD1_MASK (0x1 << 3)
#define RT5668_PWR_JD1_SHIFT 3
#define RT5668_PWR_JD2 (0x1 << 2)
#define RT5668_PWR_JD2_MASK (0x1 << 2)
#define RT5668_PWR_JD2_SHIFT 2
#define RT5668_PWR_RECMIX1 (0x1 << 1)
#define RT5668_PWR_RECMIX1_SHIFT 1
#define RT5668_PWR_RECMIX2 (0x1)
#define RT5668_PWR_RECMIX2_SHIFT 0
/* Power Management for Analog 3 (0x0065) */
#define RT5668_PWR_CBJ_MASK (0x1 << 9)
#define RT5668_PWR_CBJ_SHIFT 9
#define RT5668_PWR_CBJ_OFF (0x0 << 9)
#define RT5668_PWR_CBJ_ON (0x1 << 9)
#define RT5668_PWR_PLL (0x1 << 6)
#define RT5668_PWR_PLL_SHIFT 6
#define RT5668_PWR_LDO2 (0x1 << 2)
#define RT5668_PWR_LDO2_SHIFT 2
/* Power Management for Volume (0x0067) */
#define RT5668_PWR_MIC_DET (0x1 << 5)
#define RT5668_PWR_MIC_DET_SHIFT 5
/* MCLK and System Clock Detection Control (0x006b) */
#define RT5668_EN_ANA_CLK_DET_MASK (0x1 << 15)
#define RT5668_EN_ANA_CLK_DET_SHIFT 15
#define RT5668_EN_ANA_CLK_DET_DIS (0x0 << 15)
#define RT5668_EN_ANA_CLK_DET_AUTO (0x1 << 15)
#define RT5668_PWR_CLK_DET_MASK (0x1)
#define RT5668_PWR_CLK_DET_SHIFT 0
#define RT5668_PWR_CLK_DET_DIS (0x0)
#define RT5668_PWR_CLK_DET_EN (0x1)
/* I2S1 Audio Serial Data Port Control (0x0070) */
#define RT5668_I2S_MS_MASK (0x1 << 15)
#define RT5668_I2S_MS_SHIFT 15
#define RT5668_I2S_MS_M (0x0 << 15)
#define RT5668_I2S_MS_S (0x1 << 15)
#define RT5668_I2S_BP_MASK (0x1 << 8)
#define RT5668_I2S_BP_SHIFT 8
#define RT5668_I2S_BP_NOR (0x0 << 8)
#define RT5668_I2S_BP_INV (0x1 << 8)
#define RT5668_I2S_DL_MASK (0x3 << 4)
#define RT5668_I2S_DL_SHIFT 4
#define RT5668_I2S_DL_16 (0x0 << 4)
#define RT5668_I2S_DL_20 (0x1 << 4)
#define RT5668_I2S_DL_24 (0x2 << 4)
#define RT5668_I2S_DL_8 (0x3 << 4)
#define RT5668_I2S_DF_MASK (0x7)
#define RT5668_I2S_DF_SHIFT 0
#define RT5668_I2S_DF_I2S (0x0)
#define RT5668_I2S_DF_LEFT (0x1)
#define RT5668_I2S_DF_PCM_A (0x2)
#define RT5668_I2S_DF_PCM_B (0x3)
#define RT5668_I2S_DF_PCM_A_N (0x6)
#define RT5668_I2S_DF_PCM_B_N (0x7)
/* ADC/DAC Clock Control 1 (0x0073) */
#define RT5668_I2S_PD1_MASK (0x7 << 12)
#define RT5668_I2S_PD1_SHIFT 12
#define RT5668_M_I2S_DIV_MASK (0x7 << 8)
#define RT5668_M_I2S_DIV_SHIFT 8
#define RT5668_CLK_SRC_MASK (0x3 << 4)
#define RT5668_CLK_SRC_MCLK (0x0 << 4)
#define RT5668_CLK_SRC_PLL_OUT (0x1 << 4)
#define RT5668_CLK_SRC_DIV (0x2 << 4)
#define RT5668_CLK_SRC_RC (0x3 << 4)
#define RT5668_DAC_OSR_MASK (0x3 << 2)
#define RT5668_DAC_OSR_SHIFT 2
#define RT5668_DAC_OSR_128 (0x0 << 2)
#define RT5668_DAC_OSR_64 (0x1 << 2)
#define RT5668_DAC_OSR_32 (0x2 << 2)
#define RT5668_ADC_OSR_MASK (0x3)
#define RT5668_ADC_OSR_SHIFT 0
#define RT5668_ADC_OSR_128 (0x0)
#define RT5668_ADC_OSR_64 (0x1)
#define RT5668_ADC_OSR_32 (0x2)
/* TDM1 control 1 (0x0078) */
#define RT5668_TDM_MODE_MASK (0x1 << 15)
#define RT5668_TDM_MODE_SHIFT 15
#define RT5668_TDM_MODE_I2S (0x0 << 15)
#define RT5668_TDM_MODE_TDM (0x1 << 15)
#define RT5668_TDM_IN_CH_MASK (0x3 << 10)
#define RT5668_TDM_IN_CH_SHIFT 10
#define RT5668_TDM_IN_CH_2 (0x0 << 10)
#define RT5668_TDM_IN_CH_4 (0x1 << 10)
#define RT5668_TDM_IN_CH_6 (0x2 << 10)
#define RT5668_TDM_IN_CH_8 (0x3 << 10)
#define RT5668_TDM_OUT_CH_MASK (0x3 << 8)
#define RT5668_TDM_OUT_CH_SHIFT 8
#define RT5668_TDM_OUT_CH_2 (0x0 << 8)
#define RT5668_TDM_OUT_CH_4 (0x1 << 8)
#define RT5668_TDM_OUT_CH_6 (0x2 << 8)
#define RT5668_TDM_OUT_CH_8 (0x3 << 8)
#define RT5668_TDM_IN_LEN_MASK (0x3 << 6)
#define RT5668_TDM_IN_LEN_SHIFT 6
#define RT5668_TDM_IN_LEN_16 (0x0 << 6)
#define RT5668_TDM_IN_LEN_20 (0x1 << 6)
#define RT5668_TDM_IN_LEN_24 (0x2 << 6)
#define RT5668_TDM_IN_LEN_32 (0x3 << 6)
#define RT5668_TDM_OUT_LEN_MASK (0x3 << 4)
#define RT5668_TDM_OUT_LEN_SHIFT 4
#define RT5668_TDM_OUT_LEN_16 (0x0 << 4)
#define RT5668_TDM_OUT_LEN_20 (0x1 << 4)
#define RT5668_TDM_OUT_LEN_24 (0x2 << 4)
#define RT5668_TDM_OUT_LEN_32 (0x3 << 4)
/* Global Clock Control (0x0080) */
#define RT5668_SCLK_SRC_MASK (0x3 << 14)
#define RT5668_SCLK_SRC_SHIFT 14
#define RT5668_SCLK_SRC_MCLK (0x0 << 14)
#define RT5668_SCLK_SRC_PLL1 (0x1 << 14)
#define RT5668_SCLK_SRC_RCCLK (0x2 << 14)
#define RT5668_PLL1_SRC_MASK (0x7 << 8)
#define RT5668_PLL1_SRC_SHIFT 8
#define RT5668_PLL1_SRC_MCLK (0x0 << 8)
#define RT5668_PLL1_SRC_BCLK1 (0x1 << 8)
#define RT5668_PLL1_PD_MASK (0x1 << 4)
#define RT5668_PLL1_PD_SHIFT 4
#define RT5668_PLL_INP_MAX 40000000
#define RT5668_PLL_INP_MIN 256000
/* PLL M/N/K Code Control 1 (0x0081) */
#define RT5668_PLL_N_MAX 0x001ff
#define RT5668_PLL_N_MASK (RT5668_PLL_N_MAX << 7)
#define RT5668_PLL_N_SHIFT 7
#define RT5668_PLL_K_MAX 0x001f
#define RT5668_PLL_K_MASK (RT5668_PLL_K_MAX)
#define RT5668_PLL_K_SHIFT 0
/* PLL M/N/K Code Control 2 (0x0082) */
#define RT5668_PLL_M_MAX 0x00f
#define RT5668_PLL_M_MASK (RT5668_PLL_M_MAX << 12)
#define RT5668_PLL_M_SHIFT 12
#define RT5668_PLL_M_BP (0x1 << 11)
#define RT5668_PLL_M_BP_SHIFT 11
/* PLL tracking mode 1 (0x0083) */
#define RT5668_I2S1_ASRC_MASK (0x1 << 13)
#define RT5668_I2S1_ASRC_SHIFT 13
#define RT5668_DAC_STO1_ASRC_MASK (0x1 << 12)
#define RT5668_DAC_STO1_ASRC_SHIFT 12
#define RT5668_ADC_STO1_ASRC_MASK (0x1 << 4)
#define RT5668_ADC_STO1_ASRC_SHIFT 4
/* PLL tracking mode 2 (0x0084)*/
#define RT5668_DA_STO1_TRACK_MASK (0x7 << 12)
#define RT5668_DA_STO1_TRACK_SHIFT 12
#define RT5668_DA_STO1_TRACK_SYSCLK (0x0 << 12)
#define RT5668_DA_STO1_TRACK_I2S1 (0x1 << 12)
/* PLL tracking mode 3 (0x0085)*/
#define RT5668_AD_STO1_TRACK_MASK (0x7 << 12)
#define RT5668_AD_STO1_TRACK_SHIFT 12
#define RT5668_AD_STO1_TRACK_SYSCLK (0x0 << 12)
#define RT5668_AD_STO1_TRACK_I2S1 (0x1 << 12)
/* HPOUT Charge pump control 1 (0x0091) */
#define RT5668_OSW_HP_L_MASK (0x1 << 11)
#define RT5668_OSW_HP_L_SHIFT 11
#define RT5668_OSW_HP_L_EN (0x1 << 11)
#define RT5668_OSW_HP_L_DIS (0x0 << 11)
#define RT5668_OSW_HP_R_MASK (0x1 << 10)
#define RT5668_OSW_HP_R_SHIFT 10
#define RT5668_OSW_HP_R_EN (0x1 << 10)
#define RT5668_OSW_HP_R_DIS (0x0 << 10)
#define RT5668_SEL_PM_HP_MASK (0x3 << 8)
#define RT5668_SEL_PM_HP_SHIFT 8
#define RT5668_SEL_PM_HP_0_6 (0x0 << 8)
#define RT5668_SEL_PM_HP_0_9 (0x1 << 8)
#define RT5668_SEL_PM_HP_1_8 (0x2 << 8)
#define RT5668_SEL_PM_HP_HIGH (0x3 << 8)
#define RT5668_OVCD_HP_MASK (0x1 << 2)
#define RT5668_OVCD_HP_SHIFT 2
#define RT5668_OVCD_HP_EN (0x1 << 2)
#define RT5668_OVCD_HP_DIS (0x0 << 2)
/* RC Clock Control (0x0094) */
#define RT5668_DIG_25M_CLK_MASK (0x1 << 9)
#define RT5668_DIG_25M_CLK_SHIFT 9
#define RT5668_DIG_25M_CLK_DIS (0x0 << 9)
#define RT5668_DIG_25M_CLK_EN (0x1 << 9)
#define RT5668_DIG_1M_CLK_MASK (0x1 << 8)
#define RT5668_DIG_1M_CLK_SHIFT 8
#define RT5668_DIG_1M_CLK_DIS (0x0 << 8)
#define RT5668_DIG_1M_CLK_EN (0x1 << 8)
/* Auto Turn On 1M RC CLK (0x009f) */
#define RT5668_IRQ_POW_SAV_MASK (0x1 << 15)
#define RT5668_IRQ_POW_SAV_SHIFT 15
#define RT5668_IRQ_POW_SAV_DIS (0x0 << 15)
#define RT5668_IRQ_POW_SAV_EN (0x1 << 15)
#define RT5668_IRQ_POW_SAV_JD1_MASK (0x1 << 14)
#define RT5668_IRQ_POW_SAV_JD1_SHIFT 14
#define RT5668_IRQ_POW_SAV_JD1_DIS (0x0 << 14)
#define RT5668_IRQ_POW_SAV_JD1_EN (0x1 << 14)
/* IRQ Control 1 (0x00b6) */
#define RT5668_EN_CB_JD_MASK (0x1 << 3)
#define RT5668_EN_CB_JD_SHIFT 3
#define RT5668_EN_CB_JD_EN (0x1 << 3)
#define RT5668_EN_CB_JD_DIS (0x0 << 3)
/* IRQ Control 3 (0x00b8) */
#define RT5668_EN_IRQ_INLINE_MASK (0x1 << 6)
#define RT5668_EN_IRQ_INLINE_SHIFT 6
#define RT5668_EN_IRQ_INLINE_BYP (0x0 << 6)
#define RT5668_EN_IRQ_INLINE_NOR (0x1 << 6)
/* GPIO Control 1 (0x00c0) */
#define RT5668_GP1_PIN_MASK (0x1 << 15)
#define RT5668_GP1_PIN_SHIFT 15
#define RT5668_GP1_PIN_GPIO1 (0x0 << 15)
#define RT5668_GP1_PIN_IRQ (0x1 << 15)
/* GPIO Control 2 (0x00c1) */
#define RT5668_GP4_PIN_CONF_MASK (0x1 << 5)
#define RT5668_GP4_PIN_CONF_SHIFT 5
#define RT5668_GP4_PIN_CONF_INPUT (0x0 << 5)
#define RT5668_GP4_PIN_CONF_OUTPUT (0x1 << 5)
/* GPIO Control 2 (0x00c2) */
#define RT5668_GP8_PIN_CONF_MASK (0x1 << 13)
#define RT5668_GP8_PIN_CONF_SHIFT 13
#define RT5668_GP8_PIN_CONF_INPUT (0x0 << 13)
#define RT5668_GP8_PIN_CONF_OUTPUT (0x1 << 13)
/* 4 Buttons Inline Command Function 1 (0x00df) */
#define RT5668_4BTN_CLK_DEB_MASK (0x3 << 2)
#define RT5668_4BTN_CLK_DEB_SHIFT 2
#define RT5668_4BTN_CLK_DEB_8MS (0x0 << 2)
#define RT5668_4BTN_CLK_DEB_16MS (0x1 << 2)
#define RT5668_4BTN_CLK_DEB_32MS (0x2 << 2)
#define RT5668_4BTN_CLK_DEB_65MS (0x3 << 2)
/* Inline Command Function 6 (0x00e0) */
#define RT5668_EN_4BTN_INL_MASK (0x1 << 15)
#define RT5668_EN_4BTN_INL_SHIFT 15
#define RT5668_EN_4BTN_INL_DIS (0x0 << 15)
#define RT5668_EN_4BTN_INL_EN (0x1 << 15)
#define RT5668_RESET_4BTN_INL_MASK (0x1 << 14)
#define RT5668_RESET_4BTN_INL_SHIFT 14
#define RT5668_RESET_4BTN_INL_RESET (0x0 << 14)
#define RT5668_RESET_4BTN_INL_NOR (0x1 << 14)
/* Digital Misc Control (0x00fa) */
#define RT5668_DIG_GATE_CTRL_MASK 0x1
#define RT5668_DIG_GATE_CTRL_SHIFT (0)
#define RT5668_DIG_GATE_CTRL_DIS 0x0
#define RT5668_DIG_GATE_CTRL_EN 0x1
/* Chopper and Clock control for DAC L (0x013a)*/
#define RT5668_CKXEN_DAC1_MASK (0x1 << 13)
#define RT5668_CKXEN_DAC1_SHIFT 13
#define RT5668_CKGEN_DAC1_MASK (0x1 << 12)
#define RT5668_CKGEN_DAC1_SHIFT 12
/* Chopper and Clock control for ADC (0x013b)*/
#define RT5668_CKXEN_ADCC_MASK (0x1 << 13)
#define RT5668_CKXEN_ADCC_SHIFT 13
#define RT5668_CKGEN_ADCC_MASK (0x1 << 12)
#define RT5668_CKGEN_ADCC_SHIFT 12
/* HP Behavior Logic Control 2 (0x01db) */
#define RT5668_HP_SIG_SRC1_MASK (0x3)
#define RT5668_HP_SIG_SRC1_SHIFT 0
#define RT5668_HP_SIG_SRC1_HP_DC (0x0)
#define RT5668_HP_SIG_SRC1_HP_CALIB (0x1)
#define RT5668_HP_SIG_SRC1_REG (0x2)
#define RT5668_HP_SIG_SRC1_SILENCE (0x3)
/* RT5663 specific register */
#define RT5663_HP_OUT_EN 0x0002
#define RT5663_HP_LCH_DRE 0x0005
#define RT5663_HP_RCH_DRE 0x0006
#define RT5663_CALIB_BST 0x000a
#define RT5663_RECMIX 0x0010
#define RT5663_SIL_DET_CTL 0x0015
#define RT5663_PWR_SAV_SILDET 0x0016
#define RT5663_SIDETONE_CTL 0x0018
#define RT5663_STO1_DAC_DIG_VOL 0x0019
#define RT5663_STO1_ADC_DIG_VOL 0x001c
#define RT5663_STO1_BOOST 0x001f
#define RT5663_HP_IMP_GAIN_1 0x0022
#define RT5663_HP_IMP_GAIN_2 0x0023
#define RT5663_STO1_ADC_MIXER 0x0026
#define RT5663_AD_DA_MIXER 0x0029
#define RT5663_STO_DAC_MIXER 0x002a
#define RT5663_DIG_SIDE_MIXER 0x002c
#define RT5663_BYPASS_STO_DAC 0x002d
#define RT5663_CALIB_REC_MIX 0x0040
#define RT5663_PWR_DIG_1 0x0061
#define RT5663_PWR_DIG_2 0x0062
#define RT5663_PWR_ANLG_1 0x0063
#define RT5663_PWR_ANLG_2 0x0064
#define RT5663_PWR_ANLG_3 0x0065
#define RT5663_PWR_MIXER 0x0066
#define RT5663_SIG_CLK_DET 0x006b
#define RT5663_PRE_DIV_GATING_1 0x006e
#define RT5663_PRE_DIV_GATING_2 0x006f
#define RT5663_I2S1_SDP 0x0070
#define RT5663_ADDA_CLK_1 0x0073
#define RT5663_ADDA_RST 0x0074
#define RT5663_FRAC_DIV_1 0x0075
#define RT5663_FRAC_DIV_2 0x0076
#define RT5663_TDM_1 0x0077
#define RT5663_TDM_2 0x0078
#define RT5663_TDM_3 0x0079
#define RT5663_TDM_4 0x007a
#define RT5663_TDM_5 0x007b
#define RT5663_GLB_CLK 0x0080
#define RT5663_PLL_1 0x0081
#define RT5663_PLL_2 0x0082
#define RT5663_ASRC_1 0x0083
#define RT5663_ASRC_2 0x0084
#define RT5663_ASRC_4 0x0086
#define RT5663_DUMMY_REG 0x0087
#define RT5663_ASRC_8 0x008a
#define RT5663_ASRC_9 0x008b
#define RT5663_ASRC_11 0x008c
#define RT5663_DEPOP_1 0x008e
#define RT5663_DEPOP_2 0x008f
#define RT5663_DEPOP_3 0x0090
#define RT5663_HP_CHARGE_PUMP_1 0x0091
#define RT5663_HP_CHARGE_PUMP_2 0x0092
#define RT5663_MICBIAS_1 0x0093
#define RT5663_RC_CLK 0x0094
#define RT5663_ASRC_11_2 0x0097
#define RT5663_DUMMY_REG_2 0x0098
#define RT5663_REC_PATH_GAIN 0x009a
#define RT5663_AUTO_1MRC_CLK 0x009f
#define RT5663_ADC_EQ_1 0x00ae
#define RT5663_ADC_EQ_2 0x00af
#define RT5663_IRQ_1 0x00b6
#define RT5663_IRQ_2 0x00b7
#define RT5663_IRQ_3 0x00b8
#define RT5663_IRQ_4 0x00ba
#define RT5663_IRQ_5 0x00bb
#define RT5663_INT_ST_1 0x00be
#define RT5663_INT_ST_2 0x00bf
#define RT5663_GPIO_1 0x00c0
#define RT5663_GPIO_2 0x00c1
#define RT5663_GPIO_STA 0x00c5
#define RT5663_SIN_GEN_1 0x00cb
#define RT5663_SIN_GEN_2 0x00cc
#define RT5663_SIN_GEN_3 0x00cd
#define RT5663_SOF_VOL_ZC1 0x00d9
#define RT5663_IL_CMD_1 0x00db
#define RT5663_IL_CMD_2 0x00dc
#define RT5663_IL_CMD_3 0x00dd
#define RT5663_IL_CMD_4 0x00de
#define RT5663_IL_CMD_5 0x00df
#define RT5663_IL_CMD_6 0x00e0
#define RT5663_IL_CMD_7 0x00e1
#define RT5663_IL_CMD_8 0x00e2
#define RT5663_IL_CMD_PWRSAV1 0x00e4
#define RT5663_IL_CMD_PWRSAV2 0x00e5
#define RT5663_EM_JACK_TYPE_1 0x00e6
#define RT5663_EM_JACK_TYPE_2 0x00e7
#define RT5663_EM_JACK_TYPE_3 0x00e8
#define RT5663_EM_JACK_TYPE_4 0x00e9
#define RT5663_EM_JACK_TYPE_5 0x00ea
#define RT5663_EM_JACK_TYPE_6 0x00eb
#define RT5663_STO1_HPF_ADJ1 0x00ec
#define RT5663_STO1_HPF_ADJ2 0x00ed
#define RT5663_FAST_OFF_MICBIAS 0x00f4
#define RT5663_JD_CTRL1 0x00f6
#define RT5663_JD_CTRL2 0x00f8
#define RT5663_DIG_MISC 0x00fa
#define RT5663_DIG_VOL_ZCD 0x0100
#define RT5663_ANA_BIAS_CUR_1 0x0108
#define RT5663_ANA_BIAS_CUR_2 0x0109
#define RT5663_ANA_BIAS_CUR_3 0x010a
#define RT5663_ANA_BIAS_CUR_4 0x010b
#define RT5663_ANA_BIAS_CUR_5 0x010c
#define RT5663_ANA_BIAS_CUR_6 0x010d
#define RT5663_BIAS_CUR_5 0x010e
#define RT5663_BIAS_CUR_6 0x010f
#define RT5663_BIAS_CUR_7 0x0110
#define RT5663_BIAS_CUR_8 0x0111
#define RT5663_DACREF_LDO 0x0112
#define RT5663_DUMMY_REG_3 0x0113
#define RT5663_BIAS_CUR_9 0x0114
#define RT5663_DUMMY_REG_4 0x0116
#define RT5663_VREFADJ_OP 0x0117
#define RT5663_VREF_RECMIX 0x0118
#define RT5663_CHARGE_PUMP_1 0x0125
#define RT5663_CHARGE_PUMP_1_2 0x0126
#define RT5663_CHARGE_PUMP_1_3 0x0127
#define RT5663_CHARGE_PUMP_2 0x0128
#define RT5663_DIG_IN_PIN1 0x0132
#define RT5663_PAD_DRV_CTL 0x0137
#define RT5663_PLL_INT_REG 0x0139
#define RT5663_CHOP_DAC_L 0x013a
#define RT5663_CHOP_ADC 0x013b
#define RT5663_CALIB_ADC 0x013c
#define RT5663_CHOP_DAC_R 0x013d
#define RT5663_DUMMY_CTL_DACLR 0x013e
#define RT5663_DUMMY_REG_5 0x0140
#define RT5663_SOFT_RAMP 0x0141
#define RT5663_TEST_MODE_1 0x0144
#define RT5663_TEST_MODE_2 0x0145
#define RT5663_TEST_MODE_3 0x0146
#define RT5663_STO_DRE_1 0x0160
#define RT5663_STO_DRE_2 0x0161
#define RT5663_STO_DRE_3 0x0162
#define RT5663_STO_DRE_4 0x0163
#define RT5663_STO_DRE_5 0x0164
#define RT5663_STO_DRE_6 0x0165
#define RT5663_STO_DRE_7 0x0166
#define RT5663_STO_DRE_8 0x0167
#define RT5663_STO_DRE_9 0x0168
#define RT5663_STO_DRE_10 0x0169
#define RT5663_MIC_DECRO_1 0x0180
#define RT5663_MIC_DECRO_2 0x0181
#define RT5663_MIC_DECRO_3 0x0182
#define RT5663_MIC_DECRO_4 0x0183
#define RT5663_MIC_DECRO_5 0x0184
#define RT5663_MIC_DECRO_6 0x0185
#define RT5663_HP_DECRO_1 0x01b0
#define RT5663_HP_DECRO_2 0x01b1
#define RT5663_HP_DECRO_3 0x01b2
#define RT5663_HP_DECRO_4 0x01b3
#define RT5663_HP_DECOUP 0x01b4
#define RT5663_HP_IMP_SEN_MAP8 0x01b5
#define RT5663_HP_IMP_SEN_MAP9 0x01b6
#define RT5663_HP_IMP_SEN_MAP10 0x01b7
#define RT5663_HP_IMP_SEN_MAP11 0x01b8
#define RT5663_HP_IMP_SEN_1 0x01c0
#define RT5663_HP_IMP_SEN_2 0x01c1
#define RT5663_HP_IMP_SEN_3 0x01c2
#define RT5663_HP_IMP_SEN_4 0x01c3
#define RT5663_HP_IMP_SEN_5 0x01c4
#define RT5663_HP_IMP_SEN_6 0x01c5
#define RT5663_HP_IMP_SEN_7 0x01c6
#define RT5663_HP_IMP_SEN_8 0x01c7
#define RT5663_HP_IMP_SEN_9 0x01c8
#define RT5663_HP_IMP_SEN_10 0x01c9
#define RT5663_HP_IMP_SEN_11 0x01ca
#define RT5663_HP_IMP_SEN_12 0x01cb
#define RT5663_HP_IMP_SEN_13 0x01cc
#define RT5663_HP_IMP_SEN_14 0x01cd
#define RT5663_HP_IMP_SEN_15 0x01ce
#define RT5663_HP_IMP_SEN_16 0x01cf
#define RT5663_HP_IMP_SEN_17 0x01d0
#define RT5663_HP_IMP_SEN_18 0x01d1
#define RT5663_HP_IMP_SEN_19 0x01d2
#define RT5663_HP_IMPSEN_DIG5 0x01d3
#define RT5663_HP_IMPSEN_MAP1 0x01d4
#define RT5663_HP_IMPSEN_MAP2 0x01d5
#define RT5663_HP_IMPSEN_MAP3 0x01d6
#define RT5663_HP_IMPSEN_MAP4 0x01d7
#define RT5663_HP_IMPSEN_MAP5 0x01d8
#define RT5663_HP_IMPSEN_MAP7 0x01d9
#define RT5663_HP_LOGIC_1 0x01da
#define RT5663_HP_LOGIC_2 0x01db
#define RT5663_HP_CALIB_1 0x01dd
#define RT5663_HP_CALIB_1_1 0x01de
#define RT5663_HP_CALIB_2 0x01df
#define RT5663_HP_CALIB_3 0x01e0
#define RT5663_HP_CALIB_4 0x01e1
#define RT5663_HP_CALIB_5 0x01e2
#define RT5663_HP_CALIB_5_1 0x01e3
#define RT5663_HP_CALIB_6 0x01e4
#define RT5663_HP_CALIB_7 0x01e5
#define RT5663_HP_CALIB_9 0x01e6
#define RT5663_HP_CALIB_10 0x01e7
#define RT5663_HP_CALIB_11 0x01e8
#define RT5663_HP_CALIB_ST1 0x01ea
#define RT5663_HP_CALIB_ST2 0x01eb
#define RT5663_HP_CALIB_ST3 0x01ec
#define RT5663_HP_CALIB_ST4 0x01ed
#define RT5663_HP_CALIB_ST5 0x01ee
#define RT5663_HP_CALIB_ST6 0x01ef
#define RT5663_HP_CALIB_ST7 0x01f0
#define RT5663_HP_CALIB_ST8 0x01f1
#define RT5663_HP_CALIB_ST9 0x01f2
#define RT5663_HP_AMP_DET 0x0200
#define RT5663_DUMMY_REG_6 0x0201
#define RT5663_HP_BIAS 0x0202
#define RT5663_CBJ_1 0x0250
#define RT5663_CBJ_2 0x0251
#define RT5663_CBJ_3 0x0252
#define RT5663_DUMMY_1 0x02fa
#define RT5663_DUMMY_2 0x02fb
#define RT5663_DUMMY_3 0x02fc
#define RT5663_ANA_JD 0x0300
#define RT5663_ADC_LCH_LPF1_A1 0x03d0
#define RT5663_ADC_RCH_LPF1_A1 0x03d1
#define RT5663_ADC_LCH_LPF1_H0 0x03d2
#define RT5663_ADC_RCH_LPF1_H0 0x03d3
#define RT5663_ADC_LCH_BPF1_A1 0x03d4
#define RT5663_ADC_RCH_BPF1_A1 0x03d5
#define RT5663_ADC_LCH_BPF1_A2 0x03d6
#define RT5663_ADC_RCH_BPF1_A2 0x03d7
#define RT5663_ADC_LCH_BPF1_H0 0x03d8
#define RT5663_ADC_RCH_BPF1_H0 0x03d9
#define RT5663_ADC_LCH_BPF2_A1 0x03da
#define RT5663_ADC_RCH_BPF2_A1 0x03db
#define RT5663_ADC_LCH_BPF2_A2 0x03dc
#define RT5663_ADC_RCH_BPF2_A2 0x03dd
#define RT5663_ADC_LCH_BPF2_H0 0x03de
#define RT5663_ADC_RCH_BPF2_H0 0x03df
#define RT5663_ADC_LCH_BPF3_A1 0x03e0
#define RT5663_ADC_RCH_BPF3_A1 0x03e1
#define RT5663_ADC_LCH_BPF3_A2 0x03e2
#define RT5663_ADC_RCH_BPF3_A2 0x03e3
#define RT5663_ADC_LCH_BPF3_H0 0x03e4
#define RT5663_ADC_RCH_BPF3_H0 0x03e5
#define RT5663_ADC_LCH_BPF4_A1 0x03e6
#define RT5663_ADC_RCH_BPF4_A1 0x03e7
#define RT5663_ADC_LCH_BPF4_A2 0x03e8
#define RT5663_ADC_RCH_BPF4_A2 0x03e9
#define RT5663_ADC_LCH_BPF4_H0 0x03ea
#define RT5663_ADC_RCH_BPF4_H0 0x03eb
#define RT5663_ADC_LCH_HPF1_A1 0x03ec
#define RT5663_ADC_RCH_HPF1_A1 0x03ed
#define RT5663_ADC_LCH_HPF1_H0 0x03ee
#define RT5663_ADC_RCH_HPF1_H0 0x03ef
#define RT5663_ADC_EQ_PRE_VOL_L 0x03f0
#define RT5663_ADC_EQ_PRE_VOL_R 0x03f1
#define RT5663_ADC_EQ_POST_VOL_L 0x03f2
#define RT5663_ADC_EQ_POST_VOL_R 0x03f3
/* RT5663: RECMIX Control (0x0010) */
#define RT5663_RECMIX1_BST1_MASK (0x1)
#define RT5663_RECMIX1_BST1_SHIFT 0
#define RT5663_RECMIX1_BST1_ON (0x0)
#define RT5663_RECMIX1_BST1_OFF (0x1)
/* RT5663: Bypass Stereo1 DAC Mixer Control (0x002d) */
#define RT5663_DACL1_SRC_MASK (0x1 << 3)
#define RT5663_DACL1_SRC_SHIFT 3
#define RT5663_DACR1_SRC_MASK (0x1 << 2)
#define RT5663_DACR1_SRC_SHIFT 2
/* RT5663: TDM control 2 (0x0078) */
#define RT5663_DATA_SWAP_ADCDAT1_MASK (0x3 << 14)
#define RT5663_DATA_SWAP_ADCDAT1_SHIFT 14
#define RT5663_DATA_SWAP_ADCDAT1_LR (0x0 << 14)
#define RT5663_DATA_SWAP_ADCDAT1_RL (0x1 << 14)
#define RT5663_DATA_SWAP_ADCDAT1_LL (0x2 << 14)
#define RT5663_DATA_SWAP_ADCDAT1_RR (0x3 << 14)
/* RT5663: TDM control 5 (0x007b) */
#define RT5663_TDM_LENGTN_MASK (0x3)
#define RT5663_TDM_LENGTN_SHIFT 0
#define RT5663_TDM_LENGTN_16 (0x0)
#define RT5663_TDM_LENGTN_20 (0x1)
#define RT5663_TDM_LENGTN_24 (0x2)
#define RT5663_TDM_LENGTN_32 (0x3)
/* RT5663: Global Clock Control (0x0080) */
#define RT5663_SCLK_SRC_MASK (0x3 << 14)
#define RT5663_SCLK_SRC_SHIFT 14
#define RT5663_SCLK_SRC_MCLK (0x0 << 14)
#define RT5663_SCLK_SRC_PLL1 (0x1 << 14)
#define RT5663_SCLK_SRC_RCCLK (0x2 << 14)
#define RT5663_PLL1_SRC_MASK (0x7 << 11)
#define RT5663_PLL1_SRC_SHIFT 11
#define RT5663_PLL1_SRC_MCLK (0x0 << 11)
#define RT5663_PLL1_SRC_BCLK1 (0x1 << 11)
/* PLL tracking mode 1 (0x0083) */
#define RT5663_I2S1_ASRC_MASK (0x1 << 11)
#define RT5663_I2S1_ASRC_SHIFT 11
#define RT5663_DAC_STO1_ASRC_MASK (0x1 << 10)
#define RT5663_DAC_STO1_ASRC_SHIFT 10
#define RT5663_ADC_STO1_ASRC_MASK (0x1 << 3)
#define RT5663_ADC_STO1_ASRC_SHIFT 3
/* PLL tracking mode 2 (0x0084)*/
#define RT5663_DA_STO1_TRACK_MASK (0x7 << 12)
#define RT5663_DA_STO1_TRACK_SHIFT 12
#define RT5663_DA_STO1_TRACK_SYSCLK (0x0 << 12)
#define RT5663_DA_STO1_TRACK_I2S1 (0x1 << 12)
#define RT5663_AD_STO1_TRACK_MASK (0x7)
#define RT5663_AD_STO1_TRACK_SHIFT 0
#define RT5663_AD_STO1_TRACK_SYSCLK (0x0)
#define RT5663_AD_STO1_TRACK_I2S1 (0x1)
/* RT5663: HPOUT Charge pump control 1 (0x0091) */
#define RT5663_SI_HP_MASK (0x1 << 12)
#define RT5663_SI_HP_SHIFT 12
#define RT5663_SI_HP_EN (0x1 << 12)
#define RT5663_SI_HP_DIS (0x0 << 12)
/* RT5663: GPIO Control 2 (0x00b6) */
#define RT5663_GP1_PIN_CONF_MASK (0x1 << 2)
#define RT5663_GP1_PIN_CONF_SHIFT 2
#define RT5663_GP1_PIN_CONF_OUTPUT (0x1 << 2)
#define RT5663_GP1_PIN_CONF_INPUT (0x0 << 2)
/* RT5663: GPIO Control 2 (0x00b7) */
#define RT5663_EN_IRQ_INLINE_MASK (0x1 << 3)
#define RT5663_EN_IRQ_INLINE_SHIFT 3
#define RT5663_EN_IRQ_INLINE_NOR (0x1 << 3)
#define RT5663_EN_IRQ_INLINE_BYP (0x0 << 3)
/* RT5663: IRQ Control 1 (0x00c1) */
#define RT5663_EN_IRQ_JD1_MASK (0x1 << 6)
#define RT5663_EN_IRQ_JD1_SHIFT 6
#define RT5663_EN_IRQ_JD1_EN (0x1 << 6)
#define RT5663_EN_IRQ_JD1_DIS (0x0 << 6)
/* RT5663: Inline Command Function 2 (0x00dc) */
#define RT5663_PWR_MIC_DET_MASK (0x1)
#define RT5663_PWR_MIC_DET_SHIFT 0
#define RT5663_PWR_MIC_DET_ON (0x1)
#define RT5663_PWR_MIC_DET_OFF (0x0)
/* RT5663: Embeeded Jack and Type Detection Control 1 (0x00e6)*/
#define RT5663_CBJ_DET_MASK (0x1 << 15)
#define RT5663_CBJ_DET_SHIFT 15
#define RT5663_CBJ_DET_DIS (0x0 << 15)
#define RT5663_CBJ_DET_EN (0x1 << 15)
#define RT5663_EXT_JD_MASK (0x1 << 11)
#define RT5663_EXT_JD_SHIFT 11
#define RT5663_EXT_JD_EN (0x1 << 11)
#define RT5663_EXT_JD_DIS (0x0 << 11)
#define RT5663_POL_EXT_JD_MASK (0x1 << 10)
#define RT5663_POL_EXT_JD_SHIFT 10
#define RT5663_POL_EXT_JD_EN (0x1 << 10)
#define RT5663_POL_EXT_JD_DIS (0x0 << 10)
/* RT5663: DACREF LDO Control (0x0112)*/
#define RT5663_PWR_LDO_DACREFL_MASK (0x1 << 9)
#define RT5663_PWR_LDO_DACREFL_SHIFT 9
#define RT5663_PWR_LDO_DACREFR_MASK (0x1 << 1)
#define RT5663_PWR_LDO_DACREFR_SHIFT 1
/* RT5663: Stereo Dynamic Range Enhancement Control 9 (0x0168, 0x0169)*/
#define RT5663_DRE_GAIN_HP_MASK (0x1f)
#define RT5663_DRE_GAIN_HP_SHIFT 0
/* RT5663: Combo Jack Control (0x0250) */
#define RT5663_INBUF_CBJ_BST1_MASK (0x1 << 11)
#define RT5663_INBUF_CBJ_BST1_SHIFT 11
#define RT5663_INBUF_CBJ_BST1_ON (0x1 << 11)
#define RT5663_INBUF_CBJ_BST1_OFF (0x0 << 11)
#define RT5663_CBJ_SENSE_BST1_MASK (0x1 << 10)
#define RT5663_CBJ_SENSE_BST1_SHIFT 10
#define RT5663_CBJ_SENSE_BST1_L (0x1 << 10)
#define RT5663_CBJ_SENSE_BST1_R (0x0 << 10)
/* RT5663: Combo Jack Control (0x0251) */
#define RT5663_GAIN_BST1_MASK (0xf)
#define RT5663_GAIN_BST1_SHIFT 0
/* RT5663: Dummy register 1 (0x02fa) */
#define RT5663_EMB_CLK_MASK (0x1 << 9)
#define RT5663_EMB_CLK_SHIFT 9
#define RT5663_EMB_CLK_EN (0x1 << 9)
#define RT5663_EMB_CLK_DIS (0x0 << 9)
#define RT5663_HPA_CPL_BIAS_MASK (0x7 << 6)
#define RT5663_HPA_CPL_BIAS_SHIFT 6
#define RT5663_HPA_CPL_BIAS_0_5 (0x0 << 6)
#define RT5663_HPA_CPL_BIAS_1 (0x1 << 6)
#define RT5663_HPA_CPL_BIAS_2 (0x2 << 6)
#define RT5663_HPA_CPL_BIAS_3 (0x3 << 6)
#define RT5663_HPA_CPL_BIAS_4_1 (0x4 << 6)
#define RT5663_HPA_CPL_BIAS_4_2 (0x5 << 6)
#define RT5663_HPA_CPL_BIAS_6 (0x6 << 6)
#define RT5663_HPA_CPL_BIAS_8 (0x7 << 6)
#define RT5663_HPA_CPR_BIAS_MASK (0x7 << 3)
#define RT5663_HPA_CPR_BIAS_SHIFT 3
#define RT5663_HPA_CPR_BIAS_0_5 (0x0 << 3)
#define RT5663_HPA_CPR_BIAS_1 (0x1 << 3)
#define RT5663_HPA_CPR_BIAS_2 (0x2 << 3)
#define RT5663_HPA_CPR_BIAS_3 (0x3 << 3)
#define RT5663_HPA_CPR_BIAS_4_1 (0x4 << 3)
#define RT5663_HPA_CPR_BIAS_4_2 (0x5 << 3)
#define RT5663_HPA_CPR_BIAS_6 (0x6 << 3)
#define RT5663_HPA_CPR_BIAS_8 (0x7 << 3)
#define RT5663_DUMMY_BIAS_MASK (0x7)
#define RT5663_DUMMY_BIAS_SHIFT 0
#define RT5663_DUMMY_BIAS_0_5 (0x0)
#define RT5663_DUMMY_BIAS_1 (0x1)
#define RT5663_DUMMY_BIAS_2 (0x2)
#define RT5663_DUMMY_BIAS_3 (0x3)
#define RT5663_DUMMY_BIAS_4_1 (0x4)
#define RT5663_DUMMY_BIAS_4_2 (0x5)
#define RT5663_DUMMY_BIAS_6 (0x6)
#define RT5663_DUMMY_BIAS_8 (0x7)
/* System Clock Source */
enum {
RT5663_SCLK_S_MCLK,
RT5663_SCLK_S_PLL1,
RT5663_SCLK_S_RCCLK,
};
/* PLL1 Source */
enum {
RT5663_PLL1_S_MCLK,
RT5663_PLL1_S_BCLK1,
};
enum {
RT5663_AIF,
RT5663_AIFS,
};
/* asrc clock source */
enum {
RT5663_CLK_SEL_SYS = 0x0,
RT5663_CLK_SEL_I2S1_ASRC = 0x1,
};
/* filter mask */
enum {
RT5663_DA_STEREO_FILTER = 0x1,
RT5663_AD_STEREO_FILTER = 0x2,
};
int rt5663_set_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *hs_jack);
int rt5663_sel_asrc_clk_src(struct snd_soc_codec *codec,
unsigned int filter_mask, unsigned int clk_src);
#endif /* __RT5663_H__ */
......@@ -9,6 +9,7 @@
* published by the Free Software Foundation.
*/
#include <linux/acpi.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
......@@ -40,6 +41,15 @@
#define RT5677_PR_BASE (RT5677_PR_RANGE_BASE + (0 * RT5677_PR_SPACING))
/* GPIO indexes defined by ACPI */
enum {
RT5677_GPIO_PLUG_DET = 0,
RT5677_GPIO_MIC_PRESENT_L = 1,
RT5677_GPIO_HOTWORD_DET_L = 2,
RT5677_GPIO_DSP_INT = 3,
RT5677_GPIO_HP_AMP_SHDN_L = 4,
};
static const struct regmap_range_cfg rt5677_ranges[] = {
{
.name = "PR",
......@@ -5020,10 +5030,47 @@ static const struct regmap_config rt5677_regmap = {
static const struct i2c_device_id rt5677_i2c_id[] = {
{ "rt5677", RT5677 },
{ "rt5676", RT5676 },
{ "RT5677CE:00", RT5677 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id);
static const struct acpi_gpio_params plug_det_gpio = { RT5677_GPIO_PLUG_DET, 0, false };
static const struct acpi_gpio_params mic_present_gpio = { RT5677_GPIO_MIC_PRESENT_L, 0, false };
static const struct acpi_gpio_params headphone_enable_gpio = { RT5677_GPIO_HP_AMP_SHDN_L, 0, false };
static const struct acpi_gpio_mapping bdw_rt5677_gpios[] = {
{ "plug-det-gpios", &plug_det_gpio, 1 },
{ "mic-present-gpios", &mic_present_gpio, 1 },
{ "headphone-enable-gpios", &headphone_enable_gpio, 1 },
{ NULL },
};
static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677,
struct device *dev)
{
int ret;
u32 val;
ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev),
bdw_rt5677_gpios);
if (ret)
dev_warn(dev, "Failed to add driver gpios\n");
if (!device_property_read_u32(dev, "DCLK", &val))
rt5677->pdata.dmic2_clk_pin = val;
rt5677->pdata.in1_diff = device_property_read_bool(dev, "IN1");
rt5677->pdata.in2_diff = device_property_read_bool(dev, "IN2");
rt5677->pdata.lout1_diff = device_property_read_bool(dev, "OUT1");
rt5677->pdata.lout2_diff = device_property_read_bool(dev, "OUT2");
rt5677->pdata.lout3_diff = device_property_read_bool(dev, "OUT3");
device_property_read_u32(dev, "JD1", &rt5677->pdata.jd1_gpio);
device_property_read_u32(dev, "JD2", &rt5677->pdata.jd2_gpio);
device_property_read_u32(dev, "JD3", &rt5677->pdata.jd3_gpio);
}
static void rt5677_read_device_properties(struct rt5677_priv *rt5677,
struct device *dev)
{
......@@ -5129,8 +5176,12 @@ static int rt5677_i2c_probe(struct i2c_client *i2c,
if (pdata)
rt5677->pdata = *pdata;
else
else if (i2c->dev.of_node)
rt5677_read_device_properties(rt5677, &i2c->dev);
else if (ACPI_HANDLE(&i2c->dev))
rt5677_read_acpi_properties(rt5677, &i2c->dev);
else
return -EINVAL;
/* pow-ldo2 and reset are optional. The codec pins may be statically
* connected on the board without gpios. If the gpio device property
......
......@@ -546,6 +546,7 @@ static int uda134x_codec_probe(struct platform_device *pdev)
{
struct uda134x_platform_data *pd = pdev->dev.platform_data;
struct uda134x_priv *uda134x;
int ret;
if (!pd) {
dev_err(&pdev->dev, "Missing L3 bitbang function\n");
......@@ -559,6 +560,12 @@ static int uda134x_codec_probe(struct platform_device *pdev)
uda134x->pd = pd;
platform_set_drvdata(pdev, uda134x);
if (pd->l3.use_gpios) {
ret = l3_set_gpio_ops(&pdev->dev, &uda134x->pd->l3);
if (ret < 0)
return ret;
}
uda134x->regmap = devm_regmap_init(&pdev->dev, NULL, pd,
&uda134x_regmap_config);
if (IS_ERR(uda134x->regmap))
......
config SND_SOC_SAMSUNG
menuconfig SND_SOC_SAMSUNG
tristate "ASoC support for Samsung"
depends on (PLAT_SAMSUNG || ARCH_EXYNOS)
select SND_SOC_GENERIC_DMAENGINE_PCM
help
---help---
Say Y or M if you want to add support for codecs attached to
the Samsung SoCs' Audio interfaces. You will also need to
select the audio interfaces to support below.
if SND_SOC_SAMSUNG
config SND_S3C24XX_I2S
tristate
......@@ -18,22 +20,22 @@ config SND_S3C2412_SOC_I2S
select SND_S3C_I2SV2_SOC
config SND_SAMSUNG_PCM
tristate
tristate "Samsung PCM interface support"
config SND_SAMSUNG_AC97
tristate
select SND_SOC_AC97_BUS
config SND_SAMSUNG_SPDIF
tristate
tristate "Samsung SPDIF transmitter support"
select SND_SOC_SPDIF
config SND_SAMSUNG_I2S
tristate
tristate "Samsung I2S interface support"
config SND_SOC_SAMSUNG_NEO1973_WM8753
tristate "Audio support for Openmoko Neo1973 Smartphones (GTA02)"
depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA02
depends on MACH_NEO1973_GTA02
select SND_S3C24XX_I2S
select SND_SOC_WM8753
select SND_SOC_BT_SCO
......@@ -43,7 +45,7 @@ config SND_SOC_SAMSUNG_NEO1973_WM8753
config SND_SOC_SAMSUNG_JIVE_WM8750
tristate "SoC I2S Audio support for Jive"
depends on SND_SOC_SAMSUNG && MACH_JIVE && I2C
depends on MACH_JIVE && I2C
select SND_SOC_WM8750
select SND_S3C2412_SOC_I2S
help
......@@ -51,7 +53,7 @@ config SND_SOC_SAMSUNG_JIVE_WM8750
config SND_SOC_SAMSUNG_SMDK_WM8580
tristate "SoC I2S Audio support for WM8580 on SMDK"
depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110)
depends on MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110
depends on I2C
select SND_SOC_WM8580
select SND_SAMSUNG_I2S
......@@ -60,7 +62,6 @@ config SND_SOC_SAMSUNG_SMDK_WM8580
config SND_SOC_SAMSUNG_SMDK_WM8994
tristate "SoC I2S Audio support for WM8994 on SMDK"
depends on SND_SOC_SAMSUNG
depends on I2C=y
select MFD_WM8994
select SND_SOC_WM8994
......@@ -70,7 +71,7 @@ config SND_SOC_SAMSUNG_SMDK_WM8994
config SND_SOC_SAMSUNG_SMDK2443_WM9710
tristate "SoC AC97 Audio support for SMDK2443 - WM9710"
depends on SND_SOC_SAMSUNG && MACH_SMDK2443
depends on MACH_SMDK2443
select AC97_BUS
select SND_SOC_AC97_CODEC
select SND_SAMSUNG_AC97
......@@ -80,7 +81,7 @@ config SND_SOC_SAMSUNG_SMDK2443_WM9710
config SND_SOC_SAMSUNG_LN2440SBC_ALC650
tristate "SoC AC97 Audio support for LN2440SBC - ALC650"
depends on SND_SOC_SAMSUNG && ARCH_S3C24XX
depends on ARCH_S3C24XX
select AC97_BUS
select SND_SOC_AC97_CODEC
select SND_SAMSUNG_AC97
......@@ -90,7 +91,7 @@ config SND_SOC_SAMSUNG_LN2440SBC_ALC650
config SND_SOC_SAMSUNG_S3C24XX_UDA134X
tristate "SoC I2S Audio support UDA134X wired to a S3C24XX"
depends on SND_SOC_SAMSUNG && ARCH_S3C24XX
depends on ARCH_S3C24XX
select SND_S3C24XX_I2S
select SND_SOC_L3
select SND_SOC_UDA134X
......@@ -102,21 +103,21 @@ config SND_SOC_SAMSUNG_SIMTEC
config SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23
tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards"
depends on SND_SOC_SAMSUNG && ARCH_S3C24XX && I2C
depends on ARCH_S3C24XX && I2C
select SND_S3C24XX_I2S
select SND_SOC_TLV320AIC23_I2C
select SND_SOC_SAMSUNG_SIMTEC
config SND_SOC_SAMSUNG_SIMTEC_HERMES
tristate "SoC I2S Audio support for Simtec Hermes board"
depends on SND_SOC_SAMSUNG && ARCH_S3C24XX && I2C
depends on ARCH_S3C24XX && I2C
select SND_S3C24XX_I2S
select SND_SOC_TLV320AIC3X
select SND_SOC_SAMSUNG_SIMTEC
config SND_SOC_SAMSUNG_H1940_UDA1380
tristate "Audio support for the HP iPAQ H1940"
depends on SND_SOC_SAMSUNG && ARCH_H1940 && I2C
depends on ARCH_H1940 && I2C
select SND_S3C24XX_I2S
select SND_SOC_UDA1380
help
......@@ -124,7 +125,7 @@ config SND_SOC_SAMSUNG_H1940_UDA1380
config SND_SOC_SAMSUNG_RX1950_UDA1380
tristate "Audio support for the HP iPAQ RX1950"
depends on SND_SOC_SAMSUNG && MACH_RX1950 && I2C
depends on MACH_RX1950 && I2C
select SND_S3C24XX_I2S
select SND_SOC_UDA1380
help
......@@ -132,7 +133,7 @@ config SND_SOC_SAMSUNG_RX1950_UDA1380
config SND_SOC_SAMSUNG_SMDK_WM9713
tristate "SoC AC97 Audio support for SMDK with WM9713"
depends on SND_SOC_SAMSUNG && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110)
depends on MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110
select SND_SOC_WM9713
select SND_SAMSUNG_AC97
help
......@@ -140,20 +141,19 @@ config SND_SOC_SAMSUNG_SMDK_WM9713
config SND_SOC_SMARTQ
tristate "SoC I2S Audio support for SmartQ board"
depends on SND_SOC_SAMSUNG && MACH_SMARTQ && I2C
depends on MACH_SMARTQ && I2C
select SND_SAMSUNG_I2S
select SND_SOC_WM8750
config SND_SOC_SAMSUNG_SMDK_SPDIF
tristate "SoC S/PDIF Audio support for SMDK"
depends on SND_SOC_SAMSUNG
select SND_SAMSUNG_SPDIF
help
Say Y if you want to add support for SoC S/PDIF audio on the SMDK.
config SND_SOC_SMDK_WM8580_PCM
tristate "SoC PCM Audio support for WM8580 on SMDK"
depends on SND_SOC_SAMSUNG && (MACH_SMDKV210 || MACH_SMDKC110)
depends on MACH_SMDKV210 || MACH_SMDKC110
depends on I2C
select SND_SOC_WM8580
select SND_SAMSUNG_PCM
......@@ -162,7 +162,6 @@ config SND_SOC_SMDK_WM8580_PCM
config SND_SOC_SMDK_WM8994_PCM
tristate "SoC PCM Audio support for WM8994 on SMDK"
depends on SND_SOC_SAMSUNG
depends on I2C=y
select MFD_WM8994
select SND_SOC_WM8994
......@@ -172,7 +171,7 @@ config SND_SOC_SMDK_WM8994_PCM
config SND_SOC_SPEYSIDE
tristate "Audio support for Wolfson Speyside"
depends on SND_SOC_SAMSUNG && I2C && SPI_MASTER
depends on I2C && SPI_MASTER
depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST
select SND_SAMSUNG_I2S
select SND_SOC_WM8996
......@@ -182,14 +181,14 @@ config SND_SOC_SPEYSIDE
config SND_SOC_TOBERMORY
tristate "Audio support for Wolfson Tobermory"
depends on SND_SOC_SAMSUNG && INPUT && I2C
depends on INPUT && I2C
depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST
select SND_SAMSUNG_I2S
select SND_SOC_WM8962
config SND_SOC_BELLS
tristate "Audio support for Wolfson Bells"
depends on SND_SOC_SAMSUNG && MFD_ARIZONA && I2C && SPI_MASTER
depends on MFD_ARIZONA && I2C && SPI_MASTER
depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST
select SND_SAMSUNG_I2S
select SND_SOC_WM5102
......@@ -200,7 +199,7 @@ config SND_SOC_BELLS
config SND_SOC_LOWLAND
tristate "Audio support for Wolfson Lowland"
depends on SND_SOC_SAMSUNG && I2C
depends on I2C
depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST
select SND_SAMSUNG_I2S
select SND_SOC_WM5100
......@@ -208,7 +207,7 @@ config SND_SOC_LOWLAND
config SND_SOC_LITTLEMILL
tristate "Audio support for Wolfson Littlemill"
depends on SND_SOC_SAMSUNG && I2C
depends on I2C
depends on MACH_WLF_CRAGG_6410 || COMPILE_TEST
select SND_SAMSUNG_I2S
select MFD_WM8994
......@@ -216,7 +215,7 @@ config SND_SOC_LITTLEMILL
config SND_SOC_SNOW
tristate "Audio support for Google Snow boards"
depends on SND_SOC_SAMSUNG && I2C
depends on I2C
select SND_SOC_MAX98090
select SND_SOC_MAX98095
select SND_SAMSUNG_I2S
......@@ -226,6 +225,8 @@ config SND_SOC_SNOW
config SND_SOC_ARNDALE_RT5631_ALC5631
tristate "Audio support for RT5631(ALC5631) on Arndale Board"
depends on SND_SOC_SAMSUNG && I2C
depends on I2C
select SND_SAMSUNG_I2S
select SND_SOC_RT5631
endif #SND_SOC_SAMSUNG
......@@ -38,16 +38,16 @@ struct s3c_ac97_info {
};
static struct s3c_ac97_info s3c_ac97;
static struct s3c_dma_params s3c_ac97_pcm_out = {
.dma_size = 4,
static struct snd_dmaengine_dai_dma_data s3c_ac97_pcm_out = {
.addr_width = 4,
};
static struct s3c_dma_params s3c_ac97_pcm_in = {
.dma_size = 4,
static struct snd_dmaengine_dai_dma_data s3c_ac97_pcm_in = {
.addr_width = 4,
};
static struct s3c_dma_params s3c_ac97_mic_in = {
.dma_size = 4,
static struct snd_dmaengine_dai_dma_data s3c_ac97_mic_in = {
.addr_width = 4,
};
static void s3c_ac97_activate(struct snd_ac97 *ac97)
......@@ -74,7 +74,7 @@ static void s3c_ac97_activate(struct snd_ac97 *ac97)
writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
if (!wait_for_completion_timeout(&s3c_ac97.done, HZ))
pr_err("AC97: Unable to activate!");
pr_err("AC97: Unable to activate!\n");
}
static unsigned short s3c_ac97_read(struct snd_ac97 *ac97,
......@@ -100,7 +100,7 @@ static unsigned short s3c_ac97_read(struct snd_ac97 *ac97,
writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
if (!wait_for_completion_timeout(&s3c_ac97.done, HZ))
pr_err("AC97: Unable to read!");
pr_err("AC97: Unable to read!\n");
stat = readl(s3c_ac97.regs + S3C_AC97_STAT);
addr = (stat >> 16) & 0x7f;
......@@ -137,7 +137,7 @@ static void s3c_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
if (!wait_for_completion_timeout(&s3c_ac97.done, HZ))
pr_err("AC97: Unable to write!");
pr_err("AC97: Unable to write!\n");
ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD);
ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ;
......@@ -273,14 +273,14 @@ static const struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = {
static int s3c_ac97_dai_probe(struct snd_soc_dai *dai)
{
samsung_asoc_init_dma_data(dai, &s3c_ac97_pcm_out, &s3c_ac97_pcm_in);
snd_soc_dai_init_dma_data(dai, &s3c_ac97_pcm_out, &s3c_ac97_pcm_in);
return 0;
}
static int s3c_ac97_mic_dai_probe(struct snd_soc_dai *dai)
{
samsung_asoc_init_dma_data(dai, NULL, &s3c_ac97_mic_in);
snd_soc_dai_init_dma_data(dai, NULL, &s3c_ac97_mic_in);
return 0;
}
......@@ -346,12 +346,12 @@ static int s3c_ac97_probe(struct platform_device *pdev)
if (IS_ERR(s3c_ac97.regs))
return PTR_ERR(s3c_ac97.regs);
s3c_ac97_pcm_out.slave = ac97_pdata->dma_playback;
s3c_ac97_pcm_out.dma_addr = mem_res->start + S3C_AC97_PCM_DATA;
s3c_ac97_pcm_in.slave = ac97_pdata->dma_capture;
s3c_ac97_pcm_in.dma_addr = mem_res->start + S3C_AC97_PCM_DATA;
s3c_ac97_mic_in.slave = ac97_pdata->dma_capture_mic;
s3c_ac97_mic_in.dma_addr = mem_res->start + S3C_AC97_MIC_DATA;
s3c_ac97_pcm_out.filter_data = ac97_pdata->dma_playback;
s3c_ac97_pcm_out.addr = mem_res->start + S3C_AC97_PCM_DATA;
s3c_ac97_pcm_in.filter_data = ac97_pdata->dma_capture;
s3c_ac97_pcm_in.addr = mem_res->start + S3C_AC97_PCM_DATA;
s3c_ac97_mic_in.filter_data = ac97_pdata->dma_capture_mic;
s3c_ac97_mic_in.addr = mem_res->start + S3C_AC97_MIC_DATA;
init_completion(&s3c_ac97.done);
mutex_init(&s3c_ac97.lock);
......
/*
* dma.h --
*
* 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
......@@ -9,27 +7,15 @@
* ALSA PCM interface for the Samsung SoC
*/
#ifndef _S3C_AUDIO_H
#define _S3C_AUDIO_H
#ifndef _SAMSUNG_DMA_H
#define _SAMSUNG_DMA_H
#include <sound/dmaengine_pcm.h>
#include <linux/dmaengine.h>
struct s3c_dma_params {
void *slave; /* Channel ID */
dma_addr_t dma_addr;
int dma_size; /* Size of the DMA transfer */
char *ch_name;
struct snd_dmaengine_dai_dma_data dma_data;
};
void samsung_asoc_init_dma_data(struct snd_soc_dai *dai,
struct s3c_dma_params *playback,
struct s3c_dma_params *capture);
/*
* @tx, @rx arguments can be NULL if the DMA channel names are "tx", "rx",
* otherwise actual DMA channel names must be passed to this function.
*/
int samsung_asoc_dma_platform_register(struct device *dev, dma_filter_fn filter,
const char *tx, const char *rx);
#endif
#endif /* _SAMSUNG_DMA_H */
......@@ -16,49 +16,18 @@
*/
#include <linux/module.h>
#include <linux/amba/pl08x.h>
#include <linux/platform_data/dma-s3c24xx.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/dmaengine_pcm.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
#include "dma.h"
void samsung_asoc_init_dma_data(struct snd_soc_dai *dai,
struct s3c_dma_params *playback,
struct s3c_dma_params *capture)
{
struct snd_dmaengine_dai_dma_data *playback_data = NULL;
struct snd_dmaengine_dai_dma_data *capture_data = NULL;
if (playback) {
playback_data = &playback->dma_data;
playback_data->filter_data = playback->slave;
playback_data->chan_name = playback->ch_name;
playback_data->addr = playback->dma_addr;
playback_data->addr_width = playback->dma_size;
}
if (capture) {
capture_data = &capture->dma_data;
capture_data->filter_data = capture->slave;
capture_data->chan_name = capture->ch_name;
capture_data->addr = capture->dma_addr;
capture_data->addr_width = capture->dma_size;
}
snd_soc_dai_init_dma_data(dai, playback_data, capture_data);
}
EXPORT_SYMBOL_GPL(samsung_asoc_init_dma_data);
int samsung_asoc_dma_platform_register(struct device *dev, dma_filter_fn filter,
const char *tx, const char *rx)
{
unsigned int flags = SND_DMAENGINE_PCM_FLAG_COMPAT;
struct snd_dmaengine_pcm_config *pcm_conf;
pcm_conf = devm_kzalloc(dev, sizeof(*pcm_conf), GFP_KERNEL);
......
......@@ -87,9 +87,9 @@ struct i2s_dai {
/* Driver for this DAI */
struct snd_soc_dai_driver i2s_dai_drv;
/* DMA parameters */
struct s3c_dma_params dma_playback;
struct s3c_dma_params dma_capture;
struct s3c_dma_params idma_playback;
struct snd_dmaengine_dai_dma_data dma_playback;
struct snd_dmaengine_dai_dma_data dma_capture;
struct snd_dmaengine_dai_dma_data idma_playback;
dma_filter_fn filter;
u32 quirks;
u32 suspend_i2smod;
......@@ -692,15 +692,15 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
break;
case 2:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
i2s->dma_playback.dma_size = 4;
i2s->dma_playback.addr_width = 4;
else
i2s->dma_capture.dma_size = 4;
i2s->dma_capture.addr_width = 4;
break;
case 1:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
i2s->dma_playback.dma_size = 2;
i2s->dma_playback.addr_width = 2;
else
i2s->dma_capture.dma_size = 2;
i2s->dma_capture.addr_width = 2;
break;
default:
......@@ -754,7 +754,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
writel(mod, i2s->addr + I2SMOD);
spin_unlock_irqrestore(i2s->lock, flags);
samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
i2s->frmclk = params_rate(params);
......@@ -991,10 +991,10 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
unsigned long flags;
if (is_secondary(i2s)) { /* If this is probe on the secondary DAI */
samsung_asoc_init_dma_data(dai, &other->sec_dai->dma_playback,
snd_soc_dai_init_dma_data(dai, &other->sec_dai->dma_playback,
NULL);
} else {
samsung_asoc_init_dma_data(dai, &i2s->dma_playback,
snd_soc_dai_init_dma_data(dai, &i2s->dma_playback,
&i2s->dma_capture);
if (i2s->quirks & QUIRK_NEED_RSTCLR)
......@@ -1002,7 +1002,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
if (i2s->quirks & QUIRK_SUPPORTS_IDMA)
idma_reg_addr_init(i2s->addr,
i2s->sec_dai->idma_playback.dma_addr);
i2s->sec_dai->idma_playback.addr);
}
/* Reset any constraint on RFS and BFS */
......@@ -1262,8 +1262,8 @@ static int samsung_i2s_probe(struct platform_device *pdev)
return -EINVAL;
}
pri_dai->dma_playback.slave = i2s_pdata->dma_playback;
pri_dai->dma_capture.slave = i2s_pdata->dma_capture;
pri_dai->dma_playback.filter_data = i2s_pdata->dma_playback;
pri_dai->dma_capture.filter_data = i2s_pdata->dma_capture;
pri_dai->filter = i2s_pdata->dma_filter;
if (&i2s_pdata->type)
......@@ -1302,12 +1302,12 @@ static int samsung_i2s_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to enable clock: %d\n", ret);
return ret;
}
pri_dai->dma_playback.dma_addr = regs_base + I2STXD;
pri_dai->dma_capture.dma_addr = regs_base + I2SRXD;
pri_dai->dma_playback.ch_name = "tx";
pri_dai->dma_capture.ch_name = "rx";
pri_dai->dma_playback.dma_size = 4;
pri_dai->dma_capture.dma_size = 4;
pri_dai->dma_playback.addr = regs_base + I2STXD;
pri_dai->dma_capture.addr = regs_base + I2SRXD;
pri_dai->dma_playback.chan_name = "tx";
pri_dai->dma_capture.chan_name = "rx";
pri_dai->dma_playback.addr_width = 4;
pri_dai->dma_capture.addr_width = 4;
pri_dai->quirks = quirks;
pri_dai->variant_regs = i2s_dai_data->i2s_variant_regs;
......@@ -1318,31 +1318,33 @@ static int samsung_i2s_probe(struct platform_device *pdev)
sec_dai = i2s_alloc_dai(pdev, true);
if (!sec_dai) {
dev_err(&pdev->dev, "Unable to alloc I2S_sec\n");
return -ENOMEM;
ret = -ENOMEM;
goto err_disable_clk;
}
sec_dai->lock = &pri_dai->spinlock;
sec_dai->variant_regs = pri_dai->variant_regs;
sec_dai->dma_playback.dma_addr = regs_base + I2STXDS;
sec_dai->dma_playback.ch_name = "tx-sec";
sec_dai->dma_playback.addr = regs_base + I2STXDS;
sec_dai->dma_playback.chan_name = "tx-sec";
if (!np) {
sec_dai->dma_playback.slave = i2s_pdata->dma_play_sec;
sec_dai->dma_playback.filter_data = i2s_pdata->dma_play_sec;
sec_dai->filter = i2s_pdata->dma_filter;
}
sec_dai->dma_playback.dma_size = 4;
sec_dai->dma_playback.addr_width = 4;
sec_dai->addr = pri_dai->addr;
sec_dai->clk = pri_dai->clk;
sec_dai->quirks = quirks;
sec_dai->idma_playback.dma_addr = idma_addr;
sec_dai->idma_playback.addr = idma_addr;
sec_dai->pri_dai = pri_dai;
pri_dai->sec_dai = sec_dai;
}
if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
dev_err(&pdev->dev, "Unable to configure gpio\n");
return -EINVAL;
ret = -EINVAL;
goto err_disable_clk;
}
ret = devm_snd_soc_register_component(&pri_dai->pdev->dev,
......@@ -1366,6 +1368,8 @@ static int samsung_i2s_probe(struct platform_device *pdev)
err_free_dai:
if (sec_dai)
i2s_free_sec_dai(sec_dai);
err_disable_clk:
clk_disable_unprepare(pri_dai->clk);
return ret;
}
......
......@@ -22,7 +22,6 @@
#include "i2s.h"
#include "idma.h"
#include "dma.h"
#include "i2s-regs.h"
#define ST_RUNNING (1<<0)
......
......@@ -127,25 +127,25 @@ struct s3c_pcm_info {
struct clk *pclk;
struct clk *cclk;
struct s3c_dma_params *dma_playback;
struct s3c_dma_params *dma_capture;
struct snd_dmaengine_dai_dma_data *dma_playback;
struct snd_dmaengine_dai_dma_data *dma_capture;
};
static struct s3c_dma_params s3c_pcm_stereo_out[] = {
static struct snd_dmaengine_dai_dma_data s3c_pcm_stereo_out[] = {
[0] = {
.dma_size = 4,
.addr_width = 4,
},
[1] = {
.dma_size = 4,
.addr_width = 4,
},
};
static struct s3c_dma_params s3c_pcm_stereo_in[] = {
static struct snd_dmaengine_dai_dma_data s3c_pcm_stereo_in[] = {
[0] = {
.dma_size = 4,
.addr_width = 4,
},
[1] = {
.dma_size = 4,
.addr_width = 4,
},
};
......@@ -552,15 +552,13 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
}
clk_prepare_enable(pcm->pclk);
s3c_pcm_stereo_in[pdev->id].dma_addr = mem_res->start
+ S3C_PCM_RXFIFO;
s3c_pcm_stereo_out[pdev->id].dma_addr = mem_res->start
+ S3C_PCM_TXFIFO;
s3c_pcm_stereo_in[pdev->id].addr = mem_res->start + S3C_PCM_RXFIFO;
s3c_pcm_stereo_out[pdev->id].addr = mem_res->start + S3C_PCM_TXFIFO;
filter = NULL;
if (pcm_pdata) {
s3c_pcm_stereo_in[pdev->id].slave = pcm_pdata->dma_capture;
s3c_pcm_stereo_out[pdev->id].slave = pcm_pdata->dma_playback;
s3c_pcm_stereo_in[pdev->id].filter_data = pcm_pdata->dma_capture;
s3c_pcm_stereo_out[pdev->id].filter_data = pcm_pdata->dma_playback;
filter = pcm_pdata->dma_filter;
}
......
......@@ -24,7 +24,6 @@
#include "regs-i2s-v2.h"
#include "s3c-i2s-v2.h"
#include "dma.h"
#undef S3C_IIS_V2_SUPPORTED
......@@ -302,7 +301,7 @@ static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct s3c_i2sv2_info *i2s = to_info(dai);
struct s3c_dma_params *dma_data;
struct snd_dmaengine_dai_dma_data *dma_data;
u32 iismod;
pr_debug("Entered %s\n", __func__);
......
......@@ -60,8 +60,8 @@ struct s3c_i2sv2_info {
unsigned char master;
struct s3c_dma_params *dma_playback;
struct s3c_dma_params *dma_capture;
struct snd_dmaengine_dai_dma_data *dma_playback;
struct snd_dmaengine_dai_dma_data *dma_capture;
u32 suspend_iismod;
u32 suspend_iiscon;
......
......@@ -34,14 +34,14 @@
#include <linux/platform_data/asoc-s3c.h>
static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = {
.ch_name = "tx",
.dma_size = 4,
static struct snd_dmaengine_dai_dma_data s3c2412_i2s_pcm_stereo_out = {
.chan_name = "tx",
.addr_width = 4,
};
static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = {
.ch_name = "rx",
.dma_size = 4,
static struct snd_dmaengine_dai_dma_data s3c2412_i2s_pcm_stereo_in = {
.chan_name = "rx",
.addr_width = 4,
};
static struct s3c_i2sv2_info s3c2412_i2s;
......@@ -52,7 +52,7 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
pr_debug("Entered %s\n", __func__);
samsung_asoc_init_dma_data(dai, &s3c2412_i2s_pcm_stereo_out,
snd_soc_dai_init_dma_data(dai, &s3c2412_i2s_pcm_stereo_out,
&s3c2412_i2s_pcm_stereo_in);
ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS);
......@@ -163,10 +163,10 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev)
if (IS_ERR(s3c2412_i2s.regs))
return PTR_ERR(s3c2412_i2s.regs);
s3c2412_i2s_pcm_stereo_out.dma_addr = res->start + S3C2412_IISTXD;
s3c2412_i2s_pcm_stereo_out.slave = pdata->dma_playback;
s3c2412_i2s_pcm_stereo_in.dma_addr = res->start + S3C2412_IISRXD;
s3c2412_i2s_pcm_stereo_in.slave = pdata->dma_capture;
s3c2412_i2s_pcm_stereo_out.addr = res->start + S3C2412_IISTXD;
s3c2412_i2s_pcm_stereo_out.filter_data = pdata->dma_playback;
s3c2412_i2s_pcm_stereo_in.addr = res->start + S3C2412_IISRXD;
s3c2412_i2s_pcm_stereo_in.filter_data = pdata->dma_capture;
ret = s3c_i2sv2_register_component(&pdev->dev, -1,
&s3c2412_i2s_component,
......
......@@ -32,14 +32,14 @@
#include <linux/platform_data/asoc-s3c.h>
static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = {
.ch_name = "tx",
.dma_size = 2,
static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_out = {
.chan_name = "tx",
.addr_width = 2,
};
static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = {
.ch_name = "rx",
.dma_size = 2,
static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_in = {
.chan_name = "rx",
.addr_width = 2,
};
struct s3c24xx_i2s_info {
......@@ -360,7 +360,7 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai)
{
pr_debug("Entered %s\n", __func__);
samsung_asoc_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out,
snd_soc_dai_init_dma_data(dai, &s3c24xx_i2s_pcm_stereo_out,
&s3c24xx_i2s_pcm_stereo_in);
s3c24xx_i2s.iis_clk = devm_clk_get(dai->dev, "iis");
......@@ -469,10 +469,10 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
if (IS_ERR(s3c24xx_i2s.regs))
return PTR_ERR(s3c24xx_i2s.regs);
s3c24xx_i2s_pcm_stereo_out.dma_addr = res->start + S3C2410_IISFIFO;
s3c24xx_i2s_pcm_stereo_out.slave = pdata->dma_playback;
s3c24xx_i2s_pcm_stereo_in.dma_addr = res->start + S3C2410_IISFIFO;
s3c24xx_i2s_pcm_stereo_in.slave = pdata->dma_capture;
s3c24xx_i2s_pcm_stereo_out.addr = res->start + S3C2410_IISFIFO;
s3c24xx_i2s_pcm_stereo_out.filter_data = pdata->dma_playback;
s3c24xx_i2s_pcm_stereo_in.addr = res->start + S3C2410_IISFIFO;
s3c24xx_i2s_pcm_stereo_in.filter_data = pdata->dma_capture;
ret = devm_snd_soc_register_component(&pdev->dev,
&s3c24xx_i2s_component, &s3c24xx_i2s_dai, 1);
......
......@@ -54,8 +54,6 @@ static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
};
#endif
static struct platform_device *s3c24xx_uda134x_snd_device;
static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
......@@ -66,16 +64,16 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream)
int ret = 0;
mutex_lock(&clk_lock);
pr_debug("%s %d\n", __func__, clk_users);
if (clk_users == 0) {
xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal");
xtal = clk_get(rtd->dev, "xtal");
if (IS_ERR(xtal)) {
printk(KERN_ERR "%s cannot get xtal\n", __func__);
dev_err(rtd->dev, "%s cannot get xtal\n", __func__);
ret = PTR_ERR(xtal);
} else {
pclk = clk_get(cpu_dai->dev, "iis");
if (IS_ERR(pclk)) {
printk(KERN_ERR "%s cannot get pclk\n",
dev_err(rtd->dev, "%s cannot get pclk\n",
__func__);
clk_put(xtal);
ret = PTR_ERR(pclk);
......@@ -102,7 +100,7 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream)
SNDRV_PCM_HW_PARAM_RATE,
&hw_constraints_rates);
if (ret < 0)
printk(KERN_ERR "%s cannot set constraints\n",
dev_err(rtd->dev, "%s cannot set constraints\n",
__func__);
#endif
}
......@@ -112,7 +110,6 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream)
static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream)
{
mutex_lock(&clk_lock);
pr_debug("%s %d\n", __func__, clk_users);
clk_users -= 1;
if (clk_users == 0) {
clk_put(xtal);
......@@ -159,18 +156,19 @@ static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream,
clk_source = S3C24XX_CLKSRC_PCLK;
div = bi % 33;
}
pr_debug("%s desired rate %lu, %d\n", __func__, rate, bi);
dev_dbg(rtd->dev, "%s desired rate %lu, %d\n", __func__, rate, bi);
clk = (fs_mode == S3C2410_IISMOD_384FS ? 384 : 256) * rate;
pr_debug("%s will use: %s %s %d sysclk %d err %ld\n", __func__,
dev_dbg(rtd->dev, "%s will use: %s %s %d sysclk %d err %ld\n", __func__,
fs_mode == S3C2410_IISMOD_384FS ? "384FS" : "256FS",
clk_source == S3C24XX_CLKSRC_MPLL ? "MPLLin" : "PCLK",
div, clk, err);
if ((err * 100 / rate) > 5) {
printk(KERN_ERR "S3C24XX_UDA134X: effective frequency "
"too different from desired (%ld%%)\n",
err * 100 / rate);
dev_err(rtd->dev, "effective frequency too different "
"from desired (%ld%%)\n", err * 100 / rate);
return -EINVAL;
}
......@@ -227,115 +225,27 @@ static struct snd_soc_card snd_soc_s3c24xx_uda134x = {
.num_links = 1,
};
static struct s3c24xx_uda134x_platform_data *s3c24xx_uda134x_l3_pins;
static void setdat(int v)
{
gpio_set_value(s3c24xx_uda134x_l3_pins->l3_data, v > 0);
}
static void setclk(int v)
{
gpio_set_value(s3c24xx_uda134x_l3_pins->l3_clk, v > 0);
}
static void setmode(int v)
{
gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0);
}
/* FIXME - This must be codec platform data but in which board file ?? */
static struct uda134x_platform_data s3c24xx_uda134x = {
.l3 = {
.setdat = setdat,
.setclk = setclk,
.setmode = setmode,
.data_hold = 1,
.data_setup = 1,
.clock_high = 1,
.mode_hold = 1,
.mode = 1,
.mode_setup = 1,
},
};
static int s3c24xx_uda134x_setup_pin(int pin, char *fun)
{
if (gpio_request(pin, "s3c24xx_uda134x") < 0) {
printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
"l3 %s pin already in use", fun);
return -EBUSY;
}
gpio_direction_output(pin, 0);
return 0;
}
static int s3c24xx_uda134x_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &snd_soc_s3c24xx_uda134x;
int ret;
printk(KERN_INFO "S3C24XX_UDA134X SoC Audio driver\n");
platform_set_drvdata(pdev, card);
card->dev = &pdev->dev;
s3c24xx_uda134x_l3_pins = pdev->dev.platform_data;
if (s3c24xx_uda134x_l3_pins == NULL) {
printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
"unable to find platform data\n");
return -ENODEV;
}
s3c24xx_uda134x.power = s3c24xx_uda134x_l3_pins->power;
s3c24xx_uda134x.model = s3c24xx_uda134x_l3_pins->model;
if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_data,
"data") < 0)
return -EBUSY;
if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_clk,
"clk") < 0) {
gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
return -EBUSY;
}
if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_mode,
"mode") < 0) {
gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
return -EBUSY;
}
s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1);
if (!s3c24xx_uda134x_snd_device) {
printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
"Unable to register\n");
return -ENOMEM;
}
platform_set_drvdata(s3c24xx_uda134x_snd_device,
&snd_soc_s3c24xx_uda134x);
platform_device_add_data(s3c24xx_uda134x_snd_device, &s3c24xx_uda134x, sizeof(s3c24xx_uda134x));
ret = platform_device_add(s3c24xx_uda134x_snd_device);
if (ret) {
printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n");
platform_device_put(s3c24xx_uda134x_snd_device);
}
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret)
dev_err(&pdev->dev, "failed to register card: %d\n", ret);
return ret;
}
static int s3c24xx_uda134x_remove(struct platform_device *pdev)
{
platform_device_unregister(s3c24xx_uda134x_snd_device);
gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
gpio_free(s3c24xx_uda134x_l3_pins->l3_mode);
return 0;
}
static struct platform_driver s3c24xx_uda134x_driver = {
.probe = s3c24xx_uda134x_probe,
.remove = s3c24xx_uda134x_remove,
.driver = {
.name = "s3c24xx_uda134x",
},
};
module_platform_driver(s3c24xx_uda134x_driver);
MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
......
......@@ -16,7 +16,6 @@
#include <asm/mach-types.h>
#include "../codecs/wm8580.h"
#include "dma.h"
#include "pcm.h"
/*
......
......@@ -15,7 +15,6 @@
#include <sound/pcm_params.h>
#include "../codecs/wm8994.h"
#include "dma.h"
#include "pcm.h"
/*
......
......@@ -90,10 +90,10 @@ struct samsung_spdif_info {
u32 saved_clkcon;
u32 saved_con;
u32 saved_cstas;
struct s3c_dma_params *dma_playback;
struct snd_dmaengine_dai_dma_data *dma_playback;
};
static struct s3c_dma_params spdif_stereo_out;
static struct snd_dmaengine_dai_dma_data spdif_stereo_out;
static struct samsung_spdif_info spdif_info;
static inline struct samsung_spdif_info *to_info(struct snd_soc_dai *cpu_dai)
......@@ -179,7 +179,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai);
void __iomem *regs = spdif->regs;
struct s3c_dma_params *dma_data;
struct snd_dmaengine_dai_dma_data *dma_data;
u32 con, clkcon, cstas;
unsigned long flags;
int i, ratio;
......@@ -425,11 +425,11 @@ static int spdif_probe(struct platform_device *pdev)
goto err4;
}
spdif_stereo_out.dma_size = 2;
spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF;
spdif_stereo_out.addr_width = 2;
spdif_stereo_out.addr = mem_res->start + DATA_OUTBUF;
filter = NULL;
if (spdif_pdata) {
spdif_stereo_out.slave = spdif_pdata->dma_playback;
spdif_stereo_out.filter_data = spdif_pdata->dma_playback;
filter = spdif_pdata->dma_filter;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment