ASoC: msm: qdsp6v2: Add TDM support for PCM compressed mode

Add support for 352800 sampling rates and 32 bps for the TDM.
Add support for PCM compress passthough mode with mixer controls.

CRs-fixed: 1116515
Change-Id: Iab059a5a6b6ce8f57717023467677a399a60032e
Signed-off-by: Josh Kirsch <jkirsch@codeaurora.org>
Signed-off-by: Karthikeyan Mani <kmani@codeaurora.org>
This commit is contained in:
Josh Kirsch 2017-01-04 17:59:30 -08:00 committed by Karthikeyan Mani
parent 3a7e752617
commit d6cacdfe65
9 changed files with 754 additions and 247 deletions

View file

@ -1818,11 +1818,14 @@ struct afe_port_data_cmd_rt_proxy_port_read_v2 {
#define AFE_PORT_SAMPLE_RATE_16K 16000
#define AFE_PORT_SAMPLE_RATE_48K 48000
#define AFE_PORT_SAMPLE_RATE_96K 96000
#define AFE_PORT_SAMPLE_RATE_176P4K 176400
#define AFE_PORT_SAMPLE_RATE_192K 192000
#define AFE_PORT_SAMPLE_RATE_352P8K 352800
#define AFE_LINEAR_PCM_DATA 0x0
#define AFE_NON_LINEAR_DATA 0x1
#define AFE_LINEAR_PCM_DATA_PACKED_60958 0x2
#define AFE_NON_LINEAR_DATA_PACKED_60958 0x3
#define AFE_GENERIC_COMPRESSED 0x8
/* This param id is used to configure I2S interface */
#define AFE_PARAM_ID_I2S_CONFIG 0x0001020D
@ -2755,25 +2758,31 @@ struct afe_param_id_tdm_cfg {
- #AFE_PORT_SAMPLE_RATE_16K
- #AFE_PORT_SAMPLE_RATE_24K
- #AFE_PORT_SAMPLE_RATE_32K
- #AFE_PORT_SAMPLE_RATE_48K @tablebulletend */
- #AFE_PORT_SAMPLE_RATE_48K
- #AFE_PORT_SAMPLE_RATE_176P4K
- #AFE_PORT_SAMPLE_RATE_352P8K @tablebulletend
*/
u32 bit_width;
/**< Bit width of the sample.
@values 16, 24 */
* @values 16, 24, 32
*/
u16 data_format;
/**< Data format: linear and compressed
/**< Data format: linear ,compressed, generic compresssed
@values
- #AFE_LINEAR_PCM_DATA
- #AFE_NON_LINEAR_DATA @tablebulletend */
- #AFE_NON_LINEAR_DATA
- #AFE_GENERIC_COMPRESSED
*/
u16 sync_mode;
/**< TDM synchronization setting.
@values (short, long, slot) sync mode
- #AFE_PORT_TDM_SHORT_SYNC_BIT_MODE
- #AFE_PORT_TDM_LONG_SYNC_MODE
- #AFE_PORT_TDM_SHORT_SYNC_SLOT_MODE @tablebulletend */
- #AFE_PORT_TDM_SHORT_SYNC_SLOT_MODE @tablebulletend
*/
u16 sync_src;
/**< Synchronization source.
@ -3629,7 +3638,7 @@ struct afe_lpass_core_shared_clk_config_command {
#define DEFAULT_COPP_TOPOLOGY 0x00010314
#define DEFAULT_POPP_TOPOLOGY 0x00010BE4
#define COMPRESSED_PASSTHROUGH_DEFAULT_TOPOLOGY 0x0001076B
#define COMPRESS_PASSTHROUGH_NONE_TOPOLOGY 0x00010774
#define COMPRESSED_PASSTHROUGH_NONE_TOPOLOGY 0x00010774
#define VPM_TX_SM_ECNS_COPP_TOPOLOGY 0x00010F71
#define VPM_TX_DM_FLUENCE_COPP_TOPOLOGY 0x00010F72
#define VPM_TX_QMIC_FLUENCE_COPP_TOPOLOGY 0x00010F75
@ -3935,6 +3944,8 @@ struct asm_softvolume_params {
#define ASM_MEDIA_FMT_EVRCWB_FS 0x00010BF0
#define ASM_MEDIA_FMT_GENERIC_COMPRESSED 0x00013212
#define ASM_MAX_EQ_BANDS 12
#define ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2 0x00010D98
@ -3944,6 +3955,40 @@ u32 fmt_blk_size;
/* Media format block size in bytes.*/
} __packed;
struct asm_generic_compressed_fmt_blk_t {
struct apr_hdr hdr;
struct asm_data_cmd_media_fmt_update_v2 fmt_blk;
/*
* Channel mapping array of bitstream output.
* Channel[i] mapping describes channel i inside the buffer, where
* i < num_channels. All valid used channels must be
* present at the beginning of the array.
*/
uint8_t channel_mapping[8];
/*
* Number of channels of the incoming bitstream.
* Supported values: 1,2,3,4,5,6,7,8
*/
uint16_t num_channels;
/*
* Nominal bits per sample value of the incoming bitstream.
* Supported values: 16, 32
*/
uint16_t bits_per_sample;
/*
* Nominal sampling rate of the incoming bitstream.
* Supported values: 8000, 11025, 16000, 22050, 24000, 32000,
* 44100, 48000, 88200, 96000, 176400, 192000,
* 352800, 384000
*/
uint32_t sampling_rate;
} __packed;
struct asm_multi_channel_pcm_fmt_blk_v2 {
struct apr_hdr hdr;
struct asm_data_cmd_media_fmt_update_v2 fmt_blk;
@ -10203,6 +10248,7 @@ enum {
COMPRESSED_PASSTHROUGH_CONVERT,
COMPRESSED_PASSTHROUGH_DSD,
LISTEN,
COMPRESSED_PASSTHROUGH_GEN,
};
#define AUDPROC_MODULE_ID_COMPRESSED_MUTE 0x00010770

View file

@ -364,6 +364,6 @@ int afe_send_custom_tdm_header_cfg(
struct afe_param_id_custom_tdm_header_cfg *custom_tdm_header_cfg,
u16 port_id);
int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port,
u32 rate);
u32 rate, u16 num_groups);
void afe_set_routing_callback(routing_cb);
#endif /* __Q6AFE_V2_H__ */

