dsp: afe: add support for swr wakeup irq events

Add support for soundwire wakeup irq registration and event
notification from afe.

Change-Id: I97abe0a8bb571b997a52f90e0a0f57a26c714251
Signed-off-by: Ramprasad Katkam <katkam@codeaurora.org>
This commit is contained in:
Ramprasad Katkam
2018-08-31 03:31:54 +05:30
committed by Gerrit - the friendly Code Review server
parent b5528d39f2
commit 250075f808
3 changed files with 129 additions and 0 deletions

View File

@@ -94,6 +94,7 @@ struct afe_ctl {
atomic_t state; atomic_t state;
atomic_t status; atomic_t status;
wait_queue_head_t wait[AFE_MAX_PORTS]; wait_queue_head_t wait[AFE_MAX_PORTS];
wait_queue_head_t wait_wakeup;
struct task_struct *task; struct task_struct *task;
void (*tx_cb)(uint32_t opcode, void (*tx_cb)(uint32_t opcode,
uint32_t token, uint32_t *payload, void *priv); uint32_t token, uint32_t *payload, void *priv);
@@ -145,6 +146,7 @@ struct afe_ctl {
u32 island_mode[AFE_MAX_PORTS]; u32 island_mode[AFE_MAX_PORTS];
struct vad_config vad_cfg[AFE_MAX_PORTS]; struct vad_config vad_cfg[AFE_MAX_PORTS];
struct work_struct afe_dc_work; struct work_struct afe_dc_work;
struct notifier_block event_notifier;
}; };
static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX]; static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
@@ -367,6 +369,23 @@ static void afe_notify_dc_presence_work_fn(struct work_struct *work)
__func__, event, ret); __func__, event, ret);
} }
static int afe_aud_event_notify(struct notifier_block *self,
unsigned long action, void *data)
{
switch (action) {
case SWR_WAKE_IRQ_REGISTER:
afe_send_cmd_wakeup_register(data, true);
break;
case SWR_WAKE_IRQ_DEREGISTER:
afe_send_cmd_wakeup_register(data, false);
break;
default:
pr_err("%s: invalid event type: %lu\n", __func__, action);
return -EINVAL;
}
return 0;
}
static const char *const afe_event_port_text[] = { static const char *const afe_event_port_text[] = {
"PORT=Primary", "PORT=Primary",
@@ -569,6 +588,8 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
return -EINVAL; return -EINVAL;
} }
wake_up(&this_afe.wait[data->token]); wake_up(&this_afe.wait[data->token]);
} else if (data->opcode == AFE_EVENT_MBHC_DETECTION_SW_WA) {
msm_aud_evt_notifier_call_chain(SWR_WAKE_IRQ_EVENT, NULL);
} else if (data->payload_size) { } else if (data->payload_size) {
uint32_t *payload; uint32_t *payload;
uint16_t port_id = 0; uint16_t port_id = 0;
@@ -640,6 +661,10 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv)
atomic_set(&this_afe.state, payload[1]); atomic_set(&this_afe.state, payload[1]);
wake_up(&this_afe.wait[data->token]); wake_up(&this_afe.wait[data->token]);
break; break;
case AFE_SVC_CMD_EVENT_CFG:
atomic_set(&this_afe.state, payload[1]);
wake_up(&this_afe.wait_wakeup);
break;
default: default:
pr_err("%s: Unknown cmd 0x%x\n", __func__, pr_err("%s: Unknown cmd 0x%x\n", __func__,
payload[0]); payload[0]);
@@ -2863,6 +2888,40 @@ int afe_send_spdif_ch_status_cfg(struct afe_param_id_spdif_ch_status_cfg
} }
EXPORT_SYMBOL(afe_send_spdif_ch_status_cfg); EXPORT_SYMBOL(afe_send_spdif_ch_status_cfg);
int afe_send_cmd_wakeup_register(void *handle, bool enable)
{
struct afe_svc_cmd_evt_cfg_payload wakeup_irq;
int ret;
pr_debug("%s: enter\n", __func__);
wakeup_irq.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE),
APR_PKT_VER);
wakeup_irq.hdr.pkt_size = sizeof(wakeup_irq);
wakeup_irq.hdr.src_port = 0;
wakeup_irq.hdr.dest_port = 0;
wakeup_irq.hdr.token = 0x0;
wakeup_irq.hdr.opcode = AFE_SVC_CMD_EVENT_CFG;
wakeup_irq.event_id = AFE_EVENT_ID_MBHC_DETECTION_SW_WA;
wakeup_irq.reg_flag = enable;
pr_debug("%s: cmd device start opcode[0x%x] register:%d\n",
__func__, wakeup_irq.hdr.opcode, wakeup_irq.reg_flag);
ret = afe_apr_send_pkt(&wakeup_irq, &this_afe.wait_wakeup);
if (ret) {
pr_err("%s: AFE wakeup command register %d failed %d\n",
__func__, enable, ret);
} else if (this_afe.task != current) {
this_afe.task = current;
pr_debug("task_name = %s pid = %d\n",
this_afe.task->comm, this_afe.task->pid);
}
return ret;
}
EXPORT_SYMBOL(afe_send_cmd_wakeup_register);
static int afe_send_cmd_port_start(u16 port_id) static int afe_send_cmd_port_start(u16 port_id)
{ {
struct afe_port_cmd_device_start start; struct afe_port_cmd_device_start start;
@@ -8062,6 +8121,7 @@ int __init afe_init(void)
this_afe.vad_cfg[i].pre_roll = 0; this_afe.vad_cfg[i].pre_roll = 0;
init_waitqueue_head(&this_afe.wait[i]); init_waitqueue_head(&this_afe.wait[i]);
} }
init_waitqueue_head(&this_afe.wait_wakeup);
wakeup_source_init(&wl.ws, "spkr-prot"); wakeup_source_init(&wl.ws, "spkr-prot");
ret = afe_init_cal_data(); ret = afe_init_cal_data();
if (ret) if (ret)
@@ -8086,6 +8146,9 @@ int __init afe_init(void)
INIT_WORK(&this_afe.afe_sec_spdif_work, INIT_WORK(&this_afe.afe_sec_spdif_work,
afe_notify_sec_spdif_fmt_update_work_fn); afe_notify_sec_spdif_fmt_update_work_fn);
this_afe.event_notifier.notifier_call = afe_aud_event_notify;
msm_aud_evt_blocking_register_client(&this_afe.event_notifier);
return 0; return 0;
} }

