Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a34ec62 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: msm: qdsp6v2: assign decoder memory to ADSP"

parents 7ed24b74 3ec77b82
Loading
Loading
Loading
Loading
+83 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -29,6 +29,7 @@
#include <linux/export.h>
#include <linux/qcom_iommu.h>
#include <asm/dma-iommu.h>
#include <soc/qcom/secure_buffer.h>

#define MSM_AUDIO_ION_PROBED (1 << 0)

@@ -178,6 +179,87 @@ err:
}
EXPORT_SYMBOL(msm_audio_ion_alloc);

static int msm_audio_hyp_assign(ion_phys_addr_t *paddr, size_t *pa_len,
				u8 assign_type)
{
	int srcVM[1] = {VMID_HLOS};
	int destVM[1] = {VMID_CP_ADSP_SHARED};
	int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
	int ret = 0;

	switch (assign_type) {
	case HLOS_TO_ADSP:
		srcVM[0] = VMID_HLOS;
		destVM[0] = VMID_CP_ADSP_SHARED;
		break;
	case ADSP_TO_HLOS:
		srcVM[0] = VMID_CP_ADSP_SHARED;
		destVM[0] = VMID_HLOS;
		break;
	default:
		pr_err("%s: Invalid assign type = %d\n", __func__, assign_type);
		ret = -EINVAL;
		goto done;
	}

	ret = hyp_assign_phys(*paddr, *pa_len, srcVM, 1, destVM, destVMperm, 1);
	if (ret)
		pr_err("%s: hyp_assign_phys failed for type %d, rc = %d\n",
			 __func__, assign_type, ret);
done:
	return ret;
}

int msm_audio_ion_phys_assign(const char *name, int fd, ion_phys_addr_t *paddr,
			      size_t *pa_len, u8 assign_type)
{
	struct ion_client *client;
	struct ion_handle *handle;
	int ret;

	if (!(msm_audio_ion_data.device_status & MSM_AUDIO_ION_PROBED)) {
		pr_debug("%s:probe is not done, deferred\n", __func__);
		return -EPROBE_DEFER;
	}

	if (!name || !paddr || !pa_len) {
		pr_err("%s: Invalid params\n", __func__);
		return -EINVAL;
	}

	client = msm_audio_ion_client_create(name);
	if (IS_ERR_OR_NULL((void *)(client))) {
		pr_err("%s: ION create client failed\n", __func__);
		return -EINVAL;
	}

	handle = ion_import_dma_buf(client, fd);
	if (IS_ERR_OR_NULL((void *) (handle))) {
		pr_err("%s: ion import dma buffer failed\n",
			__func__);
		ret = -EINVAL;
		goto err_destroy_client;
	}

	ret = ion_phys(client, handle, paddr, pa_len);
	if (ret) {
		pr_err("%s: could not get physical address for handle, ret = %d\n",
			__func__, ret);
		goto err_ion_handle;
	}
	pr_debug("%s: ION Physical address is %x\n", __func__, (u32)*paddr);

	ret = msm_audio_hyp_assign(paddr, pa_len, assign_type);

err_ion_handle:
	ion_free(client, handle);

err_destroy_client:
	ion_client_destroy(client);

	return ret;
}