View file

@ -54,6 +54,7 @@
#define FORMAT_DTS 0x001c
#define FORMAT_DSD 0x001d
#define FORMAT_APTX 0x001e
#define FORMAT_GEN_COMPR 0x001f
#define ENCDEC_SBCBITRATE 0x0001
#define ENCDEC_IMMEDIATE_DECODE 0x0002
@ -500,6 +501,11 @@ int q6asm_media_format_block_multi_ch_pcm_v2(
uint32_t rate, uint32_t channels,
bool use_default_chmap, char *channel_map,
uint16_t bits_per_sample);
int q6asm_media_format_block_gen_compr(
struct audio_client *ac,
uint32_t rate, uint32_t channels,
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,

File diff suppressed because it is too large Load diff

View file

@ -110,7 +110,7 @@ static struct snd_pcm_hardware msm_pcm_hardware_playback = {
/* Conventional and unconventional sample rate supported */
static unsigned int supported_sample_rates[] = {
8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
88200, 96000, 176400, 192000, 384000
88200, 96000, 176400, 192000, 352800, 384000
};
static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
@ -285,6 +285,7 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
struct msm_plat_data *pdata;
struct snd_pcm_hw_params *params;
int ret;
uint32_t fmt_type = FORMAT_LINEAR_PCM;
uint16_t bits_per_sample;
uint16_t sample_word_size;
@ -333,38 +334,67 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
sample_word_size = 16;
break;
}
if (prtd->compress_enable) {
fmt_type = FORMAT_GEN_COMPR;
pr_debug("%s: Compressed enabled!\n", __func__);
ret = q6asm_open_write_compressed(prtd->audio_client, fmt_type,
COMPRESSED_PASSTHROUGH_GEN);
if (ret < 0) {
pr_err("%s: q6asm_open_write_compressed failed (%d)\n",
__func__, ret);
q6asm_audio_client_free(prtd->audio_client);
prtd->audio_client = NULL;
return -ENOMEM;
}
} else {
ret = q6asm_open_write_v4(prtd->audio_client,
fmt_type, bits_per_sample);
ret = q6asm_open_write_v4(prtd->audio_client,
FORMAT_LINEAR_PCM, bits_per_sample);
if (ret < 0) {
pr_err("%s: q6asm_open_write_v4 failed (%d)\n",
__func__, ret);
q6asm_audio_client_free(prtd->audio_client);
prtd->audio_client = NULL;
return -ENOMEM;
}
if (ret < 0) {
pr_err("%s: q6asm_open_write_v2 failed\n", __func__);
q6asm_audio_client_free(prtd->audio_client);
prtd->audio_client = NULL;
return -ENOMEM;
ret = q6asm_send_cal(prtd->audio_client);
if (ret < 0)
pr_debug("%s : Send cal failed : %d", __func__, ret);
}
ret = q6asm_send_cal(prtd->audio_client);
if (ret < 0)
pr_debug("%s : Send cal failed : %d", __func__, ret);
pr_debug("%s: session ID %d\n", __func__,
prtd->audio_client->session);
prtd->session_id = prtd->audio_client->session;
ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
if (prtd->compress_enable) {
ret = msm_pcm_routing_reg_phy_compr_stream(
soc_prtd->dai_link->be_id,
prtd->audio_client->perf_mode,
prtd->session_id,
SNDRV_PCM_STREAM_PLAYBACK,
COMPRESSED_PASSTHROUGH_GEN);
} else {
ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
prtd->audio_client->perf_mode,
prtd->session_id, substream->stream);
}
if (ret) {
pr_err("%s: stream reg failed ret:%d\n", __func__, ret);
return ret;
}
ret = q6asm_media_format_block_multi_ch_pcm_v4(
if (prtd->compress_enable) {
ret = q6asm_media_format_block_gen_compr(
prtd->audio_client, runtime->rate,
runtime->channels, !prtd->set_channel_map,
prtd->channel_map, bits_per_sample);
} else {
ret = q6asm_media_format_block_multi_ch_pcm_v4(
prtd->audio_client, runtime->rate,
runtime->channels, !prtd->set_channel_map,
prtd->channel_map, bits_per_sample,
sample_word_size, ASM_LITTLE_ENDIAN,
DEFAULT_QF);
}
if (ret < 0)
pr_info("%s: CMD Format block failed\n", __func__);
@ -1091,6 +1121,136 @@ static int msm_pcm_add_volume_control(struct snd_soc_pcm_runtime *rtd)
return 0;
}
static int msm_pcm_compress_ctl_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 0x2000;
return 0;
}
static int msm_pcm_compress_ctl_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
struct snd_soc_platform *platform = snd_soc_component_to_platform(comp);
struct msm_plat_data *pdata = dev_get_drvdata(platform->dev);
struct snd_pcm_substream *substream;
struct msm_audio *prtd;
if (!pdata) {
pr_err("%s pdata is NULL\n", __func__);
return -ENODEV;
}
substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
if (!substream) {
pr_err("%s substream not found\n", __func__);
return -EINVAL;
}
if (!substream->runtime) {
pr_err("%s substream runtime not found\n", __func__);
return 0;
}
prtd = substream->runtime->private_data;
if (prtd)
ucontrol->value.integer.value[0] = prtd->compress_enable;
return 0;
}
static int msm_pcm_compress_ctl_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int rc = 0;
struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
struct snd_soc_platform *platform = snd_soc_component_to_platform(comp);
struct msm_plat_data *pdata = dev_get_drvdata(platform->dev);
struct snd_pcm_substream *substream;
struct msm_audio *prtd;
int compress = ucontrol->value.integer.value[0];
if (!pdata) {
pr_err("%s pdata is NULL\n", __func__);
return -ENODEV;
}
substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
pr_debug("%s: compress : 0x%x\n", __func__, compress);
if (!substream) {
pr_err("%s substream not found\n", __func__);
return -EINVAL;
}
if (!substream->runtime) {
pr_err("%s substream runtime not found\n", __func__);
return 0;
}
prtd = substream->runtime->private_data;
if (prtd) {
pr_debug("%s: setting compress flag to 0x%x\n",
__func__, compress);
prtd->compress_enable = compress;
}
return rc;
}
static int msm_pcm_add_compress_control(struct snd_soc_pcm_runtime *rtd)
{
const char *mixer_ctl_name = "Playback ";
const char *mixer_ctl_end_name = " Compress";
const char *deviceNo = "NN";
char *mixer_str = NULL;
int ctl_len;
int ret = 0;
struct msm_plat_data *pdata;
struct snd_kcontrol_new pcm_compress_control[1] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "?",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.info = msm_pcm_compress_ctl_info,
.get = msm_pcm_compress_ctl_get,
.put = msm_pcm_compress_ctl_put,
.private_value = 0,
}
};
if (!rtd) {
pr_err("%s: NULL rtd\n", __func__);
return -EINVAL;
}
ctl_len = strlen(mixer_ctl_name) + strlen(deviceNo) +
strlen(mixer_ctl_end_name) + 1;
mixer_str = kzalloc(ctl_len, GFP_KERNEL);
if (!mixer_str)
return -ENOMEM;
snprintf(mixer_str, ctl_len, "%s%d%s", mixer_ctl_name,
rtd->pcm->device, mixer_ctl_end_name);
pcm_compress_control[0].name = mixer_str;
pcm_compress_control[0].private_value = rtd->dai_link->be_id;
pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
pdata = dev_get_drvdata(rtd->platform->dev);
if (pdata) {
if (!pdata->pcm) {
pdata->pcm = rtd->pcm;
snd_soc_add_platform_controls(rtd->platform,
pcm_compress_control,
ARRAY_SIZE
(pcm_compress_control));
pr_debug("%s: add control success plt = %pK\n",
__func__, rtd->platform);
}
} else {
pr_err("%s: NULL pdata\n", __func__);
ret = -EINVAL;
}
kfree(mixer_str);
return ret;
}
static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@ -1381,6 +1541,11 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
pr_err("%s: Could not add pcm Volume Control %d\n",
__func__, ret);
ret = msm_pcm_add_compress_control(rtd);
if (ret)
pr_err("%s: Could not add pcm Compress Control %d\n",
__func__, ret);
return ret;
}

