]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoc: tas2781: Enable RCA-based playback without DSP firmware download
authorShenghao Ding <shenghao-ding@ti.com>
Fri, 14 Jun 2024 13:36:45 +0000 (21:36 +0800)
committerMark Brown <broonie@kernel.org>
Tue, 18 Jun 2024 15:45:53 +0000 (16:45 +0100)
In only loading RCA (Reconfigurable Architecture) binary case, no DSP
program will be working inside tas2563/tas2781, that is dsp-bypass mode,
do not support speaker protection, or audio acoustic algorithms in this
mode.

Fixes: ef3bcde75d06 ("ASoC: tas2781: Add tas2781 driver")
Signed-off-by: Shenghao Ding <shenghao-ding@ti.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://msgid.link/r/20240614133646.910-1-shenghao-ding@ti.com
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/tas2781-dsp.h
sound/soc/codecs/tas2781-fmwlib.c
sound/soc/codecs/tas2781-i2c.c

index 7fba7ea26a4b07a953f618489316a5c1a5f20f60..3cda9da14f6d1dc88992b8622a723b276c031915 100644 (file)
@@ -117,10 +117,17 @@ struct tasdevice_fw {
        struct device *dev;
 };
 
-enum tasdevice_dsp_fw_state {
-       TASDEVICE_DSP_FW_NONE = 0,
+enum tasdevice_fw_state {
+       /* Driver in startup mode, not load any firmware. */
        TASDEVICE_DSP_FW_PENDING,
+       /* DSP firmware in the system, but parsing error. */
        TASDEVICE_DSP_FW_FAIL,
+       /*
+        * Only RCA (Reconfigurable Architecture) firmware load
+        * successfully.
+        */
+       TASDEVICE_RCA_FW_OK,
+       /* Both RCA and DSP firmware load successfully. */
        TASDEVICE_DSP_FW_ALL_OK,
 };
 
index 265a8ca25cbbe640d6432fe88f5999fc22ac53fb..838d29fead961e10ff9283723e8e8be898dd1aa3 100644 (file)
@@ -2324,14 +2324,21 @@ void tasdevice_tuning_switch(void *context, int state)
        struct tasdevice_fw *tas_fmw = tas_priv->fmw;
        int profile_cfg_id = tas_priv->rcabin.profile_cfg_id;
 
-       if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) {
-               dev_err(tas_priv->dev, "DSP bin file not loaded\n");
+       /*
+        * Only RCA-based Playback can still work with no dsp program running
+        * inside the chip.
+        */
+       switch (tas_priv->fw_state) {
+       case TASDEVICE_RCA_FW_OK:
+       case TASDEVICE_DSP_FW_ALL_OK:
+               break;
+       default:
                return;
        }
 
        if (state == 0) {
-               if (tas_priv->cur_prog < tas_fmw->nr_programs) {
-                       /*dsp mode or tuning mode*/
+               if (tas_fmw && tas_priv->cur_prog < tas_fmw->nr_programs) {
+                       /* dsp mode or tuning mode */
                        profile_cfg_id = tas_priv->rcabin.profile_cfg_id;
                        tasdevice_select_tuningprm_cfg(tas_priv,
                                tas_priv->cur_prog, tas_priv->cur_conf,
@@ -2340,9 +2347,10 @@ void tasdevice_tuning_switch(void *context, int state)
 
                tasdevice_select_cfg_blk(tas_priv, profile_cfg_id,
                        TASDEVICE_BIN_BLK_PRE_POWER_UP);
-       } else
+       } else {
                tasdevice_select_cfg_blk(tas_priv, profile_cfg_id,
                        TASDEVICE_BIN_BLK_PRE_SHUTDOWN);
+       }
 }
 EXPORT_SYMBOL_NS_GPL(tasdevice_tuning_switch,
        SND_SOC_TAS2781_FMWLIB);
index 9350972dfefe7e92df320602cd7f96762a946247..c64d458e524e2c6db93e720827eac7548a01afc4 100644 (file)
@@ -380,23 +380,37 @@ static void tasdevice_fw_ready(const struct firmware *fmw,
        mutex_lock(&tas_priv->codec_lock);
 
        ret = tasdevice_rca_parser(tas_priv, fmw);
-       if (ret)
+       if (ret) {
+               tasdevice_config_info_remove(tas_priv);
                goto out;
+       }
        tasdevice_create_control(tas_priv);
 
        tasdevice_dsp_remove(tas_priv);
        tasdevice_calbin_remove(tas_priv);
-       tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING;
+       /*
+        * The baseline is the RCA-only case, and then the code attempts to
+        * load DSP firmware but in case of failures just keep going, i.e.
+        * failing to load DSP firmware is NOT an error.
+        */
+       tas_priv->fw_state = TASDEVICE_RCA_FW_OK;
        scnprintf(tas_priv->coef_binaryname, 64, "%s_coef.bin",
                tas_priv->dev_name);
        ret = tasdevice_dsp_parser(tas_priv);
        if (ret) {
                dev_err(tas_priv->dev, "dspfw load %s error\n",
                        tas_priv->coef_binaryname);
-               tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
                goto out;
        }
-       tasdevice_dsp_create_ctrls(tas_priv);
+
+       /*
+        * If no dsp-related kcontrol created, the dsp resource will be freed.
+        */
+       ret = tasdevice_dsp_create_ctrls(tas_priv);
+       if (ret) {
+               dev_err(tas_priv->dev, "dsp controls error\n");
+               goto out;
+       }
 
        tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
 
@@ -417,9 +431,8 @@ static void tasdevice_fw_ready(const struct firmware *fmw,
        tasdevice_prmg_load(tas_priv, 0);
        tas_priv->cur_prog = 0;
 out:
-       if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) {
-               /*If DSP FW fail, kcontrol won't be created */
-               tasdevice_config_info_remove(tas_priv);
+       if (tas_priv->fw_state == TASDEVICE_RCA_FW_OK) {
+               /* If DSP FW fail, DSP kcontrol won't be created. */
                tasdevice_dsp_remove(tas_priv);
        }
        mutex_unlock(&tas_priv->codec_lock);
@@ -466,14 +479,14 @@ static int tasdevice_startup(struct snd_pcm_substream *substream,
 {
        struct snd_soc_component *codec = dai->component;
        struct tasdevice_priv *tas_priv = snd_soc_component_get_drvdata(codec);
-       int ret = 0;
 
-       if (tas_priv->fw_state != TASDEVICE_DSP_FW_ALL_OK) {
-               dev_err(tas_priv->dev, "DSP bin file not loaded\n");
-               ret = -EINVAL;
+       switch (tas_priv->fw_state) {
+       case TASDEVICE_RCA_FW_OK:
+       case TASDEVICE_DSP_FW_ALL_OK:
+               return 0;
+       default:
+               return -EINVAL;
        }
-
-       return ret;
 }
 
 static int tasdevice_hw_params(struct snd_pcm_substream *substream,