Unverified Commit 7e5dfedb authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: Merge rt9120 series from ChiYuan Huang:

Changes from ChiYuan Huang <cy_huang@richtek.com> to fix a couple of
bugs and add a new device ID/quirk for the rt9120s to the driver.
parents 2ce1b21c dbe638f7
Loading
Loading
Loading
Loading
+48 −10
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0

#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
@@ -23,9 +24,11 @@
#define RT9120_REG_ERRRPT	0x10
#define RT9120_REG_MSVOL	0x20
#define RT9120_REG_SWRESET	0x40
#define RT9120_REG_INTERCFG	0x63
#define RT9120_REG_INTERNAL0	0x65
#define RT9120_REG_INTERNAL1	0x69
#define RT9120_REG_UVPOPT	0x6C
#define RT9120_REG_DIGCFG	0xF8

#define RT9120_VID_MASK		GENMASK(15, 8)
#define RT9120_SWRST_MASK	BIT(7)
@@ -46,8 +49,10 @@
#define RT9120_CFG_WORDLEN_24	24
#define RT9120_CFG_WORDLEN_32	32
#define RT9120_DVDD_UVSEL_MASK	GENMASK(5, 4)
#define RT9120_AUTOSYNC_MASK	BIT(6)

#define RT9120_VENDOR_ID	0x4200
#define RT9120_VENDOR_ID	0x42
#define RT9120S_VENDOR_ID	0x43
#define RT9120_RESET_WAITMS	20
#define RT9120_CHIPON_WAITMS	20
#define RT9120_AMPON_WAITMS	50
@@ -61,9 +66,16 @@
				 SNDRV_PCM_FMTBIT_S24_LE |\
				 SNDRV_PCM_FMTBIT_S32_LE)

enum {
	CHIP_IDX_RT9120 = 0,
	CHIP_IDX_RT9120S,
	CHIP_IDX_MAX
};

struct rt9120_data {
	struct device *dev;
	struct regmap *regmap;
	int chip_idx;
};

/* 11bit [min,max,step] = [-103.9375dB, 24dB, 0.0625dB] */
@@ -149,8 +161,12 @@ static int rt9120_codec_probe(struct snd_soc_component *comp)
	snd_soc_component_init_regmap(comp, data->regmap);

	/* Internal setting */
	snd_soc_component_write(comp, RT9120_REG_INTERNAL1, 0x03);
	snd_soc_component_write(comp, RT9120_REG_INTERNAL0, 0x69);
	if (data->chip_idx == CHIP_IDX_RT9120S) {
		snd_soc_component_write(comp, RT9120_REG_INTERCFG, 0xde);
		snd_soc_component_write(comp, RT9120_REG_INTERNAL0, 0x66);
	} else
		snd_soc_component_write(comp, RT9120_REG_INTERNAL0, 0x04);

	return 0;
}

@@ -201,8 +217,8 @@ static int rt9120_hw_params(struct snd_pcm_substream *substream,
			    struct snd_soc_dai *dai)
{
	struct snd_soc_component *comp = dai->component;
	unsigned int param_width, param_slot_width;
	int width;
	unsigned int param_width, param_slot_width, auto_sync;
	int width, fs;

	switch (width = params_width(param)) {
	case 16:
@@ -240,6 +256,16 @@ static int rt9120_hw_params(struct snd_pcm_substream *substream,

	snd_soc_component_update_bits(comp, RT9120_REG_I2SWL,
				      RT9120_AUDWL_MASK, param_slot_width);

	fs = width * params_channels(param);
	/* If fs is divided by 48, disable auto sync */
	if (fs % 48 == 0)
		auto_sync = 0;
	else
		auto_sync = RT9120_AUTOSYNC_MASK;

	snd_soc_component_update_bits(comp, RT9120_REG_DIGCFG,
				      RT9120_AUTOSYNC_MASK, auto_sync);
	return 0;
}

@@ -279,9 +305,11 @@ static const struct regmap_range rt9120_rd_yes_ranges[] = {
	regmap_reg_range(0x20, 0x27),
	regmap_reg_range(0x30, 0x38),
	regmap_reg_range(0x3A, 0x40),
	regmap_reg_range(0x63, 0x63),
	regmap_reg_range(0x65, 0x65),
	regmap_reg_range(0x69, 0x69),
	regmap_reg_range(0x6C, 0x6C)
	regmap_reg_range(0x6C, 0x6C),
	regmap_reg_range(0xF8, 0xF8)
};

static const struct regmap_access_table rt9120_rd_table = {
@@ -297,9 +325,11 @@ static const struct regmap_range rt9120_wr_yes_ranges[] = {
	regmap_reg_range(0x30, 0x38),
	regmap_reg_range(0x3A, 0x3D),
	regmap_reg_range(0x40, 0x40),
	regmap_reg_range(0x63, 0x63),
	regmap_reg_range(0x65, 0x65),
	regmap_reg_range(0x69, 0x69),
	regmap_reg_range(0x6C, 0x6C)
	regmap_reg_range(0x6C, 0x6C),
	regmap_reg_range(0xF8, 0xF8)
};

static const struct regmap_access_table rt9120_wr_table = {
@@ -370,7 +400,7 @@ static int rt9120_reg_write(void *context, unsigned int reg, unsigned int val)
static const struct regmap_config rt9120_regmap_config = {
	.reg_bits = 8,
	.val_bits = 32,
	.max_register = RT9120_REG_UVPOPT,
	.max_register = RT9120_REG_DIGCFG,

	.reg_read = rt9120_reg_read,
	.reg_write = rt9120_reg_write,
@@ -388,8 +418,16 @@ static int rt9120_check_vendor_info(struct rt9120_data *data)
	if (ret)
		return ret;

	if ((devid & RT9120_VID_MASK) != RT9120_VENDOR_ID) {
		dev_err(data->dev, "DEVID not correct [0x%04x]\n", devid);
	devid = FIELD_GET(RT9120_VID_MASK, devid);
	switch (devid) {
	case RT9120_VENDOR_ID:
		data->chip_idx = CHIP_IDX_RT9120;
		break;
	case RT9120S_VENDOR_ID:
		data->chip_idx = CHIP_IDX_RT9120S;
		break;
	default:
		dev_err(data->dev, "DEVID not correct [0x%0x]\n", devid);
		return -ENODEV;
	}