summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShuming Fan <shumingf@realtek.com>2026-06-22 17:11:48 +0800
committerMark Brown <broonie@kernel.org>2026-06-29 19:36:05 +0100
commitd79828f380b337a118ef93d7f4daabb41dde24bc (patch)
treed5bd831286f685a7053991e3ddb64bdcf31ad1a8
parent84eb7c8e59ccbcd45b2678abac56b778c97ee270 (diff)
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>
-rw-r--r--sound/soc/codecs/rt1320-sdw.c699
-rw-r--r--sound/soc/codecs/rt1320-sdw.h12
2 files changed, 653 insertions, 58 deletions
diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c
index 8d6fe2e36fc7..49fe100aef6e 100644
--- a/sound/soc/codecs/rt1320-sdw.c
+++ b/sound/soc/codecs/rt1320-sdw.c
@@ -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 @@ _finish_:
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;
+
+ 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;
+ }
- 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;
+ for (i = 0; i < array_size; i++) {
+ reg = blindwrite[i].reg;
+ val = blindwrite[i].def;
+ delay = blindwrite[i].delay_us;
- if (reg == 0x3fc2dfc3)
+ 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;
}
diff --git a/sound/soc/codecs/rt1320-sdw.h b/sound/soc/codecs/rt1320-sdw.h
index a7b573883dd0..bc0f78e03529 100644
--- a/sound/soc/codecs/rt1320-sdw.h
+++ b/sound/soc/codecs/rt1320-sdw.h
@@ -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;