原创 为AM335x移植Linux内核主线代码(27)U-Boot之LCD(二)

2015-1-26 11:42 2292 8 10 分类: MCU/ 嵌入式 文集: Linux Kernel的DTS

================
Step 4: Enable LCD's clk.
(Please finish chapter 28, then come back here.)
Power Domain: Peripheral Domain.
Clock Domain: PD_PER_LCD_L3_GCLK (OCP Master Clock)
              PD_PER_LCD_L3_GCLK (OCP Slave Clock)
              PD_PER_LCD_GCLK (Functional Clock)
              
l3_clk Master Interface Clock -- 200MHz -- CORE_CLKOUTM4 -- pd_per_lcd_l3_gclk
l4_clk Slave Interface Clock -- 100MHz -- CORE_CLKOUTM4 -- pd_per_lcd_l3_gclk
lcd_clk Functional Clock -- 200MHz -- Display PLL CLKOUT -- pd_per_lcd_gclk

So, add these sentences to in function "board_init" of board.c:
(Note: reference to board/siemens/pxm2)

========
struct dpll_regs dpll_lcd_regs = {
        .cm_clkmode_dpll = CM_WKUP + 0x98,
        .cm_idlest_dpll = CM_WKUP + 0x48,
        .cm_clksel_dpll = CM_WKUP + 0x54,
};

#define PLL_GET_M(v)    ((v >> 8) & 0x7FF)
#define PLL_GET_N(v)    (v & 0X7F)

int clk_get(int clk)
{
        uint32_t val;
        uint32_t m, n;

        val = readl(dpll_lcd_regs.cm_clksel_dpll);
        m = PLL_GET_M(val);
        n = PLL_GET_N(val);
        printf("clk_get val = 0x%x, m = 0x%x, n = 0x%x\n", val, m, n);
                
        val = m * V_OSCK / n;
        printf("clk = 0x%x V_OSCK = %d\n", val, V_OSCK);
        return (m * V_OSCK) / n;
}

int board_init(void)
{
        /* other execution ...... */
     
        struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER;
        struct cm_dpll *cmdpll = (struct cm_dpll *)CM_DPLL;
        struct dpll_params dpll_lcd = {24, 1, -1, -1, -1, -1, -1};

        uint32_t *const clk_domains[] = {
                &cmper->lcdclkctrl,
                0,
        };
        uint32_t *const clk_modules_explicit_en[] = {
                &cmper->lcdclkctrl,
                &cmper->lcdcclkstctrl,
                0,
        };

        do_enable_clocks(clk_domains, clk_modules_explicit_en, 1);
        writel(0x0, &cmdpll->clklcdcpixelclk);
        do_setup_dpll(&dpll_lcd_regs, &dpll_lcd);
        
        /* other execution ...... */
}

========
clkget() is called by da8xx-fb.c file. The LCD's clk has to be initialized, otherwise LCD's registers cannot be visited.

================
Step 5: What does hbp, hfp, hsw, vbp, vfp, vsw mean?
========
http://www-mtl.mit.edu/Courses/6.111/labkit/vga.shtml
VGA Video Output
Introduction
VGA is a high-resolution video standard used mostly for computer monitors, where ability to transmit a sharp, detailed image is essential. VGA uses separate wires to transmit the three color compoment signals and vertical and horizontal synchronization signals.
 

vga_line.jpg
vga_frame.jpg



 * hbp: Horizontal Back Porch Lowbit Bits 7:0 of the horizontal back pock field.
 * hfp: Horizontal Front Porch Lowbits Encoded value (from 1-1024) used to specify the number of pixel clock periods to add to the end of a line transmission before line clock is asserted (programmed value plus 1).
 * hsw: Horizontal Sync Pulse Width Lowbits Bits 5:0 of the horizontal sync pulse width field.
 * vbp: Vertical Back Porch Value (from 0-255) use to specify the number of line clock periods to add to the beginning of a frame before the first set of pixels is output to the display.
 * vfp: Vertical Front Porch Value (from 0-255) used to specify the number of line clock periods to add to the end of each frame.
 * vsw: Vertival Sync Width Pulse In active mode (lcdtft = 1), encoded value (from 1-64) used to specify the number of line clock periods to set he lcd_fp pin active at the end of each frame after the (vfp) period elapses.

Note that AT043TN24 does not need HSYNC and VSYNC. But its clock blanking time has to be matched. DEH blanking (hbp + hfp + hsw) is 45 (40-320) CLK, and DEV (vbp + vfp + vsw) blanking is 16 (5-128) H.
 

at043tn24.jpg



================
Step 6: write panel's structures.

struct display_panel display_panel_at043 = {
        .panel_type = QVGA,
        .max_bpp = 32,
        .min_bpp = 24,
        .panel_shade = COLOR_ACTIVE,
};

struct da8xx_panel da8xx_panel_at043= {
        .name = "QIMEI-AT043TN24",
        .width = 480,
        .height = 272,
        .hbp = 0,
        .hfp = 0,
        .hsw = 45,
        .vbp = 0,
        .vfp = 0,
        .vsw = 16,
        .pxl_clk = 9000000,
        .invert_pxl_clk = 0,
};

