From 27f1ad5cccaeeac385e3d61cd0ab122780c10782 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Wed, 14 Aug 2024 08:59:56 +0800 Subject: [PATCH] ASoC: rockchip: dlp: Add support for pcm pattern playback CONFIG_SND_PCM_PATTERN_DEBUG * MSB check * channel id * as much as more 0/1 stress PATTERN8(x) (0xa0 | (x)) PATTERN16(x) (0xab00 | (x)) PATTERN32(x) (0xabcabc00 | (x)) e.g. 16bit 4ch pattern: 0xab01 0xab02 0xab03 0xab04 0xab01 ... This pattern is only used for IOCTL_READ/WRITE, not suitable for MMAP. Signed-off-by: Sugar Zhang Change-Id: I96d9664460adeee13ac86558159b39c9ab0dabe8 --- sound/soc/rockchip/rockchip_dlp.c | 63 ++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/sound/soc/rockchip/rockchip_dlp.c b/sound/soc/rockchip/rockchip_dlp.c index f0d1f4136704..0f59560fb9f3 100644 --- a/sound/soc/rockchip/rockchip_dlp.c +++ b/sound/soc/rockchip/rockchip_dlp.c @@ -857,6 +857,62 @@ static int dlp_process(struct snd_soc_component *component, return ret; } +/* + * MSB check + * channel id + * as much as more 0/1 stress + */ +#define PATTERN8(x) (0xa0 | (x)) +#define PATTERN16(x) (0xab00 | (x)) +#define PATTERN32(x) (0xabcabc00 | (x)) + +static void snd_fill_pattern_frame(char *buf, int bits, int ch) +{ + unsigned char *ptr8 = (unsigned char *)buf; + unsigned short *ptr16 = (unsigned short *)buf; + unsigned int *ptr32 = (unsigned int *)buf; + int i = 0; + + switch (bits) { + case 8: + for (i = 0; i < ch; i++) + ptr8[i] = PATTERN8(i + 1); + break; + case 16: + for (i = 0; i < ch; i++) + ptr16[i] = PATTERN16(i + 1); + break; + case 32: + for (i = 0; i < ch; i++) + ptr32[i] = PATTERN32(i + 1); + break; + default: + pr_err("invalid bits: %d\n", bits); + break; + } +} + +static int snd_fill_pattern(struct snd_pcm_substream *substream, + int channels, unsigned long hwoff, + unsigned long bytes) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_uframes_t frames; + void *buf; + int i = 0; + + buf = runtime->dma_area + hwoff + + channels * (runtime->dma_bytes / runtime->channels); + frames = bytes_to_frames(runtime, bytes); + + for (i = 0; i < frames; i++) { + snd_fill_pattern_frame(buf, runtime->sample_bits, runtime->channels); + buf += frames_to_bytes(runtime, 1); + } + + return 0; +} + int dlp_copy_user(struct snd_soc_component *component, struct snd_pcm_substream *substream, int channel, unsigned long hwoff, @@ -874,9 +930,12 @@ int dlp_copy_user(struct snd_soc_component *component, dma_ptr = runtime->dma_area + hwoff + channel * (runtime->dma_bytes / runtime->channels); - if (is_playback) - if (copy_from_user(dma_ptr, buf, bytes)) + if (is_playback) { + if (IS_ENABLED(CONFIG_SND_PCM_PATTERN_DEBUG)) + snd_fill_pattern(substream, channel, hwoff, bytes); + else if (copy_from_user(dma_ptr, buf, bytes)) return -EFAULT; + } ret = dlp_process(component, substream, hwoff, buf, bytes); if (!ret)