]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: cs35l56: Alter error codes for calibration routine
authorRichard Fitzgerald <rf@opensource.cirrus.com>
Mon, 10 Nov 2025 11:43:27 +0000 (11:43 +0000)
committerMark Brown <broonie@kernel.org>
Mon, 10 Nov 2025 12:26:32 +0000 (12:26 +0000)
Adjust the error codes returned by the calibration debugfs files
to provide a wider range of errors and make them more consistent.

There is a limited number of standard errors and it's not always
easy to find an error code that accurately describes what happened.
Additionally, user code often uses strerror() or something similar
to report a generic error description. The original calibration
code used a limited set of errors to attempt to avoid user error
strings that would be confusing or unclear on a file read/write.
However, this restricts the ability to provide informative errors.

This limited error range didn't help very much with debugging so
it has been expanded, rather than worrying about what strerror()
would return.

The errors are now more consistent:

ENXIO       Calibration is not supported by the driver.
EOPNOTSUPP  The given calibration command is not supported.
EBUSY       Cannot calibrate because the amp is playing audio.
ERANGE      Calibration result was out-of-range.
ETIMEDOUT   Calibration did not complete.
EMSGSIZE    Blob written to cal_data is the wrong size.
ENODATA     No calibration data available to read from cal_data,
            or
            Blob written to cal_data does not contain calibration,
            or
            No calibration data available to save to UEFI.
EIO         General failure to communicate with the firmware, mainly
            indicating that firmware controls are missing.
EINVAL      Has its normal meaning that an invalid argument was passed.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Link: https://patch.msgid.link/20251110114327.84370-1-rf@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/cs35l56.h
sound/soc/codecs/cs35l56-shared.c

index 82559be0f24943fb4880acad2e30014bf1a755c9..0a740a99ad31425b14e2ea11bb55ae2c1563afbd 100644 (file)
 #define CS35L56_PS3_POLL_US                            500
 #define CS35L56_PS3_TIMEOUT_US                         300000
 
+#define CS35L56_CAL_STATUS_SUCCESS                     1
+#define CS35L56_CAL_STATUS_OUT_OF_RANGE                        3
+
 #define CS35L56_CONTROL_PORT_READY_US                  2200
 #define CS35L56_HALO_STATE_POLL_US                     1000
 #define CS35L56_HALO_STATE_TIMEOUT_US                  250000
index bbacac6bda81578bcbe2f7d6a4839d31addbdecd..fe0693c3f7dee27726e2d3cf26022674e85e2437 100644 (file)
@@ -1022,8 +1022,10 @@ static int cs35l56_perform_calibration(struct cs35l56_base *cs35l56_base)
                return ret;
 
        ret = cs35l56_wait_for_ps3(cs35l56_base);
-       if (ret)
+       if (ret) {
+               ret = -EBUSY;
                goto err_pm_put;
+       }
 
        regmap_update_bits_check(cs35l56_base->regmap, CS35L56_MIXER_NGATE_CH1_CFG,
                                 CS35L56_AUX_NGATE_CHn_EN, 0, &ngate_ch1_was_enabled);
@@ -1038,7 +1040,7 @@ static int cs35l56_perform_calibration(struct cs35l56_base *cs35l56_base)
                if (!ctl) {
                        dev_err(cs35l56_base->dev, "Could not get %s control\n",
                                calibration_controls->status);
-                       ret = -ENXIO;
+                       ret = -EIO;
                        goto err;
                }
 
@@ -1050,12 +1052,15 @@ static int cs35l56_perform_calibration(struct cs35l56_base *cs35l56_base)
                                              0, &val, sizeof(val));
                if (ret < 0) {
                        dev_err(cs35l56_base->dev, "Could not write %s: %d\n", "CALI_NORM_EN", ret);
+                       ret = -EIO;
                        goto err;
                }
 
                ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_AUDIO_CALIBRATION);
-               if (ret)
+               if (ret) {
+                       ret = -EIO;
                        goto err;
+               }
 
                if (read_poll_timeout(cs_dsp_coeff_read_ctrl, ret,
                                      (val == cpu_to_be32(1)),
@@ -1065,16 +1070,24 @@ static int cs35l56_perform_calibration(struct cs35l56_base *cs35l56_base)
                                      ctl, 0, &val, sizeof(val))) {
                        dev_err(cs35l56_base->dev, "Calibration timed out (CAL_STATUS: %u)\n",
                                be32_to_cpu(val));
-                       ret = -ETIMEDOUT;
-                       goto err;
+                       switch (be32_to_cpu(val)) {
+                       case CS35L56_CAL_STATUS_OUT_OF_RANGE:
+                               ret = -ERANGE;
+                               goto err;
+                       default:
+                               ret = -ETIMEDOUT;
+                               goto err;
+                       }
                }
        }
 
        cs35l56_base->cal_data_valid = false;
        memset(&cal_data, 0, sizeof(cal_data));
        ret = cs_amp_read_cal_coeffs(dsp, calibration_controls, &cal_data);
-       if (ret)
+       if (ret) {
+               ret = -EIO;
                goto err;
+       }
 
        dev_info(cs35l56_base->dev, "Cal status:%d calR:%d ambient:%d\n",
                 cal_data.calStatus, cal_data.calR, cal_data.calAmbient);
@@ -1141,7 +1154,7 @@ ssize_t cs35l56_calibrate_debugfs_write(struct cs35l56_base *cs35l56_base,
                        return ret;
                break;
        default:
-               return -ENXIO;
+               return -EOPNOTSUPP;
        }
 
        return count;
@@ -1170,6 +1183,8 @@ ssize_t cs35l56_cal_ambient_debugfs_write(struct cs35l56_base *cs35l56_base,
                goto out;
 
        ret = cs_amp_write_ambient_temp(cs35l56_base->dsp, cs35l56_base->calibration_controls, val);
+       if (ret)
+               ret = -EIO;
 out:
        pm_runtime_put(cs35l56_base->dev);