struct lcd_ctrl_config lcd_ctrl_config_at043 = {
        .p_disp_panel = &display_panel_at043,
        .ac_bias = 0,
        .ac_bias_intrpt = 0,
        .dma_burst_sz = 16,
        .bpp = 32,
        .fdd = 0xFF,
        .tft_alt_mode = 0,
        .mono_8bit_mode = 0,
        .stn_565_mode = 0,
        .invert_line_clock = 0,
        .invert_frm_clock = 0,
        .sync_edge = 0,
        .sync_ctrl = 0,
        .raster_order = 0,
};

int board_init(void)
{
        /* other execution ...... */
        /* clock init */
        da8xx_video_init(&da8xx_panel_at043, &lcd_ctrl_config_at043,
                        lcd_ctrl_config_at043.bpp);  
        /* other execution ...... */
}

================
Step 7: Use the panel.

U-Boot# tftp 0x82000000 123.bmp
U-Boot# bmp info 0x82000000
Image size    : 480 x 386
Bits per pixel: 24
Compression   : 0
U-Boot# bmp display 0x82000000

================
结论:
啰啰嗦嗦的写了这么多,是因为准备工作很多,但真正需要的步骤很简单:
1. 定义LCD引脚的MUX;
2. 定义CONFIGS;
3. 使能LCD外设的时钟;
4. 定义LCD功能相关的结构体;
5. 使能背光和DISP的GPIO;

存在的问题:
1. 8位红色的[0:7]管脚分别是gpmc_ad[7:0],因此绘制PCB板的时候需要调回来;
2. lcd_data[0:7]代表蓝色,而不是绿色;
3. lcd_data[8:15]代表绿色,而不是蓝色;
4. lcd_ac_bias的定义:
 * Active (TFT) mode. This signal acts as an output enable (OE) signal. It is used to signal the external LCD that the data is valide on the data bus (LCD_DATA).
因此AT043TN24屏的DE线,应该和lcd_ac_bias相连。当设置好为Active模式后,这个引脚就会自动在line初始位置和frame初始位置置低。

================
效果:
使用GIMP在电脑上显示的bmp图片:

3color_2.jpg



AT043TN24的显示:

img_20150123_173328.jpg



使用GIMP在电脑上显示的bmp图片:

3color_3.jpg



AT043TN24的显示:

img_20150126_112042.jpg


 

PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

用户377235 2015-9-30 18:31

我u-boot的logo到kernel的時候頻幕會產生雪花 請問該怎麼解決才好?? 或是從哪裡可以阻止導入kernel時LCD會重新上電的步驟,讓LCD一直保持著電源應該可以解決這個問題吧? 謝謝

用户377235 2015-9-30 18:30

我u-boot的logo到kernel的時候頻幕會產生雪花 請問該怎麼解決才好?? 或是從哪裡可以阻止導入kernel時LCD會重新上電的步驟,讓LCD一直保持著電源應該可以解決這個問題吧?
相关推荐阅读
DiracFatCat 2018-09-05 12:14
【博客大赛】卡尔曼滤波学习笔记(11)从位置估计速度
卡尔曼滤波器,不仅仅是一个低通滤波器,否则也不会持续发展50年。 示例:桑先生需要测试高速列车的性能。测试的目的是判断列车在直线上能否保持80m/s的速度。速度和位置每0.1秒测量一次,但是由于...
DiracFatCat 2018-08-31 19:32
【博客大赛】卡尔曼滤波学习笔记(10)一个简单的示例
《Kalman Filtering: Theory and Practice Using MATLAB》第三章,看不懂,暂时略过。《Kalman Filtering: Theory and Pract...
DiracFatCat 2018-07-19 15:09
对sed命令的练习
sed是流编辑器。它每次处理一个输入,因此很有效率。官方手册:https://www.gnu.org/software/sed/manual/sed.html学习Linux命令,当然要阅读官方手册,所...
DiracFatCat 2018-06-19 15:10
【博客大赛】卡尔曼滤波学习笔记(八)可观测性和可控制性 ...
可观测性是指,在给定模型的情况下,动力学系统的状态是否由它的输入输出唯一确定。可观测性是系统模型的特征。如果传感器矩阵H是可逆的,则本系统可观测,因为有:如果传感器矩阵H某些时候是不可逆的,则本系统仍...
DiracFatCat 2018-06-19 10:56
【博客大赛】卡尔曼滤波学习笔记(七)Z变换
如果我们仅仅对离散线性系统感兴趣,那么就使用下面这个表达式:如果u是常量,那么可以写成:为了简化表达式,我们可以将上面写成:离散线性时不变系统的Φ求解,可以使用Z变换。(* 由于本人已经忘记了Z变换的...
DiracFatCat 2018-06-19 10:54
【博客大赛】卡尔曼滤波学习笔记(六)拉普拉斯变换
对于线性时变/时不变系统,求解Φ(t)有多种方式,拉普拉斯变换是其中一种。(* 由于本人已经忘记了拉普拉斯变换的内容,因此本节待续。)...
EE直播间
更多
我要评论
2
8
关闭 站长推荐上一条 /3 下一条