ASoC: wm_adsp: Improve handling of raw byte streams
As the register map is 16-bit or 32-bit big-endian, the 24-bit DSP words appear padded and with the bytes swapped. When reading a raw stream of bytes, the pad bytes must be removed and the data bytes swapped back to their original order. The previous implementation of this assumed that the be32_to_cpu() in wm_adsp_read_data_block() would swap back to little-endian. But this is obviously only true on a little-endian CPU. It also made two walks through the data, once to endian-swap and again to strip the pad bytes. This patch re-works the code so that the endian-swap and unpad are done together in a single walk, and it is not dependent on the endianness of the CPU. The data_word_size argument to wm_adsp_remove_padding() has been dropped because currently this is always 3. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Link: https://lore.kernel.org/r/20201216112512.26503-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
a9830fc388
commit
7726e49837
|
@ -3664,12 +3664,12 @@ int wm_adsp_compr_get_caps(struct snd_soc_component *component,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps);
|
||||
|
||||
static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type,
|
||||
unsigned int mem_addr,
|
||||
unsigned int num_words, u32 *data)
|
||||
static int wm_adsp_read_raw_data_block(struct wm_adsp *dsp, int mem_type,
|
||||
unsigned int mem_addr,
|
||||
unsigned int num_words, __be32 *data)
|
||||
{
|
||||
struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
|
||||
unsigned int i, reg;
|
||||
unsigned int reg;
|
||||
int ret;
|
||||
|
||||
if (!mem)
|
||||
|
@ -3682,16 +3682,22 @@ static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < num_words; ++i)
|
||||
data[i] = be32_to_cpu(data[i]) & 0x00ffffffu;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type,
|
||||
unsigned int mem_addr, u32 *data)
|
||||
{
|
||||
return wm_adsp_read_data_block(dsp, mem_type, mem_addr, 1, data);
|
||||
__be32 raw;
|
||||
int ret;
|
||||
|
||||
ret = wm_adsp_read_raw_data_block(dsp, mem_type, mem_addr, 1, &raw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*data = be32_to_cpu(raw) & 0x00ffffffu;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type,
|
||||
|
@ -3724,18 +3730,22 @@ static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf,
|
|||
buf->host_buf_ptr + field_offset, data);
|
||||
}
|
||||
|
||||
static void wm_adsp_remove_padding(u32 *buf, int nwords, int data_word_size)
|
||||
static void wm_adsp_remove_padding(u32 *buf, int nwords)
|
||||
{
|
||||
u8 *pack_in = (u8 *)buf;
|
||||
const __be32 *pack_in = (__be32 *)buf;
|
||||
u8 *pack_out = (u8 *)buf;
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
/* Remove the padding bytes from the data read from the DSP */
|
||||
/*
|
||||
* DSP words from the register map have pad bytes and the data bytes
|
||||
* are in swapped order. This swaps back to the original little-endian
|
||||
* order and strips the pad bytes.
|
||||
*/
|
||||
for (i = 0; i < nwords; i++) {
|
||||
for (j = 0; j < data_word_size; j++)
|
||||
*pack_out++ = *pack_in++;
|
||||
|
||||
pack_in += sizeof(*buf) - data_word_size;
|
||||
u32 word = be32_to_cpu(*pack_in++);
|
||||
*pack_out++ = (u8)word;
|
||||
*pack_out++ = (u8)(word >> 8);
|
||||
*pack_out++ = (u8)(word >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3919,12 +3929,7 @@ static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(coeff_v1.name); i++)
|
||||
coeff_v1.name[i] = be32_to_cpu(coeff_v1.name[i]);
|
||||
|
||||
wm_adsp_remove_padding((u32 *)&coeff_v1.name,
|
||||
ARRAY_SIZE(coeff_v1.name),
|
||||
WM_ADSP_DATA_WORD_SIZE);
|
||||
wm_adsp_remove_padding((u32 *)&coeff_v1.name, ARRAY_SIZE(coeff_v1.name));
|
||||
|
||||
buf->name = kasprintf(GFP_KERNEL, "%s-dsp-%s", ctl->dsp->part,
|
||||
(char *)&coeff_v1.name);
|
||||
|
@ -4263,12 +4268,12 @@ static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target)
|
|||
return 0;
|
||||
|
||||
/* Read data from DSP */
|
||||
ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr,
|
||||
nwords, compr->raw_buf);
|
||||
ret = wm_adsp_read_raw_data_block(buf->dsp, mem_type, adsp_addr,
|
||||
nwords, compr->raw_buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
wm_adsp_remove_padding(compr->raw_buf, nwords, WM_ADSP_DATA_WORD_SIZE);
|
||||
wm_adsp_remove_padding(compr->raw_buf, nwords);
|
||||
|
||||
/* update read index to account for words read */
|
||||
buf->read_index += nwords;
|
||||
|
|
Loading…
Reference in New Issue