dsp: support for AFE SPDIF input interface

Support two SPDIF input and two SPDIF output interfaces in AFE.
Support 61937 compressed capture.

Change-Id: Ie71434eb53be798567a6240e0f4bf171aee305b8
Signed-off-by: Ralf Herz <rherz@codeaurora.org>
This commit is contained in:
Ralf Herz 2018-07-17 20:19:04 +05:30
parent 1fdb5b3e3f
commit cc29b9e839
8 changed files with 501 additions and 23 deletions

View file

@ -103,6 +103,19 @@ struct afe_ctl {
void *rx_private_data;
uint32_t mmap_handle;
void (*pri_spdif_tx_cb)(uint32_t opcode,
uint32_t token, uint32_t *payload, void *priv);
void (*sec_spdif_tx_cb)(uint32_t opcode,
uint32_t token, uint32_t *payload, void *priv);
void *pri_spdif_tx_private_data;
void *sec_spdif_tx_private_data;
struct afe_port_mod_evt_rsp_hdr pri_spdif_evt_pl;
struct afe_event_fmt_update pri_spdif_fmt_event;
struct afe_port_mod_evt_rsp_hdr sec_spdif_evt_pl;
struct afe_event_fmt_update sec_spdif_fmt_event;
struct work_struct afe_pri_spdif_work;
struct work_struct afe_sec_spdif_work;
int topology[AFE_MAX_PORTS];
struct cal_type_data *cal_data[MAX_AFE_CAL_TYPES];
@ -353,6 +366,128 @@ static void afe_notify_dc_presence_work_fn(struct work_struct *work)
__func__, event, ret);
}
static const char *const afe_event_port_text[] = {
"PORT=Primary",
"PORT=Secondary",
};
static const char * const afe_event_state_text[] = {
"STATE=Inactive",
"STATE=Active",
"STATE=EOS",
};
static const char *const afe_event_rate_text[] = {
"RATE=32000",
"RATE=44100",
"RATE=48000",
"RATE=88200",
"RATE=96000",
"RATE=176400",
"RATE=192000",
};
static const char *const afe_event_format_text[] = {
"FORMAT=LPCM",
"FORMAT=Compr",
};
static void afe_notify_spdif_fmt_update_common(void *payload)
{
int ret = 0;
char *env[6];
struct afe_port_mod_evt_rsp_hdr *evt_pl;
struct afe_event_fmt_update *fmt_event;
evt_pl = (struct afe_port_mod_evt_rsp_hdr *)payload;
fmt_event = (struct afe_event_fmt_update *)
(payload + sizeof(struct afe_port_mod_evt_rsp_hdr));
env[0] = "SPDIF_FMT_UPDATE=TRUE";
if (evt_pl->port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX)
env[1] = (char *)afe_event_port_text[0];
else
env[1] = (char *)afe_event_port_text[1];
switch (fmt_event->status) {
case AFE_PORT_STATUS_AUDIO_ACTIVE:
env[2] = (char *)afe_event_state_text[1];
break;
case AFE_PORT_STATUS_AUDIO_EOS:
env[2] = (char *)afe_event_state_text[2];
break;
default:
env[2] = (char *)afe_event_state_text[0];
}
switch (fmt_event->sample_rate) {
case 32000:
env[3] = (char *)afe_event_rate_text[0];
break;
case 44100:
env[3] = (char *)afe_event_rate_text[1];
break;
case 48000:
env[3] = (char *)afe_event_rate_text[2];
break;
case 88200:
env[3] = (char *)afe_event_rate_text[3];
break;
case 96000:
env[3] = (char *)afe_event_rate_text[4];
break;
case 176400:
env[3] = (char *)afe_event_rate_text[5];
break;
case 192000:
env[3] = (char *)afe_event_rate_text[6];
break;
default:
env[3] = (char *)afe_event_rate_text[2];
}
if (fmt_event->data_format == AFE_NON_LINEAR_DATA)
env[4] = (char *)afe_event_format_text[1];
else
env[4] = (char *)afe_event_format_text[0];
env[5] = NULL;
ret = q6core_send_uevent_env(this_afe.uevent_data, env);
if (ret)
pr_err("%s: Send UEvent %s failed: %d\n", __func__,
env[0], ret);
}
static void afe_notify_pri_spdif_fmt_update_work_fn(struct work_struct *work)
{
afe_notify_spdif_fmt_update_common(&this_afe.pri_spdif_evt_pl);
}
static void afe_notify_sec_spdif_fmt_update_work_fn(struct work_struct *work)
{
afe_notify_spdif_fmt_update_common(&this_afe.sec_spdif_evt_pl);
}
static void afe_notify_spdif_fmt_update(void *payload)
{
struct afe_port_mod_evt_rsp_hdr *evt_pl;
evt_pl = (struct afe_port_mod_evt_rsp_hdr *)payload;
if (evt_pl->port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX) {
memcpy(&this_afe.pri_spdif_evt_pl, payload,
sizeof(struct afe_port_mod_evt_rsp_hdr) +
sizeof(struct afe_event_fmt_update));
schedule_work(&this_afe.afe_pri_spdif_work);
} else {
memcpy(&this_afe.sec_spdif_evt_pl, payload,
sizeof(struct afe_port_mod_evt_rsp_hdr) +
sizeof(struct afe_event_fmt_update));
schedule_work(&this_afe.afe_sec_spdif_work);
}
}
static int32_t afe_callback(struct apr_client_data *data, void *priv)
{
if (!data) {
@ -549,6 +684,20 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
flag_dc_presence[1] == 1) {
afe_notify_dc_presence();
}
} else if (evt_pl->port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX) {
if (this_afe.pri_spdif_tx_cb) {
this_afe.pri_spdif_tx_cb(data->opcode,
data->token, data->payload,
this_afe.pri_spdif_tx_private_data);
}
afe_notify_spdif_fmt_update(data->payload);
} else if (evt_pl->port_id == AFE_PORT_ID_SECONDARY_SPDIF_TX) {
if (this_afe.sec_spdif_tx_cb) {
this_afe.sec_spdif_tx_cb(data->opcode,
data->token, data->payload,
this_afe.sec_spdif_tx_private_data);
}
afe_notify_spdif_fmt_update(data->payload);
} else {
pr_debug("%s: mod ID = 0x%x event_id = 0x%x\n",
__func__, evt_pl->module_id,
@ -639,6 +788,13 @@ int afe_sizeof_cfg_cmd(u16 port_id)
ret_size =
SIZEOF_CFG_CMD(afe_param_id_hdmi_multi_chan_audio_cfg);
break;
case AFE_PORT_ID_PRIMARY_SPDIF_RX:
case AFE_PORT_ID_PRIMARY_SPDIF_TX:
case AFE_PORT_ID_SECONDARY_SPDIF_RX:
case AFE_PORT_ID_SECONDARY_SPDIF_TX:
ret_size =
SIZEOF_CFG_CMD(afe_param_id_spdif_cfg_v2);
break;
case SLIMBUS_0_RX:
case SLIMBUS_0_TX:
case SLIMBUS_1_RX:
@ -2793,7 +2949,7 @@ int afe_spdif_port_start(u16 port_id, struct afe_spdif_port_config *spdif_port,
param_hdr, (u8 *) spdif_port);
if (ret) {
pr_err("%s: AFE enable for port 0x%x failed ret = %d\n",
__func__, port_id, ret);
__func__, port_id, ret);
goto fail_cmd;
}
@ -2806,10 +2962,13 @@ int afe_spdif_port_start(u16 port_id, struct afe_spdif_port_config *spdif_port,
goto fail_cmd;
}
ret = afe_send_spdif_ch_status_cfg(&spdif_port->ch_status, port_id);
if (ret < 0) {
pr_err("%s: afe send failed %d\n", __func__, ret);
goto fail_cmd;
if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX) {
ret = afe_send_spdif_ch_status_cfg(&spdif_port->ch_status,
port_id);
if (ret < 0) {
pr_err("%s: afe send failed %d\n", __func__, ret);
goto fail_cmd;
}
}
return afe_send_cmd_port_start(port_id);
@ -2819,6 +2978,105 @@ int afe_spdif_port_start(u16 port_id, struct afe_spdif_port_config *spdif_port,
}
EXPORT_SYMBOL(afe_spdif_port_start);
/**
* afe_spdif_reg_event_cfg -
* register for event from AFE spdif port
*
* @port_id: Port ID to register event
* @reg_flag: register or unregister
* @cb: callback function to invoke for events from module
* @private_data: private data to sent back in callback fn
*
* Returns 0 on success or error on failure
*/
int afe_spdif_reg_event_cfg(u16 port_id, u16 reg_flag,
void (*cb)(uint32_t opcode,
uint32_t token, uint32_t *payload, void *priv),
void *private_data)
{
struct afe_port_cmd_event_cfg *config;
struct afe_port_cmd_mod_evt_cfg_payload pl;
int index;
int ret;
int num_events = 1;
int cmd_size = sizeof(struct afe_port_cmd_event_cfg) +
(num_events * sizeof(struct afe_port_cmd_mod_evt_cfg_payload));
config = kzalloc(cmd_size, GFP_KERNEL);
if (!config)
return -ENOMEM;
if (port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX) {
this_afe.pri_spdif_tx_cb = cb;
this_afe.pri_spdif_tx_private_data = private_data;
} else if (port_id == AFE_PORT_ID_SECONDARY_SPDIF_TX) {
this_afe.sec_spdif_tx_cb = cb;
this_afe.sec_spdif_tx_private_data = private_data;
} else {
pr_err("%s: wrong port id 0x%x\n", __func__, port_id);
ret = -EINVAL;
goto fail_idx;
}
index = q6audio_get_port_index(port_id);
if (index < 0) {
pr_err("%s: Invalid index number: %d\n", __func__, index);
ret = -EINVAL;
goto fail_idx;
}
memset(&pl, 0, sizeof(pl));
pl.module_id = AFE_MODULE_CUSTOM_EVENTS;
pl.event_id = AFE_PORT_FMT_UPDATE_EVENT;
pl.reg_flag = reg_flag;
config->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
config->hdr.pkt_size = cmd_size;
config->hdr.src_port = 1;
config->hdr.dest_port = 1;
config->hdr.token = index;
config->hdr.opcode = AFE_PORT_CMD_MOD_EVENT_CFG;
config->port_id = q6audio_get_port_id(port_id);
config->num_events = num_events;
config->version = 1;
memcpy(config->payload, &pl, sizeof(pl));
atomic_set(&this_afe.state, 1);
atomic_set(&this_afe.status, 0);
ret = apr_send_pkt(this_afe.apr, (uint32_t *) config);
if (ret < 0) {
pr_err("%s: port = 0x%x failed %d\n",
__func__, port_id, ret);
goto fail_cmd;
}
ret = wait_event_timeout(this_afe.wait[index],
(atomic_read(&this_afe.state) == 0),
msecs_to_jiffies(TIMEOUT_MS));
if (!ret) {
pr_err("%s: wait_event timeout\n", __func__);
ret = -EINVAL;
goto fail_cmd;
}
if (atomic_read(&this_afe.status) > 0) {
pr_err("%s: config cmd failed [%s]\n",
__func__, adsp_err_get_err_str(
atomic_read(&this_afe.status)));
ret = adsp_err_get_lnx_err_code(
atomic_read(&this_afe.status));
goto fail_idx;
}
ret = 0;
fail_cmd:
pr_debug("%s: config.opcode 0x%x status %d\n",
__func__, config->hdr.opcode, ret);
fail_idx:
kfree(config);
return ret;
}
EXPORT_SYMBOL(afe_spdif_reg_event_cfg);
int afe_send_slot_mapping_cfg(
struct afe_param_id_slot_mapping_cfg *slot_mapping_cfg,
u16 port_id)
@ -3880,7 +4138,10 @@ int afe_get_port_index(u16 port_id)
case MI2S_TX: return IDX_MI2S_TX;
case HDMI_RX: return IDX_HDMI_RX;
case DISPLAY_PORT_RX: return IDX_DISPLAY_PORT_RX;
case AFE_PORT_ID_SPDIF_RX: return IDX_SPDIF_RX;
case AFE_PORT_ID_PRIMARY_SPDIF_RX: return IDX_PRIMARY_SPDIF_RX;
case AFE_PORT_ID_PRIMARY_SPDIF_TX: return IDX_PRIMARY_SPDIF_TX;
case AFE_PORT_ID_SECONDARY_SPDIF_RX: return IDX_SECONDARY_SPDIF_RX;
case AFE_PORT_ID_SECONDARY_SPDIF_TX: return IDX_SECONDARY_SPDIF_TX;
case RSVD_2: return IDX_RSVD_2;
case RSVD_3: return IDX_RSVD_3;
case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
@ -4259,6 +4520,12 @@ int afe_open(u16 port_id,
case DISPLAY_PORT_RX:
cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
break;
case AFE_PORT_ID_PRIMARY_SPDIF_RX:
case AFE_PORT_ID_PRIMARY_SPDIF_TX:
case AFE_PORT_ID_SECONDARY_SPDIF_RX:
case AFE_PORT_ID_SECONDARY_SPDIF_TX:
cfg_type = AFE_PARAM_ID_SPDIF_CONFIG;
break;
case SLIMBUS_0_RX:
case SLIMBUS_0_TX:
case SLIMBUS_1_RX:
@ -6100,7 +6367,10 @@ int afe_validate_port(u16 port_id)
case MI2S_TX:
case HDMI_RX:
case DISPLAY_PORT_RX:
case AFE_PORT_ID_SPDIF_RX:
case AFE_PORT_ID_PRIMARY_SPDIF_RX:
case AFE_PORT_ID_PRIMARY_SPDIF_TX:
case AFE_PORT_ID_SECONDARY_SPDIF_RX:
case AFE_PORT_ID_SECONDARY_SPDIF_TX:
case RSVD_2:
case RSVD_3:
case DIGI_MIC_TX:
@ -7695,6 +7965,10 @@ int __init afe_init(void)
q6core_init_uevent_data(this_afe.uevent_data, "q6afe_uevent");
INIT_WORK(&this_afe.afe_dc_work, afe_notify_dc_presence_work_fn);
INIT_WORK(&this_afe.afe_pri_spdif_work,
afe_notify_pri_spdif_fmt_update_work_fn);
INIT_WORK(&this_afe.afe_sec_spdif_work,
afe_notify_sec_spdif_fmt_update_work_fn);
return 0;
}

View file

@ -1953,6 +1953,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:
case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS:
case ASM_STREAM_CMD_OPEN_READ_COMPRESSED:
case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
pr_debug("%s: session %d opcode 0x%x token 0x%x Payload = [0x%x] stat 0x%x src %d dest %d\n",
__func__, ac->session,
@ -2166,7 +2167,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
if (ac->io_mode & SYNC_IO_MODE) {
if (port->buf == NULL) {
pr_err("%s: Unexpected Write Done\n", __func__);
pr_err("%s: Unexpected Read Done\n", __func__);
spin_unlock_irqrestore(
&(session[session_id].session_lock),
flags);
@ -2833,6 +2834,85 @@ int q6asm_set_soft_volume_module_instance_ids(int instance,
}
EXPORT_SYMBOL(q6asm_set_soft_volume_module_instance_ids);
/**
* q6asm_open_read_compressed -
* command to open ASM in compressed read mode
*
* @ac: Audio client handle
* @format: capture format for ASM
* @passthrough_flag: flag to indicate passthrough option
*
* Returns 0 on success or error on failure
*/
int q6asm_open_read_compressed(struct audio_client *ac, uint32_t format,
uint32_t passthrough_flag)
{
int rc = 0;
struct asm_stream_cmd_open_read_compressed open;
if (ac == NULL) {
pr_err("%s: ac[%pK] NULL\n", __func__, ac);
rc = -EINVAL;
goto fail_cmd;
}
if (ac->apr == NULL) {
pr_err("%s: APR handle[%pK] NULL\n", __func__, ac->apr);
rc = -EINVAL;
goto fail_cmd;
}
pr_debug("%s: session[%d] wr_format[0x%x]\n", __func__, ac->session,
format);
q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ_COMPRESSED;
atomic_set(&ac->cmd_state, -1);
/*
* Below flag indicates whether DSP shall keep IEC61937 packing or
* unpack to raw compressed format
*/
if (format == FORMAT_IEC61937) {
open.mode_flags = 0x1;
pr_debug("%s: Flag 1 IEC61937 output\n", __func__);
} else {
open.mode_flags = 0;
open.frames_per_buf = 1;
pr_debug("%s: Flag 0 RAW_COMPR output\n", __func__);
}
rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
if (rc < 0) {
pr_err("%s: open failed op[0x%x]rc[%d]\n",
__func__, open.hdr.opcode, rc);
rc = -EINVAL;
goto fail_cmd;
}
rc = wait_event_timeout(ac->cmd_wait,
(atomic_read(&ac->cmd_state) >= 0), 1*HZ);
if (!rc) {
pr_err("%s: timeout. waited for OPEN_READ_COMPR rc[%d]\n",
__func__, rc);
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;
}
return 0;
fail_cmd:
return rc;
}
EXPORT_SYMBOL(q6asm_open_read_compressed);
static int __q6asm_open_read(struct audio_client *ac,
uint32_t format, uint16_t bits_per_sample,
uint32_t pcm_format_block_ver,

View file

@ -50,7 +50,10 @@ int q6audio_get_port_index(u16 port_id)
case MI2S_TX: return IDX_MI2S_TX;
case HDMI_RX: return IDX_HDMI_RX;
case DISPLAY_PORT_RX: return IDX_DISPLAY_PORT_RX;
case AFE_PORT_ID_SPDIF_RX: return IDX_SPDIF_RX;
case AFE_PORT_ID_PRIMARY_SPDIF_RX: return IDX_PRIMARY_SPDIF_RX;
case AFE_PORT_ID_PRIMARY_SPDIF_TX: return IDX_PRIMARY_SPDIF_TX;
case AFE_PORT_ID_SECONDARY_SPDIF_RX: return IDX_SECONDARY_SPDIF_RX;
case AFE_PORT_ID_SECONDARY_SPDIF_TX: return IDX_SECONDARY_SPDIF_TX;
case RSVD_2: return IDX_RSVD_2;
case RSVD_3: return IDX_RSVD_3;
case DIGI_MIC_TX: return IDX_DIGI_MIC_TX;
@ -351,7 +354,14 @@ int q6audio_get_port_id(u16 port_id)
case HDMI_RX: return AFE_PORT_ID_MULTICHAN_HDMI_RX;
case DISPLAY_PORT_RX:
return AFE_PORT_ID_HDMI_OVER_DP_RX;
case AFE_PORT_ID_SPDIF_RX: return AFE_PORT_ID_SPDIF_RX;
case AFE_PORT_ID_PRIMARY_SPDIF_RX:
return AFE_PORT_ID_PRIMARY_SPDIF_RX;
case AFE_PORT_ID_PRIMARY_SPDIF_TX:
return AFE_PORT_ID_PRIMARY_SPDIF_TX;
case AFE_PORT_ID_SECONDARY_SPDIF_RX:
return AFE_PORT_ID_SECONDARY_SPDIF_RX;
case AFE_PORT_ID_SECONDARY_SPDIF_TX:
return AFE_PORT_ID_SECONDARY_SPDIF_TX;
case RSVD_2: return IDX_RSVD_2;
case RSVD_3: return IDX_RSVD_3;
case DIGI_MIC_TX: return AFE_PORT_ID_DIGITAL_MIC_TX;
@ -777,6 +787,10 @@ int q6audio_is_digital_pcm_interface(u16 port_id)
case AFE_PORT_ID_WSA_CODEC_DMA_TX_2:
case AFE_PORT_ID_VA_CODEC_DMA_TX_0:
case AFE_PORT_ID_VA_CODEC_DMA_TX_1:
case AFE_PORT_ID_PRIMARY_SPDIF_RX:
case AFE_PORT_ID_PRIMARY_SPDIF_TX:
case AFE_PORT_ID_SECONDARY_SPDIF_RX:
case AFE_PORT_ID_SECONDARY_SPDIF_TX:
break;
default:
ret = -EINVAL;
@ -854,7 +868,10 @@ int q6audio_validate_port(u16 port_id)
case AFE_PORT_ID_QUATERNARY_MI2S_TX:
case AFE_PORT_ID_SECONDARY_MI2S_RX:
case AFE_PORT_ID_SECONDARY_MI2S_TX:
case AFE_PORT_ID_SPDIF_RX:
case AFE_PORT_ID_PRIMARY_SPDIF_RX:
case AFE_PORT_ID_PRIMARY_SPDIF_TX:
case AFE_PORT_ID_SECONDARY_SPDIF_RX:
case AFE_PORT_ID_SECONDARY_SPDIF_TX:
case AFE_PORT_ID_TERTIARY_MI2S_RX:
case AFE_PORT_ID_TERTIARY_MI2S_TX:
case AFE_PORT_ID_QUINARY_MI2S_RX:

View file

@ -189,6 +189,23 @@ int q6core_send_uevent(struct audio_uevent_data *uevent_data, char *event)
}
EXPORT_SYMBOL(q6core_send_uevent);
/**
* q6core_send_uevent_env - send uevent with list of keys to userspace.
*
* @uevent_data: uevent data.
* @event: array of event keys to send.
*
* Returns 0 on success or error otherwise.
*/
int q6core_send_uevent_env(struct audio_uevent_data *uevent_data, char *env[])
{
if (!env || !uevent_data)
return -EINVAL;
return kobject_uevent_env(&uevent_data->kobj, KOBJ_CHANGE, env);
}
EXPORT_SYMBOL(q6core_send_uevent_env);
static int parse_fwk_version_info(uint32_t *payload)
{
size_t ver_size;

View file

@ -1236,7 +1236,11 @@ struct adm_cmd_connect_afe_port_v5 {
#define AFE_PORT_ID_QUINARY_PCM_RX 0x103C
#define AFE_PORT_ID_QUINARY_PCM_TX 0x103D
#define AFE_PORT_ID_SPDIF_RX 0x5000
#define AFE_PORT_ID_PRIMARY_SPDIF_RX 0x5000
#define AFE_PORT_ID_PRIMARY_SPDIF_TX 0x5001
#define AFE_PORT_ID_SECONDARY_SPDIF_RX 0x5002
#define AFE_PORT_ID_SECONDARY_SPDIF_TX 0x5003
#define AFE_PORT_ID_RT_PROXY_PORT_001_RX 0x2000
#define AFE_PORT_ID_RT_PROXY_PORT_001_TX 0x2001
#define AFE_PORT_ID_INTERNAL_BT_SCO_RX 0x3000
@ -2270,6 +2274,7 @@ struct afe_param_id_i2s_cfg {
* This param id is used to configure PCM interface
*/
#define AFE_API_VERSION_SPDIF_CONFIG_V2 0x2
#define AFE_API_VERSION_SPDIF_CONFIG 0x1
#define AFE_API_VERSION_SPDIF_CH_STATUS_CONFIG 0x1
#define AFE_API_VERSION_SPDIF_CLK_CONFIG 0x1
@ -2283,10 +2288,20 @@ struct afe_param_id_i2s_cfg {
#define AFE_PORT_CLK_ROOT_LPAPLL 0x3
#define AFE_PORT_CLK_ROOT_LPAQ6PLL 0x4
struct afe_param_id_spdif_cfg {
#define AFE_MODULE_CUSTOM_EVENTS 0x00010251
#define AFE_PORT_FMT_UPDATE_EVENT 0x0001010E
#define AFE_API_VERSION_EVENT_FMT_UPDATE 0x1
#define AFE_PORT_STATUS_NO_SIGNAL 0
#define AFE_PORT_STATUS_AUDIO_ACTIVE 1
#define AFE_PORT_STATUS_AUDIO_EOS 2
struct afe_param_id_spdif_cfg_v2 {
/* Minor version used for tracking the version of the SPDIF
* configuration interface.
* Supported values: #AFE_API_VERSION_SPDIF_CONFIG
* Supported values: #AFE_API_VERSION_SPDIF_CONFIG,
* #AFE_API_VERSION_SPDIF_CONFIG_V2
*/
u32 spdif_cfg_minor_version;
@ -2318,6 +2333,8 @@ struct afe_param_id_spdif_cfg {
u16 bit_width;
/* This field must be set to zero. */
u16 reserved;
/* Input select for spdif input, must be set to 0 for spdif output. */
u32 src_sel;
} __packed;
struct afe_param_id_spdif_ch_status_cfg {
@ -2344,6 +2361,7 @@ struct afe_param_id_spdif_ch_status_cfg {
*/
} __packed;
/* deprecated */
struct afe_param_id_spdif_clk_cfg {
u32 clk_cfg_minor_version;
/* Minor version used for tracking the version of SPDIF
@ -2367,8 +2385,43 @@ struct afe_param_id_spdif_clk_cfg {
*/
} __packed;
struct afe_event_fmt_update {
/* Tracks the configuration of this event. */
u32 minor_version;
/* Detected port status.
* Supported values:
* - #AFE_PORT_STATUS_NO_SIGNAL
* - #AFE_PORT_STATUS_AUDIO_ACTIVE
* - #AFE_PORT_STATUS_AUDIO_EOS
*/
u32 status;
/* Sampling rate of the port.
* Supported values:
* - #AFE_PORT_SAMPLE_RATE_32K
* - #AFE_PORT_SAMPLE_RATE_44_1K
* - #AFE_PORT_SAMPLE_RATE_48K
* - #AFE_PORT_SAMPLE_RATE_88_2K
* - #AFE_PORT_SAMPLE_RATE_96K
* - #AFE_PORT_SAMPLE_RATE_176_4K
* - #AFE_PORT_SAMPLE_RATE_192K
*/
u32 sample_rate;
/* Data format of the port.
* Supported values:
* - #AFE_LINEAR_PCM_DATA
* - #AFE_NON_LINEAR_DATA
*/
u16 data_format;
/* First 6 bytes of channel status bits */
u8 channel_status[6];
} __packed;
struct afe_spdif_port_config {
struct afe_param_id_spdif_cfg cfg;
struct afe_param_id_spdif_cfg_v2 cfg;
struct afe_param_id_spdif_ch_status_cfg ch_status;
} __packed;
@ -4093,7 +4146,7 @@ union afe_port_config {
struct afe_param_id_internal_bt_fm_cfg int_bt_fm;
struct afe_param_id_pseudo_port_cfg pseudo_port;
struct afe_param_id_device_hw_delay_cfg hw_delay;
struct afe_param_id_spdif_cfg spdif;
struct afe_param_id_spdif_cfg_v2 spdif;
struct afe_param_id_set_topology_cfg topology;
struct afe_param_id_tdm_cfg tdm;
struct afe_param_id_usb_audio_cfg usb_audio;
@ -4793,7 +4846,7 @@ struct asm_generic_compressed_fmt_blk_t {
/* Command to send sample rate & channels for IEC61937 (compressed) or IEC60958
* (pcm) streams. Both audio standards use the same format and are used for
* HDMI or SPDIF.
* HDMI or SPDIF output.
*/
#define ASM_DATA_CMD_IEC_60958_MEDIA_FMT 0x0001321E
@ -7669,11 +7722,23 @@ struct asm_data_cmd_remove_silence {
#define ASM_STREAM_CMD_OPEN_READ_COMPRESSED 0x00010D95
/* Bitmask for the IEC 61937 to 61937 pass-through capture. */
#define ASM_BIT_MASK_IEC_61937_PASS_THROUGH_FLAG (0x00000001UL)
/* Shift value for the IEC 61937 to 61937 pass-through capture. */
#define ASM_SHIFT_IEC_61937_PASS_THROUGH_FLAG 0
struct asm_stream_cmd_open_read_compressed {
struct apr_hdr hdr;
u32 mode_flags;
/* Mode flags that indicate whether meta information per encoded
* frame is to be provided.
* frame is to be provided and packaging.
* Supported values for bit 0: (IEC 61937 pass-through mode)
* - 0 -- Unpack the IEC 61937 format stream to RAW compressed format
* - 1 -- Pass-through transfer of the IEC 61937 format stream
* - Use #ASM_BIT_MASK_IEC_61937_PASS_THROUGH_FLAG to set the bitmask
* and #ASM_SHIFT_IEC_61937_PASS_THROUGH_FLAG to set the shift value
* for this bit.
* Supported values for bit 4:
* - 0 -- Return data buffer contains all encoded frames only; it does
* not contain frame metadata.
@ -7687,7 +7752,9 @@ struct asm_stream_cmd_open_read_compressed {
u32 frames_per_buf;
/* Indicates the number of frames that need to be returned per
* read buffer
* Supported values: should be greater than 0
* Supported values: should be greater than 0 for IEC to RAW compressed
* unpack mode.
* Value is don't care for IEC 61937 pass-through mode.
*/
} __packed;
@ -10321,8 +10388,18 @@ enum afe_lpass_clk_mode {
/* Clock ID for AHB HDMI input */
#define Q6AFE_LPASS_CLK_ID_AHB_HDMI_INPUT 0x400
/* Clock ID for SPDIF core */
#define Q6AFE_LPASS_CLK_ID_SPDIF_CORE 0x500
/* Clock ID for the primary SPDIF output core. */
#define AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_OUTPUT_CORE 0x500
/* Clock ID for the secondary SPDIF output core. */
#define AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_OUTPUT_CORE 0x501
/* Clock ID for the primary SPDIF input core. */
#define AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_INPUT_CORE 0x502
/* Clock ID for the secondary SPDIF input core. */
#define AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_INPUT_CORE 0x503
/* Clock ID for the secondary SPDIF output NPL clk. */
#define AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_OUTPUT_NPL 0x504
/* Clock ID for the primary SPDIF output NPL clk. */
#define AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_OUTPUT_NPL 0x505
/* Clock attribute for invalid use (reserved for internal usage) */

View file

@ -107,7 +107,7 @@ enum {
/* IDX 45->49 */
IDX_SLIMBUS_6_RX,
IDX_SLIMBUS_6_TX,
IDX_SPDIF_RX,
IDX_PRIMARY_SPDIF_RX,
IDX_GLOBAL_CFG,
IDX_AUDIO_PORT_ID_I2S_RX,
/* IDX 50->53 */
@ -229,7 +229,7 @@ enum {
IDX_AFE_PORT_ID_QUINARY_TDM_TX_6,
IDX_AFE_PORT_ID_QUINARY_TDM_RX_7,
IDX_AFE_PORT_ID_QUINARY_TDM_TX_7,
/* IDX 161 to 166 */
/* IDX 161 to 167 */
IDX_AFE_PORT_ID_WSA_CODEC_DMA_RX_0,
IDX_AFE_PORT_ID_WSA_CODEC_DMA_TX_0,
IDX_AFE_PORT_ID_WSA_CODEC_DMA_RX_1,
@ -237,6 +237,10 @@ enum {
IDX_AFE_PORT_ID_WSA_CODEC_DMA_TX_2,
IDX_AFE_PORT_ID_VA_CODEC_DMA_TX_0,
IDX_AFE_PORT_ID_VA_CODEC_DMA_TX_1,
/* IDX 168 to 170 */
IDX_SECONDARY_SPDIF_RX,
IDX_PRIMARY_SPDIF_TX,
IDX_SECONDARY_SPDIF_TX,
AFE_MAX_PORTS
};
@ -389,6 +393,11 @@ int afe_send_spdif_ch_status_cfg(struct afe_param_id_spdif_ch_status_cfg
int afe_spdif_port_start(u16 port_id, struct afe_spdif_port_config *spdif_port,
u32 rate);
int afe_spdif_reg_event_cfg(u16 port_id, u16 reg_flag,
void (*cb)(uint32_t opcode,
uint32_t token, uint32_t *payload, void *priv),
void *private_data);
int afe_turn_onoff_hw_mad(u16 mad_type, u16 mad_enable);
int afe_port_set_mad_type(u16 port_id, enum afe_mad_type mad_type);
enum afe_mad_type afe_port_get_mad_type(u16 port_id);

View file

@ -323,6 +323,9 @@ int q6asm_stream_open_write_v4(struct audio_client *ac, uint32_t format,
uint16_t bits_per_sample, int32_t stream_id,
bool is_gapless_mode);
int q6asm_open_read_compressed(struct audio_client *ac, uint32_t format,
uint32_t passthrough_flag);
int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format,
uint32_t passthrough_flag);

View file

@ -35,6 +35,7 @@ struct audio_uevent_data {
int q6core_init_uevent_data(struct audio_uevent_data *uevent_data, char *name);
void q6core_destroy_uevent_data(struct audio_uevent_data *uevent_data);
int q6core_send_uevent(struct audio_uevent_data *uevent_data, char *name);
int q6core_send_uevent_env(struct audio_uevent_data *uevent_data, char *env[]);
int q6core_get_avcs_api_version_per_service(uint32_t service_id);
#define ADSP_CMD_SET_DTS_EAGLE_DATA_ID 0x00012919