Browse Source

asoc: codecs: Implement PBR feature for WSA884X

Change PBR enable to be acquired from device tree.
Using system_gain, bat_cfg, rload, set pbr thresholds based on tables.
Table values are x100 to avoid kernel float issues,
truncate when converting to reg val.
Set pbr registers during initialization.
Rename WSA_8OHMS -> WSA_8_OHMS to match system gain naming.

Change-Id: I28985496e1da37ceeb8c9db6e17f4c48d37d11c7
Signed-off-by: Matthew Rice <[email protected]>
Matthew Rice 3 years ago
parent
commit
d8711a3a66
2 changed files with 306 additions and 110 deletions
  1. 218 0
      asoc/codecs/wsa884x/internal.h
  2. 88 110
      asoc/codecs/wsa884x/wsa884x.c

+ 218 - 0
asoc/codecs/wsa884x/internal.h

@@ -102,6 +102,25 @@ enum {
 	SWR_CPS_PORT
 };
 
+enum {
+	EXT_ABOVE_3S,
+	CONFIG_1S,
+	CONFIG_2S,
+	CONFIG_3S,
+	EXT_1S,
+	EXT_2S,
+	EXT_3S,
+	CONFIG_MAX,
+};
+
+enum {
+	WSA_4_OHMS = 0,
+	WSA_6_OHMS,
+	WSA_8_OHMS,
+	WSA_32_OHMS,
+	WSA_MAX_OHMS,
+};
+
 struct wsa_ctrl_platform_data {
 	void *handle;
 	int (*update_wsa_event)(void *handle, u16 event, u32 data);
@@ -119,6 +138,205 @@ struct swr_port {
 
 extern struct regmap_config wsa884x_regmap_config;
 
+/* Aux gain from system gain */
+static const u8 pa_aux_no_comp[G_MAX_DB] = {
+	PA_AUX_18_DB,  /* G_21_DB   */
+	PA_AUX_18_DB,  /* G_19P5_DB */
+	PA_AUX_18_DB,  /* G_18_DB   */
+	PA_AUX_18_DB,  /* G_16P5_DB */
+	PA_AUX_18_DB,  /* G_15_DB   */
+	PA_AUX_12_DB,  /* G_13P5_DB */
+	PA_AUX_12_DB,  /* G_12_DB   */
+	PA_AUX_12_DB,  /* G_10P5_DB */
+	PA_AUX_7P5_DB, /* G_9_DB    */
+	PA_AUX_7P5_DB, /* G_7P5_DB  */
+	PA_AUX_7P5_DB, /* G_6_DB    */
+	PA_AUX_7P5_DB, /* G_4P5_DB  */
+	PA_AUX_0_DB,   /* G_3_DB    */
+	PA_AUX_0_DB,   /* G_1P5_DB  */
+	PA_AUX_0_DB,   /* G_0_DB    */
+	PA_AUX_M1P5_DB,/* G_M1P5_DB */
+	PA_AUX_M3_DB,  /* G_M3_DB   */
+	PA_AUX_M4P5_DB,/* G_M4P5_DB */
+	PA_AUX_M6_DB   /* G_M6_DB   */
+};
+
+/*
+ * Isense data indexed by system_gain and rload
+ * WSA_4_OHMS, WSA_6_OHMS, WSA_8_OHMS, WSA_32_OHMS
+ */
+static const u8 isense_gain_data[G_MAX_DB][WSA_MAX_OHMS] = {
+	{ISENSE_6_DB, ISENSE_6_DB, ISENSE_12_DB, ISENSE_18_DB},  /*G_21_DB   */
+	{ISENSE_6_DB, ISENSE_6_DB, ISENSE_12_DB, ISENSE_18_DB},  /*G_19P5_DB */
+	{ISENSE_6_DB, ISENSE_6_DB, ISENSE_15_DB, ISENSE_18_DB},  /*G_18_DB   */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_15_DB, ISENSE_18_DB}, /*G_16P5_DB */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_15_DB   */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_13P5_DB */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_12_DB   */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_10P5_DB */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_9_DB    */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_7P5_DB  */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_6_DB    */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_4P5_DB  */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_3_DB    */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_1P5_DB  */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_0_DB    */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_M1P5_DB */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_M3_DB   */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_M4P5_DB */
+	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_M6_DB   */
+};
+
+/* Vsense gain from system gain */
+static const u8 vsense_gain_data[G_MAX_DB] = {
+	VSENSE_M24_DB, /* G_21_DB   */
+	VSENSE_M24_DB, /* G_19P5_DB */
+	VSENSE_M21_DB, /* G_18_DB   */
+	VSENSE_M21_DB, /* G_16P5_DB */
+	VSENSE_M18_DB, /* G_15_DB   */
+	VSENSE_M18_DB, /* G_13P5_DB */
+	VSENSE_M15_DB, /* G_12_DB   */
+	VSENSE_M15_DB, /* G_10P5_DB */
+	VSENSE_M12_DB, /* G_9_DB    */
+	VSENSE_M12_DB, /* G_7P5_DB  */
+	VSENSE_M12_DB, /* G_6_DB    */
+	VSENSE_M12_DB, /* G_4P5_DB  */
+	VSENSE_M12_DB, /* G_3_DB    */
+	VSENSE_M12_DB, /* G_1P5_DB  */
+	VSENSE_M12_DB, /* G_0_DB    */
+	VSENSE_M12_DB, /* G_M1P5_DB */
+	VSENSE_M12_DB, /* G_M3_DB   */
+	VSENSE_M12_DB, /* G_M4P5_DB */
+	VSENSE_M12_DB  /* G_M6_DB   */
+};
+
+/*
+ * PBR Thresholds from system_gain, bat_cfg, and rload
+ * EXT_ABOVE_3S: WSA_4_OHMS, WSA_6_OHMS, WSA_8_OHMS, WSA_32_OHMS, CONFIG_1S: ...
+ * Values are X100 to avoid 'float' issues, divided in WSA884X_VTH_TO_REG macro
+ */
+static const int pbr_vth1_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	/* G_21_DB */
+	{
+		{0, 0, 0, 0}, {2000, 2000, 863, 0},
+		{2000, 2000, 1098, 0}, {2000, 2000, 1404, 0}
+	},
+	/* G_19P5_DB */
+	{
+		{0, 0, 0, 0}, {2000, 769, 2000, 0},
+		{2000, 957, 2000, 0}, {2000, 1216, 2000, 0}
+	},
+	/* G_18_DB */
+	{
+		{0, 0, 0, 0}, {643, 2000, 2000, 0},
+		{808, 2000, 2000, 0}, {1027, 2000, 2000, 0}
+	},
+	/* G_16P5_DB */
+	{
+		{0, 0, 0, 0}, {1575, 1575, 1575, 0},
+		{1575, 1575, 1575, 0}, {1575, 1575, 1575, 0}
+	},
+	/* G_15_DB */
+	{
+		{0, 0, 0, 0}, {1400, 1400, 1400, 0},
+		{1400, 1400, 1400, 0}, {1400, 1400, 1400, 0}
+	},
+	 /* G_13P5_DB */
+	{
+		{0, 0, 0, 0}, {1200, 1200, 1200, 0},
+		{1200, 1200, 1200, 0}, {1200, 1200, 1200, 0}
+	},
+	/* G_12_DB */
+	{
+		{0, 0, 0, 0}, {1050, 1050, 1050, 0},
+		{1050, 1050, 1050, 0}, {1050, 1050, 1050, 0}
+	},
+};
+static const int pbr_vth2_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 918, 0}, {0, 0, 1161, 0}, {0, 0, 1443, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 824, 0, 0}, {0, 988, 0, 0},  {0, 1231, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {667, 0, 0, 0}, {839, 0, 0, 0},  {1035, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth3_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 1043, 0}, {0, 0, 1278, 0}, {0, 0, 1522, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 933, 0, 0},  {0, 1082, 0, 0}, {0, 1294, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {753, 0, 0, 0},  {925, 0, 0, 0},  {1090, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth4_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 1098, 0}, {0, 0, 1341, 0}, {0, 0, 1561, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 988, 0, 0},  {0, 1137, 0, 0}, {0, 1333, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {80, 0, 0, 0},   {973, 0, 0, 0},  {1129, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth5_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 1098, 0}, {0, 0, 1341, 0}, {0, 0, 1561, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 988, 0, 0},  {0, 1137, 0, 0}, {0, 1333, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {80, 0, 0, 0},   {973, 0, 0, 0},  {1129, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth6_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 1137, 0}, {0, 0, 1380, 0}, {0, 0, 1584, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 1027, 0, 0}, {0, 1176, 0, 0}, {0, 1349, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {831, 0, 0, 0},  {996, 0, 0, 0},  {1137, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth7_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 1184, 0}, {0, 0, 1420, 0}, {0, 0, 1600, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 1059, 0, 0}, {0, 1208, 0, 0}, {0, 1365, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {918, 0, 0, 0},  {1051, 0, 0, 0}, {1153, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth8_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 1239, 0}, {0, 0, 1482, 0}, {0, 0, 1639, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 1114, 0, 0}, {0, 1263, 0, 0}, {0, 1380, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {988, 0, 0, 0},  {1114, 0, 0, 0}, {1192, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth9_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 1278, 0}, {0, 0, 1522, 0}, {0, 0, 1663, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 1192, 0, 0}, {0, 1302, 0, 0}, {0, 1420, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {1051, 0, 0, 0}, {1184, 0, 0, 0}, {1224, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth10_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 1380, 0}, {0, 0, 1600, 0}, {0, 0, 1686, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 1286, 0, 0}, {0, 1404, 0, 0}, {0, 1459, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {1145, 0, 0, 0}, {1255, 0, 0, 0}, {1278, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth11_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 1482, 0}, {0, 0, 1686, 0}, {0, 0, 1725, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 1357, 0, 0}, {0, 1498, 0, 0}, {0, 1498, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {1208, 0, 0, 0}, {1318, 0, 0, 0}, {1341, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth12_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 1584, 0}, {0, 0, 1765, 0}, {0, 0, 1780, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 1514, 0, 0}, {0, 1600, 0, 0}, {0, 1529, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {1427, 0, 0, 0}, {1467, 0, 0, 0}, {1404, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth13_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 1663, 0}, {0, 0, 1843, 0}, {0, 0, 1867, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 1671, 0, 0}, {0, 1702, 0, 0}, {0, 1569, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {1561, 0, 0, 0}, {1616, 0, 0, 0}, {1475, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth14_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 1780, 0}, {0, 0, 1922, 0}, {0, 0, 1945, 0} }, /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 1827, 0, 0}, {0, 1835, 0, 0}, {0, 1631, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {1741, 0, 0, 0}, {1788, 0, 0, 0}, {1537, 0, 0, 0} }, /* G_18_DB   */
+};
+
+static const int pbr_vth15_data[G_MAX_DB][CONFIG_MAX][WSA_MAX_OHMS] = {
+	{ {0, 0, 0, 0}, {0, 0, 2000, 0}, {0, 0, 2000, 0}, {0, 0, 2000, 0} },    /* G_21_DB   */
+	{ {0, 0, 0, 0}, {0, 2000, 0, 0}, {0, 2000, 0, 0}, {0, 1686, 0, 0} }, /* G_19P5_DB */
+	{ {0, 0, 0, 0}, {2000, 0, 0, 0}, {2000, 0, 0, 0}, {16, 0, 0, 0} },    /* G_18_DB   */
+};
+
+
 /*
  * Private data Structure for wsa884x. All parameters related to
  * WSA884X codec needs to be defined here.

+ 88 - 110
asoc/codecs/wsa884x/wsa884x.c

@@ -39,7 +39,8 @@
 #define HIGH_TEMP_THRESHOLD 45
 #define TEMP_INVALID	0xFFFF
 #define WSA884X_TEMP_RETRY 3
-
+#define PBR_MAX_VOLTAGE 20
+#define PBR_MAX_CODE 255
 #define MAX_NAME_LEN	40
 #define WSA884X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
 			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
@@ -74,95 +75,8 @@ enum {
 	COMP_OFFSET4,
 };
 
-enum {
-	EXT_ABOVE_3S,
-	CONFIG_1S,
-	CONFIG_2S,
-	CONFIG_3S,
-	EXT_1S,
-	EXT_2S,
-	EXT_3S,
-};
-
-enum {
-	WSA_4OHMS = 0,
-	WSA_6OHMS,
-	WSA_8OHMS,
-	WSA_32OHMS,
-	WSA_MAXOHMS,
-};
-
-/* Aux gain from system gain */
-static const u8 pa_aux_no_comp[G_MAX_DB] = {
-	PA_AUX_18_DB,  /* G_21_DB   */
-	PA_AUX_18_DB,  /* G_19P5_DB */
-	PA_AUX_18_DB,  /* G_18_DB   */
-	PA_AUX_18_DB,  /* G_16P5_DB */
-	PA_AUX_18_DB,  /* G_15_DB   */
-	PA_AUX_12_DB,  /* G_13P5_DB */
-	PA_AUX_12_DB,  /* G_12_DB   */
-	PA_AUX_12_DB,  /* G_10P5_DB */
-	PA_AUX_7P5_DB, /* G_9_DB    */
-	PA_AUX_7P5_DB, /* G_7P5_DB  */
-	PA_AUX_7P5_DB, /* G_6_DB    */
-	PA_AUX_7P5_DB, /* G_4P5_DB  */
-	PA_AUX_0_DB,   /* G_3_DB    */
-	PA_AUX_0_DB,   /* G_1P5_DB  */
-	PA_AUX_0_DB,   /* G_0_DB    */
-	PA_AUX_M1P5_DB,/* G_M1P5_DB */
-	PA_AUX_M3_DB,  /* G_M3_DB   */
-	PA_AUX_M4P5_DB,/* G_M4P5_DB */
-	PA_AUX_M6_DB   /* G_M6_DB   */
-};
-
-/*
- * Isense data indexed by system_gain and rload
- * WSA_4OHMS, WSA_6OHMS, WSA_8OHMS, WSA_32OHMS
- */
-static const u8 isense_gain_data[G_MAX_DB][WSA_MAXOHMS] = {
-	{ISENSE_6_DB, ISENSE_6_DB, ISENSE_12_DB, ISENSE_18_DB},  /*G_21_DB   */
-	{ISENSE_6_DB, ISENSE_6_DB, ISENSE_12_DB, ISENSE_18_DB},  /*G_19P5_DB */
-	{ISENSE_6_DB, ISENSE_6_DB, ISENSE_15_DB, ISENSE_18_DB},  /*G_18_DB   */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_15_DB, ISENSE_18_DB}, /*G_16P5_DB */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_15_DB   */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_13P5_DB */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_12_DB   */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_10P5_DB */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_9_DB    */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_7P5_DB  */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_6_DB    */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_4P5_DB  */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_3_DB    */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_1P5_DB  */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_0_DB    */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_M1P5_DB */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_M3_DB   */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_M4P5_DB */
-	{ISENSE_12_DB, ISENSE_12_DB, ISENSE_18_DB, ISENSE_18_DB}, /*G_M6_DB   */
-};
-
-/* Vsense gain from system gain */
-static const u8 vsense_gain_data[G_MAX_DB] = {
-	VSENSE_M24_DB, /* G_21_DB   */
-	VSENSE_M24_DB, /* G_19P5_DB */
-	VSENSE_M21_DB, /* G_18_DB   */
-	VSENSE_M21_DB, /* G_16P5_DB */
-	VSENSE_M18_DB, /* G_15_DB   */
-	VSENSE_M18_DB, /* G_13P5_DB */
-	VSENSE_M15_DB, /* G_12_DB   */
-	VSENSE_M15_DB, /* G_10P5_DB */
-	VSENSE_M12_DB, /* G_9_DB    */
-	VSENSE_M12_DB, /* G_7P5_DB  */
-	VSENSE_M12_DB, /* G_6_DB    */
-	VSENSE_M12_DB, /* G_4P5_DB  */
-	VSENSE_M12_DB, /* G_3_DB    */
-	VSENSE_M12_DB, /* G_1P5_DB  */
-	VSENSE_M12_DB, /* G_0_DB    */
-	VSENSE_M12_DB, /* G_M1P5_DB */
-	VSENSE_M12_DB, /* G_M3_DB   */
-	VSENSE_M12_DB, /* G_M4P5_DB */
-	VSENSE_M12_DB  /* G_M6_DB   */
-};
+#define WSA884X_VTH_TO_REG(vth) \
+	((vth) != 0 ? (((vth) - 150 / PBR_MAX_VOLTAGE) * PBR_MAX_CODE / 100) : 0)
 
 struct wsa_reg_mask_val {
 	u16 reg;
@@ -700,6 +614,77 @@ static int wsa884x_set_gain_parameters(struct snd_soc_component *component)
 	return 0;
 }
 
+static int wsa884x_set_pbr_parameters(struct snd_soc_component *component)
+{
+	struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component);
+	int vth1_reg_val;
+	int vth2_reg_val;
+	int vth3_reg_val;
+	int vth4_reg_val;
+	int vth5_reg_val;
+	int vth6_reg_val;
+	int vth7_reg_val;
+	int vth8_reg_val;
+	int vth9_reg_val;
+	int vth10_reg_val;
+	int vth11_reg_val;
+	int vth12_reg_val;
+	int vth13_reg_val;
+	int vth14_reg_val;
+	int vth15_reg_val;
+
+
+	int vth1_val = pbr_vth1_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth2_val = pbr_vth2_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth3_val = pbr_vth3_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth4_val = pbr_vth4_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth5_val = pbr_vth5_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth6_val = pbr_vth6_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth7_val = pbr_vth7_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth8_val = pbr_vth8_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth9_val = pbr_vth9_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth10_val = pbr_vth10_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth11_val = pbr_vth11_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth12_val = pbr_vth12_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth13_val = pbr_vth13_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth14_val = pbr_vth14_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+	int vth15_val = pbr_vth15_data[wsa884x->system_gain][wsa884x->bat_cfg][wsa884x->rload];
+
+	vth1_reg_val = WSA884X_VTH_TO_REG(vth1_val);
+	vth2_reg_val = WSA884X_VTH_TO_REG(vth2_val);
+	vth3_reg_val = WSA884X_VTH_TO_REG(vth3_val);
+	vth4_reg_val = WSA884X_VTH_TO_REG(vth4_val);
+	vth5_reg_val = WSA884X_VTH_TO_REG(vth5_val);
+	vth6_reg_val = WSA884X_VTH_TO_REG(vth6_val);
+	vth7_reg_val = WSA884X_VTH_TO_REG(vth7_val);
+	vth8_reg_val = WSA884X_VTH_TO_REG(vth8_val);
+	vth9_reg_val = WSA884X_VTH_TO_REG(vth9_val);
+	vth10_reg_val = WSA884X_VTH_TO_REG(vth10_val);
+	vth11_reg_val = WSA884X_VTH_TO_REG(vth11_val);
+	vth12_reg_val = WSA884X_VTH_TO_REG(vth12_val);
+	vth13_reg_val = WSA884X_VTH_TO_REG(vth13_val);
+	vth14_reg_val = WSA884X_VTH_TO_REG(vth14_val);
+	vth15_reg_val = WSA884X_VTH_TO_REG(vth15_val);
+
+	snd_soc_component_write(component, WSA884X_CLSH_VTH1, vth1_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH2, vth2_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH3, vth3_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH4, vth4_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH5, vth5_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH6, vth6_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH7, vth7_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH8, vth8_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH9, vth9_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH10, vth10_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH11, vth11_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH12, vth12_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH13, vth13_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH14, vth14_reg_val);
+	snd_soc_component_write(component, WSA884X_CLSH_VTH15, vth15_reg_val);
+
+	return 0;
+}
+
 static const char * const wsa_dev_mode_text[] = {
 	"speaker", "receiver"
 };
@@ -1138,20 +1123,6 @@ static int wsa884x_set_pbr(struct snd_kcontrol *kcontrol,
 	dev_dbg(component->dev, "%s: PBR enable current %d, new %d\n",
 		 __func__, wsa884x->pbr_enable, value);
 	wsa884x->pbr_enable = value;
-
-	if (value) {
-		snd_soc_component_update_bits(component,
-			WSA884X_CLSH_VTH1,
-			0xFF, 0xFF);
-		snd_soc_component_update_bits(component,
-			REG_FIELD_VALUE(CURRENT_LIMIT,
-			CURRENT_LIMIT_OVRD_EN, 0x00));
-	} else {
-		snd_soc_component_update_bits(component,
-			REG_FIELD_VALUE(CURRENT_LIMIT,
-			CURRENT_LIMIT_OVRD_EN, 0x01));
-	}
-
 	return 0;
 }
 
@@ -1174,7 +1145,7 @@ static int wsa884x_set_cps(struct snd_kcontrol *kcontrol,
 	struct wsa884x_priv *wsa884x = snd_soc_component_get_drvdata(component);
 	int value = ucontrol->value.integer.value[0];
 
-	dev_dbg(component->dev, "%s: VIsense enable current %d, new %d\n",
+	dev_dbg(component->dev, "%s: CPS enable current %d, new %d\n",
 		 __func__, wsa884x->cps_enable, value);
 	wsa884x->cps_enable = value;
 	return 0;
@@ -1402,6 +1373,14 @@ static int wsa884x_spkr_event(struct snd_soc_dapm_widget *w,
 				REG_FIELD_VALUE(PWM_CLK_CTL,
 				PWM_CLK_FREQ_SEL, 0x01));
 		}
+		if (wsa884x->pbr_enable)
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(CURRENT_LIMIT,
+				CURRENT_LIMIT_OVRD_EN, 0x00));
+		else
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(CURRENT_LIMIT,
+				CURRENT_LIMIT_OVRD_EN, 0x01));
 		/* Force remove group */
 		swr_remove_from_group(wsa884x->swr_slave,
 				      wsa884x->swr_slave->dev_num);
@@ -2118,13 +2097,12 @@ static int wsa884x_swr_probe(struct swr_device *pdev)
 		"%s: Bat_cfg: 0x%x rload: 0x%x, sys_gain: 0x%x %x\n", __func__,
 		wsa884x->bat_cfg, wsa884x->rload, wsa884x->bat_cfg);
 	wsa884x_set_gain_parameters(component);
+	wsa884x_set_pbr_parameters(component);
 	/* Must write WO registers in a single write */
 	wo0_val = (0xC | (wsa884x->pa_aux_gain << 0x02) | !wsa884x->dev_mode);
-	snd_soc_component_update_bits(component,
-		WSA884X_ANA_WO_CTL_0, 0xFF, wo0_val);
-	snd_soc_component_update_bits(component,
-		WSA884X_ANA_WO_CTL_1, 0xFF, 0);
-	if (wsa884x->rload == WSA_4OHMS || wsa884x->rload == WSA_6OHMS)
+	snd_soc_component_write(component, WSA884X_ANA_WO_CTL_0, wo0_val);
+	snd_soc_component_write(component, WSA884X_ANA_WO_CTL_1, 0x0);
+	if (wsa884x->rload == WSA_4_OHMS || wsa884x->rload == WSA_6_OHMS)
 		snd_soc_component_update_bits(component,
 			REG_FIELD_VALUE(OCP_CTL, OCP_CURR_LIMIT, 0x07));