From: Richard Fitzgerald Date: Wed, 31 Dec 2025 17:27:04 +0000 (+0000) Subject: firmware: cs_dsp: Handle long-offset data blocks X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bc0305cb294c693b2762cf863324defb9e5175e5;p=thirdparty%2Fkernel%2Flinux.git firmware: cs_dsp: Handle long-offset data blocks Handle a new type of data block that has a 32-bit offset. These are identical to the normal blocks except that the offset is now in the 32-bit field that was previously 'sr'. A new file version of 3 indicates that it is mandatory to process the long-offset blocks, so that older code without that support will reject the file. The original 'sr' field was never used by the driver so it has been renamed offset32. Signed-off-by: Richard Fitzgerald Link: https://patch.msgid.link/20251231172711.450024-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c index d35d0f5ccaf7b..aa6e740f9cd74 100644 --- a/drivers/firmware/cirrus/cs_dsp.c +++ b/drivers/firmware/cirrus/cs_dsp.c @@ -2138,7 +2138,8 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware const struct cs_dsp_region *mem; struct cs_dsp_alg_region *alg_region; const char *region_name; - int ret, pos, blocks, type, offset, reg, version; + int ret, pos, blocks, type, version; + unsigned int offset, reg; u8 *buf = NULL; size_t buf_len = 0; size_t region_len; @@ -2163,6 +2164,7 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware switch (be32_to_cpu(hdr->rev) & 0xff) { case 1: case 2: + case 3: break; default: cs_dsp_err(dsp, "%s: Unsupported coefficient file format %d\n", @@ -2171,7 +2173,8 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware goto out_fw; } - cs_dsp_info(dsp, "%s: v%d.%d.%d\n", file, + cs_dsp_info(dsp, "%s (v%d): v%d.%d.%d\n", file, + be32_to_cpu(hdr->rev) & 0xff, (le32_to_cpu(hdr->ver) >> 16) & 0xff, (le32_to_cpu(hdr->ver) >> 8) & 0xff, le32_to_cpu(hdr->ver) & 0xff); @@ -2202,8 +2205,9 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware (le32_to_cpu(blk->ver) >> 16) & 0xff, (le32_to_cpu(blk->ver) >> 8) & 0xff, le32_to_cpu(blk->ver) & 0xff); - cs_dsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n", - file, blocks, le32_to_cpu(blk->len), offset, type); + cs_dsp_dbg(dsp, "%s.%d: %d bytes off:%#x off32:%#x in %#x\n", + file, blocks, le32_to_cpu(blk->len), offset, + le32_to_cpu(blk->offset32), type); reg = 0; region_name = "Unknown"; @@ -2236,6 +2240,13 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware } break; + case WMFW_ADSP2_XM_LONG: + case WMFW_ADSP2_YM_LONG: + case WMFW_HALO_XM_PACKED_LONG: + case WMFW_HALO_YM_PACKED_LONG: + offset = le32_to_cpu(blk->offset32); + type &= 0xff; /* strip extended block type flags */ + fallthrough; case WMFW_ADSP1_DM: case WMFW_ADSP1_ZM: case WMFW_ADSP2_XM: diff --git a/include/linux/firmware/cirrus/wmfw.h b/include/linux/firmware/cirrus/wmfw.h index 74e5a4f6c13a0..eae24dde9e41c 100644 --- a/include/linux/firmware/cirrus/wmfw.h +++ b/include/linux/firmware/cirrus/wmfw.h @@ -172,7 +172,7 @@ struct wmfw_coeff_item { __le16 type; __le32 id; __le32 ver; - __le32 sr; + __le32 offset32; __le32 len; u8 data[]; } __packed; @@ -200,4 +200,9 @@ struct wmfw_coeff_item { #define WMFW_HALO_XM_PACKED 0x11 #define WMFW_HALO_YM_PACKED 0x12 +#define WMFW_ADSP2_XM_LONG 0xf405 +#define WMFW_ADSP2_YM_LONG 0xf406 +#define WMFW_HALO_XM_PACKED_LONG 0xf411 +#define WMFW_HALO_YM_PACKED_LONG 0xf412 + #endif