MTK_HDMI 驱动

MTK_HDMI驱动

简介

HDMI(High-DefinitionMultimediaInterface)又被称为高清晰度多媒体接口,是首个支持在单线缆上传输,不经过压缩的全数字高清晰度、多声道音频和智能格式与控制命令数据的数字接口。HDMI接口由SiliconImage美国晶像公司倡导,联合索尼、日立、松下、飞利浦、汤姆逊、东芝等八家著名的消费类电子制造商联合成立的工作组共同开发的。

MobileHigh-Definition Link (MHL) 移动终端高清影音标准接口,是一种连接便携式消费电子装置的影音标准接口,MHL仅使用一条信号电缆,通过标准HDMI输入接口即可呈现于高清电视上。它运用了现有的MicroUSB接口,不论是手机、数码相机、数字摄影机皆可将完整的媒体内容直接传输到电视上且不损伤影片高分辨率的效果。

HDMI驱动程序

HDMI驱动的组成

HDMI驱动涉及的驱动:hdmitx虚拟Platform驱动、FB_Buffer驱动、Mhal驱动、dispsys驱动、(DSIDBIDPI)总线驱动、LCM驱动。

Hdmitx虚拟驱动主要是为了管理MhlHDMIIC驱动而创建的驱动,MDMIMHL驱动主要提供一些接口,IC只要实现这些接口,我们就可以调用这些接口进行操作。Dispsys驱动,我感觉是MTK自己的和PlatformDisp_controner驱动(MTK讲平台相关的代码独立开来,方便开发,这里只是我个人的理解)。

接下来,我主要讲解的是HDMIMHL)驱动整个触发过程以及如何上报Event给上层。

1.1hdmitx虚拟Platform驱动

mediatek/kernel/drivers/hdmitx/

staticint __init hdmi_init(void)

{

intret = 0;

printk("[hdmi]%s\n",__func__);



if(platform_driver_register(&hdmi_driver))

{

printk("[hdmi]failedto register mtkfb driver\n");

return-1;

}


…………………………………………………………………………………………………

init_hdmi_mmp_events();


if(!hdmi_drv_init_context())

{

printk("[hdmi]%s,hdmi_drv_init_context fail\n", __func__);

returnHDMI_STATUS_NOT_IMPLEMENTED;

}


p->output_mode= hdmi_params->output_mode;

hdmi_drv->init();

HDMI_LOG("Outputmode is %s\n",(hdmi_params->output_mode==HDMI_OUTPUT_MODE_DPI_BYPASS)?"HDMI_OUTPUT_MODE_DPI_BYPASS":"HDMI_OUTPUT_MODE_LCD_MIRROR");


…………………………………………………………………………………….

HDMI_DBG_Init();


hdmi_switch_data.name= "hdmi";

hdmi_switch_data.index= 0;

hdmi_switch_data.state= NO_DEVICE;


//for support hdmi hotplug, inform AP the event

ret=switch_dev_register(&hdmi_switch_data);
……………………………………………………………………………………………………………….

}


module_init(hdmi_init);

上面是hdmi虚拟模块驱动加载函数。上面会Platform方式进行注册一个设备,对PlatformBus 了解的应该不难(bus的匹配规则是名字相同,一旦名字匹配成功就会调用Driverprobe函数)。下面看下这个probe函数到底做了哪些事情。



staticint hdmi_probe(struct platform_device *pdev)

{

intret = 0;

structclass_device *class_dev = NULL;


。。。。。。。。。。。。。。。。。。。
printk("[hdmi]alloc_chrdev_regionfail\n");

return-1;

}


/*For character driver register to system, device number binded to fileoperations */

hdmi_cdev= cdev_alloc();

hdmi_cdev->owner= THIS_MODULE;

hdmi_cdev->ops= &hdmi_fops;

ret= cdev_add(hdmi_cdev, hdmi_devno, 1);


