^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Copyright (c) 2018, Linaro Limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <sound/soc-dapm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <sound/compress_driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/dma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "q6asm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "q6routing.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "q6dsp-errno.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define DRV_NAME "q6asm-fe-dai"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define PLAYBACK_MIN_NUM_PERIODS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define PLAYBACK_MAX_NUM_PERIODS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define PLAYBACK_MAX_PERIOD_SIZE 65536
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define PLAYBACK_MIN_PERIOD_SIZE 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define CAPTURE_MIN_NUM_PERIODS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define CAPTURE_MAX_NUM_PERIODS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define CAPTURE_MAX_PERIOD_SIZE 4096
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define CAPTURE_MIN_PERIOD_SIZE 320
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define SID_MASK_DEFAULT 0xF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* Default values used if user space does not set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define ALAC_CH_LAYOUT_MONO ((101 << 16) | 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define ALAC_CH_LAYOUT_STEREO ((101 << 16) | 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) enum stream_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) Q6ASM_STREAM_IDLE = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) Q6ASM_STREAM_STOPPED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) Q6ASM_STREAM_RUNNING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct q6asm_dai_rtd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct snd_compr_stream *cstream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct snd_codec codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct snd_dma_buffer dma_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) phys_addr_t phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned int pcm_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned int pcm_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned int pcm_irq_pos; /* IRQ position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned int periods;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned int bytes_sent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned int bytes_received;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned int copied_total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) uint16_t bits_per_sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) uint16_t source; /* Encoding source bit mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct audio_client *audio_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) uint32_t next_track_stream_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) bool next_track;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) uint32_t stream_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) uint16_t session_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) enum stream_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) uint32_t initial_samples_drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) uint32_t trailing_samples_drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) bool notify_on_drain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct q6asm_dai_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct snd_soc_dai_driver *dais;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int num_dais;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) long long int sid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static const struct snd_pcm_hardware q6asm_dai_hardware_capture = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .formats = (SNDRV_PCM_FMTBIT_S16_LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) SNDRV_PCM_FMTBIT_S24_LE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .rates = SNDRV_PCM_RATE_8000_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .rate_min = 8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .rate_max = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .channels_max = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) CAPTURE_MAX_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .periods_min = CAPTURE_MIN_NUM_PERIODS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .periods_max = CAPTURE_MAX_NUM_PERIODS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .fifo_size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static struct snd_pcm_hardware q6asm_dai_hardware_playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .formats = (SNDRV_PCM_FMTBIT_S16_LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) SNDRV_PCM_FMTBIT_S24_LE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .rates = SNDRV_PCM_RATE_8000_192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .rate_min = 8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .rate_max = 192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .channels_max = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .buffer_bytes_max = (PLAYBACK_MAX_NUM_PERIODS *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) PLAYBACK_MAX_PERIOD_SIZE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .periods_min = PLAYBACK_MIN_NUM_PERIODS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .periods_max = PLAYBACK_MAX_NUM_PERIODS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .fifo_size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define Q6ASM_FEDAI_DRIVER(num) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .playback = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .stream_name = "MultiMedia"#num" Playback", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .rates = (SNDRV_PCM_RATE_8000_192000| \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) SNDRV_PCM_RATE_KNOT), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .formats = (SNDRV_PCM_FMTBIT_S16_LE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) SNDRV_PCM_FMTBIT_S24_LE), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .channels_min = 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .channels_max = 8, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .rate_min = 8000, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .rate_max = 192000, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .capture = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .stream_name = "MultiMedia"#num" Capture", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .rates = (SNDRV_PCM_RATE_8000_48000| \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) SNDRV_PCM_RATE_KNOT), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .formats = (SNDRV_PCM_FMTBIT_S16_LE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) SNDRV_PCM_FMTBIT_S24_LE), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .channels_min = 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .channels_max = 4, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .rate_min = 8000, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .rate_max = 48000, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .name = "MultiMedia"#num, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .id = MSM_FRONTEND_DAI_MULTIMEDIA##num, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* Conventional and unconventional sample rate supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static unsigned int supported_sample_rates[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 88200, 96000, 176400, 192000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .count = ARRAY_SIZE(supported_sample_rates),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .list = supported_sample_rates,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .mask = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static const struct snd_compr_codec_caps q6asm_compr_caps = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .num_descriptors = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .descriptor[0].max_ch = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .descriptor[0].sample_rates = { 8000, 11025, 12000, 16000, 22050,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 24000, 32000, 44100, 48000, 88200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 96000, 176400, 192000 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .descriptor[0].num_sample_rates = 13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .descriptor[0].bit_rate[0] = 320,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .descriptor[0].bit_rate[1] = 128,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .descriptor[0].num_bitrates = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .descriptor[0].profiles = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .descriptor[0].formats = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static void event_handler(uint32_t opcode, uint32_t token,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) void *payload, void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct q6asm_dai_rtd *prtd = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct snd_pcm_substream *substream = prtd->substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) switch (opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) case ASM_CLIENT_EVENT_CMD_RUN_DONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) q6asm_write_async(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) prtd->pcm_count, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) case ASM_CLIENT_EVENT_CMD_EOS_DONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) prtd->state = Q6ASM_STREAM_STOPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) case ASM_CLIENT_EVENT_DATA_WRITE_DONE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) prtd->pcm_irq_pos += prtd->pcm_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) snd_pcm_period_elapsed(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (prtd->state == Q6ASM_STREAM_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) q6asm_write_async(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) prtd->pcm_count, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) case ASM_CLIENT_EVENT_DATA_READ_DONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) prtd->pcm_irq_pos += prtd->pcm_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) snd_pcm_period_elapsed(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (prtd->state == Q6ASM_STREAM_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) q6asm_read(prtd->audio_client, prtd->stream_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int q6asm_dai_prepare(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct q6asm_dai_rtd *prtd = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct q6asm_dai_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct device *dev = component->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) pdata = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (!prtd || !prtd->audio_client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) dev_err(dev, "%s: private data null or audio client freed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) prtd->pcm_irq_pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* rate and channels are sent to audio driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (prtd->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* clear the previous setup if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) q6asm_unmap_memory_regions(substream->stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) prtd->audio_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) q6routing_stream_close(soc_prtd->dai_link->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) prtd->phys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) (prtd->pcm_size / prtd->periods),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) prtd->periods);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ret = q6asm_open_write(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) FORMAT_LINEAR_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 0, prtd->bits_per_sample, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) ret = q6asm_open_read(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) FORMAT_LINEAR_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) prtd->bits_per_sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) dev_err(dev, "%s: q6asm_open_write failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) goto open_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) prtd->session_id = q6asm_get_session_id(prtd->audio_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ret = q6routing_stream_open(soc_prtd->dai_link->id, LEGACY_PCM_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) prtd->session_id, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) dev_err(dev, "%s: stream reg failed ret:%d\n", __func__, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) goto routing_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ret = q6asm_media_format_block_multi_ch_pcm(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) runtime->rate, runtime->channels, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) prtd->bits_per_sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) runtime->rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) runtime->channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) prtd->bits_per_sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /* Queue the buffers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) for (i = 0; i < runtime->periods; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) q6asm_read(prtd->audio_client, prtd->stream_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) dev_info(dev, "%s: CMD Format block failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) prtd->state = Q6ASM_STREAM_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) routing_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) open_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) q6asm_unmap_memory_regions(substream->stream, prtd->audio_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) q6asm_audio_client_free(prtd->audio_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) prtd->audio_client = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static int q6asm_dai_trigger(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct q6asm_dai_rtd *prtd = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) ret = q6asm_run_nowait(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) prtd->state = Q6ASM_STREAM_STOPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) CMD_EOS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) CMD_PAUSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static int q6asm_dai_open(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_prtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct q6asm_dai_rtd *prtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct q6asm_dai_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct device *dev = component->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) int stream_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) stream_id = cpu_dai->driver->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) pdata = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) dev_err(dev, "Drv data not found ..\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) prtd = kzalloc(sizeof(struct q6asm_dai_rtd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (prtd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) prtd->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) prtd->audio_client = q6asm_audio_client_alloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) (q6asm_cb)event_handler, prtd, stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) LEGACY_PCM_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (IS_ERR(prtd->audio_client)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) dev_info(dev, "%s: Could not allocate memory\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) ret = PTR_ERR(prtd->audio_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) kfree(prtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) /* DSP expects stream id from 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) prtd->stream_id = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) runtime->hw = q6asm_dai_hardware_playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) runtime->hw = q6asm_dai_hardware_capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) ret = snd_pcm_hw_constraint_list(runtime, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) SNDRV_PCM_HW_PARAM_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) &constraints_sample_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) dev_info(dev, "snd_pcm_hw_constraint_list failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /* Ensure that buffer size is a multiple of period size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ret = snd_pcm_hw_constraint_integer(runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) SNDRV_PCM_HW_PARAM_PERIODS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) dev_info(dev, "snd_pcm_hw_constraint_integer failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) ret = snd_pcm_hw_constraint_minmax(runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) dev_err(dev, "constraint for buffer bytes min max ret = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) ret = snd_pcm_hw_constraint_step(runtime, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) dev_err(dev, "constraint for period bytes step ret = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) ret = snd_pcm_hw_constraint_step(runtime, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) dev_err(dev, "constraint for buffer bytes step ret = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) runtime->private_data = prtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_playback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) runtime->dma_bytes = q6asm_dai_hardware_playback.buffer_bytes_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (pdata->sid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) prtd->phys = substream->dma_buffer.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static int q6asm_dai_close(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct q6asm_dai_rtd *prtd = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (prtd->audio_client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (prtd->state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) q6asm_cmd(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) CMD_CLOSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) q6asm_unmap_memory_regions(substream->stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) prtd->audio_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) q6asm_audio_client_free(prtd->audio_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) prtd->audio_client = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) q6routing_stream_close(soc_prtd->dai_link->id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) kfree(prtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct q6asm_dai_rtd *prtd = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (prtd->pcm_irq_pos >= prtd->pcm_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) prtd->pcm_irq_pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static int q6asm_dai_mmap(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) struct device *dev = component->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return dma_mmap_coherent(dev, vma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) runtime->dma_area, runtime->dma_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) runtime->dma_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) static int q6asm_dai_hw_params(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct q6asm_dai_rtd *prtd = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) prtd->pcm_size = params_buffer_bytes(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) prtd->periods = params_periods(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) switch (params_format(params)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) case SNDRV_PCM_FORMAT_S16_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) prtd->bits_per_sample = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) case SNDRV_PCM_FORMAT_S24_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) prtd->bits_per_sample = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static void compress_event_handler(uint32_t opcode, uint32_t token,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) void *payload, void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) struct q6asm_dai_rtd *prtd = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) struct snd_compr_stream *substream = prtd->cstream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) u32 wflags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) uint64_t avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) uint32_t bytes_written, bytes_to_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) bool is_last_buffer = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) switch (opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) case ASM_CLIENT_EVENT_CMD_RUN_DONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) spin_lock_irqsave(&prtd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (!prtd->bytes_sent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) q6asm_stream_remove_initial_silence(prtd->audio_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) prtd->initial_samples_drop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) q6asm_write_async(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) prtd->pcm_count, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) prtd->bytes_sent += prtd->pcm_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) spin_unlock_irqrestore(&prtd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) case ASM_CLIENT_EVENT_CMD_EOS_DONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) spin_lock_irqsave(&prtd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (prtd->notify_on_drain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (substream->partial_drain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * Close old stream and make it stale, switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * the active stream now!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) q6asm_cmd_nowait(prtd->audio_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) CMD_CLOSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) * vaild stream ids start from 1, So we are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * toggling this between 1 and 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) prtd->stream_id = (prtd->stream_id == 1 ? 2 : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) snd_compr_drain_notify(prtd->cstream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) prtd->notify_on_drain = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) prtd->state = Q6ASM_STREAM_STOPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) spin_unlock_irqrestore(&prtd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) case ASM_CLIENT_EVENT_DATA_WRITE_DONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) spin_lock_irqsave(&prtd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) bytes_written = token >> ASM_WRITE_TOKEN_LEN_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) prtd->copied_total += bytes_written;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) snd_compr_fragment_elapsed(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (prtd->state != Q6ASM_STREAM_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) spin_unlock_irqrestore(&prtd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) avail = prtd->bytes_received - prtd->bytes_sent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (avail > prtd->pcm_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) bytes_to_write = prtd->pcm_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (substream->partial_drain || prtd->notify_on_drain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) is_last_buffer = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) bytes_to_write = avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (bytes_to_write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (substream->partial_drain && is_last_buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) wflags |= ASM_LAST_BUFFER_FLAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) q6asm_stream_remove_trailing_silence(prtd->audio_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) prtd->trailing_samples_drop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) q6asm_write_async(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) bytes_to_write, 0, 0, wflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) prtd->bytes_sent += bytes_to_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (prtd->notify_on_drain && is_last_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) q6asm_cmd_nowait(prtd->audio_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) prtd->stream_id, CMD_EOS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) spin_unlock_irqrestore(&prtd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) static int q6asm_dai_compr_open(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) struct snd_compr_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct snd_soc_pcm_runtime *rtd = stream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) struct snd_compr_runtime *runtime = stream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) struct q6asm_dai_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) struct device *dev = component->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) struct q6asm_dai_rtd *prtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) int stream_id, size, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) stream_id = cpu_dai->driver->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) pdata = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) dev_err(dev, "Drv data not found ..\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (!prtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /* DSP expects stream id from 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) prtd->stream_id = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) prtd->cstream = stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) prtd->audio_client = q6asm_audio_client_alloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) (q6asm_cb)compress_event_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) prtd, stream_id, LEGACY_PCM_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (IS_ERR(prtd->audio_client)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) dev_err(dev, "Could not allocate memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) ret = PTR_ERR(prtd->audio_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) goto free_prtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) &prtd->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) dev_err(dev, "Cannot allocate buffer(s)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) goto free_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (pdata->sid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) prtd->phys = prtd->dma_buffer.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) prtd->phys = prtd->dma_buffer.addr | (pdata->sid << 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) snd_compr_set_runtime_buffer(stream, &prtd->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) spin_lock_init(&prtd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) runtime->private_data = prtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) free_client:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) q6asm_audio_client_free(prtd->audio_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) free_prtd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) kfree(prtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) static int q6asm_dai_compr_free(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct snd_compr_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) struct snd_compr_runtime *runtime = stream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) struct q6asm_dai_rtd *prtd = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) struct snd_soc_pcm_runtime *rtd = stream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (prtd->audio_client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (prtd->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) q6asm_cmd(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) CMD_CLOSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (prtd->next_track_stream_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) q6asm_cmd(prtd->audio_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) prtd->next_track_stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) CMD_CLOSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) snd_dma_free_pages(&prtd->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) q6asm_unmap_memory_regions(stream->direction,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) prtd->audio_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) q6asm_audio_client_free(prtd->audio_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) prtd->audio_client = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) q6routing_stream_close(rtd->dai_link->id, stream->direction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) kfree(prtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) static int __q6asm_dai_compr_set_codec_params(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) struct snd_compr_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct snd_codec *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) int stream_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) struct snd_compr_runtime *runtime = stream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct q6asm_dai_rtd *prtd = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct q6asm_flac_cfg flac_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) struct q6asm_wma_cfg wma_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct q6asm_alac_cfg alac_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) struct q6asm_ape_cfg ape_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) unsigned int wma_v9 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) struct device *dev = component->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) union snd_codec_options *codec_options;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct snd_dec_flac *flac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct snd_dec_wma *wma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct snd_dec_alac *alac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) struct snd_dec_ape *ape;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) codec_options = &(prtd->codec.options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) memcpy(&prtd->codec, codec, sizeof(*codec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) switch (codec->id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) case SND_AUDIOCODEC_FLAC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) memset(&flac_cfg, 0x0, sizeof(struct q6asm_flac_cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) flac = &codec_options->flac_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) flac_cfg.ch_cfg = codec->ch_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) flac_cfg.sample_rate = codec->sample_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) flac_cfg.stream_info_present = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) flac_cfg.sample_size = flac->sample_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) flac_cfg.min_blk_size = flac->min_blk_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) flac_cfg.max_blk_size = flac->max_blk_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) flac_cfg.max_frame_size = flac->max_frame_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) flac_cfg.min_frame_size = flac->min_frame_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) ret = q6asm_stream_media_format_block_flac(prtd->audio_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) &flac_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) dev_err(dev, "FLAC CMD Format block failed:%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) case SND_AUDIOCODEC_WMA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) wma = &codec_options->wma_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) memset(&wma_cfg, 0x0, sizeof(struct q6asm_wma_cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) wma_cfg.sample_rate = codec->sample_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) wma_cfg.num_channels = codec->ch_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) wma_cfg.bytes_per_sec = codec->bit_rate / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) wma_cfg.block_align = codec->align;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) wma_cfg.bits_per_sample = prtd->bits_per_sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) wma_cfg.enc_options = wma->encoder_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) wma_cfg.adv_enc_options = wma->adv_encoder_option;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) wma_cfg.adv_enc_options2 = wma->adv_encoder_option2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (wma_cfg.num_channels == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) wma_cfg.channel_mask = 4; /* Mono Center */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) else if (wma_cfg.num_channels == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) wma_cfg.channel_mask = 3; /* Stereo FL/FR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) /* check the codec profile */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) switch (codec->profile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) case SND_AUDIOPROFILE_WMA9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) wma_cfg.fmtag = 0x161;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) wma_v9 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) case SND_AUDIOPROFILE_WMA10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) wma_cfg.fmtag = 0x166;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) case SND_AUDIOPROFILE_WMA9_PRO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) wma_cfg.fmtag = 0x162;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) case SND_AUDIOPROFILE_WMA9_LOSSLESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) wma_cfg.fmtag = 0x163;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) case SND_AUDIOPROFILE_WMA10_LOSSLESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) wma_cfg.fmtag = 0x167;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) dev_err(dev, "Unknown WMA profile:%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) codec->profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (wma_v9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) ret = q6asm_stream_media_format_block_wma_v9(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) prtd->audio_client, stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) &wma_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) ret = q6asm_stream_media_format_block_wma_v10(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) prtd->audio_client, stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) &wma_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) dev_err(dev, "WMA9 CMD failed:%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) case SND_AUDIOCODEC_ALAC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) memset(&alac_cfg, 0x0, sizeof(alac_cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) alac = &codec_options->alac_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) alac_cfg.sample_rate = codec->sample_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) alac_cfg.avg_bit_rate = codec->bit_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) alac_cfg.bit_depth = prtd->bits_per_sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) alac_cfg.num_channels = codec->ch_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) alac_cfg.frame_length = alac->frame_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) alac_cfg.pb = alac->pb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) alac_cfg.mb = alac->mb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) alac_cfg.kb = alac->kb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) alac_cfg.max_run = alac->max_run;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) alac_cfg.compatible_version = alac->compatible_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) alac_cfg.max_frame_bytes = alac->max_frame_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) switch (codec->ch_in) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_STEREO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) ret = q6asm_stream_media_format_block_alac(prtd->audio_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) &alac_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) dev_err(dev, "ALAC CMD Format block failed:%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) case SND_AUDIOCODEC_APE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) memset(&ape_cfg, 0x0, sizeof(ape_cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) ape = &codec_options->ape_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) ape_cfg.sample_rate = codec->sample_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) ape_cfg.num_channels = codec->ch_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) ape_cfg.bits_per_sample = prtd->bits_per_sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) ape_cfg.compatible_version = ape->compatible_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) ape_cfg.compression_level = ape->compression_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) ape_cfg.format_flags = ape->format_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) ape_cfg.blocks_per_frame = ape->blocks_per_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) ape_cfg.final_frame_blocks = ape->final_frame_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) ape_cfg.total_frames = ape->total_frames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) ape_cfg.seek_table_present = ape->seek_table_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) ret = q6asm_stream_media_format_block_ape(prtd->audio_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) &ape_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) dev_err(dev, "APE CMD Format block failed:%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) struct snd_compr_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) struct snd_compr_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) struct snd_compr_runtime *runtime = stream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) struct q6asm_dai_rtd *prtd = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) struct snd_soc_pcm_runtime *rtd = stream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) int dir = stream->direction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct q6asm_dai_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) struct device *dev = component->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) pdata = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (!prtd || !prtd->audio_client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) dev_err(dev, "private data null or audio client freed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) prtd->periods = runtime->fragments;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) prtd->pcm_count = runtime->fragment_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) prtd->pcm_size = runtime->fragments * runtime->fragment_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) prtd->bits_per_sample = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (dir == SND_COMPRESS_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) ret = q6asm_open_write(prtd->audio_client, prtd->stream_id, params->codec.id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) params->codec.profile, prtd->bits_per_sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) dev_err(dev, "q6asm_open_write failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) q6asm_audio_client_free(prtd->audio_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) prtd->audio_client = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) prtd->session_id = q6asm_get_session_id(prtd->audio_client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) ret = q6routing_stream_open(rtd->dai_link->id, LEGACY_PCM_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) prtd->session_id, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) dev_err(dev, "Stream reg failed ret:%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) ret = __q6asm_dai_compr_set_codec_params(component, stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) ¶ms->codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) prtd->stream_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) dev_err(dev, "codec param setup failed ret:%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) (prtd->pcm_size / prtd->periods),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) prtd->periods);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) dev_err(dev, "Buffer Mapping failed ret:%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) prtd->state = Q6ASM_STREAM_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) static int q6asm_dai_compr_set_metadata(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct snd_compr_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct snd_compr_metadata *metadata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct snd_compr_runtime *runtime = stream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) struct q6asm_dai_rtd *prtd = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) switch (metadata->key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) case SNDRV_COMPRESS_ENCODER_PADDING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) prtd->trailing_samples_drop = metadata->value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) case SNDRV_COMPRESS_ENCODER_DELAY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) prtd->initial_samples_drop = metadata->value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (prtd->next_track_stream_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) ret = q6asm_open_write(prtd->audio_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) prtd->next_track_stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) prtd->codec.id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) prtd->codec.profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) prtd->bits_per_sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) dev_err(component->dev, "q6asm_open_write failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) ret = __q6asm_dai_compr_set_codec_params(component, stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) &prtd->codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) prtd->next_track_stream_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) dev_err(component->dev, "q6asm_open_write failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) ret = q6asm_stream_remove_initial_silence(prtd->audio_client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) prtd->next_track_stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) prtd->initial_samples_drop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) prtd->next_track_stream_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) static int q6asm_dai_compr_trigger(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) struct snd_compr_stream *stream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) struct snd_compr_runtime *runtime = stream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) struct q6asm_dai_rtd *prtd = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) ret = q6asm_run_nowait(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) prtd->state = Q6ASM_STREAM_STOPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) CMD_EOS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) CMD_PAUSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) case SND_COMPR_TRIGGER_NEXT_TRACK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) prtd->next_track = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) prtd->next_track_stream_id = (prtd->stream_id == 1 ? 2 : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) case SND_COMPR_TRIGGER_DRAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) prtd->notify_on_drain = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) static int q6asm_dai_compr_pointer(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) struct snd_compr_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) struct snd_compr_tstamp *tstamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) struct snd_compr_runtime *runtime = stream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) struct q6asm_dai_rtd *prtd = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) spin_lock_irqsave(&prtd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) tstamp->copied_total = prtd->copied_total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) tstamp->byte_offset = prtd->copied_total % prtd->pcm_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) spin_unlock_irqrestore(&prtd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) static int q6asm_compr_copy(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) struct snd_compr_stream *stream, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct snd_compr_runtime *runtime = stream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) struct q6asm_dai_rtd *prtd = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) u32 wflags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) int avail, bytes_in_flight = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) void *dstn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) size_t copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) u32 app_pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) u32 bytes_received;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) bytes_received = prtd->bytes_received;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) * Make sure that next track data pointer is aligned at 32 bit boundary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) * This is a Mandatory requirement from DSP data buffers alignment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (prtd->next_track)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) bytes_received = ALIGN(prtd->bytes_received, prtd->pcm_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) app_pointer = bytes_received/prtd->pcm_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) app_pointer = bytes_received - (app_pointer * prtd->pcm_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) dstn = prtd->dma_buffer.area + app_pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (count < prtd->pcm_size - app_pointer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (copy_from_user(dstn, buf, count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) copy = prtd->pcm_size - app_pointer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (copy_from_user(dstn, buf, copy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (copy_from_user(prtd->dma_buffer.area, buf + copy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) count - copy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) spin_lock_irqsave(&prtd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) bytes_in_flight = prtd->bytes_received - prtd->copied_total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (prtd->next_track) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) prtd->next_track = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) prtd->copied_total = ALIGN(prtd->copied_total, prtd->pcm_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) prtd->bytes_sent = ALIGN(prtd->bytes_sent, prtd->pcm_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) prtd->bytes_received = bytes_received + count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) /* Kick off the data to dsp if its starving!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if (prtd->state == Q6ASM_STREAM_RUNNING && (bytes_in_flight == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) uint32_t bytes_to_write = prtd->pcm_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) avail = prtd->bytes_received - prtd->bytes_sent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (avail < prtd->pcm_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) bytes_to_write = avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) q6asm_write_async(prtd->audio_client, prtd->stream_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) bytes_to_write, 0, 0, wflags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) prtd->bytes_sent += bytes_to_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) spin_unlock_irqrestore(&prtd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) static int q6asm_dai_compr_mmap(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) struct snd_compr_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct snd_compr_runtime *runtime = stream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) struct q6asm_dai_rtd *prtd = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) struct device *dev = component->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) return dma_mmap_coherent(dev, vma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) prtd->dma_buffer.area, prtd->dma_buffer.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) prtd->dma_buffer.bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) static int q6asm_dai_compr_get_caps(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) struct snd_compr_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) struct snd_compr_caps *caps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) caps->direction = SND_COMPRESS_PLAYBACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) caps->min_fragment_size = COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) caps->num_codecs = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) caps->codecs[0] = SND_AUDIOCODEC_MP3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) caps->codecs[1] = SND_AUDIOCODEC_FLAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) caps->codecs[2] = SND_AUDIOCODEC_WMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) caps->codecs[3] = SND_AUDIOCODEC_ALAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) caps->codecs[4] = SND_AUDIOCODEC_APE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) static int q6asm_dai_compr_get_codec_caps(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) struct snd_compr_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) struct snd_compr_codec_caps *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) switch (codec->codec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) case SND_AUDIOCODEC_MP3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) *codec = q6asm_compr_caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) static struct snd_compress_ops q6asm_dai_compress_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) .open = q6asm_dai_compr_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) .free = q6asm_dai_compr_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) .set_params = q6asm_dai_compr_set_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) .set_metadata = q6asm_dai_compr_set_metadata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) .pointer = q6asm_dai_compr_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) .trigger = q6asm_dai_compr_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) .get_caps = q6asm_dai_compr_get_caps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) .get_codec_caps = q6asm_dai_compr_get_codec_caps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) .mmap = q6asm_dai_compr_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) .copy = q6asm_compr_copy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) static int q6asm_dai_pcm_new(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) struct snd_soc_pcm_runtime *rtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) struct snd_pcm_substream *psubstream, *csubstream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) struct snd_pcm *pcm = rtd->pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) int size, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) dev = component->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) size = q6asm_dai_hardware_playback.buffer_bytes_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if (psubstream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) &psubstream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) dev_err(dev, "Cannot allocate buffer(s)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (csubstream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) &csubstream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) dev_err(dev, "Cannot allocate buffer(s)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) if (psubstream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) snd_dma_free_pages(&psubstream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) static void q6asm_dai_pcm_free(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) struct snd_pcm *pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) substream = pcm->streams[i].substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if (substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) snd_dma_free_pages(&substream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) substream->dma_buffer.area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) substream->dma_buffer.addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) static const struct snd_soc_dapm_widget q6asm_dapm_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) static const struct snd_soc_component_driver q6asm_fe_dai_component = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) .name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) .open = q6asm_dai_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) .hw_params = q6asm_dai_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) .close = q6asm_dai_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) .prepare = q6asm_dai_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) .trigger = q6asm_dai_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) .pointer = q6asm_dai_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) .mmap = q6asm_dai_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) .pcm_construct = q6asm_dai_pcm_new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) .pcm_destruct = q6asm_dai_pcm_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) .compress_ops = &q6asm_dai_compress_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) .dapm_widgets = q6asm_dapm_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) .num_dapm_widgets = ARRAY_SIZE(q6asm_dapm_widgets),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) static struct snd_soc_dai_driver q6asm_fe_dais_template[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) Q6ASM_FEDAI_DRIVER(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) Q6ASM_FEDAI_DRIVER(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) Q6ASM_FEDAI_DRIVER(3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) Q6ASM_FEDAI_DRIVER(4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) Q6ASM_FEDAI_DRIVER(5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) Q6ASM_FEDAI_DRIVER(6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) Q6ASM_FEDAI_DRIVER(7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) Q6ASM_FEDAI_DRIVER(8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) static int of_q6asm_parse_dai_data(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) struct q6asm_dai_data *pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) struct snd_soc_dai_driver *dai_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) struct snd_soc_pcm_stream empty_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) struct device_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) int ret, id, dir, idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) pdata->num_dais = of_get_child_count(dev->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) if (!pdata->num_dais) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) dev_err(dev, "No dais found in DT\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) pdata->dais = devm_kcalloc(dev, pdata->num_dais, sizeof(*dai_drv),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) if (!pdata->dais)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) memset(&empty_stream, 0, sizeof(empty_stream));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) for_each_child_of_node(dev->of_node, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) ret = of_property_read_u32(node, "reg", &id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) if (ret || id >= MAX_SESSIONS || id < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) dev_err(dev, "valid dai id not found:%d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) dai_drv = &pdata->dais[idx++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) *dai_drv = q6asm_fe_dais_template[id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) ret = of_property_read_u32(node, "direction", &dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) if (dir == Q6ASM_DAI_RX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) dai_drv->capture = empty_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) else if (dir == Q6ASM_DAI_TX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) dai_drv->playback = empty_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) if (of_property_read_bool(node, "is-compress-dai"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) dai_drv->compress_new = snd_soc_new_compress;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) static int q6asm_dai_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) struct device_node *node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) struct of_phandle_args args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) struct q6asm_dai_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) pdata->sid = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) pdata->sid = args.args[0] & SID_MASK_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) dev_set_drvdata(dev, pdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) rc = of_q6asm_parse_dai_data(dev, pdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) pdata->dais, pdata->num_dais);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) static const struct of_device_id q6asm_dai_device_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) { .compatible = "qcom,q6asm-dais" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) MODULE_DEVICE_TABLE(of, q6asm_dai_device_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) static struct platform_driver q6asm_dai_platform_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) .name = "q6asm-dai",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) .of_match_table = of_match_ptr(q6asm_dai_device_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) .probe = q6asm_dai_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) module_platform_driver(q6asm_dai_platform_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) MODULE_DESCRIPTION("Q6ASM dai driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) MODULE_LICENSE("GPL v2");