summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/apr_audio-v2.h70
-rw-r--r--include/sound/q6asm-v2.h41
-rwxr-xr-xsound/soc/msm/qdsp6v2/msm-compress-q6-v2.c24
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c23
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c63
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c429
6 files changed, 595 insertions, 55 deletions
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 809d5223b638..8d9016e3557c 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -3432,6 +3432,16 @@ struct asm_multi_channel_pcm_fmt_blk_v3 {
*/
} __packed;
+/*
+ * Payload of the multichannel PCM configuration parameters in
+ * the ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3 media format.
+ */
+struct asm_multi_channel_pcm_fmt_blk_param_v3 {
+ struct apr_hdr hdr;
+ struct asm_data_cmd_media_fmt_update_v2 fmt_blk;
+ struct asm_multi_channel_pcm_fmt_blk_v3 param;
+} __packed;
+
struct asm_stream_cmd_set_encdec_param {
u32 param_id;
/* ID of the parameter. */
@@ -3467,6 +3477,66 @@ struct asm_dec_ddp_endp_param_v2 {
int endp_param_value;
} __packed;
+
+/*
+ * Payload of the multichannel PCM encoder configuration parameters in
+ * the ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3 media format.
+ */
+
+struct asm_multi_channel_pcm_enc_cfg_v3 {
+ struct apr_hdr hdr;
+ struct asm_stream_cmd_set_encdec_param encdec;
+ struct asm_enc_cfg_blk_param_v2 encblk;
+ uint16_t num_channels;
+ /*
+ * Number of PCM channels.
+ * @values
+ * - 0 -- Native mode
+ * - 1 -- 8 channels
+ * Native mode indicates that encoding must be performed with the number
+ * of channels at the input.
+ */
+ uint16_t bits_per_sample;
+ /*
+ * Number of bits per sample per channel.
+ * @values 16, 24
+ */
+ uint32_t sample_rate;
+ /*
+ * Number of samples per second.
+ * @values 0, 8000 to 48000 Hz
+ * A value of 0 indicates the native sampling rate. Encoding is
+ * performed at the input sampling rate.
+ */
+ uint16_t is_signed;
+ /*
+ * Flag that indicates the PCM samples are signed (1). Currently, only
+ * signed PCM samples are supported.
+ */
+ uint16_t sample_word_size;
+ /*
+ * The size in bits of the word that holds a sample of a channel.
+ * @values 16, 24, 32
+ * 16-bit samples are always placed in 16-bit words:
+ * sample_word_size = 1.
+ * 24-bit samples can be placed in 32-bit words or in consecutive
+ * 24-bit words.
+ * - If sample_word_size = 32, 24-bit samples are placed in the
+ * most significant 24 bits of a 32-bit word.
+ * - If sample_word_size = 24, 24-bit samples are placed in
+ * 24-bit words. @tablebulletend
+ */
+ uint8_t channel_mapping[8];
+ /*
+ * Channel mapping array expected at the encoder output.
+ * Channel[i] mapping describes channel i inside the buffer, where
+ * 0 @le i < num_channels. All valid used channels must be present at
+ * the beginning of the array.
+ * If Native mode is set for the channels, this field is ignored.
+ * @values See Section @xref{dox:PcmChannelDefs}
+ */
+};
+
/* @brief Multichannel PCM encoder configuration structure used
* in the #ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2 command.
*/
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 2f3e33fd28df..8339d538d578 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -241,6 +241,9 @@ int q6asm_open_read(struct audio_client *ac, uint32_t format
int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
uint16_t bits_per_sample);
+int q6asm_open_read_v3(struct audio_client *ac, uint32_t format,
+ uint16_t bits_per_sample);
+
int q6asm_open_write(struct audio_client *ac, uint32_t format
/*, uint16_t bits_per_sample*/);
@@ -250,9 +253,16 @@ int q6asm_open_write_v2(struct audio_client *ac, uint32_t format,
int q6asm_open_shared_io(struct audio_client *ac,
struct shared_io_config *c, int dir);
+int q6asm_open_write_v3(struct audio_client *ac, uint32_t format,
+ uint16_t bits_per_sample);
+
int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format,
- uint16_t bits_per_sample, int32_t stream_id,
- bool is_gapless_mode);
+ uint16_t bits_per_sample, int32_t stream_id,
+ bool is_gapless_mode);
+
+int q6asm_stream_open_write_v3(struct audio_client *ac, uint32_t format,
+ uint16_t bits_per_sample, int32_t stream_id,
+ bool is_gapless_mode);
int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format,
uint32_t passthrough_flag);
@@ -350,10 +360,21 @@ int q6asm_enc_cfg_blk_pcm_v2(struct audio_client *ac,
bool use_default_chmap, bool use_back_flavor,
u8 *channel_map);
+int q6asm_enc_cfg_blk_pcm_v3(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ uint16_t bits_per_sample, bool use_default_chmap,
+ bool use_back_flavor, u8 *channel_map,
+ uint16_t sample_word_size);
+
int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac,
uint32_t rate, uint32_t channels,
uint16_t bits_per_sample);
+int q6asm_enc_cfg_blk_pcm_format_support_v3(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ uint16_t bits_per_sample,
+ uint16_t sample_word_size);
+
int q6asm_set_encdec_chan_map(struct audio_client *ac,
uint32_t num_channels);
@@ -394,6 +415,15 @@ int q6asm_media_format_block_pcm_format_support_v2(struct audio_client *ac,
uint16_t bits_per_sample, int stream_id,
bool use_default_chmap, char *channel_map);
+int q6asm_media_format_block_pcm_format_support_v3(struct audio_client *ac,
+ uint32_t rate,
+ uint32_t channels,
+ uint16_t bits_per_sample,
+ int stream_id,
+ bool use_default_chmap,
+ char *channel_map,
+ uint16_t sample_word_size);
+
int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
uint32_t rate, uint32_t channels,
bool use_default_chmap, char *channel_map);
@@ -404,6 +434,13 @@ int q6asm_media_format_block_multi_ch_pcm_v2(
bool use_default_chmap, char *channel_map,
uint16_t bits_per_sample);
+int q6asm_media_format_block_multi_ch_pcm_v3(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ bool use_default_chmap,
+ char *channel_map,
+ uint16_t bits_per_sample,
+ uint16_t sample_word_size);
+
int q6asm_media_format_block_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg);
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index 5a0de63e806e..2b3609f7230c 100755
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -677,9 +677,10 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
union snd_codec_options *codec_options;
int ret = 0;
- uint16_t bit_width = 16;
+ uint16_t bit_width;
bool use_default_chmap = true;
char *chmap = NULL;
+ uint16_t sample_word_size;
pr_debug("%s: use_gapless_codec_options %d\n",
__func__, use_gapless_codec_options);
@@ -703,15 +704,26 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
chmap =
pdata->ch_map[rtd->dai_link->be_id]->channel_map;
}
- if (prtd->codec_param.codec.format == SNDRV_PCM_FORMAT_S24_LE)
+
+ switch (prtd->codec_param.codec.format) {
+ case SNDRV_PCM_FORMAT_S24_LE:
bit_width = 24;
- ret = q6asm_media_format_block_pcm_format_support_v2(
+ sample_word_size = 32;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
+ bit_width = 16;
+ sample_word_size = 16;
+ break;
+ }
+ ret = q6asm_media_format_block_pcm_format_support_v3(
prtd->audio_client,
prtd->sample_rate,
prtd->num_channels,
bit_width, stream_id,
use_default_chmap,
- chmap);
+ chmap,
+ sample_word_size);
if (ret < 0)
pr_err("%s: CMD Format block failed\n", __func__);
@@ -977,7 +989,7 @@ static int msm_compr_configure_dsp(struct snd_compr_stream *cstream)
} else {
pr_debug("%s: stream_id %d bits_per_sample %d\n",
__func__, ac->stream_id, bits_per_sample);
- ret = q6asm_stream_open_write_v2(ac,
+ ret = q6asm_stream_open_write_v3(ac,
prtd->codec, bits_per_sample,
ac->stream_id,
prtd->gapless_state.use_dsp_gapless_mode);
@@ -1897,7 +1909,7 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
pr_debug("%s: open_write stream_id %d bits_per_sample %d",
__func__, stream_id, bits_per_sample);
- rc = q6asm_stream_open_write_v2(prtd->audio_client,
+ rc = q6asm_stream_open_write_v3(prtd->audio_client,
prtd->codec, bits_per_sample,
stream_id,
prtd->gapless_state.use_dsp_gapless_mode);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
index 856f2b368d41..6e5b4e871fe6 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
@@ -87,7 +87,8 @@ static struct snd_pcm_hardware msm_pcm_hardware_playback = {
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S24_LE),
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE),
.rates = SNDRV_PCM_RATE_8000_192000,
.rate_min = 8000,
.rate_max = 192000,
@@ -110,7 +111,8 @@ static struct snd_pcm_hardware msm_pcm_hardware_capture = {
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S24_LE),
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE),
.rates = SNDRV_PCM_RATE_8000_48000,
.rate_min = 8000,
.rate_max = 48000,
@@ -253,7 +255,7 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
struct audio_buffer *buf;
struct shared_io_config config;
uint16_t sample_word_size;
- uint16_t bits_per_sample = 16;
+ uint16_t bits_per_sample;
int ret;
int dir = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? IN : OUT;
@@ -280,16 +282,21 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
switch (runtime->format) {
- case SNDRV_PCM_FORMAT_S16_LE:
- bits_per_sample = 16;
- break;
case SNDRV_PCM_FORMAT_S24_LE:
bits_per_sample = 24;
+ sample_word_size = 32;
+ break;
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ bits_per_sample = 24;
+ sample_word_size = 24;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
+ bits_per_sample = 16;
+ sample_word_size = 16;
break;
}
- sample_word_size = (bits_per_sample == 16) ? 16 : 32;
-
config.format = FORMAT_LINEAR_PCM;
config.bits_per_sample = bits_per_sample;
config.rate = params_rate(params);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index c456134b87fa..7dfa5044ab56 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -280,7 +280,8 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
struct msm_plat_data *pdata;
struct snd_pcm_hw_params *params;
int ret;
- uint16_t bits_per_sample = 16;
+ uint16_t bits_per_sample;
+ uint16_t sample_word_size;
pdata = (struct msm_plat_data *)
dev_get_drvdata(soc_prtd->platform->dev);
@@ -308,11 +309,21 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
prtd->audio_client->perf_mode = pdata->perf_mode;
pr_debug("%s: perf: %x\n", __func__, pdata->perf_mode);
- if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE)
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S24_LE:
bits_per_sample = 24;
+ sample_word_size = 32;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
+ bits_per_sample = 16;
+ sample_word_size = 16;
+ break;
+ }
+
+ ret = q6asm_open_write_v3(prtd->audio_client,
+ FORMAT_LINEAR_PCM, bits_per_sample);
- ret = q6asm_open_write_v2(prtd->audio_client,
- FORMAT_LINEAR_PCM, bits_per_sample);
if (ret < 0) {
pr_err("%s: q6asm_open_write_v2 failed\n", __func__);
q6asm_audio_client_free(prtd->audio_client);
@@ -335,19 +346,11 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
return ret;
}
- switch (runtime->format) {
- case SNDRV_PCM_FORMAT_S16_LE:
- bits_per_sample = 16;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- bits_per_sample = 24;
- break;
- }
-
- ret = q6asm_media_format_block_multi_ch_pcm_v2(
- prtd->audio_client, runtime->rate,
- runtime->channels, !prtd->set_channel_map,
- prtd->channel_map, bits_per_sample);
+ ret = q6asm_media_format_block_multi_ch_pcm_v3(
+ prtd->audio_client, runtime->rate,
+ runtime->channels, !prtd->set_channel_map,
+ prtd->channel_map, bits_per_sample,
+ sample_word_size);
if (ret < 0)
pr_info("%s: CMD Format block failed\n", __func__);
@@ -371,6 +374,7 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
int ret = 0;
int i = 0;
uint16_t bits_per_sample = 16;
+ uint16_t sample_word_size;
pdata = (struct msm_plat_data *)
dev_get_drvdata(soc_prtd->platform->dev);
@@ -401,7 +405,7 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
__func__, params_channels(params),
prtd->audio_client->perf_mode);
- ret = q6asm_open_read_v2(prtd->audio_client, FORMAT_LINEAR_PCM,
+ ret = q6asm_open_read_v3(prtd->audio_client, FORMAT_LINEAR_PCM,
bits_per_sample);
if (ret < 0) {
pr_err("%s: q6asm_open_read failed\n", __func__);
@@ -447,18 +451,25 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
return 0;
switch (runtime->format) {
- case SNDRV_PCM_FORMAT_S16_LE:
- bits_per_sample = 16;
- break;
case SNDRV_PCM_FORMAT_S24_LE:
bits_per_sample = 24;
+ sample_word_size = 32;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
+ bits_per_sample = 16;
+ sample_word_size = 16;
break;
}
- pr_debug("Samp_rate = %d\n", prtd->samp_rate);
- pr_debug("Channel = %d\n", prtd->channel_mode);
- ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client,
- prtd->samp_rate, prtd->channel_mode,
- bits_per_sample);
+
+ pr_debug("%s: Samp_rate = %d Channel = %d bit width = %d, word size = %d\n",
+ __func__, prtd->samp_rate, prtd->channel_mode,
+ bits_per_sample, sample_word_size);
+ ret = q6asm_enc_cfg_blk_pcm_format_support_v3(prtd->audio_client,
+ prtd->samp_rate,
+ prtd->channel_mode,
+ bits_per_sample,
+ sample_word_size);
if (ret < 0)
pr_debug("%s: cmd cfg pcm was block failed", __func__);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 761489b1c436..6409b81c0764 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -2226,8 +2226,10 @@ static void q6asm_add_mmaphdr(struct audio_client *ac, struct apr_hdr *hdr,
hdr->pkt_size = pkt_size;
return;
}
+
static int __q6asm_open_read(struct audio_client *ac,
- uint32_t format, uint16_t bits_per_sample)
+ uint32_t format, uint16_t bits_per_sample,
+ bool use_v3_format)
{
int rc = 0x00;
struct asm_stream_cmd_open_read_v3 open;
@@ -2270,7 +2272,10 @@ static int __q6asm_open_read(struct audio_client *ac,
switch (format) {
case FORMAT_LINEAR_PCM:
open.mode_flags |= 0x00;
- open.enc_cfg_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
+ if (use_v3_format)
+ open.enc_cfg_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3;
+ else
+ open.enc_cfg_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
break;
case FORMAT_MPEG4_AAC:
open.mode_flags |= BUFFER_META_ENABLE;
@@ -2332,15 +2337,32 @@ fail_cmd:
int q6asm_open_read(struct audio_client *ac,
uint32_t format)
{
- return __q6asm_open_read(ac, format, 16);
+ return __q6asm_open_read(ac, format, 16,
+ false /*use_v3_format*/);
}
int q6asm_open_read_v2(struct audio_client *ac, uint32_t format,
uint16_t bits_per_sample)
{
- return __q6asm_open_read(ac, format, bits_per_sample);
+ return __q6asm_open_read(ac, format, bits_per_sample,
+ false /*use_v3_format*/);
}
+/*
+ * asm_open_read_v3 - Opens audio capture session
+ *
+ * @ac: Client session handle
+ * @format: encoder format
+ * @bits_per_sample: bit width of capture session
+ */
+int q6asm_open_read_v3(struct audio_client *ac, uint32_t format,
+ uint16_t bits_per_sample)
+{
+ return __q6asm_open_read(ac, format, bits_per_sample,
+ true /*use_v3_format*/);
+}
+EXPORT_SYMBOL(q6asm_open_read_v3);
+
int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format,
uint32_t passthrough_flag)
{
@@ -2427,8 +2449,8 @@ fail_cmd:
}
static int __q6asm_open_write(struct audio_client *ac, uint32_t format,
- uint16_t bits_per_sample, uint32_t stream_id,
- bool is_gapless_mode)
+ uint16_t bits_per_sample, uint32_t stream_id,
+ bool is_gapless_mode, bool use_v3_format)
{
int rc = 0x00;
struct asm_stream_cmd_open_write_v3 open;
@@ -2504,7 +2526,11 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format,
}
switch (format) {
case FORMAT_LINEAR_PCM:
- open.dec_fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
+ if (use_v3_format)
+ open.dec_fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3;
+ else
+ open.dec_fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
+
break;
case FORMAT_MPEG4_AAC:
open.dec_fmt_id = ASM_MEDIA_FMT_AAC_V2;
@@ -2579,23 +2605,61 @@ fail_cmd:
int q6asm_open_write(struct audio_client *ac, uint32_t format)
{
return __q6asm_open_write(ac, format, 16, ac->stream_id,
- false /*gapless*/);
+ false /*gapless*/,
+ false /*use_v3_format*/);
}
int q6asm_open_write_v2(struct audio_client *ac, uint32_t format,
- uint16_t bits_per_sample)
+ uint16_t bits_per_sample)
{
return __q6asm_open_write(ac, format, bits_per_sample,
- ac->stream_id, false /*gapless*/);
+ ac->stream_id, false /*gapless*/,
+ false /*use_v3_format*/);
}
+/*
+ * q6asm_open_write_v3 - Opens audio playback session
+ *
+ * @ac: Client session handle
+ * @format: decoder format
+ * @bits_per_sample: bit width of playback session
+ */
+int q6asm_open_write_v3(struct audio_client *ac, uint32_t format,
+ uint16_t bits_per_sample)
+{
+ return __q6asm_open_write(ac, format, bits_per_sample,
+ ac->stream_id, false /*gapless*/,
+ true /*use_v3_format*/);
+}
+EXPORT_SYMBOL(q6asm_open_write_v3);
+
int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format,
- uint16_t bits_per_sample, int32_t stream_id,
- bool is_gapless_mode)
+ uint16_t bits_per_sample, int32_t stream_id,
+ bool is_gapless_mode)
+{
+ return __q6asm_open_write(ac, format, bits_per_sample,
+ stream_id, is_gapless_mode,
+ false /*use_v3_format*/);
+}
+
+/*
+ * q6asm_stream_open_write_v3 - Creates audio stream for playback
+ *
+ * @ac: Client session handle
+ * @format: asm playback format
+ * @bits_per_sample: bit width of requested stream
+ * @stream_id: stream id of stream to be associated with this session
+ * @is_gapless_mode: true if gapless mode needs to be enabled
+ */
+int q6asm_stream_open_write_v3(struct audio_client *ac, uint32_t format,
+ uint16_t bits_per_sample, int32_t stream_id,
+ bool is_gapless_mode)
{
return __q6asm_open_write(ac, format, bits_per_sample,
- stream_id, is_gapless_mode);
+ stream_id, is_gapless_mode,
+ true /*use_v3_format*/);
}
+EXPORT_SYMBOL(q6asm_stream_open_write_v3);
static int __q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format,
uint32_t wr_format, bool is_meta_data_mode,
@@ -3416,6 +3480,103 @@ fail_cmd:
return rc;
}
+/*
+ * q6asm_enc_cfg_blk_pcm_v3 - sends encoder configuration parameters
+ *
+ * @ac: Client session handle
+ * @rate: sample rate
+ * @channels: number of channels
+ * @bits_per_sample: bit width of encoder session
+ * @use_default_chmap: true if default channel map to be used
+ * @use_back_flavor: to configure back left and right channel
+ * @channel_map: input channel map
+ * @sample_word_size: Size in bits of the word that holds a sample of a channel
+ */
+int q6asm_enc_cfg_blk_pcm_v3(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ uint16_t bits_per_sample, bool use_default_chmap,
+ bool use_back_flavor, u8 *channel_map,
+ uint16_t sample_word_size)
+{
+ struct asm_multi_channel_pcm_enc_cfg_v3 enc_cfg;
+ struct asm_enc_cfg_blk_param_v2 enc_fg_blk;
+ u8 *channel_mapping;
+ u32 frames_per_buf = 0;
+ int rc;
+
+ if (!use_default_chmap && (channel_map == NULL)) {
+ pr_err("%s: No valid chan map and can't use default\n",
+ __func__);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+
+ pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
+ ac->session, rate, channels,
+ bits_per_sample, sample_word_size);
+
+ memset(&enc_cfg, 0, sizeof(enc_cfg));
+ q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE);
+ atomic_set(&ac->cmd_state, -1);
+ enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
+ enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
+ enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) -
+ sizeof(enc_cfg.encdec);
+ enc_cfg.encblk.frames_per_buf = frames_per_buf;
+ enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size -
+ sizeof(enc_fg_blk);
+ enc_cfg.num_channels = channels;
+ enc_cfg.bits_per_sample = bits_per_sample;
+ enc_cfg.sample_rate = rate;
+ enc_cfg.is_signed = 1;
+ enc_cfg.sample_word_size = sample_word_size;
+ channel_mapping = enc_cfg.channel_mapping;
+
+ memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+
+ if (use_default_chmap) {
+ pr_debug("%s: setting default channel map for %d channels",
+ __func__, channels);
+ if (q6asm_map_channels(channel_mapping, channels,
+ use_back_flavor)) {
+ pr_err("%s: map channels failed %d\n",
+ __func__, channels);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ } else {
+ pr_debug("%s: Using pre-defined channel map", __func__);
+ memcpy(channel_mapping, channel_map,
+ PCM_FORMAT_MAX_NUM_CHANNEL);
+ }
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg);
+ if (rc < 0) {
+ pr_err("%s: Comamnd open failed %d\n", __func__, rc);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: timeout opcode[0x%x]\n",
+ __func__, enc_cfg.hdr.opcode);
+ rc = -ETIMEDOUT;
+ goto fail_cmd;
+ }
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s]\n",
+ __func__, adsp_err_get_err_str(
+ atomic_read(&ac->cmd_state)));
+ rc = adsp_err_get_lnx_err_code(
+ atomic_read(&ac->cmd_state));
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return rc;
+}
+EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v3);
+
int q6asm_enc_cfg_blk_pcm_v2(struct audio_client *ac,
uint32_t rate, uint32_t channels, uint16_t bits_per_sample,
bool use_default_chmap, bool use_back_flavor, u8 *channel_map)
@@ -3495,6 +3656,15 @@ fail_cmd:
return rc;
}
+static int __q6asm_enc_cfg_blk_pcm_v3(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ uint16_t bits_per_sample,
+ uint16_t sample_word_size)
+{
+ return q6asm_enc_cfg_blk_pcm_v3(ac, rate, channels,
+ bits_per_sample, true, false, NULL,
+ sample_word_size);
+}
static int __q6asm_enc_cfg_blk_pcm(struct audio_client *ac,
uint32_t rate, uint32_t channels, uint16_t bits_per_sample)
@@ -3515,6 +3685,26 @@ int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac,
return __q6asm_enc_cfg_blk_pcm(ac, rate, channels, bits_per_sample);
}
+/*
+ * q6asm_enc_cfg_blk_pcm_format_support_v3 - sends encoder configuration
+ * parameters
+ *
+ * @ac: Client session handle
+ * @rate: sample rate
+ * @channels: number of channels
+ * @bits_per_sample: bit width of encoder session
+ * @sample_word_size: Size in bits of the word that holds a sample of a channel
+ */
+int q6asm_enc_cfg_blk_pcm_format_support_v3(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ uint16_t bits_per_sample,
+ uint16_t sample_word_size)
+{
+ return __q6asm_enc_cfg_blk_pcm_v3(ac, rate, channels,
+ bits_per_sample, sample_word_size);
+}
+EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v3);
+
int q6asm_enc_cfg_blk_pcm_native(struct audio_client *ac,
uint32_t rate, uint32_t channels)
{
@@ -4066,6 +4256,87 @@ fail_cmd:
return rc;
}
+static int __q6asm_media_format_block_pcm_v3(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ uint16_t bits_per_sample,
+ int stream_id,
+ bool use_default_chmap,
+ char *channel_map,
+ uint16_t sample_word_size)
+{
+ struct asm_multi_channel_pcm_fmt_blk_param_v3 fmt;
+ u8 *channel_mapping;
+ int rc;
+
+ pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
+ ac->session, rate, channels,
+ bits_per_sample, sample_word_size);
+
+ memset(&fmt, 0, sizeof(fmt));
+ q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id);
+ atomic_set(&ac->cmd_state, -1);
+ /*
+ * Updated the token field with stream/session for compressed playback
+ * Platform driver must know the the stream with which the command is
+ * associated
+ */
+ if (ac->io_mode & COMPRESSED_STREAM_IO)
+ fmt.hdr.token = ((ac->session << 8) & 0xFFFF00) |
+ (stream_id & 0xFF);
+
+ pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n",
+ __func__, fmt.hdr.token, stream_id, ac->session);
+
+ fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
+ fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
+ sizeof(fmt.fmt_blk);
+ fmt.param.num_channels = channels;
+ fmt.param.bits_per_sample = bits_per_sample;
+ fmt.param.sample_rate = rate;
+ fmt.param.is_signed = 1;
+ fmt.param.sample_word_size = sample_word_size;
+ channel_mapping = fmt.param.channel_mapping;
+
+ memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+
+ if (use_default_chmap) {
+ if (q6asm_map_channels(channel_mapping, channels, false)) {
+ pr_err("%s: map channels failed %d\n",
+ __func__, channels);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ } else {
+ memcpy(channel_mapping, channel_map,
+ PCM_FORMAT_MAX_NUM_CHANNEL);
+ }
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+ if (rc < 0) {
+ pr_err("%s: Comamnd open failed %d\n", __func__, rc);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: timeout. waited for format update\n", __func__);
+ rc = -ETIMEDOUT;
+ goto fail_cmd;
+ }
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s]\n",
+ __func__, adsp_err_get_err_str(
+ atomic_read(&ac->cmd_state)));
+ rc = adsp_err_get_lnx_err_code(
+ atomic_read(&ac->cmd_state));
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return rc;
+}
+
int q6asm_media_format_block_pcm(struct audio_client *ac,
uint32_t rate, uint32_t channels)
{
@@ -4098,6 +4369,41 @@ int q6asm_media_format_block_pcm_format_support_v2(struct audio_client *ac,
use_default_chmap, channel_map);
}
+/*
+ * q6asm_media_format_block_pcm_format_support_v3- sends pcm decoder
+ * configuration parameters
+ *
+ * @ac: Client session handle
+ * @rate: sample rate
+ * @channels: number of channels
+ * @bits_per_sample: bit width of encoder session
+ * @stream_id: stream id of stream to be associated with this session
+ * @use_default_chmap: true if default channel map to be used
+ * @channel_map: input channel map
+ * @sample_word_size: Size in bits of the word that holds a sample of a channel
+ */
+int q6asm_media_format_block_pcm_format_support_v3(struct audio_client *ac,
+ uint32_t rate,
+ uint32_t channels,
+ uint16_t bits_per_sample,
+ int stream_id,
+ bool use_default_chmap,
+ char *channel_map,
+ uint16_t sample_word_size)
+{
+ if (!use_default_chmap && (channel_map == NULL)) {
+ pr_err("%s: No valid chan map and can't use default\n",
+ __func__);
+ return -EINVAL;
+ }
+ return __q6asm_media_format_block_pcm_v3(ac, rate,
+ channels, bits_per_sample, stream_id,
+ use_default_chmap, channel_map,
+ sample_word_size);
+
+}
+EXPORT_SYMBOL(q6asm_media_format_block_pcm_format_support_v3);
+
static int __q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
uint32_t rate, uint32_t channels,
bool use_default_chmap, char *channel_map,
@@ -4162,6 +4468,76 @@ fail_cmd:
return rc;
}
+static int __q6asm_media_format_block_multi_ch_pcm_v3(struct audio_client *ac,
+ uint32_t rate,
+ uint32_t channels,
+ bool use_default_chmap,
+ char *channel_map,
+ uint16_t bits_per_sample,
+ uint16_t sample_word_size)
+{
+ struct asm_multi_channel_pcm_fmt_blk_param_v3 fmt;
+ u8 *channel_mapping;
+ int rc;
+
+ pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__,
+ ac->session, rate, channels,
+ bits_per_sample, sample_word_size);
+
+ memset(&fmt, 0, sizeof(fmt));
+ q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
+ atomic_set(&ac->cmd_state, -1);
+
+ fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
+ fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
+ sizeof(fmt.fmt_blk);
+ fmt.param.num_channels = channels;
+ fmt.param.bits_per_sample = bits_per_sample;
+ fmt.param.sample_rate = rate;
+ fmt.param.is_signed = 1;
+ fmt.param.sample_word_size = sample_word_size;
+ channel_mapping = fmt.param.channel_mapping;
+
+ memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+
+ if (use_default_chmap) {
+ if (q6asm_map_channels(channel_mapping, channels, false)) {
+ pr_err("%s: map channels failed %d\n",
+ __func__, channels);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ } else {
+ memcpy(channel_mapping, channel_map,
+ PCM_FORMAT_MAX_NUM_CHANNEL);
+ }
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+ if (rc < 0) {
+ pr_err("%s: Comamnd open failed %d\n", __func__, rc);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: timeout. waited for format update\n", __func__);
+ rc = -ETIMEDOUT;
+ goto fail_cmd;
+ }
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s]\n",
+ __func__, adsp_err_get_err_str(
+ atomic_read(&ac->cmd_state)));
+ rc = adsp_err_get_lnx_err_code(
+ atomic_read(&ac->cmd_state));
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return rc;
+}
+
+
int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
uint32_t rate, uint32_t channels,
bool use_default_chmap, char *channel_map)
@@ -4181,6 +4557,33 @@ int q6asm_media_format_block_multi_ch_pcm_v2(
bits_per_sample);
}
+/*
+ * q6asm_media_format_block_multi_ch_pcm_v3 - sends pcm decoder configuration
+ * parameters
+ *
+ * @ac: Client session handle
+ * @rate: sample rate
+ * @channels: number of channels
+ * @bits_per_sample: bit width of encoder session
+ * @use_default_chmap: true if default channel map to be used
+ * @channel_map: input channel map
+ * @sample_word_size: Size in bits of the word that holds a sample of a channel
+ */
+int q6asm_media_format_block_multi_ch_pcm_v3(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ bool use_default_chmap,
+ char *channel_map,
+ uint16_t bits_per_sample,
+ uint16_t sample_word_size)
+{
+ return __q6asm_media_format_block_multi_ch_pcm_v3(ac, rate, channels,
+ use_default_chmap,
+ channel_map,
+ bits_per_sample,
+ sample_word_size);
+}
+EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v3);
+
static int __q6asm_media_format_block_multi_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg, int stream_id)
{