三、HDMI IC的驱动分析,这里用的是lt8618sxb的芯片,具体分析见kernel-3.18\drivers\misc\mediatek\hdmi\lt8618sxb.c。 1、lt8618sxb_init()主要是创建了hdmi的线程和定时器; static int lt8618sxb_init(void) { HDMI_DEF_LOG("lt8618sxb_init\n"); init_waitqueue_head(&hdmi_timer_wq); hdmi_timer_task= kthread_create(hdmi_timer_kthread, NULL, "hdmi_timer_kthread"); wake_up_process(hdmi_timer_task); init_waitqueue_head(<8618sxb_nlh_wq); lt8618sxb_nlh_task= kthread_create(lt8618sxb_nlh_kthread, NULL,"lt8618sxb_nlh_kthread"); wake_up_process(lt8618sxb_nlh_task); memset((void*)&r_hdmi_timer, 0, sizeof(r_hdmi_timer)); r_hdmi_timer.expires= jiffies + 1000 / (1000 / HZ); /*wait 1s to stable */ r_hdmi_timer.function= hdmi_poll_isr; r_hdmi_timer.data= 0; init_timer(&r_hdmi_timer); add_timer(&r_hdmi_timer); lt8618sxb_hdmi_debug_init(); lt8618sxb_hdmi_factory_callback= NULL; return0; } 2、 hdmi_timer_impl()就是在创建的HDMI的线程中调用的,主要是检测hdmi插拔状态(HDMI插拔状态是通过I2C读取IC寄存器的值,在此之前一定要确保I2C是正常通信的),并将插拔的状态上报到switch设备。 void hdmi_timer_impl(void) { //HDMI_DEF_LOG("enter%s\n",__func__); //LT8618SX_Video_check(); //HDMI_DEF_LOG("lt8618sxb_hdmiinit:%d,lt8618sxb_hotinit:%d,lt8618sxb_hotplugstate: %d\n",lt8618sxb_hdmiinit,lt8618sxb_hotinit,lt8618sxb_hotplugstate); if(lt8618sxb_hdmiinit == 0) { lt8618sxb_hdmiinit= 1; /*lt8618sxb_power_off(); */ //vInitAvInfoVar(); return; } if(lt8618sxb_hotinit != 1) lt8618sxb_hdmiinit++; #if defined(CONFIG_HAS_EARLYSUSPEND) if(lt8618sxb_hdmiearlysuspend == 1) { #else { #endif if(((lt8618sxb_hdmiinit > 5) || (lt8618sxb_hotinit == 0)) &&(lt8618sxb_hotinit != 1)) { //MT8193_PLUG_LOG("enterhere!\n"); if(bCheckPordHotPlug(PORD_MODE | HOTPLUG_MODE) == FALSE) { if((lt8618sxb_hotplugstate == HDMI_STATE_HOT_PLUGIN_AND_POWER_ON) && (lt8618sxb_hotinit == 2)) { //vSetSharedInfo(SI_HDMI_RECEIVER_STATUS,HDMI_PLUG_OUT); lt8618sxb_hotplugstate= HDMI_STATE_HOT_PLUG_OUT; vPlugDetectService(HDMI_STATE_HOT_PLUG_OUT); MT8193_PLUG_LOG ("[detectcable1] lt8618sxb_hotinit =%d,lt8618sxb_hdmiinit=%d\n", lt8618sxb_hotinit, lt8618sxb_hdmiinit); } #if 1 if((lt8618sxb_hotinit == 0) && (bCheckPordHotPlug(HOTPLUG_MODE)== TRUE)) { lt8618sxb_hotinit= 2; lt8618sxb_hotplugstate= HDMI_STATE_HOT_PLUGIN_AND_POWER_ON; vPlugDetectService(HDMI_STATE_HOT_PLUGIN_AND_POWER_ON); //vWriteHdmiIntMask(0xff); /* INT mask MDI */ MT8193_PLUG_LOG ("[detectcable2] lt8618sxb_hotinit =%d,lt8618sxb_hdmiinit=%d\n", lt8618sxb_hotinit, lt8618sxb_hdmiinit); } #endif if((lt8618sxb_hotinit == 0) && (bCheckPordHotPlug(HOTPLUG_MODE)== FALSE)) { lt8618sxb_hotinit= 2; lt8618sxb_hotplugstate= HDMI_STATE_HOT_PLUG_OUT; vPlugDetectService(HDMI_STATE_HOT_PLUG_OUT); MT8193_PLUG_LOG ("[detectcable1] lt8618sxb_hotinit =%d,lt8618sxb_hdmiinit=%d\n", lt8618sxb_hotinit, lt8618sxb_hdmiinit); } }else if ((lt8618sxb_hotplugstate == HDMI_STATE_HOT_PLUG_OUT) && (bCheckPordHotPlug(PORD_MODE |HOTPLUG_MODE) == TRUE)) { lt8618sxb_hotplugstate= HDMI_STATE_HOT_PLUGIN_AND_POWER_ON; lt8618sxb_hotinit= 2; vPlugDetectService(HDMI_STATE_HOT_PLUGIN_AND_POWER_ON); //vWriteHdmiIntMask(0xff); /* INT mask MDI */ MT8193_PLUG_LOG ("[detectcable3] lt8618sxb_hotinit =%d,lt8618sxb_hdmiinit=%d\n", lt8618sxb_hotinit, lt8618sxb_hdmiinit); }else if ((lt8618sxb_hotplugstate == HDMI_STATE_HOT_PLUGIN_AND_POWER_ON) && ((e_hdcp_ctrl_state ==HDCP_WAIT_RI) || (e_hdcp_ctrl_state ==HDCP_CHECK_LINK_INTEGRITY))) { //MT8193_PLUG_LOG("enter here2!\n"); if(bCheckHDCPStatus(HDCP_STA_RI_RDY)) { vSetHDCPState(HDCP_CHECK_LINK_INTEGRITY); vSendHdmiCmd(HDMI_HDCP_PROTOCAL_CMD); } } lt8618sxb_hdmiinit= 1; } } if(lt8618sxb_hdmiCmd == HDMI_PLUG_DETECT_CMD) { vClearHdmiCmd(); /*vcheckhdmiplugstate(); */ /*vPlugDetectService(e_hdmi_ctrl_state); */ }else if (lt8618sxb_hdmiCmd == HDMI_HDCP_PROTOCAL_CMD) { vClearHdmiCmd(); } } 总结: HDMI工作流程就是linux kernel bootup,加载mtk_extd_mgr_init,获得HDMI驱动接口,匹配成功调用mtk_extd_mgr_probe,初始化hdmi,上层应用检测属性ro.mtk_hdmi_support=1,支持HDMI功能,setting hdmi poweron,底层收到MTK_HDMI_AUDIO_VIDEO_ENABLE将会hdmi_enable(),hdmi_enable()调用hdmi_drv_init()→hdmi_power_on();HDMI进入待机状态,等待hdmi设备的插入。
|