struct msm_ext_disp {
struct platform_device *pdev;
enum msm_ext_disp_type current_disp;
struct msm_ext_disp_audio_codec_ops *ops;
struct switch_dev hdmi_sdev;
struct switch_dev audio_sdev;
bool ack_enabled;
bool audio_session_on;
struct list_head display_list;
struct mutex lock;
struct completion hpd_comp;
bool update_audio;
u32 flags;
};
Freamwork:
WiredAccessoryManager:
WiredAccessoryManager //監聽Uevent;
msm_ext_disp_register_intf
init_data->intf_ops.hpd = msm_ext_disp_hpd;
msm_ext_disp_hpd
msm_ext_disp_process_audio
msm_ext_disp_send_audio_notification
switch_set_state
sdm660_64:/sys/class/switch/hdmi_audio/subsystem/hdmi_audio/state
./msm-4.4/drivers/video/fbdev/msm/mdss_hdmi_tx.c:419: if (hdmi_ctrl && hdmi_ctrl->ext_audio_data.intf_ops.hpd)
hdmi_tx_send_audio_notification
kernel notify 過程;
struct lt9611 {
......
struct notifier_block lt9611_notif;
}
lt9611_notify_clients(&pdata->dev_info, MSM_DBA_CB_AUDIO_CONNECT);
pdata->lt9611_notif.notifier_call = lt9611_notifier_callback;
static int lt9611_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
{
struct fb_event *evdata = data;
int *blank;
struct lt9611 *pdata = container_of(self, struct lt9611, lt9611_notif);
if (evdata && evdata->data && event == FB_EVENT_BLANK) {
blank = evdata->data;
if (*blank == FB_BLANK_UNBLANK){
if(lt9611_connected == 0){
lt9611_notify_clients(&pdata->dev_info,MSM_DBA_CB_HPD_CONNECT);
lt9611_connected = 1;
pr_err("%s: Rx CONNECTED\n", __func__);
}
}//lt9611_resume(pdata);
......
}
fb_register_client(&pdata->lt9611_notif);
./drivers/video/fbdev/core/fb_notify.c
int fb_register_client(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&fb_notifier_list, nb);
}
int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
struct notifier_block *n)
{
......
return notifier_chain_register(&nh->head, n);
......
}
static int notifier_chain_register(struct notifier_block **nl,
struct notifier_block *n)
{
while ((*nl) != NULL) {
if (n->priority > (*nl)->priority)
break;
nl = &((*nl)->next);
}
n->next = *nl;
rcu_assign_pointer(*nl, n);
return 0;
}
static void lt9611_notify_clients(struct msm_dba_device_info *dev,
enum msm_dba_callback_event event)
{
struct msm_dba_client_info *c;
struct list_head *pos = NULL;
if (!dev) {
pr_err("%s: invalid input\n", __func__);
return;
}
list_for_each(pos, &dev->client_list) {
c = list_entry(pos, struct msm_dba_client_info, list);
pr_err("%s: notifying event %d to client %s\n", __func__,
event, c->client_name);=
if (c && c->cb)
c->cb(c->cb_data, event);
}
}
./kernel/include/video/msm_dba.h
enum msm_dba_callback_event {
MSM_DBA_CB_REMOTE_INT = BIT(0),
MSM_DBA_CB_HDCP_LINK_AUTHENTICATED = BIT(1),
MSM_DBA_CB_HDCP_LINK_UNAUTHENTICATED = BIT(2),
MSM_DBA_CB_HPD_CONNECT = BIT(3),
MSM_DBA_CB_HPD_DISCONNECT = BIT(4),
MSM_DBA_CB_VIDEO_FAILURE = BIT(5),
MSM_DBA_CB_AUDIO_FAILURE = BIT(6),
MSM_DBA_CB_CEC_WRITE_SUCCESS = BIT(7),
MSM_DBA_CB_CEC_WRITE_FAIL = BIT(8),
MSM_DBA_CB_CEC_READ_PENDING = BIT(9),
MSM_DBA_CB_PRE_RESET = BIT(10),
MSM_DBA_CB_POST_RESET = BIT(11),
MSM_DBA_CB_DDC_I2C_ERROR = BIT(12),
MSM_DBA_CB_DDC_TIMEOUT = BIT(13),
};