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

Commit 5c33e02c authored by Dhanalakshmi Siddani's avatar Dhanalakshmi Siddani
Browse files

ASoC: msm: Aptx decoder integration changes



Add changes to support aptx decoder in offload mode.
Add support to set BT device address and add new mixer control
to set license key.

CRs-Fixed: 1106128
Change-Id: Idd4ec8ab829883ef4848be8b686e24101ccbed60
Signed-off-by: default avatarDhanalakshmi Siddani <dsiddani@codeaurora.org>
parent ae0ff772
Loading
Loading
Loading
Loading
+29 −4
Original line number Diff line number Diff line
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-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
@@ -4316,7 +4316,7 @@ struct asm_amrwbplus_fmt_blk_v2 {
#define ASM_MEDIA_FMT_ALAC                   0x00012F31
#define ASM_MEDIA_FMT_VORBIS                 0x00010C15
#define ASM_MEDIA_FMT_APE                    0x00012F32

#define ASM_MEDIA_FMT_APTX                   0x000131FF

/* Media format ID for adaptive transform acoustic coding. This
 * ID is used by the #ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED command
@@ -8325,6 +8325,31 @@ struct asm_dts_eagle_param_get {
	struct asm_stream_cmd_get_pp_params_v2 param;
} __packed;

/* Opcode to set BT address and license for aptx decoder */
#define APTX_DECODER_BT_ADDRESS 0x00013201
#define APTX_CLASSIC_DEC_LICENSE_ID 0x00013202

struct aptx_dec_bt_addr_cfg {
	uint32_t lap;
	uint32_t uap;
	uint32_t nap;
} __packed;

struct aptx_dec_bt_dev_addr {
	struct apr_hdr hdr;
	struct asm_stream_cmd_set_encdec_param encdec;
	struct aptx_dec_bt_addr_cfg bt_addr_cfg;
} __packed;

struct asm_aptx_dec_fmt_blk_v2 {
	struct apr_hdr hdr;
	struct asm_data_cmd_media_fmt_update_v2 fmtblk;
	u32     sample_rate;
/* Number of samples per second.
 * Supported values: 44100 and 48000 Hz
 */
} __packed;

/* LSM Specific */
#define VW_FEAT_DIM					(39)

+9 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-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
@@ -53,6 +53,7 @@
#define FORMAT_G711_ALAW_FS 0x001a
#define FORMAT_G711_MLAW_FS 0x001b
#define FORMAT_DTS          0x001c
#define FORMAT_APTX         0x001d

#define ENCDEC_SBCBITRATE   0x0001
#define ENCDEC_IMMEDIATE_DECODE 0x0002
@@ -492,6 +493,9 @@ int q6asm_stream_media_format_block_vorbis(struct audio_client *ac,
int q6asm_media_format_block_ape(struct audio_client *ac,
			struct asm_ape_cfg *cfg, int stream_id);

int q6asm_stream_media_format_block_aptx_dec(struct audio_client *ac,
						uint32_t sr, int stream_id);

int q6asm_ds1_set_endp_params(struct audio_client *ac,
				int param_id, int param_value);

@@ -514,6 +518,10 @@ int q6asm_dts_eagle_set(struct audio_client *ac, int param_id, uint32_t size,
int q6asm_dts_eagle_get(struct audio_client *ac, int param_id, uint32_t size,
			void *data, struct param_outband *po, int m_id);

/* Send aptx decoder BT address */
int q6asm_set_aptx_dec_bt_addr(struct audio_client *ac,
				struct aptx_dec_bt_addr_cfg *cfg);

/* Set SoftPause Params */
int q6asm_set_softpause(struct audio_client *ac,
			struct asm_softpause_params *param);
+30 −3
Original line number Diff line number Diff line
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-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
@@ -781,6 +781,7 @@ static void populate_codec_list(struct msm_compr_audio *prtd)
	prtd->compr_cap.codecs[10] = SND_AUDIOCODEC_ALAC;
	prtd->compr_cap.codecs[11] = SND_AUDIOCODEC_APE;
	prtd->compr_cap.codecs[12] = SND_AUDIOCODEC_DTS;
	prtd->compr_cap.codecs[13] = SND_AUDIOCODEC_APTX;
}

static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
@@ -799,6 +800,7 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
	struct asm_vorbis_cfg vorbis_cfg;
	struct asm_alac_cfg alac_cfg;
	struct asm_ape_cfg ape_cfg;
	struct aptx_dec_bt_addr_cfg aptx_cfg;
	union snd_codec_options *codec_options;

	int ret = 0;
@@ -1010,7 +1012,24 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
		pr_debug("SND_AUDIOCODEC_DTS\n");
		/* no media format block needed */
		break;

	case FORMAT_APTX:
		pr_debug("SND_AUDIOCODEC_APTX\n");
		memset(&aptx_cfg, 0x0, sizeof(struct aptx_dec_bt_addr_cfg));
		ret = q6asm_stream_media_format_block_aptx_dec(
							prtd->audio_client,
							prtd->sample_rate,
							stream_id);
		if (ret >= 0) {
			aptx_cfg.nap = codec_options->aptx_dec.nap;
			aptx_cfg.uap = codec_options->aptx_dec.uap;
			aptx_cfg.lap = codec_options->aptx_dec.lap;
			q6asm_set_aptx_dec_bt_addr(prtd->audio_client,
							&aptx_cfg);
		} else {
			pr_err("%s: CMD Format block failed ret %d\n",
					 __func__, ret);
		}
		break;
	default:
		pr_debug("%s, unsupported format, skip", __func__);
		break;
@@ -1798,7 +1817,11 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream,
		prtd->codec = FORMAT_DTS;
		break;
	}

	case SND_AUDIOCODEC_APTX: {
		pr_debug("%s: SND_AUDIOCODEC_APTX\n", __func__);
		prtd->codec = FORMAT_APTX;
		break;
	}
	default:
		pr_err("codec not supported, id =%d\n", params->codec.id);
		return -EINVAL;
@@ -2671,6 +2694,8 @@ static int msm_compr_get_codec_caps(struct snd_compr_stream *cstream,
		break;
	case SND_AUDIOCODEC_DTS:
		break;
	case SND_AUDIOCODEC_APTX:
		break;
	default:
		pr_err("%s: Unsupported audio codec %d\n",
			__func__, codec->codec);
@@ -3082,6 +3107,7 @@ static int msm_compr_send_dec_params(struct snd_compr_stream *cstream,
	switch (prtd->codec) {
	case FORMAT_MP3:
	case FORMAT_MPEG4_AAC:
	case FORMAT_APTX:
		pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
			 prtd->codec);
		break;
@@ -3147,6 +3173,7 @@ static int msm_compr_dec_params_put(struct snd_kcontrol *kcontrol,
	case FORMAT_ALAC:
	case FORMAT_APE:
	case FORMAT_DTS:
	case FORMAT_APTX:
		pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
			 prtd->codec);
		break;
+30 −0
Original line number Diff line number Diff line
@@ -10374,6 +10374,33 @@ static const struct snd_kcontrol_new device_pp_params_mixer_controls[] = {
	msm_routing_put_device_pp_params_mixer),
};

static int msm_aptx_dec_license_control_get(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	ucontrol->value.integer.value[0] =
			core_get_license_status(ASM_MEDIA_FMT_APTX);
	pr_debug("%s: status %ld\n", __func__,
			ucontrol->value.integer.value[0]);
	return 0;
}

static int msm_aptx_dec_license_control_put(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	int32_t status = 0;

	status = core_set_license(ucontrol->value.integer.value[0],
				APTX_CLASSIC_DEC_LICENSE_ID);
	pr_debug("%s: status %d\n", __func__, status);
	return status;
}

static const struct snd_kcontrol_new aptx_dec_license_controls[] = {
	SOC_SINGLE_EXT("APTX Dec License", SND_SOC_NOPM, 0,
	0xFFFF, 0, msm_aptx_dec_license_control_get,
	msm_aptx_dec_license_control_put),
};

static struct snd_pcm_ops msm_routing_pcm_ops = {
	.hw_params	= msm_pcm_routing_hw_params,
	.close          = msm_pcm_routing_close,
@@ -10431,6 +10458,9 @@ static int msm_routing_probe(struct snd_soc_platform *platform)

	snd_soc_add_platform_controls(platform, msm_source_tracking_controls,
				      ARRAY_SIZE(msm_source_tracking_controls));

	snd_soc_add_platform_controls(platform, aptx_dec_license_controls,
					ARRAY_SIZE(aptx_dec_license_controls));
	return 0;
}

+118 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
 * Author: Brian Swetland <swetland@google.com>
 *
 * This software is licensed under the terms of the GNU General Public
@@ -2613,6 +2613,9 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format,
	case FORMAT_APE:
		open.dec_fmt_id = ASM_MEDIA_FMT_APE;
		break;
	case FORMAT_APTX:
		open.dec_fmt_id = ASM_MEDIA_FMT_APTX;
		break;
	default:
		pr_err("%s: Invalid format 0x%x\n", __func__, format);
		rc = -EINVAL;
@@ -5238,6 +5241,57 @@ fail_cmd:
	return rc;
}

int q6asm_stream_media_format_block_aptx_dec(struct audio_client *ac,
						uint32_t srate, int stream_id)
{
	struct asm_aptx_dec_fmt_blk_v2 aptx_fmt;
	int rc = 0;

	if (!ac->session) {
		pr_err("%s: ac session invalid\n", __func__);
		rc = -EINVAL;
		goto fail_cmd;
	}
	pr_debug("%s :session[%d] rate[%d] stream_id[%d]\n",
		__func__, ac->session, srate, stream_id);

	q6asm_stream_add_hdr(ac, &aptx_fmt.hdr, sizeof(aptx_fmt), TRUE,
				stream_id);
	atomic_set(&ac->cmd_state, -1);

	aptx_fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
	aptx_fmt.fmtblk.fmt_blk_size = sizeof(aptx_fmt) - sizeof(aptx_fmt.hdr) -
						sizeof(aptx_fmt.fmtblk);

	aptx_fmt.sample_rate = srate;

	rc = apr_send_pkt(ac->apr, (uint32_t *) &aptx_fmt);
	if (rc < 0) {
		pr_err("%s :Comamnd media format update failed %d\n",
				__func__, rc);
		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));
		goto fail_cmd;
	}
	rc = 0;