。。。。。。。。。。。。。。。。。。。。。。。。。。。

if(!hdmi_drv_init_context())

{

printk("[hdmi]%s, hdmi_drv_init_context fail\n",__func__);

returnHDMI_STATUS_NOT_IMPLEMENTED;

}


init_waitqueue_head(&hdmi_video_mode_wq);

INIT_LIST_HEAD(&hdmi_video_mode_buffer_list);


init_waitqueue_head(&hdmi_update_wq);

hdmi_update_task= kthread_create(hdmi_update_kthread, NULL, "hdmi_update_kthread");

wake_up_process(hdmi_update_task);


init_waitqueue_head(&hdmi_overlay_config_wq);

hdmi_overlay_config_task= kthread_create(hdmi_overlay_config_kthread, NULL,"hdmi_overlay_config_kthread");

wake_up_process(hdmi_overlay_config_task);


init_waitqueue_head(&hdmi_rdma_config_wq);

init_waitqueue_head(&reg_update_wq);

init_waitqueue_head(&dst_reg_update_wq);


return0;

}


Probe函数主要是创建了HDMI的设备、调用hdmi_drv_init_context获得具体的MHL(HDMI)IC实现的函数列表接口、创建HDMI更新线程以及Overlayconfig 线程。

      1. hdmi_drv_init_context初始化函数

staticBOOL hdmi_drv_init_context(void)

{

staticconst HDMI_UTIL_FUNCS hdmi_utils =

{

.udelay = hdmi_udelay,

.mdelay = hdmi_mdelay,

.state_callback =hdmi_state_callback,

};


if(hdmi_drv != NULL)

returnTRUE;



hdmi_drv= (HDMI_DRIVER*)HDMI_GetDriver();


if(NULL == hdmi_drv) return FALSE;


hdmi_drv->set_util_funcs(&hdmi_utils);

hdmi_drv->get_params(hdmi_params);


returnTRUE;

}

上面完成了获得具体的MHL(HDMI)IC的驱动接口HDMI_DRIVERHdmi_utils赋值给hdmi_drvHDMI_GetDriver这个函数是全局类型的,我们实现了哪个IC驱动,就会调用实现的HDMI_GetDriver函数。

我们使用的Sii8338这个IC,厂商会实现HDMI_DRIVER这个Functionlist

mediatek/kernel/drivers/mhl/linux_driver/hdmi_drv.c



constHDMI_DRIVER* HDMI_GetDriver(void)

{

staticconst HDMI_DRIVER HDMI_DRV =

{

.set_util_funcs= hdmi_drv_set_util_funcs,

.get_params = hdmi_drv_get_params,

.init = hdmi_drv_init,

.enter = hdmi_drv_enter,

.exit = hdmi_drv_exit,

.suspend = hdmi_drv_suspend,

.resume = hdmi_drv_resume,

.video_config = hdmi_drv_video_config,

.audio_config = hdmi_drv_audio_config,

.video_enable = hdmi_drv_video_enable,

.audio_enable = hdmi_drv_audio_enable,

.power_on = hdmi_drv_power_on,

.power_off = hdmi_drv_power_off,

.get_state = hdmi_drv_get_state,

.log_enable = hdmi_drv_log_enable

};


HDMI_FUNC();

return&HDMI_DRV;

}

      1. hdmi更新函数

下面的线程更新函数在Hdmi虚拟Platform驱动Probe函数里面进行了创建,通过原子变量、workqueue实现的。

  1. staticint hdmi_update_kthread(void *data)

  2. {

  3. 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

  4. for(;; ) {

  5. wait_event_interruptible(hdmi_update_wq,atomic_read(&hdmi_update_event));


  1. atomic_set(&hdmi_update_event,0);

  2. hdmi_update_impl();

  3. if(kthread_should_stop())

  4. break;

  5. }


  6. return0;

  7. }

