@@ -97,6 +97,7 @@ struct tas2783_prv {
u8 rca_binaryname[64];
u8 dev_name[32];
bool hw_init;
+ unsigned int fw_version;
/* wq for firmware download */
wait_queue_head_t fw_wait;
bool fw_dl_task_done;
@@ -346,8 +347,10 @@ static int tas2783_sdca_mbq_size(struct device *dev, u32 reg)
case 0x300 ... 0x340: /* Data port 3. */
case 0x400 ... 0x440: /* Data port 4. */
case 0x500 ... 0x540: /* Data port 5. */
- case 0x800000 ... 0x803fff: /* Page 0 ~ 127. */
- case 0x807e80 ... 0x807eff: /* Page 253. */
+ case TASDEV_REG_SDW(0, 0, 0) ... TASDEV_REG_SDW(0x00, 0x01, 0x80):
+ case TASDEV_REG_SDW(0, 0xfd, 0) ... TASDEV_REG_SDW(0, 0xfd, 0x80):
+ case PRAM_ADDR_START ... PRAM_ADDR_END:
+ case YRAM_ADDR_START ... YRAM_ADDR_END:
case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_UDMPU23,
TAS2783_SDCA_CTL_UDMPU_CLUSTER, 0):
case SDW_SDCA_CTL(1, TAS2783_SDCA_ENT_FU21, TAS2783_SDCA_CTL_FU_MUTE,
@@ -570,7 +573,7 @@ static const struct regmap_config tas_regmap = {
.volatile_reg = tas2783_volatile_register,
.reg_defaults = tas2783_reg_default,
.num_reg_defaults = ARRAY_SIZE(tas2783_reg_default),
- .max_register = 0x41008000 + TASDEV_REG_SDW(0xa1, 0x60, 0x7f),
+ .max_register = 0x41000000 + PRAM_ADDR_END,
.cache_type = REGCACHE_MAPLE,
.use_single_read = true,
.use_single_write = true,
@@ -785,6 +788,7 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context)
const u8 *buf = NULL;
s32 img_sz, ret = 0, cur_file = 0;
s32 offset = 0;
+ u32 val[4], fw_version;
struct tas_fw_hdr *hdr __free(kfree) = kzalloc_obj(*hdr);
struct tas_fw_file *file __free(kfree) = kzalloc_obj(*file);
@@ -826,6 +830,11 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context)
}
mutex_lock(&tas_dev->pde_lock);
+ ret = regmap_bulk_read(tas_dev->regmap, TAS2783_FW_VERSION, &val, 4);
+ fw_version = (val[0] << 24) | (val[1] << 16) | (val[2] << 8) | val[3];
+ dev_dbg(tas_dev->dev, "Get Firmware version: %08x == %08x?, err=%d",
+ fw_version, tas_dev->fw_version, ret);
+
while (offset < (img_sz - FW_FL_HDR)) {
offset += tas_fw_get_next_file(&buf[offset], file);
dev_dbg(tas_dev->dev,
@@ -834,6 +843,13 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context)
file->version, file->length,
file->dest_addr, file->fw_data);
+ if (tas_dev->fw_version == fw_version &&
+ file->dest_addr >= PRAM_ADDR_START &&
+ (file->dest_addr + file->length) <= PRAM_ADDR_END) {
+ cur_file++;
+ dev_dbg(tas_dev->dev, "Ignore PRAM block");
+ continue;
+ }
ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral,
file->dest_addr,
file->length,
@@ -841,17 +857,34 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context)
if (ret < 0) {
dev_err(tas_dev->dev,
"FW download failed: %d", ret);
- break;
+ /*
+ * We do retry here for some special case of download
+ * failed after Power-On.
+ */
+ ret = sdw_nwrite_no_pm(tas_dev->sdw_peripheral,
+ file->dest_addr,
+ file->length,
+ file->fw_data);
+ if (ret < 0) {
+ dev_err(tas_dev->dev,
+ "FW download failed again: %d", ret);
+ break;
+ }
}
cur_file++;
}
mutex_unlock(&tas_dev->pde_lock);
+ regcache_drop_region(tas_dev->regmap, 0, UINT_MAX);
if (cur_file == 0) {
dev_err(tas_dev->dev, "fw with no files");
ret = -EINVAL;
} else {
tas2783_update_calibdata(tas_dev);
+ ret = regmap_bulk_read(tas_dev->regmap, TAS2783_FW_VERSION,
+ &val, 4);
+ tas_dev->fw_version = (val[0] << 24) | (val[1] << 16) |
+ (val[2] << 8) | val[3];
}
out:
@@ -1002,30 +1035,6 @@ static s32 tas_sdw_hw_params(struct snd_pcm_substream *substream,
snd_sdw_params_to_config(substream, params,
&stream_config, &port_config);
- /*
- * The two mono amps each render one channel of the stereo stream:
- * snd_sdw_params_to_config() hands every codec the full mask for
- * playback, which leaves the pair in mirror mode and one channel
- * unreproduced. Claim a single channel instead, keyed off the
- * machine-assigned component prefix rather than the SoundWire
- * address, which is board-specific: soc_sdw_ti_amp.c names the amps
- * tas2783-1..4.
- *
- * Which side an amp then renders does not follow from the bit that
- * is set - sdw_compute_slave_ports() advances the payload offset by
- * the popcount of ch_mask and never looks at which bit it is - but
- * from the amp's position in the codec order of the DAI link, which
- * on these boards matches the prefix numbering.
- */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
- params_channels(params) == 2 && component->name_prefix) {
- const char *idx_str = strrchr(component->name_prefix, '-');
- unsigned long idx;
-
- if (idx_str && !kstrtoul(idx_str + 1, 10, &idx) && idx)
- port_config.ch_mask = (idx & 1) ? BIT(0) : BIT(1);
- }
-
/* port 1 for playback */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
port_config.num = 1;
@@ -1114,7 +1123,7 @@ static const struct snd_soc_component_driver soc_codec_driver_tasdevice = {
.num_dapm_widgets = ARRAY_SIZE(tas_dapm_widgets),
.dapm_routes = tas_audio_map,
.num_dapm_routes = ARRAY_SIZE(tas_audio_map),
- .idle_bias_on = 1,
+ .idle_bias_on = 0,
.endianness = 1,
};
@@ -1274,6 +1283,8 @@ static s32 tas_io_init(struct device *dev, struct sdw_slave *slave)
ret = regmap_multi_reg_write(tas_dev->regmap, tas2783_init_seq,
ARRAY_SIZE(tas2783_init_seq));
+ /* Re-active AMP after resume. */
+ regmap_write(tas_dev->regmap, TASDEV_REG_SDW(0, 0, 2), 0);
if (ret)
dev_err(tas_dev->dev,
"init writes failed, err=%d", ret);
@@ -1453,6 +1464,7 @@ static s32 tas_sdw_probe(struct sdw_slave *peripheral,
tas_dev->dev = dev;
tas_dev->sdw_peripheral = peripheral;
tas_dev->hw_init = false;
+ tas_dev->fw_version = 0;
mutex_init(&tas_dev->calib_lock);
mutex_init(&tas_dev->pde_lock);
@@ -35,10 +35,12 @@
#define TAS2783_AMP_LEVEL_MASK GENMASK(5, 1)
#define PRAM_ADDR_START TASDEV_REG_SDW(0x8c, 0x01, 0x8)
-#define PRAM_ADDR_END TASDEV_REG_SDW(0x8c, 0xff, 0x7f)
+#define PRAM_ADDR_END TASDEV_REG_SDW(0x8c, 0xff, 0x80)
#define YRAM_ADDR_START TASDEV_REG_SDW(0x00, 0x02, 0x8)
#define YRAM_ADDR_END TASDEV_REG_SDW(0x00, 0x37, 0x7f)
+#define TAS2783_FW_VERSION TASDEV_REG_SDW(0x00, 0x20, 0x3c)
+
/* Calibration data */
#define TAS2783_CAL_R0 TASDEV_REG_SDW(0, 0x16, 0x4C)
#define TAS2783_CAL_INVR0 TASDEV_REG_SDW(0, 0x16, 0x5C)