fail_cmd:
	return rc;
}

static int __q6asm_ds1_set_endp_params(struct audio_client *ac, int param_id,
				int param_value, int stream_id)
{
@@ -6266,6 +6320,69 @@ int q6asm_set_volume_v2(struct audio_client *ac, int volume, int instance)
	return __q6asm_set_volume(ac, volume, instance);
}

int q6asm_set_aptx_dec_bt_addr(struct audio_client *ac,
				struct aptx_dec_bt_addr_cfg *cfg)
{
	struct aptx_dec_bt_dev_addr paylod;
	int sz = 0;
	int rc = 0;

	pr_debug("%s: BT addr nap %d, uap %d, lap %d\n", __func__, cfg->nap,
			cfg->uap, cfg->lap);

	if (ac == NULL) {
		pr_err("%s: AC handle NULL\n", __func__);
		rc = -EINVAL;
		goto fail_cmd;
	}
	if (ac->apr == NULL) {
		pr_err("%s: AC APR handle NULL\n", __func__);
		rc = -EINVAL;
		goto fail_cmd;
	}

	sz = sizeof(struct aptx_dec_bt_dev_addr);
	q6asm_add_hdr_async(ac, &paylod.hdr, sz, TRUE);
	atomic_set(&ac->cmd_state, -1);
	paylod.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
	paylod.encdec.param_id = APTX_DECODER_BT_ADDRESS;
	paylod.encdec.param_size = sz - sizeof(paylod.hdr)
					- sizeof(paylod.encdec);
	paylod.bt_addr_cfg.lap = cfg->lap;
	paylod.bt_addr_cfg.uap = cfg->uap;
	paylod.bt_addr_cfg.nap = cfg->nap;

	rc = apr_send_pkt(ac->apr, (uint32_t *) &paylod);
	if (rc < 0) {
		pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
				__func__, paylod.encdec.param_id, 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, set-params paramid[0x%x]\n", __func__,
			paylod.encdec.param_id);
		rc = -ETIMEDOUT;
		goto fail_cmd;
	}
	if (atomic_read(&ac->cmd_state) > 0) {
		pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n",
				__func__, adsp_err_get_err_str(
				atomic_read(&ac->cmd_state)),
				paylod.encdec.param_id);
		rc = adsp_err_get_lnx_err_code(
			atomic_read(&ac->cmd_state));
		goto fail_cmd;
	}
	pr_debug("%s: set BT addr is success\n", __func__);
	rc = 0;
fail_cmd:
	return rc;
}

int q6asm_set_softpause(struct audio_client *ac,
			struct asm_softpause_params *pause_param)
{