上面创建的线程是一个for无限循环,当hdmi_update_eventFalse的时候当前线程就会进入睡眠,当为True的时候就会唤醒这个线程调用hdmi_update_impl函数进行Update。这里我们要关注的是这个线程是什么时候唤醒的(这里留个悬念,在下面会进行讲解)。同样的hdmi_overlay_config_kthread这个线程执行的流程和这个差不多,这里就不再多详述。

1.2FB_Buffer中断

在上面说的悬念,就是Hdmiupdate 线程是在什么时候唤醒的呢?


staticvoid mtkfb_lcd_complete_interrupt(void *param)

{

if(atomic_read(&has_pending_update))

{

wake_up_interruptible(&screen_update_wq);

}


#ifdefined(MTK_HDMI_SUPPORT)

hdmi_source_buffer_switch();

if(is_hdmi_active())

{

hdmi_update();

}

#endif


}

上面的是LCD的中断回调处理函数。MTK_HDMI_SUPPORT这个宏在控制HDMI的部分。这个宏是在ProjectConfig.mk里面在控制的。

mediatek/config/mt6589_phone_k89v2/ProjectConfig.mk

上面的MTK_HDMI_SUPPORT=yes说明是在支持HDMI的,下面的CUSTOM_KERNEL_HDMI是在配置我们所使用的HDMIIC 驱动的目录。目前我们使用的是Sii8338这个IC,在驱动的Makefile目录里面进行了判断:mediatek/kernel/drivers/mhl/Makefile

include$(MTK_PATH_BUILD)/common.mk

ifeq($(CUSTOM_KERNEL_HDMI),Sii8338)

obj-y+= $(call all-subdir-src-or-makefile)

endif

obj-y+= dummy.o

再次回到FB_buffer的中断处理函数中来;

hdmi_source_buffer_switch

voidhdmi_source_buffer_switch(void)

{

//printk("lcdwrite buffer:%d\n", hdmi_buffer_lcdw_id);


RET_VOID_IF_NOLOG(IS_HDMI_NOT_ON());

RET_VOID_IF_NOLOG(p->output_mode== HDMI_OUTPUT_MODE_DPI_BYPASS);

RET_VOID_IF_NOLOG(IS_HDMI_IN_VIDEO_MODE());


if(p->lcm_is_video_mode)

{

atomic_set(&hdmi_overlay_config_event,1);

wake_up_interruptible(&hdmi_overlay_config_wq);

//DISP_Config_Overlay_to_Memory(temp_mva_w+ p->lcm_width * p->lcm_height * 3 * hdmi_buffer_lcdw_id_tmp,1);

}

else

{

hdmi_buffer_lcdw_id= (hdmi_buffer_lcdw_id+1)%hdmi_params->intermediat_buffer_num;

DISP_Config_Overlay_to_Memory(temp_mva_w+ p->lcm_width * p->lcm_height * 3 * hdmi_buffer_lcdw_id, 1);

}

}

当我们支持HDMI的时候,我们会执行上面的函数,根据现在的LCM的模式是vedio还是cmd模式执行不同的case,当是vedio模式的时候就会将hdmi_overlay_config_event置为1,从而调用上面的更新函数hdmi_overlay_config_kthread,如果不是vedio模式就会直接配置overlay的配置Memory的函数。

接下来会执行:

/*Will be called in LCD Interrupt handler to check whether HDMI isactived */

boolis_hdmi_active(void)

{

returnIS_HDMI_ON();

}

这里会判断我们有没有HDMI的插入。IS_HDMI_ON函数的实现如下:

#defineIS_HDMI_ON() (HDMI_POWER_STATE_ON == atomic_read(&p->state))

上面是判断&p->state的值,如果为True的时候,我们就会执行hdmi_update()函数进行Update到外置显示器上面。

我们现在Trace下这个state是什么时候置为True的,我们用逆推得方法找出在哪里置为True的。下面的执行流程全部是逆方向的。


