Merge "ASoC: msm: enhance ADSP Stream Callback"
This commit is contained in:
commit
d575147a75
7 changed files with 249 additions and 90 deletions
|
@ -15,6 +15,7 @@
|
||||||
#define _APR_AUDIO_V2_H_
|
#define _APR_AUDIO_V2_H_
|
||||||
|
|
||||||
#include <linux/qdsp6v2/apr.h>
|
#include <linux/qdsp6v2/apr.h>
|
||||||
|
#include <linux/msm_audio.h>
|
||||||
|
|
||||||
/* size of header needed for passing data out of band */
|
/* size of header needed for passing data out of band */
|
||||||
#define APR_CMD_OB_HDR_SZ 12
|
#define APR_CMD_OB_HDR_SZ 12
|
||||||
|
@ -447,6 +448,18 @@ struct adm_param_data_v5 {
|
||||||
#define ASM_STREAM_PP_EVENT 0x00013214
|
#define ASM_STREAM_PP_EVENT 0x00013214
|
||||||
#define DSP_STREAM_CMD "ADSP Stream Cmd"
|
#define DSP_STREAM_CMD "ADSP Stream Cmd"
|
||||||
#define DSP_STREAM_CALLBACK "ADSP Stream Callback Event"
|
#define DSP_STREAM_CALLBACK "ADSP Stream Callback Event"
|
||||||
|
#define DSP_STREAM_CALLBACK_QUEUE_SIZE 1024
|
||||||
|
|
||||||
|
struct dsp_stream_callback_list {
|
||||||
|
struct list_head list;
|
||||||
|
struct msm_adsp_event_data event;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dsp_stream_callback_prtd {
|
||||||
|
uint16_t event_count;
|
||||||
|
struct list_head event_queue;
|
||||||
|
spinlock_t prtd_spin_lock;
|
||||||
|
};
|
||||||
|
|
||||||
/* set customized mixing on matrix mixer */
|
/* set customized mixing on matrix mixer */
|
||||||
#define ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5 0x00010344
|
#define ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5 0x00010344
|
||||||
|
|
|
@ -460,4 +460,14 @@ struct msm_hwacc_effects_config {
|
||||||
__s32 topology;
|
__s32 topology;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ADSP_STREAM_PP_EVENT 0
|
||||||
|
#define ADSP_STREAM_ENCDEC_EVENT 1
|
||||||
|
#define ADSP_STREAM_EVENT_MAX 2
|
||||||
|
|
||||||
|
struct msm_adsp_event_data {
|
||||||
|
__u32 event_type;
|
||||||
|
__u32 payload_len;
|
||||||
|
__u8 payload[0];
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -749,8 +749,7 @@ static void compr_event_handler(uint32_t opcode,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = msm_adsp_inform_mixer_ctl(rtd, DSP_STREAM_CALLBACK,
|
ret = msm_adsp_inform_mixer_ctl(rtd, payload);
|
||||||
payload);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("%s: failed to inform mixer ctrl. err = %d\n",
|
pr_err("%s: failed to inform mixer ctrl. err = %d\n",
|
||||||
__func__, ret);
|
__func__, ret);
|
||||||
|
@ -1583,6 +1582,7 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream)
|
||||||
pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
|
pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
|
||||||
prtd->audio_client->perf_mode = false;
|
prtd->audio_client->perf_mode = false;
|
||||||
prtd->session_id = prtd->audio_client->session;
|
prtd->session_id = prtd->audio_client->session;
|
||||||
|
msm_adsp_init_mixer_ctl_pp_event_queue(rtd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1738,7 +1738,7 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream)
|
||||||
q6asm_audio_client_buf_free_contiguous(dir, ac);
|
q6asm_audio_client_buf_free_contiguous(dir, ac);
|
||||||
|
|
||||||
q6asm_audio_client_free(ac);
|
q6asm_audio_client_free(ac);
|
||||||
|
msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
|
||||||
kfree(pdata->audio_effects[soc_prtd->dai_link->be_id]);
|
kfree(pdata->audio_effects[soc_prtd->dai_link->be_id]);
|
||||||
pdata->audio_effects[soc_prtd->dai_link->be_id] = NULL;
|
pdata->audio_effects[soc_prtd->dai_link->be_id] = NULL;
|
||||||
kfree(pdata->dec_params[soc_prtd->dai_link->be_id]);
|
kfree(pdata->dec_params[soc_prtd->dai_link->be_id]);
|
||||||
|
@ -3978,7 +3978,6 @@ static int msm_compr_add_audio_adsp_stream_callback_control(
|
||||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||||
.info = msm_adsp_stream_callback_info,
|
.info = msm_adsp_stream_callback_info,
|
||||||
.get = msm_adsp_stream_callback_get,
|
.get = msm_adsp_stream_callback_get,
|
||||||
.put = msm_adsp_stream_callback_put,
|
|
||||||
.private_value = 0,
|
.private_value = 0,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -4019,6 +4018,7 @@ static int msm_compr_add_audio_adsp_stream_callback_control(
|
||||||
}
|
}
|
||||||
|
|
||||||
kctl->private_data = NULL;
|
kctl->private_data = NULL;
|
||||||
|
|
||||||
free_mixer_str:
|
free_mixer_str:
|
||||||
kfree(mixer_str);
|
kfree(mixer_str);
|
||||||
done:
|
done:
|
||||||
|
|
|
@ -239,8 +239,7 @@ static void event_handler(uint32_t opcode,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = msm_adsp_inform_mixer_ctl(rtd, DSP_STREAM_CALLBACK,
|
ret = msm_adsp_inform_mixer_ctl(rtd, payload);
|
||||||
payload);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("%s: failed to inform mixer ctl. err = %d\n",
|
pr_err("%s: failed to inform mixer ctl. err = %d\n",
|
||||||
__func__, ret);
|
__func__, ret);
|
||||||
|
@ -691,6 +690,7 @@ static int msm_pcm_open(struct snd_pcm_substream *substream)
|
||||||
prtd->set_channel_map = false;
|
prtd->set_channel_map = false;
|
||||||
prtd->reset_event = false;
|
prtd->reset_event = false;
|
||||||
runtime->private_data = prtd;
|
runtime->private_data = prtd;
|
||||||
|
msm_adsp_init_mixer_ctl_pp_event_queue(soc_prtd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -833,6 +833,7 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
|
||||||
}
|
}
|
||||||
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
|
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
|
||||||
SNDRV_PCM_STREAM_PLAYBACK);
|
SNDRV_PCM_STREAM_PLAYBACK);
|
||||||
|
msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
|
||||||
kfree(prtd);
|
kfree(prtd);
|
||||||
runtime->private_data = NULL;
|
runtime->private_data = NULL;
|
||||||
|
|
||||||
|
@ -1187,7 +1188,6 @@ static int msm_pcm_add_audio_adsp_stream_callback_control(
|
||||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
|
||||||
.info = msm_adsp_stream_callback_info,
|
.info = msm_adsp_stream_callback_info,
|
||||||
.get = msm_adsp_stream_callback_get,
|
.get = msm_adsp_stream_callback_get,
|
||||||
.put = msm_adsp_stream_callback_put,
|
|
||||||
.private_value = 0,
|
.private_value = 0,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1231,6 +1231,7 @@ static int msm_pcm_add_audio_adsp_stream_callback_control(
|
||||||
}
|
}
|
||||||
|
|
||||||
kctl->private_data = NULL;
|
kctl->private_data = NULL;
|
||||||
|
|
||||||
free_mixer_str:
|
free_mixer_str:
|
||||||
kfree(mixer_str);
|
kfree(mixer_str);
|
||||||
done:
|
done:
|
||||||
|
|
|
@ -45,21 +45,6 @@ enum {
|
||||||
EQ_BAND_MAX,
|
EQ_BAND_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msm_audio_eq_band {
|
|
||||||
uint16_t band_idx; /* The band index, 0 .. 11 */
|
|
||||||
uint32_t filter_type; /* Filter band type */
|
|
||||||
uint32_t center_freq_hz; /* Filter band center frequency */
|
|
||||||
uint32_t filter_gain; /* Filter band initial gain (dB) */
|
|
||||||
/* Range is +12 dB to -12 dB with 1dB increments. */
|
|
||||||
uint32_t q_factor;
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
struct msm_audio_eq_stream_config {
|
|
||||||
uint32_t enable; /* Number of consequtive bands specified */
|
|
||||||
uint32_t num_bands;
|
|
||||||
struct msm_audio_eq_band eq_bands[EQ_BAND_MAX];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/* Audio Sphere data structures */
|
/* Audio Sphere data structures */
|
||||||
struct msm_audio_pp_asphere_state_s {
|
struct msm_audio_pp_asphere_state_s {
|
||||||
uint32_t enabled;
|
uint32_t enabled;
|
||||||
|
@ -817,18 +802,133 @@ static int msm_qti_pp_asphere_set(struct snd_kcontrol *kcontrol,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int msm_adsp_init_mixer_ctl_pp_event_queue(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
{
|
||||||
|
struct snd_kcontrol *kctl;
|
||||||
|
const char *deviceNo = "NN";
|
||||||
|
char *mixer_str = NULL;
|
||||||
|
int ctl_len = 0, ret = 0;
|
||||||
|
const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
|
||||||
|
struct dsp_stream_callback_prtd *kctl_prtd = NULL;
|
||||||
|
|
||||||
|
if (!rtd) {
|
||||||
|
pr_err("%s: rtd is NULL\n", __func__);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
|
||||||
|
mixer_str = kzalloc(ctl_len, GFP_KERNEL);
|
||||||
|
if (!mixer_str) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name,
|
||||||
|
rtd->pcm->device);
|
||||||
|
kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
|
||||||
|
kfree(mixer_str);
|
||||||
|
if (!kctl) {
|
||||||
|
pr_err("%s: failed to get kctl.\n", __func__);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kctl->private_data != NULL) {
|
||||||
|
pr_err("%s: kctl_prtd is not NULL at initialization.\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
kctl_prtd = kzalloc(sizeof(struct dsp_stream_callback_prtd),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!kctl_prtd) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_init(&kctl_prtd->prtd_spin_lock);
|
||||||
|
INIT_LIST_HEAD(&kctl_prtd->event_queue);
|
||||||
|
kctl_prtd->event_count = 0;
|
||||||
|
kctl->private_data = kctl_prtd;
|
||||||
|
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int msm_adsp_clean_mixer_ctl_pp_event_queue(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
{
|
||||||
|
struct snd_kcontrol *kctl;
|
||||||
|
const char *deviceNo = "NN";
|
||||||
|
char *mixer_str = NULL;
|
||||||
|
int ctl_len = 0, ret = 0;
|
||||||
|
struct dsp_stream_callback_list *node, *n;
|
||||||
|
unsigned long spin_flags;
|
||||||
|
const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
|
||||||
|
struct dsp_stream_callback_prtd *kctl_prtd = NULL;
|
||||||
|
|
||||||
|
if (!rtd) {
|
||||||
|
pr_err("%s: rtd is NULL\n", __func__);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
|
||||||
|
mixer_str = kzalloc(ctl_len, GFP_KERNEL);
|
||||||
|
if (!mixer_str) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name,
|
||||||
|
rtd->pcm->device);
|
||||||
|
kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
|
||||||
|
kfree(mixer_str);
|
||||||
|
if (!kctl) {
|
||||||
|
pr_err("%s: failed to get kctl.\n", __func__);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
kctl_prtd = (struct dsp_stream_callback_prtd *)
|
||||||
|
kctl->private_data;
|
||||||
|
if (kctl_prtd != NULL) {
|
||||||
|
spin_lock_irqsave(&kctl_prtd->prtd_spin_lock, spin_flags);
|
||||||
|
/* clean the queue */
|
||||||
|
list_for_each_entry_safe(node, n,
|
||||||
|
&kctl_prtd->event_queue, list) {
|
||||||
|
list_del(&node->list);
|
||||||
|
kctl_prtd->event_count--;
|
||||||
|
pr_debug("%s: %d remaining events after del.\n",
|
||||||
|
__func__, kctl_prtd->event_count);
|
||||||
|
kfree(node);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&kctl_prtd->prtd_spin_lock, spin_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree(kctl_prtd);
|
||||||
|
kctl->private_data = NULL;
|
||||||
|
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd,
|
int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd,
|
||||||
const char *mixer_ctl_name,
|
|
||||||
uint32_t *payload)
|
uint32_t *payload)
|
||||||
{
|
{
|
||||||
/* adsp pp event notifier */
|
/* adsp pp event notifier */
|
||||||
struct snd_kcontrol *kctl;
|
struct snd_kcontrol *kctl;
|
||||||
struct snd_ctl_elem_value control;
|
struct snd_ctl_elem_value control;
|
||||||
uint32_t payload_size = 0;
|
|
||||||
const char *deviceNo = "NN";
|
const char *deviceNo = "NN";
|
||||||
char *mixer_str = NULL;
|
char *mixer_str = NULL;
|
||||||
int ctl_len = 0, ret = 0;
|
int ctl_len = 0, ret = 0;
|
||||||
|
struct dsp_stream_callback_list *new_event;
|
||||||
|
struct dsp_stream_callback_list *oldest_event;
|
||||||
|
unsigned long spin_flags;
|
||||||
|
struct dsp_stream_callback_prtd *kctl_prtd = NULL;
|
||||||
|
struct msm_adsp_event_data *event_data = NULL;
|
||||||
|
const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
|
||||||
|
struct snd_ctl_elem_info kctl_info;
|
||||||
|
|
||||||
if (!rtd || !payload) {
|
if (!rtd || !payload) {
|
||||||
pr_err("%s: %s is NULL\n", __func__,
|
pr_err("%s: %s is NULL\n", __func__,
|
||||||
|
@ -837,6 +937,12 @@ int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rtd->card->snd_card == NULL) {
|
||||||
|
pr_err("%s: snd_card is null.\n", __func__);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
|
ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
|
||||||
mixer_str = kzalloc(ctl_len, GFP_ATOMIC);
|
mixer_str = kzalloc(ctl_len, GFP_ATOMIC);
|
||||||
if (!mixer_str) {
|
if (!mixer_str) {
|
||||||
|
@ -854,21 +960,59 @@ int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
control.id = kctl->id;
|
event_data = (struct msm_adsp_event_data *)payload;
|
||||||
payload_size = payload[0];
|
kctl->info(kctl, &kctl_info);
|
||||||
/* Copy complete payload */
|
if (sizeof(struct msm_adsp_event_data)
|
||||||
memcpy(control.value.bytes.data, (void *)payload,
|
+ event_data->payload_len > kctl_info.count) {
|
||||||
sizeof(payload_size) + payload_size);
|
pr_err("%s: payload length exceeds limit of %u bytes.\n",
|
||||||
kctl->put(kctl, &control);
|
__func__, kctl_info.count);
|
||||||
if (rtd->card->snd_card == NULL) {
|
|
||||||
pr_err("%s: snd_card is null.\n", __func__);
|
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kctl_prtd = (struct dsp_stream_callback_prtd *)
|
||||||
|
kctl->private_data;
|
||||||
|
if (kctl_prtd == NULL) {
|
||||||
|
/* queue is not initialized */
|
||||||
|
ret = -EINVAL;
|
||||||
|
pr_err("%s: event queue is not initialized.\n", __func__);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_event = kzalloc(sizeof(struct dsp_stream_callback_list)
|
||||||
|
+ event_data->payload_len,
|
||||||
|
GFP_ATOMIC);
|
||||||
|
if (new_event == NULL) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
memcpy((void *)&new_event->event, (void *)payload,
|
||||||
|
event_data->payload_len
|
||||||
|
+ sizeof(struct msm_adsp_event_data));
|
||||||
|
|
||||||
|
spin_lock_irqsave(&kctl_prtd->prtd_spin_lock, spin_flags);
|
||||||
|
while (kctl_prtd->event_count >= DSP_STREAM_CALLBACK_QUEUE_SIZE) {
|
||||||
|
pr_info("%s: queue of size %d is full. delete oldest one.\n",
|
||||||
|
__func__, DSP_STREAM_CALLBACK_QUEUE_SIZE);
|
||||||
|
oldest_event = list_first_entry(&kctl_prtd->event_queue,
|
||||||
|
struct dsp_stream_callback_list, list);
|
||||||
|
pr_info("%s: event deleted: type %d length %d\n",
|
||||||
|
__func__, oldest_event->event.event_type,
|
||||||
|
oldest_event->event.payload_len);
|
||||||
|
list_del(&oldest_event->list);
|
||||||
|
kctl_prtd->event_count--;
|
||||||
|
kfree(oldest_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_add_tail(&new_event->list, &kctl_prtd->event_queue);
|
||||||
|
kctl_prtd->event_count++;
|
||||||
|
spin_unlock_irqrestore(&kctl_prtd->prtd_spin_lock, spin_flags);
|
||||||
|
|
||||||
|
control.id = kctl->id;
|
||||||
snd_ctl_notify(rtd->card->snd_card,
|
snd_ctl_notify(rtd->card->snd_card,
|
||||||
SNDRV_CTL_EVENT_MASK_INFO,
|
SNDRV_CTL_EVENT_MASK_INFO,
|
||||||
&control.id);
|
&control.id);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -877,44 +1021,8 @@ int msm_adsp_stream_cmd_info(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
|
||||||
uinfo->count = 512;
|
uinfo->count =
|
||||||
|
sizeof(((struct snd_ctl_elem_value *)0)->value.bytes.data);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int msm_adsp_stream_callback_put(struct snd_kcontrol *kcontrol,
|
|
||||||
struct snd_ctl_elem_value *ucontrol)
|
|
||||||
{
|
|
||||||
uint32_t payload_size = 0, last_payload_size = 0;
|
|
||||||
|
|
||||||
/* fetch payload size in first four bytes */
|
|
||||||
memcpy(&payload_size, ucontrol->value.bytes.data, sizeof(uint32_t));
|
|
||||||
|
|
||||||
if (kcontrol->private_data == NULL) {
|
|
||||||
/* buffer is empty */
|
|
||||||
kcontrol->private_data =
|
|
||||||
kzalloc(payload_size + sizeof(payload_size),
|
|
||||||
GFP_ATOMIC);
|
|
||||||
if (kcontrol->private_data == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
} else {
|
|
||||||
memcpy(&last_payload_size, kcontrol->private_data,
|
|
||||||
sizeof(uint32_t));
|
|
||||||
if (last_payload_size < payload_size) {
|
|
||||||
/* new payload size exceeds old one.
|
|
||||||
* reallocate buffer
|
|
||||||
*/
|
|
||||||
kfree(kcontrol->private_data);
|
|
||||||
kcontrol->private_data =
|
|
||||||
kzalloc(payload_size + sizeof(payload_size),
|
|
||||||
GFP_ATOMIC);
|
|
||||||
if (kcontrol->private_data == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(kcontrol->private_data, ucontrol->value.bytes.data,
|
|
||||||
sizeof(uint32_t) + payload_size);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -923,26 +1031,53 @@ int msm_adsp_stream_callback_get(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_value *ucontrol)
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
uint32_t payload_size = 0;
|
uint32_t payload_size = 0;
|
||||||
|
struct dsp_stream_callback_list *oldest_event;
|
||||||
|
unsigned long spin_flags;
|
||||||
|
struct dsp_stream_callback_prtd *kctl_prtd = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (kcontrol->private_data == NULL) {
|
kctl_prtd = (struct dsp_stream_callback_prtd *)
|
||||||
pr_err("%s: ASM Stream PP Event Data Unavailable\n", __func__);
|
kcontrol->private_data;
|
||||||
return -EINVAL;
|
if (kctl_prtd == NULL) {
|
||||||
|
pr_err("%s: ASM Stream PP event queue is not initialized.\n",
|
||||||
|
__func__);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&payload_size, kcontrol->private_data, sizeof(uint32_t));
|
spin_lock_irqsave(&kctl_prtd->prtd_spin_lock, spin_flags);
|
||||||
memcpy(ucontrol->value.bytes.data, kcontrol->private_data,
|
pr_debug("%s: %d events in queue.\n", __func__, kctl_prtd->event_count);
|
||||||
sizeof(uint32_t) + payload_size);
|
if (list_empty(&kctl_prtd->event_queue)) {
|
||||||
kfree(kcontrol->private_data);
|
pr_err("%s: ASM Stream PP event queue is empty.\n", __func__);
|
||||||
kcontrol->private_data = NULL;
|
ret = -EINVAL;
|
||||||
|
spin_unlock_irqrestore(&kctl_prtd->prtd_spin_lock, spin_flags);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
oldest_event = list_first_entry(&kctl_prtd->event_queue,
|
||||||
|
struct dsp_stream_callback_list, list);
|
||||||
|
list_del(&oldest_event->list);
|
||||||
|
kctl_prtd->event_count--;
|
||||||
|
spin_unlock_irqrestore(&kctl_prtd->prtd_spin_lock, spin_flags);
|
||||||
|
|
||||||
|
payload_size = oldest_event->event.payload_len;
|
||||||
|
pr_debug("%s: event fetched: type %d length %d\n",
|
||||||
|
__func__, oldest_event->event.event_type,
|
||||||
|
oldest_event->event.payload_len);
|
||||||
|
memcpy(ucontrol->value.bytes.data, &oldest_event->event,
|
||||||
|
sizeof(struct msm_adsp_event_data) + payload_size);
|
||||||
|
kfree(oldest_event);
|
||||||
|
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int msm_adsp_stream_callback_info(struct snd_kcontrol *kcontrol,
|
int msm_adsp_stream_callback_info(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
|
||||||
uinfo->count = 512;
|
uinfo->count =
|
||||||
|
sizeof(((struct snd_ctl_elem_value *)0)->value.bytes.data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,12 +14,11 @@
|
||||||
|
|
||||||
#include <sound/soc.h>
|
#include <sound/soc.h>
|
||||||
int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd,
|
int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd,
|
||||||
const char *mixer_ctl_name,
|
|
||||||
uint32_t *payload);
|
uint32_t *payload);
|
||||||
|
int msm_adsp_init_mixer_ctl_pp_event_queue(struct snd_soc_pcm_runtime *rtd);
|
||||||
|
int msm_adsp_clean_mixer_ctl_pp_event_queue(struct snd_soc_pcm_runtime *rtd);
|
||||||
int msm_adsp_stream_cmd_info(struct snd_kcontrol *kcontrol,
|
int msm_adsp_stream_cmd_info(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_info *uinfo);
|
struct snd_ctl_elem_info *uinfo);
|
||||||
int msm_adsp_stream_callback_put(struct snd_kcontrol *kcontrol,
|
|
||||||
struct snd_ctl_elem_value *ucontrol);
|
|
||||||
int msm_adsp_stream_callback_get(struct snd_kcontrol *kcontrol,
|
int msm_adsp_stream_callback_get(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_value *ucontrol);
|
struct snd_ctl_elem_value *ucontrol);
|
||||||
int msm_adsp_stream_callback_info(struct snd_kcontrol *kcontrol,
|
int msm_adsp_stream_callback_info(struct snd_kcontrol *kcontrol,
|
||||||
|
|
|
@ -1675,7 +1675,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
|
||||||
int32_t ret = 0;
|
int32_t ret = 0;
|
||||||
union asm_token_struct asm_token;
|
union asm_token_struct asm_token;
|
||||||
uint8_t buf_index;
|
uint8_t buf_index;
|
||||||
char *pp_event_package = NULL;
|
struct msm_adsp_event_data *pp_event_package = NULL;
|
||||||
uint32_t payload_size = 0;
|
uint32_t payload_size = 0;
|
||||||
|
|
||||||
if (ac == NULL) {
|
if (ac == NULL) {
|
||||||
|
@ -2046,17 +2046,18 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
|
||||||
pr_debug("%s: ASM_STREAM_PP_EVENT payload[0][0x%x] payload[1][0x%x]",
|
pr_debug("%s: ASM_STREAM_PP_EVENT payload[0][0x%x] payload[1][0x%x]",
|
||||||
__func__, payload[0], payload[1]);
|
__func__, payload[0], payload[1]);
|
||||||
/* repack payload for asm_stream_pp_event
|
/* repack payload for asm_stream_pp_event
|
||||||
* package is composed of size + actual payload
|
* package is composed of event type + size + actual payload
|
||||||
*/
|
*/
|
||||||
payload_size = data->payload_size;
|
payload_size = data->payload_size;
|
||||||
pp_event_package =
|
pp_event_package = kzalloc(payload_size
|
||||||
kzalloc(payload_size + sizeof(payload_size),
|
+ sizeof(struct msm_adsp_event_data),
|
||||||
GFP_ATOMIC);
|
GFP_ATOMIC);
|
||||||
if (!pp_event_package)
|
if (!pp_event_package)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
memcpy((void *)pp_event_package,
|
|
||||||
&payload_size, sizeof(payload_size));
|
pp_event_package->event_type = ASM_STREAM_PP_EVENT;
|
||||||
memcpy((void *)pp_event_package + sizeof(payload_size),
|
pp_event_package->payload_len = payload_size;
|
||||||
|
memcpy((void *)pp_event_package->payload,
|
||||||
data->payload, payload_size);
|
data->payload, payload_size);
|
||||||
ac->cb(data->opcode, data->token,
|
ac->cb(data->opcode, data->token,
|
||||||
(void *)pp_event_package, ac->priv);
|
(void *)pp_event_package, ac->priv);
|
||||||
|
|
Loading…
Add table
Reference in a new issue