Merge "asoc: msm: update asm channel map for push pull mode"
This commit is contained in:
commit
ed06521452
4 changed files with 149 additions and 80 deletions
|
@ -275,6 +275,8 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
int dir = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? IN : OUT;
|
||||
unsigned long topology;
|
||||
int perf_mode;
|
||||
bool use_default_chmap = true;
|
||||
char *chmap = NULL;
|
||||
|
||||
pdata = (struct msm_plat_data *)
|
||||
dev_get_drvdata(soc_prtd->platform->dev);
|
||||
|
@ -311,6 +313,13 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
if (prtd->enabled)
|
||||
return 0;
|
||||
|
||||
if (pdata->ch_map[soc_prtd->dai_link->id]) {
|
||||
use_default_chmap =
|
||||
!(pdata->ch_map[soc_prtd->dai_link->id]->set_ch_map);
|
||||
chmap =
|
||||
pdata->ch_map[soc_prtd->dai_link->id]->channel_map;
|
||||
}
|
||||
|
||||
switch (runtime->format) {
|
||||
case SNDRV_PCM_FORMAT_S24_LE:
|
||||
bits_per_sample = 24;
|
||||
|
@ -335,7 +344,8 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
config.bufsz = params_buffer_bytes(params) / params_periods(params);
|
||||
config.bufcnt = params_periods(params);
|
||||
|
||||
ret = q6asm_open_shared_io(prtd->audio_client, &config, dir);
|
||||
ret = q6asm_open_shared_io(prtd->audio_client, &config, dir,
|
||||
use_default_chmap, chmap);
|
||||
if (ret) {
|
||||
pr_err("%s: q6asm_open_write_shared_io failed ret: %d\n",
|
||||
__func__, ret);
|
||||
|
@ -718,89 +728,126 @@ static int msm_pcm_add_volume_control(struct snd_soc_pcm_runtime *rtd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
static int msm_pcm_channel_map_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int i;
|
||||
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
||||
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
|
||||
struct snd_pcm_substream *substream;
|
||||
struct msm_audio *prtd;
|
||||
struct snd_soc_component *pcm = snd_kcontrol_chip(kcontrol);
|
||||
u64 fe_id = kcontrol->private_value;
|
||||
struct msm_plat_data *pdata = (struct msm_plat_data *)
|
||||
snd_soc_component_get_drvdata(pcm);
|
||||
int rc = 0, i = 0;
|
||||
|
||||
pr_debug("%s", __func__);
|
||||
substream = snd_pcm_chmap_substream(info, idx);
|
||||
if (!substream)
|
||||
return -ENODEV;
|
||||
if (!substream->runtime)
|
||||
return 0;
|
||||
pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
|
||||
|
||||
prtd = substream->runtime->private_data;
|
||||
if (prtd) {
|
||||
prtd->set_channel_map = true;
|
||||
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
|
||||
prtd->channel_map[i] =
|
||||
(char)(ucontrol->value.integer.value[i]);
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MAX) {
|
||||
pr_err("%s Received out of bounds fe_id %llu\n",
|
||||
__func__, fe_id);
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (pdata->ch_map[fe_id]) {
|
||||
pdata->ch_map[fe_id]->set_ch_map = true;
|
||||
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
|
||||
pdata->ch_map[fe_id]->channel_map[i] =
|
||||
(char)(ucontrol->value.integer.value[i]);
|
||||
} else {
|
||||
pr_debug("%s: no memory for ch_map, default will be set\n",
|
||||
__func__);
|
||||
}
|
||||
end:
|
||||
pr_debug("%s: ret %d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_pcm_channel_map_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->count = 8;
|
||||
uinfo->value.integer.min = 0;
|
||||
uinfo->value.integer.max = 0xFFFFFFFF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
static int msm_pcm_channel_map_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int i;
|
||||
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
||||
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
|
||||
struct snd_pcm_substream *substream;
|
||||
struct msm_audio *prtd;
|
||||
struct snd_soc_component *pcm = snd_kcontrol_chip(kcontrol);
|
||||
u64 fe_id = kcontrol->private_value;
|
||||
struct msm_plat_data *pdata = (struct msm_plat_data *)
|
||||
snd_soc_component_get_drvdata(pcm);
|
||||
int rc = 0, i = 0;
|
||||
|
||||
pr_debug("%s", __func__);
|
||||
substream = snd_pcm_chmap_substream(info, idx);
|
||||
if (!substream)
|
||||
return -ENODEV;
|
||||
memset(ucontrol->value.integer.value, 0,
|
||||
sizeof(ucontrol->value.integer.value));
|
||||
if (!substream->runtime)
|
||||
return 0; /* no channels set */
|
||||
|
||||
prtd = substream->runtime->private_data;
|
||||
|
||||
if (prtd && prtd->set_channel_map == true) {
|
||||
pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
|
||||
if (fe_id >= MSM_FRONTEND_DAI_MAX) {
|
||||
pr_err("%s: Received out of bounds fe_id %llu\n",
|
||||
__func__, fe_id);
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
if (pdata->ch_map[fe_id]) {
|
||||
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
|
||||
ucontrol->value.integer.value[i] =
|
||||
(int)prtd->channel_map[i];
|
||||
} else {
|
||||
for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
|
||||
ucontrol->value.integer.value[i] = 0;
|
||||
pdata->ch_map[fe_id]->channel_map[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
end:
|
||||
pr_debug("%s: ret %d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_pcm_add_chmap_control(struct snd_soc_pcm_runtime *rtd)
|
||||
static int msm_pcm_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_pcm *pcm = rtd->pcm;
|
||||
struct snd_pcm_chmap *chmap_info;
|
||||
struct snd_kcontrol *kctl;
|
||||
char device_num[12];
|
||||
int i, ret;
|
||||
const char *mixer_ctl_name = "Playback Channel Map";
|
||||
const char *deviceNo = "NN";
|
||||
char *mixer_str = NULL;
|
||||
struct msm_plat_data *pdata = NULL;
|
||||
int ctl_len = 0;
|
||||
struct snd_kcontrol_new fe_channel_map_control[1] = {
|
||||
{
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.name = "?",
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||
.info = msm_pcm_channel_map_info,
|
||||
.get = msm_pcm_channel_map_get,
|
||||
.put = msm_pcm_channel_map_put,
|
||||
.private_value = 0,
|
||||
}
|
||||
};
|
||||
|
||||
pr_debug("%s, Channel map cntrl add\n", __func__);
|
||||
ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
|
||||
snd_pcm_std_chmaps,
|
||||
PCM_FORMAT_MAX_NUM_CHANNEL, 0,
|
||||
&chmap_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!rtd) {
|
||||
pr_err("%s: NULL rtd\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
kctl = chmap_info->kctl;
|
||||
for (i = 0; i < kctl->count; i++)
|
||||
kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
|
||||
snprintf(device_num, sizeof(device_num), "%d", pcm->device);
|
||||
strlcat(kctl->id.name, device_num, sizeof(kctl->id.name));
|
||||
pr_debug("%s, Overwriting channel map control name to: %s",
|
||||
__func__, kctl->id.name);
|
||||
kctl->put = msm_pcm_chmap_ctl_put;
|
||||
kctl->get = msm_pcm_chmap_ctl_get;
|
||||
pr_debug("%s: added new pcm FE with name %s, id %d, cpu dai %s, device no %d\n",
|
||||
__func__, rtd->dai_link->name, rtd->dai_link->id,
|
||||
rtd->dai_link->cpu_dai_name, rtd->pcm->device);
|
||||
|
||||
ctl_len = strlen(mixer_ctl_name) + strlen(deviceNo) + 1;
|
||||
mixer_str = kzalloc(ctl_len, GFP_KERNEL);
|
||||
if (!mixer_str)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(mixer_str, ctl_len, "%s%d", mixer_ctl_name, rtd->pcm->device);
|
||||
|
||||
fe_channel_map_control[0].name = mixer_str;
|
||||
fe_channel_map_control[0].private_value = rtd->dai_link->id;
|
||||
pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
|
||||
snd_soc_add_platform_controls(rtd->platform,
|
||||
fe_channel_map_control,
|
||||
ARRAY_SIZE(fe_channel_map_control));
|
||||
|
||||
pdata = snd_soc_platform_get_drvdata(rtd->platform);
|
||||
pdata->ch_map[rtd->dai_link->id] =
|
||||
kzalloc(sizeof(struct msm_pcm_ch_map), GFP_KERNEL);
|
||||
if (!pdata->ch_map[rtd->dai_link->id]) {
|
||||
pr_err("%s: Could not allocate memory for channel map\n",
|
||||
__func__);
|
||||
kfree(mixer_str);
|
||||
return -ENOMEM;
|
||||
}
|
||||
kfree(mixer_str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1155,11 +1202,11 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
|
|||
if (!card->dev->coherent_dma_mask)
|
||||
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
|
||||
ret = msm_pcm_add_chmap_control(rtd);
|
||||
if (ret) {
|
||||
pr_err("%s failed to add chmap cntls\n", __func__);
|
||||
goto exit;
|
||||
}
|
||||
ret = msm_pcm_add_channel_map_control(rtd);
|
||||
if (ret)
|
||||
pr_err("%s: Could not add pcm Channel Map Control\n",
|
||||
__func__);
|
||||
|
||||
ret = msm_pcm_add_volume_control(rtd);
|
||||
if (ret) {
|
||||
pr_err("%s: Could not add pcm Volume Control %d\n",
|
||||
|
@ -1181,7 +1228,7 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
|
|||
if (ret)
|
||||
pr_err("%s: Could not add hw dep node\n", __func__);
|
||||
pcm->nonatomic = true;
|
||||
exit:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#define _MSM_PCM_H
|
||||
#include <dsp/apr_audio-v2.h>
|
||||
#include <dsp/q6asm-v2.h>
|
||||
|
||||
#include "msm-pcm-routing-v2.h"
|
||||
|
||||
|
||||
/* Support unconventional sample rates 12000, 24000 as well */
|
||||
|
@ -125,6 +125,12 @@ struct output_meta_data_st {
|
|||
struct msm_plat_data {
|
||||
int perf_mode;
|
||||
struct snd_pcm *pcm;
|
||||
struct msm_pcm_ch_map *ch_map[MSM_FRONTEND_DAI_MAX];
|
||||
};
|
||||
|
||||
struct msm_pcm_ch_map {
|
||||
bool set_ch_map;
|
||||
char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL];
|
||||
};
|
||||
|
||||
#endif /*_MSM_PCM_H*/
|
||||
|
|
25
dsp/q6asm.c
25
dsp/q6asm.c
|
@ -4027,11 +4027,13 @@ int q6asm_set_shared_pos_buff(struct audio_client *ac,
|
|||
* parameters
|
||||
* config - session parameters (channels, bits_per_sample, sr)
|
||||
* dir - stream direction (IN for playback, OUT for capture)
|
||||
* use_default_chmap: true if default channel map to be used
|
||||
* channel_map: input channel map
|
||||
* returns 0 if successful, error code otherwise
|
||||
*/
|
||||
int q6asm_open_shared_io(struct audio_client *ac,
|
||||
struct shared_io_config *config,
|
||||
int dir)
|
||||
int dir, bool use_default_chmap, u8 *channel_map)
|
||||
{
|
||||
struct asm_stream_cmd_open_shared_io *open;
|
||||
u8 *channel_mapping;
|
||||
|
@ -4041,6 +4043,12 @@ int q6asm_open_shared_io(struct audio_client *ac,
|
|||
if (!ac || !config)
|
||||
return -EINVAL;
|
||||
|
||||
if (!use_default_chmap && (channel_map == NULL)) {
|
||||
pr_err("%s: No valid chan map and can't use default\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bufsz = config->bufsz;
|
||||
bufcnt = config->bufcnt;
|
||||
num_watermarks = 0;
|
||||
|
@ -4137,10 +4145,17 @@ int q6asm_open_shared_io(struct audio_client *ac,
|
|||
|
||||
memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
|
||||
|
||||
rc = q6asm_map_channels(channel_mapping, config->channels, false);
|
||||
if (rc) {
|
||||
pr_err("%s: Map channels failed, ret: %d\n", __func__, rc);
|
||||
goto done;
|
||||
if (use_default_chmap) {
|
||||
rc = q6asm_map_channels(channel_mapping, config->channels,
|
||||
false);
|
||||
if (rc) {
|
||||
pr_err("%s: Map channels failed, ret: %d\n",
|
||||
__func__, rc);
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
memcpy(channel_mapping, channel_map,
|
||||
PCM_FORMAT_MAX_NUM_CHANNEL);
|
||||
}
|
||||
|
||||
open->num_watermark_levels = num_watermarks;
|
||||
|
|
|
@ -303,7 +303,8 @@ int q6asm_open_write_v2(struct audio_client *ac, uint32_t format,
|
|||
uint16_t bits_per_sample);
|
||||
|
||||
int q6asm_open_shared_io(struct audio_client *ac,
|
||||
struct shared_io_config *c, int dir);
|
||||
struct shared_io_config *c, int dir,
|
||||
bool use_default_chmap, u8 *channel_map);
|
||||
|
||||
int q6asm_open_write_v3(struct audio_client *ac, uint32_t format,
|
||||
uint16_t bits_per_sample);
|
||||
|
|
Loading…
Add table
Reference in a new issue