summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/rt712-sdca.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/rt712-sdca.c')
-rw-r--r--sound/soc/codecs/rt712-sdca.c103
1 files changed, 88 insertions, 15 deletions
diff --git a/sound/soc/codecs/rt712-sdca.c b/sound/soc/codecs/rt712-sdca.c
index 13574513b181..38052cb19790 100644
--- a/sound/soc/codecs/rt712-sdca.c
+++ b/sound/soc/codecs/rt712-sdca.c
@@ -23,6 +23,7 @@
#include <linux/soundwire/sdw_registers.h>
#include <linux/slab.h>
#include <sound/soc-dapm.h>
+#include <sound/sdw.h>
#include <sound/tlv.h>
#include "rt712-sdca.h"
@@ -72,14 +73,57 @@ static int rt712_sdca_index_update_bits(struct rt712_sdca_priv *rt712,
return rt712_sdca_index_write(rt712, nid, reg, tmp);
}
+static void rt712_sdca_clk_patch(struct rt712_sdca_priv *rt712)
+{
+ rt712_sdca_index_write(rt712, RT712_VENDOR_REG, 0x65, 0x0000);
+ regmap_write(rt712->regmap, RT712_SDW_ROOT_CLK, 0x03);
+ usleep_range(1000, 1100);
+ regmap_write(rt712->regmap, RT712_SDW_ROOT_CLK, 0x02);
+ usleep_range(1000, 1100);
+ regmap_update_bits(rt712->regmap, RT712_PLL2_CONF2, 0x0080, 0x0000);
+ regmap_update_bits(rt712->regmap, RT712_PLL2_CONF2, 0x001f, 0x0017);
+ regmap_update_bits(rt712->regmap, RT712_PLL2_CONF3, 0x0010, 0x0000);
+ regmap_update_bits(rt712->regmap, RT712_PLL2_CONF1, 0x0081, 0x0001);
+ regmap_write(rt712->regmap, RT712_SDW_ROOT_CLK, 0x03);
+ usleep_range(1000, 1100);
+ regmap_update_bits(rt712->regmap, RT712_PLL2_CONF1, 0x0081, 0x0081);
+ regmap_update_bits(rt712->regmap, RT712_PLL2_CONF2, 0x0080, 0x0080);
+ regmap_update_bits(rt712->regmap, RT712_PLL2_CONF2, 0x001f, 0x0000);
+ regmap_update_bits(rt712->regmap, RT712_PLL2_CONF3, 0x0010, 0x0010);
+ usleep_range(1000, 1100);
+ rt712_sdca_index_write(rt712, RT712_VENDOR_REG, 0x65, 0x0081);
+}
+
+static void rt712_sdca_clk_patch2(struct rt712_sdca_priv *rt712)
+{
+ rt712_sdca_index_update_bits(rt712, RT712_VENDOR_REG, 0x49, 0x0800,
+ 0x0000);
+ rt712_sdca_index_update_bits(rt712, RT712_VENDOR_REG, 0x49, 0xf000,
+ 0x0000);
+ rt712_sdca_index_write(rt712, RT712_VENDOR_REG, 0x65, 0x0000);
+ rt712_sdca_index_update_bits(rt712, RT712_VENDOR_ANALOG_CTL, 0x0c, 0xc000,
+ 0xc000);
+ rt712_sdca_index_update_bits(rt712, RT712_VENDOR_ANALOG_CTL, 0x00, 0xc000,
+ 0xc000);
+ rt712_sdca_index_write(rt712, RT712_VENDOR_REG, 0x65, 0x0081);
+ regmap_write(rt712->regmap, RT712_SDW_ROOT_CLK, 0x02);
+ usleep_range(1000, 1100);
+ regmap_write(rt712->regmap, RT712_SDW_ROOT_CLK, 0x03);
+ usleep_range(1000, 1100);
+ rt712_sdca_index_write(rt712, RT712_VENDOR_REG, 0x65, 0x0000);
+}
+
static int rt712_sdca_calibration(struct rt712_sdca_priv *rt712)
{
unsigned int val, loop_rc = 0, loop_dc = 0;
struct device *dev;
struct regmap *regmap = rt712->regmap;
+ unsigned int clk_base;
int chk_cnt = 100;
int ret = 0;
+ regmap_read(rt712->regmap, RT712_SDW_ROOT_CLK, &clk_base);
+
mutex_lock(&rt712->calibrate_mutex);
dev = regmap_get_device(regmap);
@@ -108,8 +152,35 @@ static int rt712_sdca_calibration(struct rt712_sdca_priv *rt712)
if (ret < 0)
goto _cali_fail_;
}
- if (loop_dc == chk_cnt)
- dev_err(dev, "%s, calibration time-out!\n", __func__);
+
+ if (loop_dc == chk_cnt) {
+ if (clk_base == RT712_CLK_FREQ_24_576MHZ) {
+ rt712_sdca_clk_patch(rt712);
+ rt712_sdca_clk_patch2(rt712);
+ }
+ rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_FSM_CTL, 0x4100);
+ rt712_sdca_index_write(rt712, RT712_VENDOR_CALI,
+ RT712_DAC_DC_CALI_CTL1, 0x7883);
+ rt712_sdca_index_write(rt712, RT712_VENDOR_CALI,
+ RT712_DAC_DC_CALI_CTL1, 0xf893);
+ rt712_sdca_index_read(rt712, RT712_VENDOR_CALI,
+ RT712_DAC_DC_CALI_CTL1, &val);
+
+ for (loop_dc = 0; loop_dc < chk_cnt &&
+ (val & RT712_DAC_DC_CALI_TRIGGER); loop_dc++) {
+ usleep_range(10000, 11000);
+ ret = rt712_sdca_index_read(rt712, RT712_VENDOR_CALI,
+ RT712_DAC_DC_CALI_CTL1, &val);
+
+ if (ret < 0)
+ goto _cali_fail_;
+ }
+
+ if (loop_dc == chk_cnt)
+ dev_err(dev, "%s, calibration time-out!\n", __func__);
+ else
+ dev_dbg(dev, "%s, calibration success!\n", __func__);
+ }
if (loop_dc == chk_cnt || loop_rc == chk_cnt)
ret = -ETIMEDOUT;
@@ -1449,11 +1520,10 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_component *component = dai->component;
struct rt712_sdca_priv *rt712 = snd_soc_component_get_drvdata(component);
- struct sdw_stream_config stream_config;
+ struct sdw_stream_config stream_config = {0};
struct sdw_port_config port_config;
- enum sdw_data_direction direction;
struct sdw_stream_runtime *sdw_stream;
- int retval, port, num_channels;
+ int retval, port;
unsigned int sampling_rate;
dev_dbg(dai->dev, "%s %s id %d", __func__, dai->name, dai->id);
@@ -1471,7 +1541,6 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
/* SoundWire specific configuration */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- direction = SDW_DATA_DIR_RX;
if (dai->id == RT712_AIF1)
port = 1;
else if (dai->id == RT712_AIF2)
@@ -1479,7 +1548,6 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
else
return -EINVAL;
} else {
- direction = SDW_DATA_DIR_TX;
if (dai->id == RT712_AIF1)
port = 4;
else if (dai->id == RT712_AIF3)
@@ -1488,13 +1556,8 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- stream_config.frame_rate = params_rate(params);
- stream_config.ch_count = params_channels(params);
- stream_config.bps = snd_pcm_format_width(params_format(params));
- stream_config.direction = direction;
-
- num_channels = params_channels(params);
- port_config.ch_mask = GENMASK(num_channels - 1, 0);
+ /* SoundWire specific configuration */
+ snd_sdw_params_to_config(substream, params, &stream_config, &port_config);
port_config.num = port;
retval = sdw_stream_add_slave(rt712->slave, &stream_config,
@@ -1766,9 +1829,13 @@ static void rt712_sdca_va_io_init(struct rt712_sdca_priv *rt712)
static void rt712_sdca_vb_io_init(struct rt712_sdca_priv *rt712)
{
- int ret = 0;
unsigned int jack_func_status, mic_func_status, amp_func_status;
struct device *dev = &rt712->slave->dev;
+ unsigned int clk_base;
+ int ret = 0;
+
+ regmap_read(rt712->regmap, RT712_SDW_ROOT_CLK, &clk_base);
+ dev_dbg(dev, "%s clk_base=%x", __func__, clk_base);
regmap_read(rt712->regmap,
SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT712_SDCA_ENT0, RT712_SDCA_CTL_FUNC_STATUS, 0), &jack_func_status);
@@ -1780,6 +1847,12 @@ static void rt712_sdca_vb_io_init(struct rt712_sdca_priv *rt712)
__func__, jack_func_status, mic_func_status, amp_func_status);
rt712_sdca_index_write(rt712, RT712_VENDOR_REG, RT712_JD_CTL3, 0x7778);
+
+ if (clk_base == RT712_CLK_FREQ_24_576MHZ) {
+ rt712_sdca_clk_patch(rt712);
+ rt712_sdca_clk_patch2(rt712);
+ }
+
/* DMIC */
if ((mic_func_status & FUNCTION_NEEDS_INITIALIZATION) || (!rt712->first_hw_init)) {
rt712_sdca_index_write(rt712, RT712_VENDOR_HDA_CTL, RT712_DMIC2_FU_IT_FLOAT_CTL, 0x1526);