View File

@@ -4205,6 +4205,69 @@ union afe_port_config {
struct afe_param_id_cdc_dma_cfg_t cdc_dma; struct afe_param_id_cdc_dma_cfg_t cdc_dma;
} __packed; } __packed;
/*
* AFE event registration related APIs and corresponding payloads
*/
#define AFE_SVC_CMD_EVENT_CFG 0x000100FE
#define AFE_CMD_APPS_WAKEUP_IRQ_REGISTER_MINOR_VERSION 0x1
/* Flag to indicate AFE to register APPS wakeup Interrupt */
#define AFE_APPS_WAKEUP_IRQ_REGISTER_FLAG 1
/* Flag to indicate AFE to de-register APPS wakeup Interrupt */
#define AFE_APPS_WAKEUP_IRQ_DEREGISTER_FLAG 0
/* Default interrupt trigger value. */
#define DEFAULT_SETTINGS 0x00000001
/* Interrupt is triggered only if the input signal at the source is high. */
#define LEVEL_HIGH_TRIGGER 0x00000002
/* Interrupt is triggered only if the input signal at the source is low. */
#define LEVEL_LOW_TRIGGER 0x00000003
/* Interrupt is triggered only if the input signal at the source transitions
*from low to high.
*/
#define RISING_EDGE_TRIGGER 0x00000004
/* Interrupt is triggered only if the input signal at the source transitions
*from high to low.
*/
#define FALLING_EDGE_TRIGGER 0x00000005
/* Macro for invalid trigger type. This should not be used. */
#define INVALID_TRIGGER 0x00000006
#define AFE_EVENT_ID_MBHC_DETECTION_SW_WA 0x1
/* @weakgroup weak_afe_svc_cmd_evt_cfg_payload
*
* This is payload of each event that is to be
* registered with AFE service.
*/
struct afe_svc_cmd_evt_cfg_payload {
struct apr_hdr hdr;
uint32_t event_id;
/* Unique ID of the event.
*
* @values
* -# AFE_EVENT_ID_MBHC_DETECTION_SW_WA
*/
uint32_t reg_flag;
/* Flag for registering or de-registering an event.
* @values
* - #AFE_SVC_REGISTER_EVENT_FLAG
* - #AFE_SVC_DEREGISTER_EVENT_FLAG
*/
} __packed;
#define AFE_EVENT_MBHC_DETECTION_SW_WA 0x0001010F
#define AFE_PORT_CMD_DEVICE_START 0x000100E5 #define AFE_PORT_CMD_DEVICE_START 0x000100E5
/* Payload of the #AFE_PORT_CMD_DEVICE_START.*/ /* Payload of the #AFE_PORT_CMD_DEVICE_START.*/

View File

@@ -442,4 +442,7 @@ int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats,
u16 port); u16 port);
int afe_cal_init_hwdep(void *card); int afe_cal_init_hwdep(void *card);
int afe_send_port_island_mode(u16 port_id); int afe_send_port_island_mode(u16 port_id);
int afe_send_cmd_wakeup_register(void *handle, bool enable);
void afe_register_wakeup_irq_callback(
void (*afe_cb_wakeup_irq)(void *handle));
#endif /* __Q6AFE_V2_H__ */ #endif /* __Q6AFE_V2_H__ */