int msm_audio_ion_import(const char *name, struct ion_client **client,
			struct ion_handle **handle, int fd,
			unsigned long *ionflag, size_t bufsz,
+11 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2015, 2017 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,12 @@
#include <sound/pcm.h>
#include <linux/msm_ion.h>

enum {
	HLOS_TO_ADSP = 1,
	ADSP_TO_HLOS,
};

#define VMID_CP_ADSP_SHARED 33

int msm_audio_ion_alloc(const char *name, struct ion_client **client,
			struct ion_handle **handle, size_t bufsz,
@@ -26,6 +32,7 @@ int msm_audio_ion_import(const char *name, struct ion_client **client,
			struct ion_handle **handle, int fd,
			unsigned long *ionflag, size_t bufsz,
			ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr);

int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle);
int msm_audio_ion_mmap(struct audio_buffer *substream,
		       struct vm_area_struct *vma);
@@ -42,4 +49,7 @@ int msm_audio_ion_import_legacy(const char *name, struct ion_client *client,
int msm_audio_ion_free_legacy(struct ion_client *client,
			struct ion_handle *handle);
u32 msm_audio_populate_upper_32_bits(ion_phys_addr_t pa);

int msm_audio_ion_phys_assign(const char *name, int fd, ion_phys_addr_t *paddr,
				size_t *pa_len, u8 assign_type);
#endif /* _LINUX_MSM_AUDIO_ION_H */
+1 −1
Original line number Diff line number Diff line
@@ -639,7 +639,7 @@ int q6asm_send_audio_effects_params(struct audio_client *ac, char *params,
int q6asm_send_stream_cmd(struct audio_client *ac,
			  struct msm_adsp_event_data *data);

int q6asm_send_ion_fd(struct audio_client *ac, int fd);
int q6asm_audio_map_shm_fd(struct audio_client *ac, int fd);

int q6asm_send_rtic_event_ack(struct audio_client *ac,
			      void *param, uint32_t params_length);
+15 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2016, 2017 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -20,6 +20,8 @@
#define AVCS_CMDRSP_ADSP_EVENT_GET_STATE	0x0001290D

bool q6core_is_adsp_ready(void);
int q6core_add_remove_pool_pages(phys_addr_t buf_add, uint32_t bufsz,
			uint32_t mempool_id, bool add_pages);

#define ADSP_CMD_SET_DTS_EAGLE_DATA_ID 0x00012919
#define DTS_EAGLE_LICENSE_ID           0x00028346
@@ -153,4 +155,16 @@ struct avcs_cmd_deregister_topologies {
int32_t core_set_license(uint32_t key, uint32_t module_id);
int32_t core_get_license_status(uint32_t module_id);

#define ADSP_MEMORY_MAP_HLOS_PHYSPOOL 4
#define AVCS_CMD_ADD_POOL_PAGES 0x0001292E
#define AVCS_CMD_REMOVE_POOL_PAGES 0x0001292F

struct avs_mem_assign_region {
	struct apr_hdr       hdr;
	u32                  pool_id;
	u32                  size;
	u32                  addr_lsw;
	u32                  addr_msw;
} __packed;

#endif /* __Q6CORE_H__ */
+155 −22
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@

#include <sound/apr_audio-v2.h>
#include <sound/q6asm-v2.h>
#include <sound/q6core.h>
#include <sound/compress_params.h>
#include <sound/compress_offload.h>
#include <sound/compress_driver.h>
@@ -103,6 +104,7 @@ struct msm_compr_pdata {
	bool use_legacy_api; /* indicates use older asm apis*/
	struct msm_compr_dec_params *dec_params[MSM_FRONTEND_DAI_MAX];
	struct msm_compr_ch_map *ch_map[MSM_FRONTEND_DAI_MAX];
	int32_t ion_fd[MSM_FRONTEND_DAI_MAX];
};

struct msm_compr_audio {
@@ -156,6 +158,8 @@ struct msm_compr_audio {
	uint32_t start_delay_lsw;
	uint32_t start_delay_msw;

	int32_t shm_ion_fd;

	uint64_t marker_timestamp;

	struct msm_compr_gapless_state gapless_state;
@@ -1506,6 +1510,40 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream)
	return ret;
}

static int msm_compr_map_unmap_fd(int fd, bool add_pages)
{
	ion_phys_addr_t paddr;
	size_t pa_len = 0;
	int ret = 0;
	u8 assign_type;

	if (add_pages)
		assign_type = HLOS_TO_ADSP;
	else
		assign_type = ADSP_TO_HLOS;

	ret = msm_audio_ion_phys_assign("audio_lib_mem_client", fd,
					&paddr, &pa_len, assign_type);
	if (ret) {
		pr_err("%s: audio lib ION phys failed, rc = %d\n",
			__func__, ret);
		goto done;
	}

	ret = q6core_add_remove_pool_pages(paddr, pa_len,
				 ADSP_MEMORY_MAP_HLOS_PHYSPOOL, add_pages);
	if (ret) {
		pr_err("%s: add remove pages failed, rc = %d\n", __func__, ret);
		/* Assign back to HLOS if add pages cmd failed */
		if (add_pages)
			msm_audio_ion_phys_assign("audio_lib_mem_client", fd,
						&paddr, &pa_len, ADSP_TO_HLOS);
	}

done:
	return ret;
}

static int msm_compr_playback_open(struct snd_compr_stream *cstream)
{
	struct snd_compr_runtime *runtime = cstream->runtime;
@@ -1513,6 +1551,7 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream)
	struct msm_compr_audio *prtd;
	struct msm_compr_pdata *pdata =
			snd_soc_platform_get_drvdata(rtd->platform);
	int ret = 0;

	pr_debug("%s\n", __func__);
	prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL);
@@ -1528,19 +1567,16 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream)
		 kzalloc(sizeof(struct msm_compr_audio_effects), GFP_KERNEL);
	if (!pdata->audio_effects[rtd->dai_link->be_id]) {
		pr_err("%s: Could not allocate memory for effects\n", __func__);
		pdata->cstream[rtd->dai_link->be_id] = NULL;
		kfree(prtd);
		return -ENOMEM;
		ret = -ENOMEM;
		goto effect_err;
	}
	pdata->dec_params[rtd->dai_link->be_id] =
		 kzalloc(sizeof(struct msm_compr_dec_params), GFP_KERNEL);
	if (!pdata->dec_params[rtd->dai_link->be_id]) {
		pr_err("%s: Could not allocate memory for dec params\n",
			__func__);
		kfree(pdata->audio_effects[rtd->dai_link->be_id]);
		pdata->cstream[rtd->dai_link->be_id] = NULL;
		kfree(prtd);
		return -ENOMEM;
		ret = -ENOMEM;
		goto param_err;
	}
	prtd->codec = FORMAT_MP3;
	prtd->bytes_received = 0;
@@ -1584,19 +1620,32 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream)
				(app_cb)compr_event_handler, prtd);
	if (!prtd->audio_client) {
		pr_err("%s: Could not allocate memory for client\n", __func__);
		kfree(pdata->audio_effects[rtd->dai_link->be_id]);
		kfree(pdata->dec_params[rtd->dai_link->be_id]);
		pdata->cstream[rtd->dai_link->be_id] = NULL;
		runtime->private_data = NULL;
		kfree(prtd);
		return -ENOMEM;
		ret = -ENOMEM;
		goto ac_err;
	}
	pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
	prtd->audio_client->perf_mode = false;
	prtd->session_id = prtd->audio_client->session;
	msm_adsp_init_mixer_ctl_pp_event_queue(rtd);

	if (pdata->ion_fd[rtd->dai_link->be_id] > 0) {
		ret = msm_compr_map_unmap_fd(
				pdata->ion_fd[rtd->dai_link->be_id], true);
		if (ret < 0)
			goto map_err;
	}
	return 0;

