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

Commit a2119070 authored by Ben Romberger's avatar Ben Romberger
Browse files

ASoC: msm: Change RTAC to use ION memory



Change the RTAC driver to use shared memory for
Q6 communication. This is needed for calibration
parameters that use more then 4k of memory.

Change-Id: Ic6bdbeac04cc73e42139510c66a9ba919280c87a
Signed-off-by: default avatarBen Romberger <bromberg@codeaurora.org>
parent a9544cf6
Loading
Loading
Loading
Loading
+27 −1
Original line number Diff line number Diff line
/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011, 2013, 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
@@ -19,6 +19,31 @@
#define RTAC_CVS		1
#define RTAC_VOICE_MODES	2

enum {
	ADM_RTAC_CAL,
	ASM_RTAC_CAL,
	VOICE_RTAC_CAL,
	MAX_RTAC_BLOCKS
};

struct rtac_cal_mem_map_data {
	uint32_t		map_size;
	uint32_t		map_handle;
	struct ion_client	*ion_client;
	struct ion_handle	*ion_handle;
};

struct rtac_cal_data {
	uint32_t		size;
	uint32_t		kvaddr;
	uint32_t		paddr;
};

struct rtac_cal_block_data {
	struct rtac_cal_mem_map_data	map_data;
	struct rtac_cal_data		cal_data;
};

void rtac_add_adm_device(u32 port_id, u32 copp_id, u32 path_id, u32 popp_id);
void rtac_remove_adm_device(u32 port_id);
void rtac_remove_popp_from_adm_devices(u32 popp_id);
@@ -35,5 +60,6 @@ void rtac_copy_asm_payload_to_user(void *payload, u32 payload_size);
void rtac_set_voice_handle(u32 mode, void *handle);
bool rtac_make_voice_callback(u32 mode, uint32_t *payload, u32 payload_size);
void rtac_copy_voice_payload_to_user(void *payload, u32 payload_size);
int rtac_clear_mapping(uint32_t cal_type);

#endif
+4 −1
Original line number Diff line number Diff line
/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011, 2013 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
@@ -42,6 +42,7 @@ void rtac_remove_voice(u32 cvs_handle) {}
void rtac_set_voice_handle(u32 mode, void *handle) {}
bool rtac_make_voice_callback(u32 mode, uint32_t *payload,
		u32 payload_size) {return false; }
int rtac_clear_mapping(uint32_t cal_type) {return false; }

#else

@@ -123,6 +124,8 @@ struct mutex rtac_asm_apr_mutex;
struct mutex			rtac_voice_mutex;
struct mutex			rtac_voice_apr_mutex;

int rtac_clear_mapping(uint32_t cal_type) {return false; }

static int rtac_open(struct inode *inode, struct file *f)
{
	pr_debug("%s\n", __func__);
+5 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#define ADM_PATH_PLAYBACK 0x1
#define ADM_PATH_LIVE_REC 0x2
#define ADM_PATH_NONLIVE_REC 0x3
#include <mach/qdsp6v2/rtac.h>
#include <sound/q6afe-v2.h>
#include <sound/q6audio-v2.h>

@@ -43,6 +44,10 @@ int adm_multi_ch_copp_open(int port, int path, int rate, int mode,

int adm_unmap_cal_blocks(void);

int adm_map_rtac_block(struct rtac_cal_block_data *cal_block);

int adm_unmap_rtac_block(uint32_t *mem_map_handle);

int adm_memory_map_regions(int port_id, uint32_t *buf_add, uint32_t mempool_id,
				uint32_t *bufsz, uint32_t bufcnt);

+5 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#define __Q6_ASM_V2_H__

#include <mach/qdsp6v2/apr.h>
#include <mach/qdsp6v2/rtac.h>
#include <sound/apr_audio-v2.h>
#include <linux/list.h>
#include <linux/msm_ion.h>
@@ -227,6 +228,10 @@ int q6asm_memory_unmap(struct audio_client *ac, uint32_t buf_add,

int q6asm_unmap_cal_blocks(void);

int q6asm_map_rtac_block(struct rtac_cal_block_data *cal_block);

int q6asm_unmap_rtac_block(uint32_t *mem_map_handle);

int q6asm_run(struct audio_client *ac, uint32_t flags,
		uint32_t msw_ts, uint32_t lsw_ts);

+113 −11
Original line number Diff line number Diff line
@@ -18,8 +18,6 @@
#include <linux/atomic.h>
#include <linux/wait.h>

#include <mach/qdsp6v2/rtac.h>

#include <sound/apr_audio-v2.h>
#include <mach/qdsp6v2/apr.h>
#include <sound/q6adm-v2.h>
@@ -33,7 +31,9 @@

#define RESET_COPP_ID 99
#define INVALID_COPP_ID 0xFF
#define ADM_GET_PARAMETER_LENGTH 350
/* Used for inband payload copy, max size is 4k */
/* 2 is to account for module & param ID in payload */
#define ADM_GET_PARAMETER_LENGTH  (4096 - APR_HDR_SIZE - 2 * sizeof(uint32_t))


enum {
@@ -42,6 +42,7 @@ enum {
	ADM_RX_AUDVOL_CAL,
	ADM_TX_AUDVOL_CAL,
	ADM_CUSTOM_TOP_CAL,
	ADM_RTAC,
	ADM_MAX_CAL_TYPES
};

@@ -541,6 +542,10 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
			this_adm.apr = NULL;
			reset_custom_topology_flags();
			this_adm.set_custom_topology = 1;
			for (i = 0; i < ADM_MAX_CAL_TYPES; i++)
				atomic_set(&this_adm.mem_map_cal_handles[i],
					0);
			rtac_clear_mapping(ADM_RTAC_CAL);
		}
		pr_debug("Resetting calibration blocks");
		for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
@@ -659,13 +664,18 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv)
			if (payload[0] != 0)
				pr_err("%s: ADM_CMDRSP_GET_PP_PARAMS_V5 returned error = 0x%x\n",
					__func__, payload[0]);
			rtac_make_adm_callback(payload,
				data->payload_size);
			if (rtac_make_adm_callback(payload,
					data->payload_size))
				break;

			if (data->payload_size > (4 * sizeof(uint32_t))) {
				adm_get_parameters[0] = payload[3];
				pr_debug("GET_PP PARAM:received parameter length: %x\n",
						adm_get_parameters[0]);
				/* storing param size then params */
				for (i = 0; i < payload[3]; i++)
					adm_get_parameters[1+i] = payload[4+i];
			}
			atomic_set(&this_adm.copp_stat[index], 1);
			wake_up(&this_adm.wait[index]);
			break;
@@ -839,11 +849,15 @@ static void send_adm_cal(int port_id, int path)
	int			result = 0;
	s32			acdb_path;
	struct acdb_cal_block	aud_cal;
	int			size = 4096;
	int			size;
	pr_debug("%s\n", __func__);

	/* Maps audio_dev_ctrl path definition to ACDB definition */
	acdb_path = path - 1;
	if (acdb_path == TX_CAL)
		size = 4096 * 4;
	else
		size = 4096;

	pr_debug("%s: Sending audproc cal\n", __func__);
	get_audproc_cal(acdb_path, &aud_cal);
@@ -913,6 +927,92 @@ static void send_adm_cal(int port_id, int path)
			__func__, port_id, acdb_path);
}