#defineSET_HDMI_ON() atomic_set(&p->state,HDMI_POWER_STATE_ON)

TraceSET_HDMI_ON在哪里调用



/*static*/void hdmi_resume(void)

{

SET_HDMI_ON();

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

hdmi_dpi_power_switch(true);

hdmi_drv->resume();

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
}


TraceSET_HDMI_ON在哪里调用


/*HDMI Driver state callback function */

voidhdmi_state_callback(HDMI_STATE state)

{

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

switch(state)

。。。。。。。。。。。。。。。。。。
case HDMI_STATE_ACTIVE:

{

hdmi_resume();

代码路径是:mediatek/kernel/drivers/mhl/component/mhl_tx/si_mhl_tx.c.这里会根据根据传递的State参数进行调用hdmi_state_callback

void SiiMhlTxNotifyDsHpdChange(uint8_t dsHpdStatus )

{

//xuecheng, notify for cable plug in

hdmi_state_callback(HDMI_STATE_NO_DEVICE);

}

else

{

//xuecheng, notify for cable plug in

hdmi_state_callback(HDMI_STATE_ACTIVE);

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
}



staticvoid Int1Isr(void)

{………………………………………………………

TX_DEBUG_PRINT(("Drv:Downstream HPD changed to: %02X\n", (int) cbusStatus));

SiiMhlTxNotifyDsHpdChange(status );




voidSiiMhlTxDeviceIsr( void )

{
…………………………………………………………………………………….

MhlCbusIsr();

Int5Isr();

Int1Isr();

Int2Isr();

}


下面的Hdmi_drv_init函数是HDMIIC 驱动提供的接口函数列表里面的初始化函数。是注册一个中断,当有HDMI插入的时候,就会触发这个中断触发函数。将状态报告给上层。

staticint hdmi_drv_init(void)

{


halStatus= HalOpenI2cDevice(MHL_PART_NAME, MHL_DRIVER_NAME);

//msleep(200);

#ifdefSiI8338DRIVER_INTERRUPT_MODE

halStatus= HalInstallIrqHandler(SiiMhlTxDeviceIsr);



以上就是HDMI整个触发的过程,那么上层是如何知道我们的HDMI的状态的呢?

1.3HDMI驱动和上层交互

上层一般是通过设备文件和底层进行交互的,在这里是通过开关文件进行交互的,根据开关文件的状态的不同,上层进行不同的操作。

hdmi_switch_data.name= "hdmi";

hdmi_switch_data.index= 0;

hdmi_switch_data.state= NO_DEVICE;


//for support hdmi hotplug, inform AP the event

ret= switch_dev_register(&hdmi_switch_data);

上面是我们在驱动里面创建的开关设备文件。我们会根据HDMI的不同状态去改变它的状态的。

当有HDMI插入的时候,我们会执行下面的代码:

caseHDMI_STATE_ACTIVE:

{

hdmi_resume();

//forceupdate screen

DISP_UpdateScreen(0,0, DISP_GetScreenWidth(), DISP_GetScreenHeight());

if(HDMI_OUTPUT_MODE_LCD_MIRROR == p->output_mode)

{

msleep(1000);

}

switch_set_state(&hdmi_switch_data,HDMI_STATE_ACTIVE);

HDMI的状态一共有以下几种状态:

typedefenum{

HDMI_STATE_NO_DEVICE,

HDMI_STATE_ACTIVE,

#ifdefined(MTK_MT8193_HDMI_SUPPORT)

HDMI_STATE_PLUGIN_ONLY,

HDMI_STATE_EDID_UPDATE,

HDMI_STATE_CEC_UPDATE

#endif

}HDMI_STATE;

上面是通过改变/sys/class/switch/hdmi/state的值,上层通过监听它的值来判断有没有HDMI的插入。


  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: MTK_DRM_DRIVERS是一组用于支持媒体Tek的数码芯片和ARM处理器的虚拟设备驱动程序集。该集合主要包含了支持解码/编码、图形处理和视频传输的核心驱动程序,其中包括V4L2驱动程序、HDMI驱动程序、VDEC和VENC驱动程序,以及屏幕刷新管理(FB)驱动程序等等。这些驱动程序都是为了支持MTK平台上不同的多媒体功能所开发的。 由于MTK的平台复杂性,其需要准确的硬件支持和软件配合。MTK_DRM_DRIVERS的设计是为高效地协同开发硬件规格与软件驱动程序。该驱动程序集有效地支持了多媒体应用程序运行时所需要的显卡和视频输出功能,为开发者提供足够的资源来应对不断变化的业务需求。 总之,MTK_DRM_DRIVERS是MTK平台上用于管理和支持媒体Tek芯片和ARM处理器的一组重要软件驱动程序,它对于保障硬件和软件的协同开发和多媒体应用程序的高效运行都具有至关重要的作用。 ### 回答2: mtk_drm_drivers 是针对 联发科技(MediaTek)的系统芯片系列所开发的一个 DRM 驱动程序。MTK是集成电路硅基芯片设计制造商,其系统芯片常常被用于手机、平板电脑等移动设备中。 DRM (Direct Rendering Manager) 是Linux内核的一个子系统,负责管理系统的图形显示,支持多个图形驱动mtk_drm_drivers 所开发的 DRM 驱动程序主要用于管理基于联发科技芯片的移动设备的图形系统,包括显示、刷新、屏幕控制等。 mtk_drm_drivers 的开发工作是开源的,主要的开发者来自联发科技,该驱动程序是通过向 Linux 内核提交补丁的方式逐步实现的。mtk_drm_drivers 是一个复杂的系统,由许多不同部分组成,包括显卡驱动、触摸屏驱动、音频处理、图像处理等。它提供了一些功能强大而灵活的接口,允许开发人员对其进行修改和扩展,以适应各种应用场景。 mtk_drm_drivers 的发展主要受到了 Linux 内核演进的影响,因为它需要紧密地与内核协作才能实现。作为针对联发科技系统芯片的一个主要开源项目,它面临着许多挑战和机遇。随着移动设备市场不断发展,mtk_drm_drivers 的重要性也会逐步增大。 ### 回答3: mtk_drm_drivers是指用于支持MediaTek(MTK)SoC芯片组中的显示和图形操作的驱动程序集合。这些驱动程序被编写并优化,以提供最佳的图形性能和稳定性,能够支持当前流行的视频编解码器 (codec) 和显示接口。 随着人们在移动设备上使用的应用程序变得越来越多,对高质量的视频和流畅的图形性能的需求也不断增加。 MTK_drm_drivers提供了可靠的底层支持,其能使屏幕保持高清和顺畅运行。这项技术不仅用于智能手机,还被广泛应用于平板电脑、可穿戴设备和其他各种设备。 mtk_drm_drivers驱动程序提供了包括HDMI、DisplayPort、MIPI-DSI和LVDS等多种显示接口的支持,这样使硬件制造商可以选择最优的显示技术以满足其用户的需求。 对于开发人员和制造商来说,mtk_drm_drivers提供了一个可扩展的平台,使其能够开发和集成其他新的驱动程序或模块。这项技术也可以被用于开发运行在新一代设备上的更高级别的图形应用程序。 除此之外,mtk_drm_drivers高度可配置,支持不同的输出分辨率和DPI设置,保证了在不同设备和操作系统上的体验统一。它还提供了灵活的屏幕旋转、裁剪和缩放功能,有助于用户实现自适应屏幕布局。 总之,mtk_drm_drivers为移动设备提供了高度优化的图形和显示性能,其可以使硬件生产商开发出更加强大和高效的移动设备。这不仅提升了用户的体验和满意度,同时也为整个移动产业注入了更多的活力和创新力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值