map_err:
	q6asm_audio_client_free(prtd->audio_client);
ac_err:
	kfree(pdata->dec_params[rtd->dai_link->be_id]);
param_err:
	kfree(pdata->audio_effects[rtd->dai_link->be_id]);
effect_err:
	pdata->cstream[rtd->dai_link->be_id] = NULL;
	runtime->private_data = NULL;
	kfree(prtd);
	return ret;
}

static int msm_compr_capture_open(struct snd_compr_stream *cstream)
@@ -1675,6 +1724,8 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream)
	int dir = IN, ret = 0, stream_id;
	unsigned long flags;
	uint32_t stream_index;
	ion_phys_addr_t paddr;
	size_t pa_len = 0;

	pr_debug("%s\n", __func__);

@@ -1748,6 +1799,15 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream)
	}

	q6asm_audio_client_buf_free_contiguous(dir, ac);
	if (prtd->shm_ion_fd > 0)
		msm_audio_ion_phys_assign("audio_shm_mem_client",
					  prtd->shm_ion_fd,
					  &paddr, &pa_len, ADSP_TO_HLOS);
	if (pdata->ion_fd[soc_prtd->dai_link->be_id] > 0) {
		msm_compr_map_unmap_fd(pdata->ion_fd[soc_prtd->dai_link->be_id],
					false);
		pdata->ion_fd[soc_prtd->dai_link->be_id] = 0;
	}

	q6asm_audio_client_free(ac);
	msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
