- Adds support for a minimal framebuffer driver of TI's AM335x SoC to be compatible with Wolfgang Denk's LCD-Framework (CONFIG_LCD, common/lcd.c) Signed-off-by: Hannes Petermaier <oe5hpm@oevsv.at>master
parent
8d9eaafdd1
commit
3c5fabd139
@ -0,0 +1,169 @@ |
||||
/*
|
||||
* Copyright (C) 2013 Hannes Petermaier <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 <asm/arch/hardware.h> |
||||
#include <lcd.h> |
||||
#include "am335x-fb.h" |
||||
|
||||
#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) |
||||
|
||||
|
||||
/* 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; |
||||
|
||||
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; |
||||
} |
||||
|
||||
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)); |
||||
|
||||
/* palette default entry */ |
||||
memset((void *)gd->fb_base, 0, 0x20); |
||||
*(unsigned int *)gd->fb_base = 0x4000; |
||||
|
||||
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 */ |
||||
|
||||
/* turn ON display through powercontrol function if accessible */ |
||||
if (0 != panel->panel_power_ctrl) { |
||||
mdelay(panel->pon_delay); |
||||
panel->panel_power_ctrl(1); |
||||
} |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,67 @@ |
||||
/*
|
||||
* Copyright (C) 2013 Hannes Petermaier <oe5hpm@oevsv.at> - |
||||
* Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
|
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#ifndef AM335X_FB_H |
||||
#define AM335X_FB_H |
||||
|
||||
#define HSVS_CONTROL (0x01 << 25) /* |
||||
* 0 = lcd_lp and lcd_fp are driven on |
||||
* opposite edges of pixel clock than |
||||
* the lcd_pixel_o |
||||
* 1 = lcd_lp and lcd_fp are driven |
||||
* according to bit 24 Note that this |
||||
* bit MUST be set to '0' for Passive |
||||
* Matrix displays the edge timing is |
||||
* fixed |
||||
*/ |
||||
#define HSVS_RISEFALL (0x01 << 24) /* |
||||
* 0 = lcd_lp and lcd_fp are driven on |
||||
* the rising edge of pixel clock (bit |
||||
* 25 must be set to 1) |
||||
* 1 = lcd_lp and lcd_fp are driven on |
||||
* the falling edge of pixel clock (bit |
||||
* 25 must be set to 1) |
||||
*/ |
||||
#define DE_INVERT (0x01 << 23) /* |
||||
* 0 = DE is low-active |
||||
* 1 = DE is high-active |
||||
*/ |
||||
#define PXCLK_INVERT (0x01 << 22) /* |
||||
* 0 = pix-clk is high-active |
||||
* 1 = pic-clk is low-active |
||||
*/ |
||||
#define HSYNC_INVERT (0x01 << 21) /* |
||||
* 0 = HSYNC is active high |
||||
* 1 = HSYNC is avtive low |
||||
*/ |
||||
#define VSYNC_INVERT (0x01 << 20) /* |
||||
* 0 = VSYNC is active high |
||||
* 1 = VSYNC is active low |
||||
*/ |
||||
|
||||
struct am335x_lcdpanel { |
||||
unsigned int hactive; /* Horizontal active area */ |
||||
unsigned int vactive; /* Vertical active area */ |
||||
unsigned int bpp; /* bits per pixel */ |
||||
unsigned int hfp; /* Horizontal front porch */ |
||||
unsigned int hbp; /* Horizontal back porch */ |
||||
unsigned int hsw; /* Horizontal Sync Pulse Width */ |
||||
unsigned int vfp; /* Vertical front porch */ |
||||
unsigned int vbp; /* Vertical back porch */ |
||||
unsigned int vsw; /* Vertical Sync Pulse Width */ |
||||
unsigned int pxl_clk_div; /* Pixel clock divider*/ |
||||
unsigned int pol; /* polarity of sync, clock signals */ |
||||
unsigned int pon_delay; /*
|
||||
* time in ms for turning on lcd after |
||||
* initializing lcd-controller |
||||
*/ |
||||
void (*panel_power_ctrl)(int); /* fp for power on/off display */ |
||||
}; |
||||
|
||||
int am335xfb_init(struct am335x_lcdpanel *panel); |
||||
|
||||
#endif /* AM335X_FB_H */ |
Loading…
Reference in new issue