ASoC: rt1321: add support for rt1321 VA1/VA2

This patch adds support for the RT1321 VA1 and VA2 amplifier.

Signed-off-by: Shuming Fan <shumingf@realtek.com>
Link: https://patch.msgid.link/20260622091149.2183334-1-shumingf@realtek.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Shuming Fan 2026-06-22 17:11:48 +08:00 committed by Mark Brown
parent 84eb7c8e59
commit d79828f380
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
2 changed files with 653 additions and 58 deletions

View File

@ -411,6 +411,402 @@ static const struct reg_sequence rt1321_blind_write[] = {
{ 0x41001988, 0x03 },
};
static const struct reg_sequence rt1321_va1_blind_write[] = {
{ 0x0000c003, 0xf0 },
{ 0x0000c01b, 0xfc },
{ 0x0000c5c3, 0xf2 },
{ 0x0000c5c2, 0x00 },
{ 0x0000c5c1, 0x10 },
{ 0x0000c5c0, 0x04 },
{ 0x0000c5c7, 0x03 },
{ 0x0000c5c6, 0x10 },
{ 0x0000c526, 0x47 },
{ 0x0000c5c4, 0x12 },
{ 0x0000c5c5, 0x60 },
{ 0x0000c520, 0x10 },
{ 0x0000c521, 0x32 },
{ 0x0000c5c7, 0x00 },
{ 0x0000c5c8, 0x03 },
{ 0x0000c5d3, 0x08 },
{ 0x0000c5d2, 0x0a },
{ 0x0000c5d1, 0x49 },
{ 0x0000c5d0, 0x0f },
{ 0x0000c580, 0x10 },
{ 0x0000c581, 0x32 },
{ 0x0000c582, 0x01 },
{ 0x0000c682, 0x60 },
{ 0x0000c019, 0x10 },
{ 0x0000c5f0, 0x01 },
{ 0x0000c5f7, 0x22 },
{ 0x0000c5f6, 0x22 },
{ 0x0000c057, 0x51 },
{ 0x0000c054, 0x55 },
{ 0x0000c053, 0x55 },
{ 0x0000c052, 0x55 },
{ 0x0000c051, 0x01 },
{ 0x0000c050, 0x15 },
{ 0x0000c060, 0x99 },
{ 0x0000c030, 0x55 },
{ 0x0000c061, 0x55 },
{ 0x0000c063, 0x55 },
{ 0x0000c065, 0xa5 },
{ 0x0000c06b, 0x0a },
{ 0x0000ca05, 0xd6 },
{ 0x0000ca06, 0x11 },
{ 0x0000ca07, 0x1e },
{ 0x0000ca25, 0xd6 },
{ 0x0000ca26, 0x11 },
{ 0x0000ca27, 0x1e },
{ 0x0000cd00, 0x05 },
{ 0x0000cd81, 0x49 },
{ 0x0000cd82, 0x49 },
{ 0x0000c604, 0x40 },
{ 0x0000c609, 0x40 },
{ 0x0000c046, 0xf7 },
{ 0x0000c045, 0xff },
{ 0x0000c044, 0xff },
{ 0x0000c043, 0xff },
{ 0x0000c042, 0xff },
{ 0x0000c041, 0xff },
{ 0x0000c040, 0xff },
{ 0x0000c049, 0xff },
{ 0x0000c028, 0x3f },
{ 0x0000c020, 0x3f },
{ 0x0000c032, 0x13 },
{ 0x0000c033, 0x01 },
{ 0x0000cc10, 0x01 },
{ 0x0000dc20, 0x03 },
{ 0x0000de03, 0x05 },
{ 0x0000dc00, 0x00 },
{ 0x0000c700, 0xf0 },
{ 0x0000c701, 0x13 },
{ 0x0000c900, 0xc3 },
{ 0x0000c570, 0x08 },
{ 0x0000c086, 0x02 },
{ 0x0000c085, 0x7f },
{ 0x0000c084, 0x00 },
{ 0x0000c081, 0xff },
{ 0x0000f084, 0x0f },
{ 0x0000f083, 0xff },
{ 0x0000f082, 0xff },
{ 0x0000f081, 0xff },
{ 0x0000f080, 0xff },
{ 0x20003003, 0x3f },
{ 0x20005818, 0x81 },
{ 0x20009018, 0x81 },
{ 0x2000301c, 0x81 },
{ 0x0000c003, 0xc0 },
{ 0x0000c047, 0x80 },
{ 0x0000d541, 0x80 },
{ 0x0000d487, 0x0b },
{ 0x0000d487, 0x3b },
{ 0x0000d486, 0xc3 },
{ 0x0000d470, 0x89 },
{ 0x0000d471, 0x3a },
{ 0x0000d472, 0x3d },
{ 0x0000d474, 0x11 },
{ 0x0000d475, 0x32 },
{ 0x0000d476, 0x64 },
{ 0x0000d477, 0x10 },
{ 0x0000d478, 0xff },
{ 0x0000d479, 0x20 },
{ 0x0000d47a, 0x10 },
{ 0x0000d73c, 0xb7 },
{ 0x0000d73d, 0xd7 },
{ 0x0000d73e, 0x00 },
{ 0x0000d73f, 0x10 },
{ 0x1000cd56, 0x00 },
{ 0x3fc2dfc0, 0x03 },
{ 0x3fc2dfc1, 0x00 },
{ 0x3fc2dfc2, 0x00 },
{ 0x3fc2dfc3, 0x00 },
{ 0x3fc2dfc4, 0x01 },
{ 0x3fc2dfc5, 0x00 },
{ 0x3fc2dfc6, 0x00 },
{ 0x3fc2dfc7, 0x00 },
{ 0x3fc2df80, 0x00 },
{ 0x3fc2df81, 0x00 },
{ 0x3fc2df82, 0x00 },
{ 0x3fc2df83, 0x00 },
{ 0x0000d541, 0x40 },
{ 0x0000d486, 0x43 },
{ 0x1000db00, 0x04 },
{ 0x1000db01, 0x00 },
{ 0x1000db02, 0x10 },
{ 0x1000db03, 0x00 },
{ 0x1000db04, 0x00 },
{ 0x1000db05, 0x45 },
{ 0x1000db06, 0x0d },
{ 0x1000db07, 0x01 },
{ 0x1000db08, 0x00 },
{ 0x1000db09, 0x00 },
{ 0x1000db0a, 0xbf },
{ 0x1000db0b, 0x0b },
{ 0x1000db0c, 0x11 },
{ 0x1000db0d, 0x00 },
{ 0x1000db0e, 0x00 },
{ 0x1000db0f, 0x00 },
{ 0x1000db10, 0x2c },
{ 0x1000db11, 0xfa },
{ 0x1000db12, 0x00 },
{ 0x1000db13, 0x00 },
{ 0x1000db14, 0x09 },
{ 0x0000d540, 0x21 },
{ 0x0000c570, 0x08 },
{ 0x0000d714, 0x17 },
{ 0x0000c5c3, 0xf2 },
{ 0x0000c5c8, 0x03 },
{ 0x20009012, 0x00 },
{ 0x0000dd08, 0x17 },
{ 0x0000dd09, 0x0e },
{ 0x0000dd0a, 0x17 },
{ 0x0000dd0b, 0x0e },
{ 0x0000c570, 0x08 },
{ 0x0000d471, 0x3a },
{ 0x0000db00, 0x00 },
{ 0x0000db01, 0x00 },
{ 0x0000db02, 0x73 },
{ 0x0000db03, 0x00 },
{ 0x0000db04, 0x00 },
{ 0x0000db05, 0x00 },
{ 0x0000db06, 0x00 },
{ 0x0000db07, 0x00 },
{ 0x0000db08, 0x7f },
{ 0x0000db09, 0x00 },
{ 0x0000db1a, 0x00 },
{ 0x0000db1b, 0x00 },
{ 0x0000db19, 0x00 },
};
static const struct reg_sequence rt1321_va2_blind_write[] = {
{ 0x0000c003, 0xf0 },
{ 0x0000c01b, 0xfc },
{ 0x0000c5c3, 0xf2 },
{ 0x0000c5c2, 0x00 },
{ 0x0000c5c1, 0x10 },
{ 0x0000c5c0, 0x04 },
{ 0x0000c5c7, 0x03 },
{ 0x0000c5c6, 0x10 },
{ 0x0000c526, 0x47 },
{ 0x0000c5c4, 0x12 },
{ 0x0000c5c5, 0x60 },
{ 0x0000c520, 0x10 },
{ 0x0000c521, 0x32 },
{ 0x0000c5c7, 0x00 },
{ 0x0000c5c8, 0x03 },
{ 0x0000c5d3, 0x08 },
{ 0x0000c5d2, 0x0a },
{ 0x0000c5d1, 0x49 },
{ 0x0000c5d0, 0x0f },
{ 0x0000c580, 0x10 },
{ 0x0000c581, 0x32 },
{ 0x0000c582, 0x01 },
{ 0x0000c682, 0x60 },
{ 0x0000c019, 0x10 },
{ 0x0000c5f0, 0x01 },
{ 0x0000c5f7, 0x22 },
{ 0x0000c5f6, 0x22 },
{ 0x0000c057, 0x51 },
{ 0x0000c054, 0x55 },
{ 0x0000c053, 0x55 },
{ 0x0000c052, 0x55 },
{ 0x0000c051, 0x01 },
{ 0x0000c050, 0x15 },
{ 0x0000c060, 0x99 },
{ 0x0000c030, 0x55 },
{ 0x0000c061, 0x55 },
{ 0x0000c063, 0x55 },
{ 0x0000c065, 0xa5 },
{ 0x0000c06b, 0x0a },
{ 0x0000ca05, 0xd6 },
{ 0x0000ca06, 0x11 },
{ 0x0000ca07, 0x1e },
{ 0x0000ca25, 0xd6 },
{ 0x0000ca26, 0x11 },
{ 0x0000ca27, 0x1e },
{ 0x0000cd00, 0x05 },
{ 0x0000cd81, 0x49 },
{ 0x0000cd82, 0x49 },
{ 0x0000c604, 0x40 },
{ 0x0000c609, 0x40 },
{ 0x0000c046, 0xf7 },
{ 0x0000c045, 0xff },
{ 0x0000c044, 0xff },
{ 0x0000c043, 0xff },
{ 0x0000c042, 0xff },
{ 0x0000c041, 0xff },
{ 0x0000c040, 0xff },
{ 0x0000c049, 0xff },
{ 0x0000c028, 0x3f },
{ 0x0000c020, 0x3f },
{ 0x0000c032, 0x13 },
{ 0x0000c033, 0x01 },
{ 0x0000cc10, 0x01 },
{ 0x0000dc20, 0x03 },
{ 0x0000de03, 0x05 },
{ 0x0000dc00, 0x00 },
{ 0x0000c700, 0xf0 },
{ 0x0000c701, 0x13 },
{ 0x0000c900, 0xc3 },
{ 0x0000c570, 0x08 },
{ 0x0000c086, 0x02 },
{ 0x0000c085, 0x7f },
{ 0x0000c084, 0x00 },
{ 0x0000c081, 0xff },
{ 0x0000f084, 0x0f },
{ 0x0000f083, 0xff },
{ 0x0000f082, 0xff },
{ 0x0000f081, 0xff },
{ 0x0000f080, 0xff },
{ 0x20003003, 0x3f },
{ 0x20005818, 0x81 },
{ 0x20009018, 0x81 },
{ 0x2000301c, 0x81 },
{ 0x0000c003, 0xc0 },
{ 0x0000c047, 0x80 },
{ 0x0000d541, 0x80 },
{ 0x0000d487, 0x0b },
{ 0x0000d487, 0x3b },
{ 0x0000d486, 0xc3 },
{ 0x0000d470, 0x89 },
{ 0x0000d471, 0x3a },
{ 0x0000d472, 0x3d },
{ 0x0000d474, 0x11 },
{ 0x0000d475, 0x32 },
{ 0x0000d476, 0x64 },
{ 0x0000d477, 0x10 },
{ 0x0000d478, 0xff },
{ 0x0000d479, 0x20 },
{ 0x0000d47a, 0x10 },
{ 0x10008000, 0x67 },
{ 0x10008001, 0x80 },
{ 0x10008002, 0x00 },
{ 0x10008003, 0x00 },
{ 0x1000cd56, 0x00 },
{ 0x0000d486, 0x43 },
{ 0x3fc2dfc3, 0x00 },
{ 0x3fc2dfc2, 0x00 },
{ 0x3fc2dfc1, 0x00 },
{ 0x3fc2dfc0, 0x03 },
{ 0x3fc2dfc7, 0x00 },
{ 0x3fc2dfc6, 0x00 },
{ 0x3fc2dfc5, 0x00 },
{ 0x3fc2dfc4, 0x01 },
{ 0x3fc2dfa3, 0x00 },
{ 0x3fc2dfa2, 0x00 },
{ 0x3fc2dfa1, 0x00 },
{ 0x3fc2dfa0, 0x00 },
{ 0x3fc2df80, 0x10 },
{ 0x3fc2df81, 0x20 },
{ 0x3fc2df82, 0x00 },
{ 0x3fc2df83, 0x00 },
{ 0x3fc2df84, 0x50 },
{ 0x3fc2df85, 0x19 },
{ 0x3fc2df86, 0x00 },
{ 0x3fc2df87, 0x00 },
{ 0x3fc2df88, 0x52 },
{ 0x3fc2df89, 0x23 },
{ 0x3fc2df8a, 0x00 },
{ 0x3fc2df8b, 0x00 },
{ 0x3fc2df8c, 0xe0 },
{ 0x3fc2df8d, 0x2e },
{ 0x3fc2df8e, 0x00 },
{ 0x3fc2df8f, 0x00 },
{ 0x3fc2df90, 0xe0 },
{ 0x3fc2df91, 0x2e },
{ 0x3fc2df92, 0x00 },
{ 0x3fc2df93, 0x00 },
{ 0x3fc2df94, 0x01 },
{ 0x3fc2df95, 0x08 },
{ 0x3fc2df96, 0x00 },
{ 0x3fc2df97, 0x00 },
{ 0x3fc2df40, 0x80 },
{ 0x3fc2df41, 0xbb },
{ 0x3fc2df42, 0x00 },
{ 0x3fc2df43, 0x00 },
{ 0x3fc2df44, 0xc0 },
{ 0x3fc2df45, 0x99 },
{ 0x3fc2df46, 0x01 },
{ 0x3fc2df47, 0x00 },
{ 0x3fc2df48, 0x00 },
{ 0x3fc2df49, 0x00 },
{ 0x3fc2df4a, 0x00 },
{ 0x3fc2df4b, 0x00 },
{ 0x3fc2df4c, 0x00 },
{ 0x3fc2df4d, 0x00 },
{ 0x3fc2df4e, 0x00 },
{ 0x3fc2df4f, 0x00 },
{ 0x3fc2df50, 0x01 },
{ 0x3fc2df51, 0x00 },
{ 0x3fc2df52, 0x00 },
{ 0x3fc2df53, 0x00 },
{ 0x3fc2df54, 0x01 },
{ 0x3fc2df55, 0x00 },
{ 0x3fc2df56, 0x00 },
{ 0x3fc2df57, 0x00 },
{ 0x3fc2df58, 0x00 },
{ 0x3fc2df59, 0x00 },
{ 0x3fc2df5a, 0x00 },
{ 0x3fc2df5b, 0x00 },
{ 0x3fc2df5c, 0x01 },
{ 0x3fc2df5d, 0x00 },
{ 0x3fc2df5e, 0x00 },
{ 0x3fc2df5f, 0x00 },
{ 0x3fc2df60, 0x00 },
{ 0x3fc2df61, 0x00 },
{ 0x3fc2df62, 0x00 },
{ 0x3fc2df63, 0x00 },
{ 0x3fc2df64, 0x00 },
{ 0x3fc2df65, 0x00 },
{ 0x3fc2df66, 0x00 },
{ 0x3fc2df67, 0x10 },
{ 0x3fc2df68, 0x01 },
{ 0x3fc2df69, 0x00 },
{ 0x3fc2df6a, 0x00 },
{ 0x3fc2df6b, 0x00 },
{ 0x3fc2df6c, 0x01 },
{ 0x3fc2df6d, 0x00 },
{ 0x3fc2df6e, 0x00 },
{ 0x3fc2df6f, 0x00 },
{ 0x3fc2df70, 0x04 },
{ 0x3fc2df71, 0x00 },
{ 0x3fc2df72, 0x00 },
{ 0x3fc2df73, 0x00 },
{ 0x3fc2df74, 0x01 },
{ 0x3fc2df75, 0x00 },
{ 0x3fc2df76, 0x00 },
{ 0x3fc2df77, 0x00 },
{ 0x1000db00, 0x04 },
{ 0x1000db01, 0x00 },
{ 0x1000db02, 0x10 },
{ 0x1000db03, 0x00 },
{ 0x1000db04, 0x00 },
{ 0x1000db05, 0x45 },
{ 0x1000db06, 0x0d },
{ 0x1000db07, 0x01 },
{ 0x1000db08, 0x00 },
{ 0x1000db09, 0x00 },
{ 0x1000db0a, 0xbf },
{ 0x1000db0b, 0x0b },
{ 0x1000db0c, 0x11 },
{ 0x1000db0d, 0x00 },
{ 0x1000db0e, 0x00 },
{ 0x1000db0f, 0x00 },
{ 0x1000db10, 0x2c },
{ 0x1000db11, 0xfa },
{ 0x1000db12, 0x00 },
{ 0x1000db13, 0x00 },
{ 0x1000db14, 0x09 },
{ 0x0000d540, 0x21 },
{ 0x0000d714, 0x17 },
{ 0x0000dd0b, 0x0d },
{ 0x0000dd0a, 0xff },
{ 0x0000dd09, 0x0d },
{ 0x0000dd08, 0xff },
{ 0x0000c5fb, 0x12 },
{ 0x0000c570, 0x08 },
};
static const struct reg_default rt1320_reg_defaults[] = {
{ SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 },
{ SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_01), 0x01 },
@ -498,10 +894,15 @@ static bool rt1320_readable_register(struct device *dev, unsigned int reg)
case RT1321_PATCH_MAIN_VER ... RT1321_PATCH_BETA_VER:
case 0x1000f008:
case 0x1000f021:
case 0x2000300f:
case 0x20003000 ... 0x2000300f:
case 0x2000301c:
case 0x2000900f:
case 0x20003040 ... 0x20003059:
case 0x20005800 ... 0x2000580f:
case 0x20005818:
case 0x20005840 ... 0x20005859:
case 0x20009000 ... 0x2000900f:
case 0x20009018:
case 0x20009040 ... 0x20009059:
case 0x3fc000c0 ... 0x3fc2dfc8:
case 0x3fe00000 ... 0x3fe36fff:
/* 0x40801508/0x40801809/0x4080180a/0x40801909/0x4080190a */
@ -597,15 +998,20 @@ static bool rt1320_volatile_register(struct device *dev, unsigned int reg)
case 0x1000c000 ... 0x1000dfff:
case 0x1000f008:
case 0x1000f021:
case 0x2000300f:
case 0x2000300e ... 0x2000300f:
case 0x2000301c:
case 0x2000900f:
case 0x20003040 ... 0x20003059:
case 0x2000580e ... 0x2000580f:
case 0x20005818:
case 0x20005840 ... 0x20005859:
case 0x2000900e ... 0x2000900f:
case 0x20009018:
case 0x20009040 ... 0x20009059:
case 0x3fc2ab80 ... 0x3fc2ac4c:
case 0x3fc2b780:
case 0x3fc2bf80 ... 0x3fc2bf83:
case 0x3fc2bfc0 ... 0x3fc2bfc8:
case 0x3fc2d300 ... 0x3fc2d354:
case 0x3fc2d300 ... 0x3fc2d3cc:
case 0x3fc2dfc0 ... 0x3fc2dfc8:
case 0x3fe2e000 ... 0x3fe2e003:
case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0):
@ -1019,6 +1425,9 @@ static int rt1320_fw_param_protocol(struct rt1320_sdw_priv *rt1320, enum rt1320_
if (!tempbuf)
return -ENOMEM;
if (rt1320->dev_id == RT1321_DEV_ID && rt1320->version_id == RT1321_VA2)
paramid += 0x0bff0000;
paramhr.moudleid = 1;
paramhr.commandtype = cmdid;
/* 8 is "sizeof(paramid) + sizeof(paramlength)" */
@ -1157,6 +1566,52 @@ static void rt1320_calc_r0(struct rt1320_sdw_priv *rt1320)
l_calir0, l_calir0_lo, r_calir0, r_calir0_lo);
}
static int rt1320_pilot_tone_output(struct rt1320_sdw_priv *rt1320)
{
struct device *dev = &rt1320->sdw_slave->dev;
int l_targetpostgain, r_targetpostgain;
unsigned long long factor = (1 << 12);
int l_pilotgain[9], r_pilotgain[9];
const int postgain_step = 234;
int targetGain;
switch (rt1320->dev_id) {
case RT1320_DEV_ID:
targetGain = -320000;
break;
case RT1321_DEV_ID:
targetGain = -420000;
if (rt1320->version_id == RT1321_VA0)
targetGain = -320000;
break;
default:
dev_err(dev, "%s: Unknown device ID %d\n", __func__, rt1320->dev_id);
return -EINVAL;
}
rt1320_fw_param_protocol(rt1320, RT1320_GET_PARAM, 70, &l_pilotgain[0], sizeof(l_pilotgain));
rt1320_fw_param_protocol(rt1320, RT1320_GET_PARAM, 71, &r_pilotgain[0], sizeof(r_pilotgain));
dev_dbg(dev, "%s, LR pilotgain %d, %d\n", __func__, l_pilotgain[2], r_pilotgain[2]);
/* calculate pilot tone gain */
l_pilotgain[2] = (l_pilotgain[2] * 10000) / factor;
r_pilotgain[2] = (r_pilotgain[2] * 10000) / factor;
/* calculate post gain to meet target gain */
l_targetpostgain = abs(targetGain - l_pilotgain[2]) / postgain_step;
r_targetpostgain = abs(targetGain - r_pilotgain[2]) / postgain_step;
l_targetpostgain = 0xfff - l_targetpostgain;
r_targetpostgain = 0xfff - r_targetpostgain;
dev_dbg(dev, "%s, LR targetpostgain=0x%x, 0x%x\n", __func__, l_targetpostgain, r_targetpostgain);
regmap_write(rt1320->regmap, 0xdd0b, (l_targetpostgain & 0xf00) >> 8);
regmap_write(rt1320->regmap, 0xdd0a, l_targetpostgain & 0xff);
regmap_write(rt1320->regmap, 0xdd09, (r_targetpostgain & 0xf00) >> 8);
regmap_write(rt1320->regmap, 0xdd08, r_targetpostgain & 0xff);
return 0;
}
static void rt1320_calibrate(struct rt1320_sdw_priv *rt1320)
{
struct device *dev = &rt1320->sdw_slave->dev;
@ -1174,16 +1629,10 @@ static void rt1320_calibrate(struct rt1320_sdw_priv *rt1320)
if (!rt1320->component)
return;
/* set volume 0dB */
regmap_read(rt1320->regmap, 0xdd0b, &vol_reg[3]);
regmap_read(rt1320->regmap, 0xdd0a, &vol_reg[2]);
regmap_read(rt1320->regmap, 0xdd09, &vol_reg[1]);
regmap_read(rt1320->regmap, 0xdd08, &vol_reg[0]);
regmap_write(rt1320->regmap, 0xdd0b, 0x0f);
regmap_write(rt1320->regmap, 0xdd0a, 0xff);
regmap_write(rt1320->regmap, 0xdd09, 0x0f);
regmap_write(rt1320->regmap, 0xdd08, 0xff);
regmap_read(rt1320->regmap, 0xc5fb, &reg_c5fb);
regmap_read(rt1320->regmap, 0xc570, &reg_c570);
regmap_read(rt1320->regmap, 0xcd00, &reg_cd00);
@ -1208,8 +1657,19 @@ static void rt1320_calibrate(struct rt1320_sdw_priv *rt1320)
goto _finish_;
}
if (rt1320->dev_id == RT1320_DEV_ID)
regmap_write(rt1320->regmap, 0xc5fb, 0x00);
/* fine tune pilot tone output */
ret = rt1320_pilot_tone_output(rt1320);
if (ret < 0) {
dev_dbg(dev, "%s, Failed to tune pilot tone output\n", __func__);
goto _finish_;
}
if (rt1320->dev_id == RT1321_DEV_ID) {
regmap_update_bits(rt1320->regmap, 0xc047, 0x80, 0x00);
regmap_write(rt1320->regmap, 0xc5c4, 0x12);
}
regmap_write(rt1320->regmap, 0xc5fb, 0x00);
regmap_write(rt1320->regmap, 0xc570, 0x0b);
regmap_write(rt1320->regmap, 0xcd00, 0xc5);
@ -1270,6 +1730,11 @@ static void rt1320_calibrate(struct rt1320_sdw_priv *rt1320)
SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0x03);
rt1320_pde_transition_delay(rt1320, FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, 0x03);
if (rt1320->dev_id == RT1321_DEV_ID) {
regmap_update_bits(rt1320->regmap, 0xc047, 0x80, 0x80);
regmap_write(rt1320->regmap, 0xc5c4, 0x10);
}
/* advance gain will be set when R0 load, not here */
regmap_write(rt1320->regmap, 0xdd0b, vol_reg[3]);
regmap_write(rt1320->regmap, 0xdd0a, vol_reg[2]);
@ -1336,6 +1801,9 @@ static void rt1320_load_mcu_patch(struct rt1320_sdw_priv *rt1320)
max_addr = 0x10007fff;
break;
case RT1321_DEV_ID:
if (rt1320->version_id == RT1321_VA2)
return;
filename = RT1321_VA_MCU_PATCH;
min_addr = 0x10008000;
max_addr = 0x10008fff;
@ -1494,22 +1962,48 @@ static int rt1320_rae_load(struct rt1320_sdw_priv *rt1320)
request_firmware(&rae_fw, rae_filename, dev);
if (rae_fw) {
/* RAE CRC clear */
regmap_write(rt1320->regmap, 0xe80b, 0x0f);
/* RAE stop & CRC disable */
regmap_update_bits(rt1320->regmap, 0xe803, 0xbc, 0x00);
while (--retry) {
regmap_read(rt1320->regmap, 0xe83f, &value);
if (value & 0x40)
break;
usleep_range(1000, 1100);
}
if (!retry && !(value & 0x40)) {
dev_err(dev, "%s: RAE is not ready to load\n", __func__);
release_firmware(rae_fw);
return -ETIMEDOUT;
switch (rt1320->dev_id) {
case RT1320_DEV_ID:
/* RAE CRC clear */
regmap_write(rt1320->regmap, 0xe80b, 0x0f);
/* RAE stop & CRC disable */
regmap_update_bits(rt1320->regmap, 0xe803, 0xbc, 0x00);
while (--retry) {
regmap_read(rt1320->regmap, 0xe83f, &value);
if (value & 0x40)
break;
usleep_range(1000, 1100);
}
if (!retry && !(value & 0x40)) {
dev_err(dev, "%s: RAE is not ready to load\n", __func__);
release_firmware(rae_fw);
return -ETIMEDOUT;
}
break;
case RT1321_DEV_ID:
/* RAE CRC clear */
regmap_write(rt1320->regmap, 0x2000300e, 0xc0);
regmap_write(rt1320->regmap, 0x2000300f, 0x0f);
/* RAE stop & Phase sync & CRC disable */
regmap_update_bits(rt1320->regmap, 0x20003003, 0xfe, 0x00);
regmap_update_bits(rt1320->regmap, 0xc047, 0x80, 0x00);
regmap_update_bits(rt1320->regmap, 0x2000301c, 0x01, 0x00);
/* check whether write state is ready */
while (--retry) {
regmap_read(rt1320->regmap, 0x20003043, &value);
if (value & 0x40)
break;
usleep_range(1000, 1100);
}
if (!retry && !(value & 0x40)) {
dev_err(dev, "%s: RAE is not ready to load\n", __func__);
release_firmware(rae_fw);
return -ETIMEDOUT;
}
break;
default:
dev_err(dev, "%s: Unknown device ID %d\n", __func__, rt1320->dev_id);
return -EINVAL;
}
dev_dbg(dev, "%s, rae_fw size=0x%zx\n", __func__, rae_fw->size);
@ -1570,18 +2064,34 @@ static int rt1320_rae_load(struct rt1320_sdw_priv *rt1320)
goto _exit_;
}
/* RAE CRC enable */
regmap_update_bits(rt1320->regmap, 0xe803, 0x0c, 0x0c);
/* RAE update */
regmap_update_bits(rt1320->regmap, 0xe80b, 0x80, 0x00);
regmap_update_bits(rt1320->regmap, 0xe80b, 0x80, 0x80);
/* RAE run */
regmap_update_bits(rt1320->regmap, 0xe803, 0x80, 0x80);
regmap_read(rt1320->regmap, 0xe80b, &value);
dev_dbg(dev, "%s: CAE run => 0xe80b reg = 0x%x\n", __func__, value);
switch (rt1320->dev_id) {
case RT1320_DEV_ID:
/* RAE CRC enable */
regmap_update_bits(rt1320->regmap, 0xe803, 0x0c, 0x0c);
/* RAE update */
regmap_update_bits(rt1320->regmap, 0xe80b, 0x80, 0x00);
regmap_update_bits(rt1320->regmap, 0xe80b, 0x80, 0x80);
/* RAE run */
regmap_update_bits(rt1320->regmap, 0xe803, 0x80, 0x80);
regmap_read(rt1320->regmap, 0xe80b, &value);
dev_dbg(dev, "%s: CAE run => 0xe80b reg = 0x%x\n", __func__, value);
break;
case RT1321_DEV_ID:
/* RAE CRC enable */
regmap_update_bits(rt1320->regmap, 0x20003003, 0x30, 0x30);
/* RAE update */
regmap_update_bits(rt1320->regmap, 0x2000301c, 0x80, 0x00);
regmap_update_bits(rt1320->regmap, 0x2000301c, 0x80, 0x80);
regmap_update_bits(rt1320->regmap, 0x20009018, 0x80, 0x00);
regmap_update_bits(rt1320->regmap, 0x20009018, 0x80, 0x80);
regmap_update_bits(rt1320->regmap, 0x20005818, 0x80, 0x00);
regmap_update_bits(rt1320->regmap, 0x20005818, 0x80, 0x80);
/* RAE run */
regmap_update_bits(rt1320->regmap, 0x2000301c, 0x01, 0x01);
/* Phase sync eanble */
regmap_update_bits(rt1320->regmap, 0xc047, 0x80, 0x80);
break;
}
rt1320->rae_update_done = true;
@ -1620,6 +2130,8 @@ struct rt1320_dspfwheader {
unsigned int hdr_size = 0;
const char *dmi_vendor, *dmi_product, *dmi_sku;
int len_vendor, len_product, len_sku;
unsigned char boot_mode = 0; /* 0: from RAM; 1: from ROM */
unsigned char has_0x3fc00000 = 0;
char filename[512];
dmi_vendor = dmi_get_system_info(DMI_SYS_VENDOR);
@ -1657,9 +2169,6 @@ struct rt1320_dspfwheader {
goto _exit_;
}
/* change to IRAM */
regmap_update_bits(rt1320->regmap, 0xf01e, 0x80, 0x00);
request_firmware(&fw, filename, dev);
if (fw) {
fwheader = (struct rt1320_dspfwheader *)fw->data;
@ -1705,9 +2214,11 @@ struct rt1320_dspfwheader {
dev_fw_match = true;
break;
case RT1321_DEV_ID:
if (ptr_img->addr == 0x3fc00000)
if (fw_data[9] == '1')
if (ptr_img->addr == 0x3fc00000) {
if (fw_data[7] == '1')
dev_fw_match = true;
has_0x3fc00000 = 1;
}
break;
default:
dev_err(dev, "%s: Unknown device ID %d\n", __func__, rt1320->dev_id);
@ -1717,6 +2228,22 @@ struct rt1320_dspfwheader {
fw_offset += ptr_img->size;
}
if (rt1320->dev_id == RT1321_DEV_ID && rt1320->version_id == RT1321_VA2) {
/*
* For 1321 VA2, if the FW doesn't include the section for address 0x3fc00000,
* it means the FW will boot from ROM and force dev_fw_match to true to download FW by BRA.
*/
if (!has_0x3fc00000) {
boot_mode = 1;
dev_fw_match = true;
}
dev_dbg(dev, "%s: Boot from %s for VA2\n", __func__, (boot_mode ? "ROM" : "RAM"));
}
/* change to IRAM */
if (!boot_mode)
regmap_update_bits(rt1320->regmap, 0xf01e, 0x80, 0x00);
if (dev_fw_match) {
dev_dbg(dev, "%s, starting BRA downloading FW..\n", __func__);
rt1320->bra_msg.dev_num = rt1320->sdw_slave->dev_num;
@ -1739,24 +2266,39 @@ struct rt1320_dspfwheader {
goto _exit_;
}
/* run RAM code */
regmap_read(rt1320->regmap, 0x3fc2bfc0, &val);
val |= 0x8;
regmap_write(rt1320->regmap, 0x3fc2bfc0, val);
/* clear frame counter */
switch (rt1320->dev_id) {
case RT1320_DEV_ID:
/* run RAM code */
regmap_read(rt1320->regmap, 0x3fc2bfc0, &val);
val |= 0x8;
regmap_write(rt1320->regmap, 0x3fc2bfc0, val);
/* clear frame counter */
regmap_write(rt1320->regmap, 0x3fc2bfcb, 0x00);
regmap_write(rt1320->regmap, 0x3fc2bfca, 0x00);
regmap_write(rt1320->regmap, 0x3fc2bfc9, 0x00);
regmap_write(rt1320->regmap, 0x3fc2bfc8, 0x00);
break;
case RT1321_DEV_ID:
if (!boot_mode) {
/* run RAM code */
regmap_read(rt1320->regmap, 0x3fc2dfc0, &val);
val |= 0x8;
regmap_write(rt1320->regmap, 0x3fc2dfc0, val);
}
/* clear frame counter */
regmap_write(rt1320->regmap, 0x3fc2dfcb, 0x00);
regmap_write(rt1320->regmap, 0x3fc2dfca, 0x00);
regmap_write(rt1320->regmap, 0x3fc2dfc9, 0x00);
regmap_write(rt1320->regmap, 0x3fc2dfc8, 0x00);
/* enable handshake */
regmap_write(rt1320->regmap, 0x3fc2dfc4, 0x00);
regmap_write(rt1320->regmap, 0xd470, 0xad);
/* minimum phase settings */
regmap_write(rt1320->regmap, 0xc5c4, 0x10);
regmap_write(rt1320->regmap, 0x20003003, 0x31);
regmap_update_bits(rt1320->regmap, 0x20003002, 0x40, 0x00);
regmap_write(rt1320->regmap, 0xc5b3, 0x01);
regmap_write(rt1320->regmap, 0xc052, 0x11);
break;
}
@ -1839,14 +2381,35 @@ static void rt1320_vc_preset(struct rt1320_sdw_priv *rt1320)
static void rt1321_preset(struct rt1320_sdw_priv *rt1320)
{
const struct reg_sequence *blindwrite;
unsigned int i, reg, val, delay;
unsigned int array_size;
for (i = 0; i < ARRAY_SIZE(rt1321_blind_write); i++) {
reg = rt1321_blind_write[i].reg;
val = rt1321_blind_write[i].def;
delay = rt1321_blind_write[i].delay_us;
switch (rt1320->version_id) {
case RT1321_VA0:
blindwrite = rt1321_blind_write;
array_size = ARRAY_SIZE(rt1321_blind_write);
break;
case RT1321_VA1:
blindwrite = rt1321_va1_blind_write;
array_size = ARRAY_SIZE(rt1321_va1_blind_write);
break;
case RT1321_VA2:
blindwrite = rt1321_va2_blind_write;
array_size = ARRAY_SIZE(rt1321_va2_blind_write);
break;
default:
dev_err(&rt1320->sdw_slave->dev, "%s: Unknown version ID %d\n",
__func__, rt1320->version_id);
return;
}
if (reg == 0x3fc2dfc3)
for (i = 0; i < array_size; i++) {
reg = blindwrite[i].reg;
val = blindwrite[i].def;
delay = blindwrite[i].delay_us;
if (reg == 0x1000cd56)
rt1320_load_mcu_patch(rt1320);
regmap_write(rt1320->regmap, reg, val);
@ -1888,6 +2451,24 @@ static int rt1320_io_init(struct device *dev, struct sdw_slave *slave)
regmap_read(rt1320->regmap, RT1320_DEV_ID_0, &val);
regmap_read(rt1320->regmap, RT1320_DEV_ID_1, &tmp);
rt1320->dev_id = (val << 8) | tmp;
/* This is a workaround that reads the value twice to obtain the correct result. */
rt1320_pr_read(rt1320, RT1320_HV_DEV_ID_0, &val);
rt1320_pr_read(rt1320, RT1320_HV_DEV_ID_1, &tmp);
rt1320_pr_read(rt1320, RT1320_HV_DEV_ID_0, &val);
rt1320_pr_read(rt1320, RT1320_HV_DEV_ID_1, &tmp);
val = (val << 8) | tmp;
if (rt1320->dev_id == RT1321_DEV_ID) {
if (rt1320->version_id == 0x01)
rt1320->version_id = RT1321_VA2;
else if (val == RT1321_DEV_HV_VA0_ID)
rt1320->version_id = RT1321_VA0;
else if (val == RT1321_DEV_HV_VA1_ID)
rt1320->version_id = RT1321_VA1;
else
dev_err(dev, "%s: Unknown version ID 0x%x for RT1321\n", __func__, rt1320->version_id);
}
}
regmap_read(rt1320->regmap,
@ -2440,7 +3021,7 @@ static int rt1320_dspfw_load_put(struct snd_kcontrol *kcontrol,
if (!rt1320->hw_init)
return 0;
ret = pm_runtime_resume(component->dev);
ret = pm_runtime_resume_and_get(component->dev);
if (ret < 0 && ret != -EACCES)
return ret;
@ -2451,6 +3032,8 @@ static int rt1320_dspfw_load_put(struct snd_kcontrol *kcontrol,
if (!ucontrol->value.integer.value[0])
rt1320->fw_load_done = false;
pm_runtime_mark_last_busy(component->dev);
pm_runtime_put_autosuspend(component->dev);
return 0;
}

View File

@ -17,12 +17,17 @@
#define RT1320_DEV_ID 0x6981
#define RT1321_DEV_ID 0x7045
#define RT1321_DEV_HV_VA0_ID 0x6997
#define RT1321_DEV_HV_VA1_ID 0x7071
/* imp-defined registers */
#define RT1320_DEV_VERSION_ID_1 0xc404
#define RT1320_DEV_ID_1 0xc405
#define RT1320_DEV_ID_0 0xc406
#define RT1320_HV_DEV_ID_0 0xf622
#define RT1320_HV_DEV_ID_1 0xf623
#define RT1320_POWER_STATE 0xc560
#define RT1321_PATCH_MAIN_VER 0x1000cffe
@ -94,6 +99,12 @@ enum rt1320_version_id {
RT1320_VC,
};
enum rt1321_version_id {
RT1321_VA0,
RT1321_VA1,
RT1321_VA2,
};
#define RT1320_VER_B_ID 0x07392238
#define RT1320_VAB_MCU_PATCH "realtek/rt1320/rt1320-patch-code-vab.bin"
#define RT1320_VC_MCU_PATCH "realtek/rt1320/rt1320-patch-code-vc.bin"
@ -121,6 +132,7 @@ struct rt1320_datafixpoint {
int invrs;
};
/* FW parameter id 1300 */
typedef struct FwPara_HwSwGain {
unsigned int SwAdvGain;
unsigned int SwBasGain;