@@ -3655,7 +3715,7 @@ done:
	return ret;
}

static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
static int msm_compr_shm_ion_fd_map_put(struct snd_kcontrol *kcontrol,
				    struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
@@ -3664,7 +3724,6 @@ static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
				snd_soc_component_get_drvdata(comp);
	struct snd_compr_stream *cstream = NULL;
	struct msm_compr_audio *prtd;
	int fd;
	int ret = 0;

	if (fe_id >= MSM_FRONTEND_DAI_MAX) {
@@ -3694,10 +3753,34 @@ static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
		goto done;
	}

	memcpy(&fd, ucontrol->value.bytes.data, sizeof(fd));
	ret = q6asm_send_ion_fd(prtd->audio_client, fd);
	memcpy(&prtd->shm_ion_fd, ucontrol->value.bytes.data,
		sizeof(prtd->shm_ion_fd));
	ret = q6asm_audio_map_shm_fd(prtd->audio_client, prtd->shm_ion_fd);
	if (ret < 0)
		pr_err("%s: failed to register ion fd\n", __func__);
		pr_err("%s: failed to map shm mem\n", __func__);
done:
	return ret;
}

static int msm_compr_lib_ion_fd_map_put(struct snd_kcontrol *kcontrol,
				    struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
	unsigned long fe_id = kcontrol->private_value;
	struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
				snd_soc_component_get_drvdata(comp);
	int ret = 0;

	if (fe_id >= MSM_FRONTEND_DAI_MAX) {
		pr_err("%s Received out of bounds invalid fe_id %lu\n",
			__func__, fe_id);
		ret = -EINVAL;
		goto done;
	}

	memcpy(&pdata->ion_fd[fe_id], ucontrol->value.bytes.data,
		   sizeof(pdata->ion_fd[fe_id]));

done:
	return ret;
}
@@ -4329,7 +4412,7 @@ static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
	return 0;
}

static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
static int msm_compr_add_shm_ion_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
{
	const char *mixer_ctl_name = "Playback ION FD";
	const char *deviceNo = "NN";
@@ -4341,7 +4424,52 @@ static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
		.name = "?",
		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
		.info = msm_adsp_stream_cmd_info,
		.put = msm_compr_ion_fd_map_put,
		.put = msm_compr_shm_ion_fd_map_put,
		.private_value = 0,
		}
	};

	if (!rtd) {
		pr_err("%s NULL rtd\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 = -ENOMEM;
		goto done;
	}

	snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
	fe_ion_fd_config_control[0].name = mixer_str;
	fe_ion_fd_config_control[0].private_value = rtd->dai_link->be_id;
	pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
	ret = snd_soc_add_platform_controls(rtd->platform,
				fe_ion_fd_config_control,
				ARRAY_SIZE(fe_ion_fd_config_control));
	if (ret < 0)
		pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);

	kfree(mixer_str);
done:
	return ret;
}

static int msm_compr_add_lib_ion_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
{
	const char *mixer_ctl_name = "Playback ION LIB FD";
	const char *deviceNo = "NN";
	char *mixer_str = NULL;
	int ctl_len = 0, ret = 0;
	struct snd_kcontrol_new fe_ion_fd_config_control[1] = {
		{
		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name = "?",
		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
		.info = msm_adsp_stream_cmd_info,
		.put = msm_compr_lib_ion_fd_map_put,
		.private_value = 0,
		}
	};
@@ -4442,11 +4570,16 @@ static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
		pr_err("%s: Could not add Compr ADSP Stream Callback Control\n",
			__func__);

	rc = msm_compr_add_io_fd_cmd_control(rtd);
	rc = msm_compr_add_shm_ion_fd_cmd_control(rtd);
	if (rc)
		pr_err("%s: Could not add Compr ion fd Control\n",
			__func__);

	rc = msm_compr_add_lib_ion_fd_cmd_control(rtd);
	if (rc)
		pr_err("%s: Could not add Compr ion lib fd Control\n",
			__func__);

	rc = msm_compr_add_event_ack_cmd_control(rtd);
	if (rc)
		pr_err("%s: Could not add Compr event ack Control\n",
Loading