主屏通过lt8911exb 将mipi信号转换成EDP信号输出,调试从大的方向上看,主要是两方面,一个是bootloader阶段的lt8911exb初始化,为了让现实过程更完整,需要在lk的display init之前就要将lt8911exb准备好.当lt8911exb准备好后,就可以当lt8911exb不存在,以平时的方式去调试一个屏幕。本次调试lt8911exb 的I2C接到SDM450的I2C3接口上,以下是调试步骤概要
1、原理图的简单分析
2、lt8911exb的初始化
3、bootloader阶段的屏幕调试
4、kernel阶段移植
一、原理图的简单分析
原理图分析这一块,因为涉及到具体的产品,所以这里只是简单的介绍lt8911exb主控的接口
图一
图2
图三
主控部分和I2C上拉,电平转换等都没有贴出来,以下是简单的总结一下LT8911和主控的接口描述
LT8911的mipi输入端和SDM450的主屏(mdss_dsi0)通过4lane连接
LT8911的I2C接口接SDM450的I2C3
LT8911的上电使能管脚(LCDO_PWR)接SDM450的GPIO19
LT8911的reset管脚(LCD0_RST)接SDM450的GPIO61
屏幕的上电使能(LCD0_EN)接SDM450的GPIO24
屏幕的背光使能(EDP_BL_EN)接SDM450的GPIO44
屏幕的背光接(EDP_BL_PWM)接SDM450主屏PWM
LT8911和屏幕通过2lane连接
LT8911七位I2C地址是0x29
对于LT8911的操作主要是上电、复位、初始化,对于屏幕来说就是上电是能、背光控制
二、lt8911exb初始化
主屏幕的lt8911exb初始化放在bootloader完成,由于SDM450的bootloader阶段I2C接口还没做初始化,所以我们得先初始化好I2C后,再初始化lt8911,具体过程如下
1、SDM450bootloader阶段I2C3初始化
I2C3时钟初始化
bootable/bootloader/lk/platform/msm8953/include/platform/iomap.h +#define BLSP_QUP_BASE(blsp_id, qup_id) (PERIPH_SS_BASE + 0xB5000 + 0x1000 * qup_id) +#define GCC_BLSP1_QUP3_APPS_CBCR (CLK_CTL_BASE + 0x04020) +#define GCC_BLSP1_QUP3_CMD_RCGR (CLK_CTL_BASE + 0x04000) +#define GCC_BLSP1_QUP3_CFG_RCGR (CLK_CTL_BASE + 0x04004) bootable/bootloader/lk/platform/msm8953/msm8953-clock.c +static struct clk_freq_tbl ftbl_gcc_blsp1_qup3_i2c_apps_clk_src[] = +{ + F( 96000, cxo, 10, 1, 2), + F( , cxo, 4, 0, 0), + F( , cxo, 2, 0, 0), + F( , gpll0, 10, 1, 5), + F( , gpll0, 1, 0, 0), + F( , gpll0, 16, 1, 2), + F( , gpll0, 16, 0, 0), + F_END +}; +static struct rcg_clk gcc_blsp1_qup3_i2c_apps_clk_src = +{ + .cmd_reg = (uint32_t *) GCC_BLSP1_QUP3_CMD_RCGR, + .cfg_reg = (uint32_t *) GCC_BLSP1_QUP3_CFG_RCGR, + .set_rate = clock_lib2_rcg_set_rate_hid, + .freq_tbl = ftbl_gcc_blsp1_qup3_i2c_apps_clk_src, + .current_freq = &rcg_dummy_freq, + + .c = { + .dbg_name = "gcc_blsp1_qup3_i2c_apps_clk_src", + .ops = &clk_ops_rcg, + }, +}; +static struct branch_clk gcc_blsp1_qup3_i2c_apps_clk = { + .cbcr_reg = (uint32_t *)GCC_BLSP1_QUP3_APPS_CBCR, + .parent = &gcc_blsp1_qup3_i2c_apps_clk_src.c, + + .c = { + .dbg_name = "gcc_blsp1_qup3_i2c_apps_clk", + .ops = &clk_ops_branch, + }, +}; static struct rcg_clk sdcc2_apps_clk_src ={ ........ + CLK_LOOKUP("blsp1_ahb_clk", gcc_blsp1_ahb_clk.c), + CLK_LOOKUP("gcc_blsp1_qup3_i2c_apps_clk_src", gcc_blsp1_qup3_i2c_apps_clk_src.c), + CLK_LOOKUP("gcc_blsp1_qup3_i2c_apps_clk", gcc_blsp1_qup3_i2c_apps_clk.c), } //实现时钟配置函数 bootable/bootloader/lk/platform/msm8953/include/platform/clock.h void clock_config_blsp_i2c(uint8_t blsp_id, uint8_t qup_id); bootable/bootloader/lk/platform/msm8953/acpuclock.c #include <blsp_qup.h> void clock_config_blsp_i2c(uint8_t blsp_id, uint8_t qup_id) { uint8_t ret = 0; char clk_name[64]; struct clk *qup_clk; if((blsp_id != BLSP_ID_1) || (qup_id > QUP_ID_5)) { dprintf(CRITICAL, "Incorrect BLSP-%d or QUP-%d configuration\n", blsp_id, qup_id); ASSERT(0); } snprintf(clk_name, sizeof(clk_name), "blsp1_ahb_clk"); ret = clk_get_set_enable(clk_name, 0 , 1); if (ret) { dprintf(CRITICAL, "Failed to enable %s clock\n", clk_name); return; } snprintf(clk_name, sizeof(clk_name), "gcc_blsp1_qup3_i2c_apps_clk"); qup_clk = clk_get(clk_name); if (!qup_clk) { dprintf(CRITICAL, "Failed to get %s\n", clk_name); return; } ret = clk_enable(qup_clk); if (ret) { dprintf(CRITICAL, "Failed to enable %s\n", clk_name); return; } }
2、SDM450 I2C3管脚复用功能配置接口实现
bootable/bootloader/lk/platform/msm8953/include/platform/gpio.h +void gpio_config_blsp_i2c(uint8_t blsp_id, uint8_t qup_id); bootable/bootloader/lk/platform/msm8953/gpio.c void gpio_config_blsp_i2c(uint8_t blsp_id, uint8_t qup_id) { if(blsp_id == BLSP_ID_1) { switch (qup_id) { case QUP_ID_2: /* configure I2C SDA gpio */ /* 1 arg: GPIO # 2 arg: GPIO Function (Check GPIO MAP) 3 arg: Doesn't matter 4 arg: Should be GPIO_NO_PULL 5 arg: Drive Strength: Lower the better 6 arg: doesn't matter /* configure I2C SDA gpio */ gpio_tlmm_config(10, 2, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA, GPIO_DISABLE); /* configure I2C SCL gpio */ gpio_tlmm_config(11, 2, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA, GPIO_DISABLE); break; case QUP_ID_1: /* configure I2C SDA gpio */ /* 1 arg: GPIO # 2 arg: GPIO Function (Check GPIO MAP) 3 arg: Doesn't matter 4 arg: Should be GPIO_NO_PULL 5 arg: Drive Strength: Lower the better 6 arg: doesn't matter */ /* configure I2C SDA gpio */ gpio_tlmm_config(6, 3, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA, GPIO_DISABLE); /* configure I2C SCL gpio */ gpio_tlmm_config(7, 3, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA, GPIO_DISABLE); break; default: dprintf(CRITICAL, "Incorrect QUP id %d\n",qup_id); ASSERT(0); }; } else { dprintf(CRITICAL, "Incorrect BLSP id %d\n",blsp_id); ASSERT(0); } }
3、配置I2C3控制器的内部中断
bootable/bootloader/lk/platform/msm8953/include/platform/irqs.h +#define BLSP_QUP_IRQ(blsp_id, qup_id) (GIC_SPI_START + 95 + qup_id)
4、实现I2C3接口的配置函数(这里其实是bootloader自带的)
bootable/bootloader/lk/platform/msm_shared/mipi_dsi_i2c.c int mipi_dsi_i2c_device_init(uint8_t blsp_id, uint8_t qup_id) { i2c_dev = qup_blsp_i2c_init(blsp_id, qup_id, I2C_CLK_FREQ, I2C_SRC_CLK_FREQ); if(!i2c_dev) { dprintf(CRITICAL, "mipi_dsi_i2c_device_init() failed\n"); return ERR_NOT_VALID; } return NO_ERROR; } bootable/bootloader/lk/platform/msm_shared/i2c_qup.c struct qup_i2c_dev *qup_blsp_i2c_init(uint8_t blsp_id, uint8_t qup_id, uint32_t clk_freq, uint32_t src_clk_freq) { struct qup_i2c_dev *dev; if (dev_addr != NULL) { return dev_addr; } dev = malloc(sizeof(struct qup_i2c_dev)); if (!dev) { return NULL; } dev = memset(dev, 0, sizeof(struct qup_i2c_dev)); /* Platform uses BLSP */ dev->qup_irq = BLSP_QUP_IRQ(blsp_id, qup_id); dev->qup_base = BLSP_QUP_BASE(blsp_id, qup_id); /* This must be done for qup_i2c_interrupt to work. */ dev_addr = dev; /* Initialize the GPIO for BLSP i2c */ gpio_config_blsp_i2c(blsp_id, qup_id); clock_config_blsp_i2c(blsp_id, qup_id); qup_i2c_sec_init(dev, clk_freq, src_clk_freq); return dev; }
5、将i2c_qup.c 和mipi_dsi_i2c.c
bootable/bootloader/lk/platform/msm_shared/rules.mk + $(LOCAL_DIR)/i2c_qup.o \ + $(LOCAL_DIR)/mipi_dsi_i2c.o
6、初始化lt8911exb, 这部分只贴出大概架构,其他的没贴出来
bootable/bootloader/lk/include/target.h 定义lt8911exb_config void lt8911exb_config(void); bootable/bootloader/lk/app/aboot/aboot.c 在aboot init中添加lt8911的初始化 void aboot_init(const struct app_descriptor *app) { .......... lt8911exb_config(); .......... } bootable/bootloader/lk/target/msm8953/lt8911exb_config.c void lt8911exb_config(void) { lt8911exb_reset(); mipi_dsi_i2c_device_init(BLSP_ID_1, QUP_ID_2); mdelay(50); lt8911exb_read_chip_id(); lt8911exb_edp_video_cfg(); lt8911exb_init(); Read_DPCD010A = dpcd_read( 0x010A ) & 0x01; if( Read_DPCD010A ) { ScrambleMode = 1; }else { ScrambleMode = 0; } lt8911exb_link_train( ); lt8911exb_tx_swing_pre_set( ); lcd_and_bl_power_on(); }
三、bootloader阶段的屏幕调试
1、添加屏幕信息头文件,这个不详细介绍如何生成文件 bootable/bootloader/lk/dev/gcdb/display/include/panel_pt156fhm_n10_1080p_video.h 2、修改bootable/bootloader/lk/target/msm8953/oem_panel.c文件进行屏幕的添加 bootable/bootloader/lk/target/msm8953/oem_panel.c +#include "panel_pt156fhm_n10_1080p_video.h" enum { +PB156FHM_N10_800P_VIDEO_PANEL, } static struct panel_list supp_panels[] = { +{"pt156fnm_n10_1080p_video", PB156FHM_N10_800P_VIDEO_PANEL}, } static int init_panel_data(struct panel_struct *panelstruct, struct msm_panel_info *pinfo, struct mdss_dsi_phy_ctrl *phy_db) { case PB156FHM_N10_800P_VIDEO_PANEL: panelstruct->paneldata = &pt156fhm_n10_1080p_video_panel_data; panelstruct->panelres = &pt156fhm_n10_1080p_video_panel_res; panelstruct->color = &pt156fhm_n10_1080p_video_color; panelstruct->videopanel = &pt156fhm_n10_1080p_video_video_panel; panelstruct->commandpanel = &pt156fhm_n10_1080p_video_command_panel; panelstruct->state = &pt156fhm_n10_1080p_video_state; panelstruct->laneconfig = &pt156fhm_n10_1080p_video_lane_config; panelstruct->paneltiminginfo = &pt156fhm_n10_1080p_video_timing_info; panelstruct->panelresetseq = &pt156fhm_n10_1080p_video_reset_seq; panelstruct->backlightinfo = &pt156fhm_n10_1080p_video_backlight; pinfo->mipi.panel_on_cmds = pt156fhm_n10_1080p_video_on_command; pinfo->mipi.num_of_panel_on_cmds = PT156FHM_N10_1080P_VIDEO_OFF_COMMAND; pinfo->mipi.panel_off_cmds = pt156fhm_n10_1080p_video_off_command; pinfo->mipi.num_of_panel_off_cmds = PT156FHM_N10_1080P_VIDEO_OFF_COMMAND; memcpy(phy_db->timing, pt156fhm_n10_14nm_1080p_video_timings, MAX_TIMING_CONFIG * sizeof(uint32_t)); pinfo->mipi.signature = PT156FHM_N10_1080P_VEDIO_SIGNATURE; break; } int oem_panel_select(const char *panel_name, struct panel_struct *panelstruct, struct msm_panel_info *pinfo, struct mdss_dsi_phy_ctrl *phy_db) { case HW_PLATFORM_RCM: panel_id = PB156FHM_N10_800P_VIDEO_PANEL; }
四、kernel阶段移植
1、添加屏幕的dtsi文件,具体怎么生成这个文件,不做讲解 kernel/msm-4.9/arch/arm64/boot/dts/qcom/dsi-panel-pt156fnm-n10-1080p-video.dtsi 2、增加这款屏幕支持 kernel/msm-4.9/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi +#include "dsi-panel-pt156fnm-n10-1080p-video.dtsi" kernel/msm-4.9/arch/arm64/boot/dts/qcom/msm8953-nopmi-panel-camera.dtsi
五、调试总结
在调试过程中,注意事项:
1、LT8911的地址,在调试过程中先保证出彩条,确认后级电路没问题
2、LT8911的复位时,reset管脚的高低高输出
3、LT8911和主控mipi端接口是几lane
4、LT8911和屏幕的接口是几lane
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/169156.html