View file

@ -1,7 +1,7 @@
/*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
* Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@ -109,6 +109,7 @@ struct msm_audio {
int cmd_interrupt;
bool meta_data_mode;
uint32_t volume;
bool compress_enable;
/* array of frame info */
struct msm_audio_in_frame_info in_frame_info[CAPTURE_MAX_NUM_PERIODS];
};
@ -123,6 +124,7 @@ struct output_meta_data_st {
struct msm_plat_data {
int perf_mode;
struct snd_pcm *pcm;
};
#endif /*_MSM_PCM_H*/

View file

@ -1143,8 +1143,10 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode,
topology = msm_routing_get_adm_topology(fe_id,
session_type,
i);
if (passthr_mode == COMPRESSED_PASSTHROUGH_DSD)
topology = COMPRESS_PASSTHROUGH_NONE_TOPOLOGY;
if ((passthr_mode == COMPRESSED_PASSTHROUGH_DSD)
|| (passthr_mode ==
COMPRESSED_PASSTHROUGH_GEN))
topology = COMPRESSED_PASSTHROUGH_NONE_TOPOLOGY;
pr_debug("%s: Before adm open topology %d\n", __func__,
topology);
@ -1194,7 +1196,9 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode,
num_copps++;
}
}
if (passthr_mode != COMPRESSED_PASSTHROUGH_DSD) {
if (passthr_mode != COMPRESSED_PASSTHROUGH_DSD
&& passthr_mode !=
COMPRESSED_PASSTHROUGH_GEN) {
msm_routing_send_device_pp_params(
msm_bedais[i].port_id,
copp_idx);
@ -12175,6 +12179,42 @@ static const struct snd_soc_dapm_route intercon[] = {
{"QUAT_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"},
{"QUAT_TDM_RX_0", NULL, "QUAT_TDM_RX_0 Audio Mixer"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia1", "MM_DL1"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia2", "MM_DL2"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia3", "MM_DL3"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia4", "MM_DL4"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia5", "MM_DL5"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia6", "MM_DL6"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia7", "MM_DL7"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia8", "MM_DL8"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia9", "MM_DL9"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia10", "MM_DL10"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia11", "MM_DL11"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia12", "MM_DL12"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia13", "MM_DL13"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia14", "MM_DL14"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia15", "MM_DL15"},
{"PRI_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"},
{"PRI_TDM_RX_0", NULL, "PRI_TDM_RX_0 Audio Mixer"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia1", "MM_DL1"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia2", "MM_DL2"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia3", "MM_DL3"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia4", "MM_DL4"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia5", "MM_DL5"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia6", "MM_DL6"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia7", "MM_DL7"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia8", "MM_DL8"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia9", "MM_DL9"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia10", "MM_DL10"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia11", "MM_DL11"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia12", "MM_DL12"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia13", "MM_DL13"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia14", "MM_DL14"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia15", "MM_DL15"},
{"SEC_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"},
{"SEC_TDM_RX_0", NULL, "SEC_TDM_RX_0 Audio Mixer"},
{"QUAT_TDM_TX_0 Audio Mixer", "MultiMedia1", "MM_DL1"},
{"QUAT_TDM_TX_0 Audio Mixer", "MultiMedia2", "MM_DL2"},
{"QUAT_TDM_TX_0 Audio Mixer", "MultiMedia3", "MM_DL3"},

View file

@ -2541,7 +2541,7 @@ fail_cmd:
}
int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port,
u32 rate)
u32 rate, u16 num_groups)
{
struct afe_audioif_config_command config;
int ret = 0;
@ -2581,9 +2581,10 @@ int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port,
this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
}
/* Also send the topology id here: */
/* Also send the topology id here if multiple ports: */
port_index = afe_get_port_index(port_id);
if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE) &&
num_groups > 1) {
/* One time call: only for first time */
afe_send_custom_topology();
afe_send_port_topology_id(port_id);
@ -2645,11 +2646,14 @@ int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port,
ret = -EINVAL;
goto fail_cmd;
}
ret = afe_send_slot_mapping_cfg(&tdm_port->slot_mapping, port_id);
if (ret < 0) {
pr_err("%s: afe send failed %d\n", __func__, ret);
goto fail_cmd;
/* slot mapping is not need if there is only one group */
if (num_groups > 1) {
ret = afe_send_slot_mapping_cfg(&tdm_port->slot_mapping,
port_id);
if (ret < 0) {
pr_err("%s: afe send failed %d\n", __func__, ret);
goto fail_cmd;
}
}
if (tdm_port->custom_tdm_header.header_type) {

View file

@ -2490,6 +2490,10 @@ int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format,
case FORMAT_DSD:
open.fmt_id = ASM_MEDIA_FMT_DSD;
break;
case FORMAT_GEN_COMPR:
open.fmt_id = ASM_MEDIA_FMT_GENERIC_COMPRESSED;
break;
default:
pr_err("%s: Invalid format[%d]\n", __func__, format);
rc = -EINVAL;
@ -2498,7 +2502,8 @@ int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format,
/*Below flag indicates the DSP that Compressed audio input
stream is not IEC 61937 or IEC 60958 packetizied*/
if (passthrough_flag == COMPRESSED_PASSTHROUGH ||
passthrough_flag == COMPRESSED_PASSTHROUGH_DSD) {
passthrough_flag == COMPRESSED_PASSTHROUGH_DSD ||
passthrough_flag == COMPRESSED_PASSTHROUGH_GEN) {
open.flags = 0x0;
pr_debug("%s: Flag 0 COMPRESSED_PASSTHROUGH\n", __func__);
} else if (passthrough_flag == COMPRESSED_PASSTHROUGH_CONVERT) {
@ -2665,6 +2670,9 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format,
case FORMAT_APTX:
open.dec_fmt_id = ASM_MEDIA_FMT_APTX;
break;
case FORMAT_GEN_COMPR:
open.dec_fmt_id = ASM_MEDIA_FMT_GENERIC_COMPRESSED;
break;
default:
pr_err("%s: Invalid format 0x%x\n", __func__, format);
rc = -EINVAL;
@ -5191,6 +5199,82 @@ int q6asm_media_format_block_multi_ch_pcm_v4(struct audio_client *ac,
}
EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v4);
/*
* q6asm_media_format_block_gen_compr - set up generic compress format params
*
* @ac: Client session handle
* @rate: sample rate
* @channels: number of channels
* @use_default_chmap: true if default channel map to be used
* @channel_map: input channel map
* @bits_per_sample: bit width of gen compress stream
*/
int q6asm_media_format_block_gen_compr(struct audio_client *ac,
uint32_t rate, uint32_t channels,
bool use_default_chmap, char *channel_map,
uint16_t bits_per_sample)
{
struct asm_generic_compressed_fmt_blk_t fmt;
u8 *channel_mapping;
int rc = 0;
pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]\n",
__func__, ac->session, rate,
channels, bits_per_sample);
memset(&fmt, 0, sizeof(fmt));
q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
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.num_channels = channels;
fmt.bits_per_sample = bits_per_sample;
fmt.sampling_rate = rate;
channel_mapping = fmt.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);
return -EINVAL;
}
} else {
memcpy(channel_mapping, channel_map,
PCM_FORMAT_MAX_NUM_CHANNEL);
}
atomic_set(&ac->cmd_state, -1);
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));
}
return 0;
fail_cmd:
return rc;
}
EXPORT_SYMBOL(q6asm_media_format_block_gen_compr);
static int __q6asm_media_format_block_multi_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg, int stream_id)
{