int adm_map_rtac_block(struct rtac_cal_block_data *cal_block)
{
	int	result = 0;
	pr_debug("%s\n", __func__);

	if (cal_block == NULL) {
		pr_err("%s: cal_block is NULL!\n",
			__func__);
		result = -EINVAL;
		goto done;
	}

	if (cal_block->cal_data.paddr == 0) {
		pr_debug("%s: No address to map!\n",
			__func__);
		result = -EINVAL;
		goto done;
	}

	if (cal_block->map_data.map_size == 0) {
		pr_debug("%s: map size is 0!\n",
			__func__);
		result = -EINVAL;
		goto done;
	}

	/* valid port ID needed for callback use primary I2S */
	atomic_set(&this_adm.mem_map_cal_index, ADM_RTAC);
	result = adm_memory_map_regions(PRIMARY_I2S_RX,
			&cal_block->cal_data.paddr, 0,
			&cal_block->map_data.map_size, 1);
	if (result < 0) {
		pr_err("%s: RTAC mmap did not work! addr = 0x%x, size = %d\n",
			__func__, cal_block->cal_data.paddr,
			cal_block->map_data.map_size);
		goto done;
	}

	cal_block->map_data.map_handle = atomic_read(
		&this_adm.mem_map_cal_handles[ADM_RTAC]);
done:
	return result;
}

int adm_unmap_rtac_block(uint32_t *mem_map_handle)
{
	int	result = 0;
	pr_debug("%s\n", __func__);

	if (mem_map_handle == NULL) {
		pr_debug("%s: Map handle is NULL, nothing to unmap\n",
			__func__);
		goto done;
	}

	if (*mem_map_handle == 0) {
		pr_debug("%s: Map handle is 0, nothing to unmap\n",
			__func__);
		goto done;
	}

	if (*mem_map_handle != atomic_read(
			&this_adm.mem_map_cal_handles[ADM_RTAC])) {
		pr_err("%s: Map handles do not match! Unmapping RTAC, RTAC map 0x%x, ADM map 0x%x\n",
			__func__, *mem_map_handle, atomic_read(
			&this_adm.mem_map_cal_handles[ADM_RTAC]));

		/* if mismatch use handle passed in to unmap */
		atomic_set(&this_adm.mem_map_cal_handles[ADM_RTAC],
			   *mem_map_handle);
	}

	/* valid port ID needed for callback use primary I2S */
	atomic_set(&this_adm.mem_map_cal_index, ADM_RTAC);
	result = adm_memory_unmap_regions(PRIMARY_I2S_RX);
	if (result < 0) {
		pr_debug("%s: adm_memory_unmap_regions failed, error %d\n",
			__func__, result);
	} else {
		atomic_set(&this_adm.mem_map_cal_handles[ADM_RTAC], 0);
		*mem_map_handle = 0;
	}
done:
	return result;
}

int adm_unmap_cal_blocks(void)
{
	int	i;
@@ -934,6 +1034,8 @@ int adm_unmap_cal_blocks(void)
					= 0;
			} else if (i == ADM_CUSTOM_TOP_CAL) {
				this_adm.set_custom_topology = 1;
			} else {
				continue;
			}

			/* valid port ID needed for callback use primary I2S */
Loading