AM335x u-boot中添加LCD驱动,不能操作LCD控制器,怎么解决?

AM335x u-boot中添加LCD驱动,不能操作LCD控制器,怎么解决?

此问题尚无答案
All Replies
  1. 秀才160分
    AM335x u-boot中添加LCD驱动,不能操作LCD控制器,怎么解决? LCD控制是通过lcd_ctrl_init来完成的,具体的lcd_ctrl_init代码如下~~ /* * Copyright (C) 2013 Hannes Schmelzer <oe5hpm@oevsv.at> * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com * * minimal framebuffer driver for TI's AM335x SoC to be compatible with * Wolfgang Denk's LCD-Framework (CONFIG_LCD, common/lcd.c) * * - supporting only 24bit RGB/TFT raster Mode (not using palette) * - sets up LCD controller as in 'am335x_lcdpanel' struct given * - starts output DMA from gd->fb_base buffer * * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> #include <version.h> #include <asm/arch/hardware.h> #include <lcd.h> #include "am3354-lcd.h" #include <asm/io.h> #include <asm/arch/gpio.h> #include <asm/gpio.h> #define LCD_CNTL_BASE 0x4830E000 #if !defined(LCD_CNTL_BASE) #error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!" #endif /* LCD Control Register */ #define LCD_CLK_DIVISOR(x) ((x) << 8) #define LCD_RASTER_MODE 0x01 /* LCD Clock Enable Register */ #define LCD_CORECLKEN (0x01 << 0) #define LCD_LIDDCLKEN (0x01 << 1) #define LCD_DMACLKEN (0x01 << 2) /* LCD DMA Control Register */ #define LCD_DMA_BURST_SIZE(x) ((x) << 4) #define LCD_DMA_BURST_1 0x0 #define LCD_DMA_BURST_2 0x1 #define LCD_DMA_BURST_4 0x2 #define LCD_DMA_BURST_8 0x3 #define LCD_DMA_BURST_16 0x4 /* LCD Timing_0 Register */ #define LCD_HBPLSB(x) ((((x)-1) & 0xFF) << 24) #define LCD_HFPLSB(x) ((((x)-1) & 0xFF) << 16) #define LCD_HSWLSB(x) ((((x)-1) & 0x3F) << 10) #define LCD_HORLSB(x) (((((x) >> 4)-1) & 0x3F) << 4) #define LCD_HORMSB(x) (((((x) >> 4)-1) & 0x40) >> 4) /* LCD Timing_1 Register */ #define LCD_VBP(x) ((x) << 24) #define LCD_VFP(x) ((x) << 16) #define LCD_VSW(x) (((x)-1) << 10) #define LCD_VERLSB(x) (((x)-1) & 0x3FF) /* LCD Timing_2 Register */ #define LCD_HSWMSB(x) ((((x)-1) & 0x3C0) << 21) #define LCD_VERMSB(x) ((((x)-1) & 0x400) << 16) #define LCD_HBPMSB(x) ((((x)-1) & 0x300) >> 4) #define LCD_HFPMSB(x) ((((x)-1) & 0x300) >> 8) #define LCD_INVMASK(x) ((x) & 0x3F00000) /* LCD Raster Ctrl Register */ #define LCD_TFT_24BPP_MODE (1 << 25) #define LCD_TFT_24BPP_UNPACK (1 << 26) #define LCD_PALMODE_RAWDATA (0x10 << 20) #define LCD_TFT_MODE (0x01 << 7) #define LCD_RASTER_ENABLE (0x01 << 0) #define LCD_RASTER_DISABLE (0x00 << 0) /* Macro definitions */ #define FBSIZE(x) ((x->hactive * x->vactive * x->bpp) >> 3) struct am335x_lcdhw { unsigned int pid; /* 0x00 */ unsigned int ctrl; /* 0x04 */ unsigned int gap0; /* 0x08 */ unsigned int lidd_ctrl; /* 0x0C */ unsigned int lidd_cs0_conf; /* 0x10 */ unsigned int lidd_cs0_addr; /* 0x14 */ unsigned int lidd_cs0_data; /* 0x18 */ unsigned int lidd_cs1_conf; /* 0x1C */ unsigned int lidd_cs1_addr; /* 0x20 */ unsigned int lidd_cs1_data; /* 0x24 */ unsigned int raster_ctrl; /* 0x28 */ unsigned int raster_timing0; /* 0x2C */ unsigned int raster_timing1; /* 0x30 */ unsigned int raster_timing2; /* 0x34 */ unsigned int raster_subpanel; /* 0x38 */ unsigned int raster_subpanel2; /* 0x3C */ unsigned int lcddma_ctrl; /* 0x40 */ unsigned int lcddma_fb0_base; /* 0x44 */ unsigned int lcddma_fb0_ceiling; /* 0x48 */ unsigned int lcddma_fb1_base; /* 0x4C */ unsigned int lcddma_fb1_ceiling; /* 0x50 */ unsigned int sysconfig; /* 0x54 */ unsigned int irqstatus_raw; /* 0x58 */ unsigned int irqstatus; /* 0x5C */ unsigned int irqenable_set; /* 0x60 */ unsigned int irqenable_clear; /* 0x64 */ unsigned int gap1; /* 0x68 */ unsigned int clkc_enable; /* 0x6C */ unsigned int clkc_reset; /* 0x70 */ }; static struct am335x_lcdhw *lcdhw = (void *)LCD_CNTL_BASE; DECLARE_GLOBAL_DATA_PTR; struct am335x_lcdpanel lcd_panelq = { .hactive=480, /* Horizontal active area */ .vactive=272, /* Vertical active area */ .bpp=24, /* bits per pixel */ .hfp=2, /* Horizontal front porch */ .hbp=2, /* Horizontal back porch */ .hsw=41, /* Horizontal Sync Pulse Width */ .vfp=2, /* Vertical front porch */ .vbp=2, /* Vertical back porch */ .vsw=10, /* Vertical Sync Pulse Width */ .pxl_clk_div=5, /* Pixel clock divider*/ .pol=0x3F000000, /* polarity of sync, clock signals */ .pup_delay=50, /* * time in ms after power on to * initialization of lcd-controller * (VCC ramp up time) */ .pon_delay=50, /* * time in ms after initialization of * lcd-controller (pic stabilization) */ //void (*panel_power_ctrl)(int); /* fp for power on/off display */ }; vidinfo_t panel_info = { .vl_col = 480, .vl_row = 272, .vl_bpix = 5 }; int load_lcdtiming(struct am335x_lcdpanel *panel) { struct am335x_lcdpanel pnltmp; pnltmp.hactive = 480; pnltmp.vactive = 272; pnltmp.bpp = 32; pnltmp.hfp = 2; pnltmp.hbp = 2; pnltmp.hsw = 41; pnltmp.vfp = 2; pnltmp.vbp = 2; pnltmp.vsw = 10; pnltmp.pxl_clk_div = 5; pnltmp.pol = 0x3F000000; pnltmp.pup_delay = 50; pnltmp.pon_delay = 50; //panel_info.vl_rot = getenv_ulong("ds1_rotation", 10, 0); if ( ~0UL == (pnltmp.hactive) || ~0UL == (pnltmp.vactive) || ~0UL == (pnltmp.bpp) || ~0UL == (pnltmp.hfp) || ~0UL == (pnltmp.hbp) || ~0UL == (pnltmp.hsw) || ~0UL == (pnltmp.vfp) || ~0UL == (pnltmp.vbp) || ~0UL == (pnltmp.vsw) || ~0UL == (pnltmp.pxl_clk_div) || ~0UL == (pnltmp.pol) || ~0UL == (pnltmp.pup_delay) || ~0UL == (pnltmp.pon_delay) ) { puts("lcd-settings in env/dtb incomplete!\n"); printf("display-timings:\n" "================\n" "hactive: %d\n" "vactive: %d\n" "bpp : %d\n" "hfp : %d\n" "hbp : %d\n" "hsw : %d\n" "vfp : %d\n" "vbp : %d\n" "vsw : %d\n" "pxlclk : %d\n" "pol : 0x%08x\n" "pondly : %d\n", pnltmp.hactive, pnltmp.vactive, pnltmp.bpp, pnltmp.hfp, pnltmp.hbp, pnltmp.hsw, pnltmp.vfp, pnltmp.vbp, pnltmp.vsw, pnltmp.pxl_clk_div, pnltmp.pol, pnltmp.pon_delay); return -1; } debug("lcd-settings in env complete, taking over.\n"); memcpy((void *)panel, (void *)&pnltmp, sizeof(struct am335x_lcdpanel)); return 0; } void lcdbacklight(int on) { gpio_request( (3*32+17), "led_light" ); gpio_direction_output( (3*32+17), 0 ); } void br_summaryscreen(void) { br_summaryscreen_printenv(" - B&R -", "br_orderno", 0, "-\n"); br_summaryscreen_printenv(" Serial/Rev :", "br_serial", 0, "\n"); br_summaryscreen_printenv(" MAC (IF1) :", "br_mac1", "ethaddr", "\n"); br_summaryscreen_printenv(" MAC (IF2) :", "br_mac2", 0, "\n"); lcd_puts(" Bootloader : " PLAIN_VERSION "\n"); lcd_puts("\n"); } static void br_summaryscreen_printenv(char *prefix, char *name, char *altname, char *suffix) { char *envval = getenv(name); if (0 != envval) { lcd_printf("%s %s %s", prefix, envval, suffix); } else if (0 != altname) { envval = getenv(altname); if (0 != envval) lcd_printf("%s %s %s", prefix, envval, suffix); } else { lcd_printf("\n"); } } int lcd_get_size(int *line_length) { *line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; return *line_length * panel_info.vl_row + 0x20; } void lcd_ctrl_init(void *lcdbase) { printf("lcd_ctrl_init\n"); struct am335x_lcdpanel lcd_panel; memset(&lcd_panel, 0, sizeof(struct am335x_lcdpanel)); if (load_lcdtiming(&lcd_panel) != 0) return; //lcd_panel.panel_power_ctrl = &lcdpower; if (0 != am335xfb_init(&lcd_panel)) printf("ERROR: failed to initialize video!\n"); panel_info.vl_col = lcd_panel.hactive; panel_info.vl_row = lcd_panel.vactive; lcd_set_flush_dcache(1); } void lcd_enable(void) { br_summaryscreen(); lcdbacklight(1); } int am335xfb_init(struct am335x_lcdpanel *panel) { if (0 == gd->fb_base) { printf("ERROR: no valid fb_base stored in GLOBAL_DATA_PTR!\n"); return -1; } if (0 == panel) { printf("ERROR: missing ptr to am335x_lcdpanel!\n"); return -1; } debug("setting up LCD-Controller for %dx%dx%d (hfp=%d,hbp=%d,hsw=%d / ", panel->hactive, panel->vactive, panel->bpp, panel->hfp, panel->hbp, panel->hsw); debug("vfp=%d,vbp=%d,vsw=%d / clk-div=%d)\n", panel->vfp, panel->vfp, panel->vsw, panel->pxl_clk_div); debug("using frambuffer at 0x%08x with size %d.\n", (unsigned int)gd->fb_base, FBSIZE(panel)); printf("using frambuffer at0x%x with size %x\n", (unsigned int)gd->fb_base, FBSIZE(panel)); /* palette default entry */ memset((void *)gd->fb_base, 0, 0x20); *(unsigned int *)gd->fb_base = 0x4000; printf("printf address of lcdhw->clk_enable2 %x\n",*(unsigned int *)gd->fb_base); /* turn ON display through powercontrol function if accessible */ /* if (0 != panel->panel_power_ctrl) panel->panel_power_ctrl(1); */ debug("am335x-fb: wait for stable power ...\n"); mdelay(panel->pup_delay); writel( LCD_CORECLKEN | LCD_LIDDCLKEN | LCD_DMACLKEN, (LCD_CNTL_BASE+lcdhw->clkc_enable) ); printf("printf address of lcdhw->clk_enable2 %x\n",lcdhw->clkc_enable); lcdhw->clkc_enable = LCD_CORECLKEN | LCD_LIDDCLKEN | LCD_DMACLKEN; lcdhw->raster_ctrl = 0; lcdhw->ctrl = LCD_CLK_DIVISOR(panel->pxl_clk_div) | LCD_RASTER_MODE; lcdhw->lcddma_fb0_base = gd->fb_base; lcdhw->lcddma_fb0_ceiling = gd->fb_base + FBSIZE(panel) + 0x20; lcdhw->lcddma_fb1_base = gd->fb_base; lcdhw->lcddma_fb1_ceiling = gd->fb_base + FBSIZE(panel) + 0x20; lcdhw->lcddma_ctrl = LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16); lcdhw->raster_timing0 = LCD_HORLSB(panel->hactive) | LCD_HORMSB(panel->hactive) | LCD_HFPLSB(panel->hfp) | LCD_HBPLSB(panel->hbp) | LCD_HSWLSB(panel->hsw); lcdhw->raster_timing1 = LCD_VBP(panel->vbp) | LCD_VFP(panel->vfp) | LCD_VSW(panel->vsw) | LCD_VERLSB(panel->vactive); lcdhw->raster_timing2 = LCD_HSWMSB(panel->hsw) | LCD_VERMSB(panel->vactive) | LCD_INVMASK(panel->pol) | LCD_HBPMSB(panel->hbp) | LCD_HFPMSB(panel->hfp) | 0x0000FF00; /* clk cycles for ac-bias */ lcdhw->raster_ctrl = LCD_TFT_24BPP_MODE | LCD_TFT_24BPP_UNPACK | LCD_PALMODE_RAWDATA | LCD_TFT_MODE | LCD_RASTER_ENABLE; gd->fb_base += 0x20; /* point fb behind palette */ debug("am335x-fb: waiting picture to be stable.\n."); mdelay(panel->pon_delay); return 0; } 编译能通过,但是CPU运行的 writel( LCD_CORECLKEN | LCD_LIDDCLKEN | LCD_DMACLKEN, (LCD_CNTL_BASE+lcdhw->clkc_enable) ); 这里就死掉了,过会就自动复位了,串口显示如下: U-Boot 2016.03 (May 09 2017 - 18:25:01 +0800) U-Boot code: 80800000 -> 8085FBE4 BSS_END: -> 808AC4BC
    Watchdog enabled
    I2C: ready
    DRAM: 256 MiB
    lcd_init
    [LCD] Initializing LCD frambuffer at 8ff70000
    lcd_ctrl_init
    using frambuffer at0x8ff70000 with size 7f800
    printf address of lcdhw->clk_enable2 4000
    CCCCCCCCCCCCCCCCCCCCCCCC
  2. 探花15855分
    可以通过CCS仿真器 手动修改这些寄存器看看
  3. 秀才160分
    我手上没有CCS仿真器,我用的是AM335x Starter Kit的开发板。会不会CPU运行内存地址有问题? int am335xfb_init(struct am335x_lcdpanel *panel) { if (0 == gd->fb_base) { printf("ERROR: no valid fb_base stored in GLOBAL_DATA_PTR!\n"); return -1; } if (0 == panel) { printf("ERROR: missing ptr to am335x_lcdpanel!\n"); return -1; } debug("setting up LCD-Controller for %dx%dx%d (hfp=%d,hbp=%d,hsw=%d / ", panel->hactive, panel->vactive, panel->bpp, panel->hfp, panel->hbp, panel->hsw); debug("vfp=%d,vbp=%d,vsw=%d / clk-div=%d)\n", panel->vfp, panel->vfp, panel->vsw, panel->pxl_clk_div); debug("using frambuffer at 0x%08x with size %d.\n", (unsigned int)gd->fb_base, FBSIZE(panel)); printf("using frambuffer at0x%x with size %x\n", (unsigned int)gd->fb_base, FBSIZE(panel)); /* palette default entry */ memset((void *)gd->fb_base, 0, 0x20); *(unsigned int *)gd->fb_base = 0x4000; printf("printf address of lcdhw->clk_enable2 %x\n",*(unsigned int *)gd->fb_base); /* turn ON display through powercontrol function if accessible */ /* if (0 != panel->panel_power_ctrl) panel->panel_power_ctrl(1); */ debug("am335x-fb: wait for stable power ...\n"); mdelay(panel->pup_delay); /* writel( LCD_CORECLKEN | LCD_LIDDCLKEN | LCD_DMACLKEN, (LCD_CNTL_BASE+lcdhw->clkc_enable) ); printf("printf address of lcdhw->clk_enable2 %x\n",lcdhw->clkc_enable); lcdhw->clkc_enable = LCD_CORECLKEN | LCD_LIDDCLKEN | LCD_DMACLKEN; lcdhw->raster_ctrl = 0; lcdhw->ctrl = LCD_CLK_DIVISOR(panel->pxl_clk_div) | LCD_RASTER_MODE; lcdhw->lcddma_fb0_base = gd->fb_base; lcdhw->lcddma_fb0_ceiling = gd->fb_base + FBSIZE(panel) + 0x20; lcdhw->lcddma_fb1_base = gd->fb_base; lcdhw->lcddma_fb1_ceiling = gd->fb_base + FBSIZE(panel) + 0x20; lcdhw->lcddma_ctrl = LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16); lcdhw->raster_timing0 = LCD_HORLSB(panel->hactive) | LCD_HORMSB(panel->hactive) | LCD_HFPLSB(panel->hfp) | LCD_HBPLSB(panel->hbp) | LCD_HSWLSB(panel->hsw); lcdhw->raster_timing1 = LCD_VBP(panel->vbp) | LCD_VFP(panel->vfp) | LCD_VSW(panel->vsw) | LCD_VERLSB(panel->vactive); lcdhw->raster_timing2 = LCD_HSWMSB(panel->hsw) | LCD_VERMSB(panel->vactive) | LCD_INVMASK(panel->pol) | LCD_HBPMSB(panel->hbp) | LCD_HFPMSB(panel->hfp) | 0x0000FF00; /* clk cycles for ac-bias */ lcdhw->raster_ctrl = LCD_TFT_24BPP_MODE | LCD_TFT_24BPP_UNPACK | LCD_PALMODE_RAWDATA | LCD_TFT_MODE | LCD_RASTER_ENABLE; gd->fb_base += 0x20; debug("am335x-fb: waiting picture to be stable.\n."); mdelay(panel->pon_delay); */ return 0; } 我如果把此函数 int am335xfb_init(struct am335x_lcdpanel *panel) 内读写LCD控制器的相关代码给注释掉,u-boot就可以跑完了,除了用CCS仿真器意外,还有什么解决方案吗?还是在读写LCD控制器之前要初始化其他什么东东
  4. 进士8227分
    你是对lcd的clk的寄存器写失败,很大可能你还没有使能display 的PLL
  5. 秀才160分
    根据资料我在SPL启动期间对LCD的时钟进行了这样的配置: 在相应的文件代码里加入: 1、 const struct dpll_regs dpll_disp_regs = {
    .cm_clkmode_dpll = CM_WKUP + 0x98,
    .cm_idlest_dpll = CM_WKUP + 0x48,
    .cm_clksel_dpll = CM_WKUP + 0x54,
    .cm_div_m2_dpll = CM_WKUP + 0xA4,
    };
    2、 const struct dpll_params dpll_disp = {
    100, OSC-1, 1, -1, -1, -1, -1};
    3、 const struct dpll_params *get_dpll_disp_params(void)
    {
    return &dpll_disp;
    }
    4、 enable_basic_clocks     clk_domains[]      + --->&cmper->lcdcclkstctrl,     clk_modules_explicit_en[]      + --->&cmper->lcdclkctrl, 原文件中有对应的l3clkstctrl,l3sclkstctrl,l4lsclkstctrl时钟唤醒与时钟使能(l3clkctrl,l4lsclkctrl) 5、 setup_dplls writel(0x300, &cmwkup->clkdcoldodpllper);    +   ---->writel(0x0, &cmdpll->clklcdcpixelclk);//根据ti_manual Figure 8-13选择CLKOUT作为LCD_CLK----LCD_CLK=CLKIN*100/((24-1)+1)*1    +          params = get_dpll_disp_params();    +           do_setup_dpll(&dpll_disp_regs, params); params = get_dpll_ddr_params(); 编译下载,现象并没有改善,我以为这样至少能访问LCD控制器了,但是还是不能,在u-boot中不可以这样使能LCD时钟?
  6. 进士8227分
    参考我之前发过的帖子,里面有时钟见解和LCD配置 http://www.deyisupport.com/question_answer/dsp_arm/sitara_arm/f/25/t/122028.aspx
  7. 秀才160分
    我写之前没有看到您的帖子,后来浏览论坛看到了您的帖子,之前不知道l3'l4ls这些寄存器的作用,看到之后知道了,后来我又根据你的帖子对照了一些自己的程序感觉是没有错误的。我在想是不是真的lcd时钟配置多样性,不能在uboot自带的时钟配置程序中添加,需要另外写一个时钟配置函数? 不过非常感谢您的回复!!!!
  8. 进士8227分
    是的,对于LCD需要enable lcd的时钟,我的link里面有相关文件
  9. 秀才160分
    参考您给的问题处理方案,Uboot中已成功添加LCD的驱动,除了你提到的修改的地方,还要注意,Drivers文件下的Makefile的修改(添加obj-y += lcd/),以及./a.out 480 272 ./图片名称.bmp ./image.h 24 RGB 生成image.h时用RGB不是BGR。
  10. 秀才160分
    根据你给的问题解决方案:uboot中已成功添加LCD驱动,除了你提到的修改的地方,还需要注意生成image.h时,最后用RGB而不是BGR(./a.out 480 272 ./图片名称.bmp ./image.h 24 BGR),还要注意drivers目录下的Makefile文件的修改(添加obj-y += lcd/)。
  11. 进士8227分
    对的,你说的没错,当时我可能只是为了测试,文章写漏了, 所以你还有其他问题吗?
  12. 秀才160分
    暂时uboot中添加简单LCD驱动已经没问题了,后续产生的问题再说。
  13. 秀才240分
    您好:        您这边问题解决了吗?我现在也在uboot下显示公司的logo,我们这边也是使用的am335x starter kit  SDK06版本,uboot版本为2013.01的,现在编译都有问题,能发个例子吗?
  14. 秀才160分
    我不知道你要的是什么例子,但是我用的是u-boot-2016.03,直接按ti网站上的对u-boot的编译方式就可以了,没什么要修改的的。 #! /bin/bash echo "Configure the u-boot" make arch=arm CROSS_COMPILE=arm-linux-gnueabihf- O=am335x_evm am335x_evm_defconfig all 这个是我自己弄得编译u-boot的脚本。不想每次编译都在终端打印一大串指令。
  15. 秀才240分
    您好,我这边是根据ti的技术支持提供的lcd驱动包,按照这个文档进行的移植(AM335x 在 在 Uboot  增加 自定义的制 命令控制 LCD  功能),一大堆的错误提示,我的版本是uboot-2013.01,也可以按照你帖子上面的内容进行移植吗?你那边有整理好的lcd驱动吗?可否参考一下?感谢感谢!
鸿运国际网址