summaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/tas6424.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/tas6424.c')
-rw-r--r--sound/soc/codecs/tas6424.c70
1 files changed, 58 insertions, 12 deletions
diff --git a/sound/soc/codecs/tas6424.c b/sound/soc/codecs/tas6424.c
index 14999b999fd3..36aebdb8f55c 100644
--- a/sound/soc/codecs/tas6424.c
+++ b/sound/soc/codecs/tas6424.c
@@ -41,6 +41,7 @@ struct tas6424_data {
struct regmap *regmap;
struct regulator_bulk_data supplies[TAS6424_NUM_SUPPLIES];
struct delayed_work fault_check_work;
+ unsigned int last_cfault;
unsigned int last_fault1;
unsigned int last_fault2;
unsigned int last_warn;
@@ -406,9 +407,54 @@ static void tas6424_fault_check_work(struct work_struct *work)
unsigned int reg;
int ret;
+ ret = regmap_read(tas6424->regmap, TAS6424_CHANNEL_FAULT, &reg);
+ if (ret < 0) {
+ dev_err(dev, "failed to read CHANNEL_FAULT register: %d\n", ret);
+ goto out;
+ }
+
+ if (!reg) {
+ tas6424->last_cfault = reg;
+ goto check_global_fault1_reg;
+ }
+
+ /*
+ * Only flag errors once for a given occurrence. This is needed as
+ * the TAS6424 will take time clearing the fault condition internally
+ * during which we don't want to bombard the system with the same
+ * error message over and over.
+ */
+ if ((reg & TAS6424_FAULT_OC_CH1) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH1))
+ dev_crit(dev, "experienced a channel 1 overcurrent fault\n");
+
+ if ((reg & TAS6424_FAULT_OC_CH2) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH2))
+ dev_crit(dev, "experienced a channel 2 overcurrent fault\n");
+
+ if ((reg & TAS6424_FAULT_OC_CH3) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH3))
+ dev_crit(dev, "experienced a channel 3 overcurrent fault\n");
+
+ if ((reg & TAS6424_FAULT_OC_CH4) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH4))
+ dev_crit(dev, "experienced a channel 4 overcurrent fault\n");
+
+ if ((reg & TAS6424_FAULT_DC_CH1) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH1))
+ dev_crit(dev, "experienced a channel 1 DC fault\n");
+
+ if ((reg & TAS6424_FAULT_DC_CH2) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH2))
+ dev_crit(dev, "experienced a channel 2 DC fault\n");
+
+ if ((reg & TAS6424_FAULT_DC_CH3) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH3))
+ dev_crit(dev, "experienced a channel 3 DC fault\n");
+
+ if ((reg & TAS6424_FAULT_DC_CH4) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH4))
+ dev_crit(dev, "experienced a channel 4 DC fault\n");
+
+ /* Store current fault1 value so we can detect any changes next time */
+ tas6424->last_cfault = reg;
+
+check_global_fault1_reg:
ret = regmap_read(tas6424->regmap, TAS6424_GLOB_FAULT1, &reg);
if (ret < 0) {
- dev_err(dev, "failed to read FAULT1 register: %d\n", ret);
+ dev_err(dev, "failed to read GLOB_FAULT1 register: %d\n", ret);
goto out;
}
@@ -424,15 +470,11 @@ static void tas6424_fault_check_work(struct work_struct *work)
TAS6424_FAULT_PVDD_UV |
TAS6424_FAULT_VBAT_UV;
- if (reg)
+ if (!reg) {
+ tas6424->last_fault1 = reg;
goto check_global_fault2_reg;
+ }
- /*
- * Only flag errors once for a given occurrence. This is needed as
- * the TAS6424 will take time clearing the fault condition internally
- * during which we don't want to bombard the system with the same
- * error message over and over.
- */
if ((reg & TAS6424_FAULT_PVDD_OV) && !(tas6424->last_fault1 & TAS6424_FAULT_PVDD_OV))
dev_crit(dev, "experienced a PVDD overvoltage fault\n");
@@ -451,7 +493,7 @@ static void tas6424_fault_check_work(struct work_struct *work)
check_global_fault2_reg:
ret = regmap_read(tas6424->regmap, TAS6424_GLOB_FAULT2, &reg);
if (ret < 0) {
- dev_err(dev, "failed to read FAULT2 register: %d\n", ret);
+ dev_err(dev, "failed to read GLOB_FAULT2 register: %d\n", ret);
goto out;
}
@@ -461,8 +503,10 @@ check_global_fault2_reg:
TAS6424_FAULT_OTSD_CH3 |
TAS6424_FAULT_OTSD_CH4;
- if (!reg)
+ if (!reg) {
+ tas6424->last_fault2 = reg;
goto check_warn_reg;
+ }
if ((reg & TAS6424_FAULT_OTSD) && !(tas6424->last_fault2 & TAS6424_FAULT_OTSD))
dev_crit(dev, "experienced a global overtemp shutdown\n");
@@ -497,8 +541,10 @@ check_warn_reg:
TAS6424_WARN_VDD_OTW_CH3 |
TAS6424_WARN_VDD_OTW_CH4;
- if (!reg)
+ if (!reg) {
+ tas6424->last_warn = reg;
goto out;
+ }
if ((reg & TAS6424_WARN_VDD_UV) && !(tas6424->last_warn & TAS6424_WARN_VDD_UV))
dev_warn(dev, "experienced a VDD under voltage condition\n");
@@ -524,7 +570,7 @@ check_warn_reg:
/* Store current warn value so we can detect any changes next time */
tas6424->last_warn = reg;
- /* Clear any faults by toggling the CLEAR_FAULT control bit */
+ /* Clear any warnings by toggling the CLEAR_FAULT control bit */
ret = regmap_write_bits(tas6424->regmap, TAS6424_MISC_CTRL3,
TAS6424_CLEAR_FAULT, TAS6424_CLEAR_FAULT);
if (ret < 0)