diff options
Diffstat (limited to 'drivers/video/da8xx-fb.c')
-rw-r--r-- | drivers/video/da8xx-fb.c | 1048 |
1 files changed, 0 insertions, 1048 deletions
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c deleted file mode 100644 index 462c318..0000000 --- a/drivers/video/da8xx-fb.c +++ /dev/null @@ -1,1048 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Porting to u-boot: - * - * (C) Copyright 2011 - * Stefano Babic, DENX Software Engineering, sbabic@denx.de. - * - * Copyright (C) 2008-2009 MontaVista Software Inc. - * Copyright (C) 2008-2009 Texas Instruments Inc - * - * Based on the LCD driver for TI Avalanche processors written by - * Ajay Singh and Shalom Hai. - */ - -#include <common.h> -#include <log.h> -#include <malloc.h> -#include <memalign.h> -#include <video_fb.h> -#include <asm/global_data.h> -#include <linux/delay.h> -#include <linux/list.h> -#include <linux/fb.h> - -#include <linux/errno.h> -#include <asm/io.h> -#include <asm/arch/hardware.h> - -#include "videomodes.h" -#include "da8xx-fb.h" - -#if !defined(DA8XX_LCD_CNTL_BASE) -#define DA8XX_LCD_CNTL_BASE DAVINCI_LCD_CNTL_BASE -#endif - -#define DRIVER_NAME "da8xx_lcdc" - -#define LCD_VERSION_1 1 -#define LCD_VERSION_2 2 - -/* LCD Status Register */ -#define LCD_END_OF_FRAME1 (1 << 9) -#define LCD_END_OF_FRAME0 (1 << 8) -#define LCD_PL_LOAD_DONE (1 << 6) -#define LCD_FIFO_UNDERFLOW (1 << 5) -#define LCD_SYNC_LOST (1 << 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 -#define LCD_V1_END_OF_FRAME_INT_ENA (1 << 2) -#define LCD_V2_END_OF_FRAME0_INT_ENA (1 << 8) -#define LCD_V2_END_OF_FRAME1_INT_ENA (1 << 9) -#define LCD_DUAL_FRAME_BUFFER_ENABLE (1 << 0) - -#define LCD_V2_TFT_24BPP_MODE (1 << 25) -#define LCD_V2_TFT_24BPP_UNPACK (1 << 26) - -/* LCD Control Register */ -#define LCD_CLK_DIVISOR(x) ((x) << 8) -#define LCD_RASTER_MODE 0x01 - -/* LCD Raster Control Register */ -#define LCD_PALETTE_LOAD_MODE(x) ((x) << 20) -#define PALETTE_AND_DATA 0x00 -#define PALETTE_ONLY 0x01 -#define DATA_ONLY 0x02 - -#define LCD_MONO_8BIT_MODE (1 << 9) -#define LCD_RASTER_ORDER (1 << 8) -#define LCD_TFT_MODE (1 << 7) -#define LCD_V1_UNDERFLOW_INT_ENA (1 << 6) -#define LCD_V2_UNDERFLOW_INT_ENA (1 << 5) -#define LCD_V1_PL_INT_ENA (1 << 4) -#define LCD_V2_PL_INT_ENA (1 << 6) -#define LCD_MONOCHROME_MODE (1 << 1) -#define LCD_RASTER_ENABLE (1 << 0) -#define LCD_TFT_ALT_ENABLE (1 << 23) -#define LCD_STN_565_ENABLE (1 << 24) -#define LCD_V2_DMA_CLK_EN (1 << 2) -#define LCD_V2_LIDD_CLK_EN (1 << 1) -#define LCD_V2_CORE_CLK_EN (1 << 0) -#define LCD_V2_LPP_B10 26 -#define LCD_V2_TFT_24BPP_MODE (1 << 25) -#define LCD_V2_TFT_24BPP_UNPACK (1 << 26) - -/* LCD Raster Timing 2 Register */ -#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) -#define LCD_AC_BIAS_FREQUENCY(x) ((x) << 8) -#define LCD_SYNC_CTRL (1 << 25) -#define LCD_SYNC_EDGE (1 << 24) -#define LCD_INVERT_PIXEL_CLOCK (1 << 22) -#define LCD_INVERT_LINE_CLOCK (1 << 21) -#define LCD_INVERT_FRAME_CLOCK (1 << 20) - -/* Clock registers available only on Version 2 */ -#define LCD_CLK_MAIN_RESET (1 << 3) -/* LCD Block */ -struct da8xx_lcd_regs { - u32 revid; - u32 ctrl; - u32 stat; - u32 lidd_ctrl; - u32 lidd_cs0_conf; - u32 lidd_cs0_addr; - u32 lidd_cs0_data; - u32 lidd_cs1_conf; - u32 lidd_cs1_addr; - u32 lidd_cs1_data; - u32 raster_ctrl; - u32 raster_timing_0; - u32 raster_timing_1; - u32 raster_timing_2; - u32 raster_subpanel; - u32 reserved; - u32 dma_ctrl; - u32 dma_frm_buf_base_addr_0; - u32 dma_frm_buf_ceiling_addr_0; - u32 dma_frm_buf_base_addr_1; - u32 dma_frm_buf_ceiling_addr_1; - u32 resv1; - u32 raw_stat; - u32 masked_stat; - u32 int_ena_set; - u32 int_ena_clr; - u32 end_of_int_ind; - /* Clock registers available only on Version 2 */ - u32 clk_ena; - u32 clk_reset; -}; - -#define LCD_NUM_BUFFERS 1 - -#define WSI_TIMEOUT 50 -#define PALETTE_SIZE 256 -#define LEFT_MARGIN 64 -#define RIGHT_MARGIN 64 -#define UPPER_MARGIN 32 -#define LOWER_MARGIN 32 -#define WAIT_FOR_FRAME_DONE true -#define NO_WAIT_FOR_FRAME_DONE false - -#define calc_fbsize() (panel.plnSizeX * panel.plnSizeY * panel.gdfBytesPP) - -static struct da8xx_lcd_regs *da8xx_fb_reg_base; - -DECLARE_GLOBAL_DATA_PTR; - -/* graphics setup */ -static GraphicDevice gpanel; -static const struct da8xx_panel *lcd_panel; -static struct fb_info *da8xx_fb_info; -static int bits_x_pixel; -static unsigned int lcd_revision; -const struct lcd_ctrl_config *da8xx_lcd_cfg; - -static inline unsigned int lcdc_read(u32 *addr) -{ - return (unsigned int)readl(addr); -} - -static inline void lcdc_write(unsigned int val, u32 *addr) -{ - writel(val, addr); -} - -struct da8xx_fb_par { - u32 p_palette_base; - unsigned char *v_palette_base; - dma_addr_t vram_phys; - unsigned long vram_size; - void *vram_virt; - unsigned int dma_start; - unsigned int dma_end; - struct clk *lcdc_clk; - int irq; - unsigned short pseudo_palette[16]; - unsigned int palette_sz; - unsigned int pxl_clk; - int blank; - int vsync_flag; - int vsync_timeout; -}; - - -/* Variable Screen Information */ -static struct fb_var_screeninfo da8xx_fb_var = { - .xoffset = 0, - .yoffset = 0, - .transp = {0, 0, 0}, - .nonstd = 0, - .activate = 0, - .height = -1, - .width = -1, - .pixclock = 46666, /* 46us - AUO display */ - .accel_flags = 0, - .left_margin = LEFT_MARGIN, - .right_margin = RIGHT_MARGIN, - .upper_margin = UPPER_MARGIN, - .lower_margin = LOWER_MARGIN, - .sync = 0, - .vmode = FB_VMODE_NONINTERLACED -}; - -static struct fb_fix_screeninfo da8xx_fb_fix = { - .id = "DA8xx FB Drv", - .type = FB_TYPE_PACKED_PIXELS, - .type_aux = 0, - .visual = FB_VISUAL_PSEUDOCOLOR, - .xpanstep = 0, - .ypanstep = 1, - .ywrapstep = 0, - .accel = FB_ACCEL_NONE -}; - -/* Enable the Raster Engine of the LCD Controller */ -static inline void lcd_enable_raster(void) -{ - u32 reg; - - /* Put LCDC in reset for several cycles */ - if (lcd_revision == LCD_VERSION_2) - lcdc_write(LCD_CLK_MAIN_RESET, - &da8xx_fb_reg_base->clk_reset); - - udelay(1000); - /* Bring LCDC out of reset */ - if (lcd_revision == LCD_VERSION_2) - lcdc_write(0, - &da8xx_fb_reg_base->clk_reset); - - udelay(1000); - - reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl); - if (!(reg & LCD_RASTER_ENABLE)) - lcdc_write(reg | LCD_RASTER_ENABLE, - &da8xx_fb_reg_base->raster_ctrl); -} - -/* Disable the Raster Engine of the LCD Controller */ -static inline void lcd_disable_raster(bool wait_for_frame_done) -{ - u32 reg; - u32 loop_cnt = 0; - u32 stat; - u32 i = 0; - - if (wait_for_frame_done) - loop_cnt = 5000; - - reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl); - if (reg & LCD_RASTER_ENABLE) - lcdc_write(reg & ~LCD_RASTER_ENABLE, - &da8xx_fb_reg_base->raster_ctrl); - - /* Wait for the current frame to complete */ - do { - if (lcd_revision == LCD_VERSION_1) - stat = lcdc_read(&da8xx_fb_reg_base->stat); - else - stat = lcdc_read(&da8xx_fb_reg_base->raw_stat); - - mdelay(1); - } while (!(stat & 0x01) && (i++ < loop_cnt)); - - if (lcd_revision == LCD_VERSION_1) - lcdc_write(stat, &da8xx_fb_reg_base->stat); - else - lcdc_write(stat, &da8xx_fb_reg_base->raw_stat); - - if ((loop_cnt != 0) && (i >= loop_cnt)) { - printf("LCD Controller timed out\n"); - return; - } -} - -static void lcd_blit(int load_mode, struct da8xx_fb_par *par) -{ - u32 start; - u32 end; - u32 reg_ras; - u32 reg_dma; - u32 reg_int; - - /* init reg to clear PLM (loading mode) fields */ - reg_ras = lcdc_read(&da8xx_fb_reg_base->raster_ctrl); - reg_ras &= ~(3 << 20); - - reg_dma = lcdc_read(&da8xx_fb_reg_base->dma_ctrl); - - if (load_mode == LOAD_DATA) { - start = par->dma_start; - end = par->dma_end; - - reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); - if (lcd_revision == LCD_VERSION_1) { - reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA; - } else { - reg_int = lcdc_read(&da8xx_fb_reg_base->int_ena_set) | - LCD_V2_END_OF_FRAME0_INT_ENA | - LCD_V2_END_OF_FRAME1_INT_ENA | - LCD_V2_UNDERFLOW_INT_ENA | LCD_SYNC_LOST; - lcdc_write(reg_int, &da8xx_fb_reg_base->int_ena_set); - } - -#if (LCD_NUM_BUFFERS == 2) - reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; - lcdc_write(start, &da8xx_fb_reg_base->dma_frm_buf_base_addr_0); - lcdc_write(end, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0); - lcdc_write(start, &da8xx_fb_reg_base->dma_frm_buf_base_addr_1); - lcdc_write(end, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_1); -#else - reg_dma &= ~LCD_DUAL_FRAME_BUFFER_ENABLE; - lcdc_write(start, &da8xx_fb_reg_base->dma_frm_buf_base_addr_0); - lcdc_write(end, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0); - lcdc_write(0, &da8xx_fb_reg_base->dma_frm_buf_base_addr_1); - lcdc_write(0, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_1); -#endif - - } else if (load_mode == LOAD_PALETTE) { - start = par->p_palette_base; - end = start + par->palette_sz - 1; - - reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); - if (lcd_revision == LCD_VERSION_1) { - reg_ras |= LCD_V1_PL_INT_ENA; - } else { - reg_int = lcdc_read(&da8xx_fb_reg_base->int_ena_set) | - LCD_V2_PL_INT_ENA; - lcdc_write(reg_int, &da8xx_fb_reg_base->int_ena_set); - } - - lcdc_write(start, &da8xx_fb_reg_base->dma_frm_buf_base_addr_0); - lcdc_write(end, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0); - } - - lcdc_write(reg_dma, &da8xx_fb_reg_base->dma_ctrl); - lcdc_write(reg_ras, &da8xx_fb_reg_base->raster_ctrl); - - /* - * The Raster enable bit must be set after all other control fields are - * set. - */ - lcd_enable_raster(); -} - -/* Configure the Burst Size of DMA */ -static int lcd_cfg_dma(int burst_size) -{ - u32 reg; - - reg = lcdc_read(&da8xx_fb_reg_base->dma_ctrl) & 0x00000001; - switch (burst_size) { - case 1: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1); - break; - case 2: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2); - break; - case 4: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4); - break; - case 8: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8); - break; - case 16: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16); - break; - default: - return -EINVAL; - } - lcdc_write(reg, &da8xx_fb_reg_base->dma_ctrl); - - return 0; -} - -static void lcd_cfg_ac_bias(int period, int transitions_per_int) -{ - u32 reg; - - /* Set the AC Bias Period and Number of Transitions per Interrupt */ - reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_2) & 0xFFF00000; - reg |= LCD_AC_BIAS_FREQUENCY(period) | - LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int); - lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_2); -} - -static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width, - int front_porch) -{ - u32 reg; - - reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_0) & 0xf; - reg |= ((back_porch & 0xff) << 24) - | ((front_porch & 0xff) << 16) - | ((pulse_width & 0x3f) << 10); - lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_0); -} - -static void lcd_cfg_vertical_sync(int back_porch, int pulse_width, - int front_porch) -{ - u32 reg; - - reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_1) & 0x3ff; - reg |= ((back_porch & 0xff) << 24) - | ((front_porch & 0xff) << 16) - | ((pulse_width & 0x3f) << 10); - lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_1); -} - -static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) -{ - u32 reg; - u32 reg_int; - - reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl) & ~(LCD_TFT_MODE | - LCD_MONO_8BIT_MODE | - LCD_MONOCHROME_MODE); - - switch (cfg->p_disp_panel->panel_shade) { - case MONOCHROME: - reg |= LCD_MONOCHROME_MODE; - if (cfg->mono_8bit_mode) - reg |= LCD_MONO_8BIT_MODE; - break; - case COLOR_ACTIVE: - reg |= LCD_TFT_MODE; - if (cfg->tft_alt_mode) - reg |= LCD_TFT_ALT_ENABLE; - break; - - case COLOR_PASSIVE: - if (cfg->stn_565_mode) - reg |= LCD_STN_565_ENABLE; - break; - - default: - return -EINVAL; - } - - /* enable additional interrupts here */ - if (lcd_revision == LCD_VERSION_1) { - reg |= LCD_V1_UNDERFLOW_INT_ENA; - } else { - reg_int = lcdc_read(&da8xx_fb_reg_base->int_ena_set) | - LCD_V2_UNDERFLOW_INT_ENA; - lcdc_write(reg_int, &da8xx_fb_reg_base->int_ena_set); - } - - lcdc_write(reg, &da8xx_fb_reg_base->raster_ctrl); - - reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_2); - - if (cfg->sync_ctrl) - reg |= LCD_SYNC_CTRL; - else - reg &= ~LCD_SYNC_CTRL; - - if (cfg->sync_edge) - reg |= LCD_SYNC_EDGE; - else - reg &= ~LCD_SYNC_EDGE; - - if (cfg->invert_line_clock) - reg |= LCD_INVERT_LINE_CLOCK; - else - reg &= ~LCD_INVERT_LINE_CLOCK; - - if (cfg->invert_frm_clock) - reg |= LCD_INVERT_FRAME_CLOCK; - else - reg &= ~LCD_INVERT_FRAME_CLOCK; - - lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_2); - - return 0; -} - -static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, - u32 bpp, u32 raster_order) -{ - u32 reg; - - /* Set the Panel Width */ - /* Pixels per line = (PPL + 1)*16 */ - if (lcd_revision == LCD_VERSION_1) { - /* - * 0x3F in bits 4..9 gives max horizontal resolution = 1024 - * pixels - */ - width &= 0x3f0; - } else { - /* - * 0x7F in bits 4..10 gives max horizontal resolution = 2048 - * pixels. - */ - width &= 0x7f0; - } - reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_0); - reg &= 0xfffffc00; - if (lcd_revision == LCD_VERSION_1) { - reg |= ((width >> 4) - 1) << 4; - } else { - width = (width >> 4) - 1; - reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3); - } - lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_0); - - /* Set the Panel Height */ - /* Set bits 9:0 of Lines Per Pixel */ - reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_1); - reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00); - lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_1); - - /* Set bit 10 of Lines Per Pixel */ - if (lcd_revision == LCD_VERSION_2) { - reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_2); - reg |= ((height - 1) & 0x400) << 16; - lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_2); - } - - /* Set the Raster Order of the Frame Buffer */ - reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl) & ~(1 << 8); - if (raster_order) - reg |= LCD_RASTER_ORDER; - - if (bpp == 24) - reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE); - else if (bpp == 32) - reg |= (LCD_TFT_MODE | LCD_V2_TFT_24BPP_MODE - | LCD_V2_TFT_24BPP_UNPACK); - - lcdc_write(reg, &da8xx_fb_reg_base->raster_ctrl); - - switch (bpp) { - case 1: - case 2: - case 4: - case 16: - case 24: - case 32: - par->palette_sz = 16 * 2; - break; - - case 8: - par->palette_sz = 256 * 2; - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info) -{ - struct da8xx_fb_par *par = info->par; - unsigned short *palette = (unsigned short *) par->v_palette_base; - u_short pal; - int update_hw = 0; - - if (regno > 255) - return 1; - - if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) - return 1; - - if (info->var.bits_per_pixel == 8) { - red >>= 4; - green >>= 8; - blue >>= 12; - - pal = (red & 0x0f00); - pal |= (green & 0x00f0); - pal |= (blue & 0x000f); - - if (palette[regno] != pal) { - update_hw = 1; - palette[regno] = pal; - } - } else if ((info->var.bits_per_pixel == 16) && regno < 16) { - red >>= (16 - info->var.red.length); - red <<= info->var.red.offset; - - green >>= (16 - info->var.green.length); - green <<= info->var.green.offset; - - blue >>= (16 - info->var.blue.length); - blue <<= info->var.blue.offset; - - par->pseudo_palette[regno] = red | green | blue; - - if (palette[0] != 0x4000) { - update_hw = 1; - palette[0] = 0x4000; - } - } else if (((info->var.bits_per_pixel == 32) && regno < 32) || - ((info->var.bits_per_pixel == 24) && regno < 24)) { - red >>= (24 - info->var.red.length); - red <<= info->var.red.offset; - - green >>= (24 - info->var.green.length); - green <<= info->var.green.offset; - - blue >>= (24 - info->var.blue.length); - blue <<= info->var.blue.offset; - - par->pseudo_palette[regno] = red | green | blue; - - if (palette[0] != 0x4000) { - update_hw = 1; - palette[0] = 0x4000; - } - } - - /* Update the palette in the h/w as needed. */ - if (update_hw) - lcd_blit(LOAD_PALETTE, par); - - return 0; -} - -static void lcd_reset(struct da8xx_fb_par *par) -{ - /* Disable the Raster if previously Enabled */ - lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE); - - /* DMA has to be disabled */ - lcdc_write(0, &da8xx_fb_reg_base->dma_ctrl); - lcdc_write(0, &da8xx_fb_reg_base->raster_ctrl); - - if (lcd_revision == LCD_VERSION_2) { - lcdc_write(0, &da8xx_fb_reg_base->int_ena_set); - /* Write 1 to reset */ - lcdc_write(LCD_CLK_MAIN_RESET, &da8xx_fb_reg_base->clk_reset); - lcdc_write(0, &da8xx_fb_reg_base->clk_reset); - } -} - -static void lcd_calc_clk_divider(struct da8xx_fb_par *par) -{ - unsigned int lcd_clk, div; - - /* Get clock from sysclk2 */ - lcd_clk = clk_get(2); - - div = lcd_clk / par->pxl_clk; - debug("LCD Clock: %d Divider: %d PixClk: %d\n", - lcd_clk, div, par->pxl_clk); - - /* Configure the LCD clock divisor. */ - lcdc_write(LCD_CLK_DIVISOR(div) | - (LCD_RASTER_MODE & 0x1), &da8xx_fb_reg_base->ctrl); - - if (lcd_revision == LCD_VERSION_2) - lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN | - LCD_V2_CORE_CLK_EN, - &da8xx_fb_reg_base->clk_ena); -} - -static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, - const struct da8xx_panel *panel) -{ - u32 bpp; - int ret = 0; - - lcd_reset(par); - - /* Calculate the divider */ - lcd_calc_clk_divider(par); - - if (panel->invert_pxl_clk) - lcdc_write((lcdc_read(&da8xx_fb_reg_base->raster_timing_2) | - LCD_INVERT_PIXEL_CLOCK), - &da8xx_fb_reg_base->raster_timing_2); - else - lcdc_write((lcdc_read(&da8xx_fb_reg_base->raster_timing_2) & - ~LCD_INVERT_PIXEL_CLOCK), - &da8xx_fb_reg_base->raster_timing_2); - - /* Configure the DMA burst size. */ - ret = lcd_cfg_dma(cfg->dma_burst_sz); - if (ret < 0) - return ret; - - /* Configure the AC bias properties. */ - lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt); - - /* Configure the vertical and horizontal sync properties. */ - lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp); - lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp); - - /* Configure for display */ - ret = lcd_cfg_display(cfg); - if (ret < 0) - return ret; - - if ((QVGA != cfg->p_disp_panel->panel_type) && - (WVGA != cfg->p_disp_panel->panel_type)) - return -EINVAL; - - if (cfg->bpp <= cfg->p_disp_panel->max_bpp && - cfg->bpp >= cfg->p_disp_panel->min_bpp) - bpp = cfg->bpp; - else - bpp = cfg->p_disp_panel->max_bpp; - if (bpp == 12) - bpp = 16; - ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width, - (unsigned int)panel->height, bpp, - cfg->raster_order); - if (ret < 0) - return ret; - - /* Configure FDD */ - lcdc_write((lcdc_read(&da8xx_fb_reg_base->raster_ctrl) & 0xfff00fff) | - (cfg->fdd << 12), &da8xx_fb_reg_base->raster_ctrl); - - return 0; -} - -static void lcdc_dma_start(void) -{ - struct da8xx_fb_par *par = da8xx_fb_info->par; - lcdc_write(par->dma_start, - &da8xx_fb_reg_base->dma_frm_buf_base_addr_0); - lcdc_write(par->dma_end, - &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0); - lcdc_write(0, - &da8xx_fb_reg_base->dma_frm_buf_base_addr_1); - lcdc_write(0, - &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_1); -} - -static u32 lcdc_irq_handler_rev01(void) -{ - struct da8xx_fb_par *par = da8xx_fb_info->par; - u32 stat = lcdc_read(&da8xx_fb_reg_base->stat); - u32 reg_ras; - - if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { - debug("LCD_SYNC_LOST\n"); - lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE); - lcdc_write(stat, &da8xx_fb_reg_base->stat); - lcd_enable_raster(); - return LCD_SYNC_LOST; - } else if (stat & LCD_PL_LOAD_DONE) { - debug("LCD_PL_LOAD_DONE\n"); - /* - * Must disable raster before changing state of any control bit. - * And also must be disabled before clearing the PL loading - * interrupt via the following write to the status register. If - * this is done after then one gets multiple PL done interrupts. - */ - lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE); - - lcdc_write(stat, &da8xx_fb_reg_base->stat); - - /* Disable PL completion interrupt */ - reg_ras = lcdc_read(&da8xx_fb_reg_base->raster_ctrl); - reg_ras &= ~LCD_V1_PL_INT_ENA; - lcdc_write(reg_ras, &da8xx_fb_reg_base->raster_ctrl); - - /* Setup and start data loading mode */ - lcd_blit(LOAD_DATA, par); - return LCD_PL_LOAD_DONE; - } else { - lcdc_write(stat, &da8xx_fb_reg_base->stat); - - if (stat & LCD_END_OF_FRAME0) - debug("LCD_END_OF_FRAME0\n"); - - lcdc_write(par->dma_start, - &da8xx_fb_reg_base->dma_frm_buf_base_addr_0); - lcdc_write(par->dma_end, - &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0); - par->vsync_flag = 1; - return LCD_END_OF_FRAME0; - } - return stat; -} - -static u32 lcdc_irq_handler_rev02(void) -{ - struct da8xx_fb_par *par = da8xx_fb_info->par; - u32 stat = lcdc_read(&da8xx_fb_reg_base->masked_stat); - u32 reg_int; - - if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { - debug("LCD_SYNC_LOST\n"); - lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE); - lcdc_write(stat, &da8xx_fb_reg_base->masked_stat); - lcd_enable_raster(); - lcdc_write(0, &da8xx_fb_reg_base->end_of_int_ind); - return LCD_SYNC_LOST; - } else if (stat & LCD_PL_LOAD_DONE) { - debug("LCD_PL_LOAD_DONE\n"); - /* - * Must disable raster before changing state of any control bit. - * And also must be disabled before clearing the PL loading - * interrupt via the following write to the status register. If - * this is done after then one gets multiple PL done interrupts. - */ - lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE); - - lcdc_write(stat, &da8xx_fb_reg_base->masked_stat); - - /* Disable PL completion interrupt */ - reg_int = lcdc_read(&da8xx_fb_reg_base->int_ena_clr) | - (LCD_V2_PL_INT_ENA); - lcdc_write(reg_int, &da8xx_fb_reg_base->int_ena_clr); - - /* Setup and start data loading mode */ - lcd_blit(LOAD_DATA, par); - lcdc_write(0, &da8xx_fb_reg_base->end_of_int_ind); - return LCD_PL_LOAD_DONE; - } else { - lcdc_write(stat, &da8xx_fb_reg_base->masked_stat); - - if (stat & LCD_END_OF_FRAME0) - debug("LCD_END_OF_FRAME0\n"); - - lcdc_write(par->dma_start, - &da8xx_fb_reg_base->dma_frm_buf_base_addr_0); - lcdc_write(par->dma_end, - &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0); - par->vsync_flag = 1; - lcdc_write(0, &da8xx_fb_reg_base->end_of_int_ind); - return LCD_END_OF_FRAME0; - } - lcdc_write(0, &da8xx_fb_reg_base->end_of_int_ind); - return stat; -} - -static u32 lcdc_irq_handler(void) -{ - if (lcd_revision == LCD_VERSION_1) - return lcdc_irq_handler_rev01(); - else - return lcdc_irq_handler_rev02(); -} - -static u32 wait_for_event(u32 event) -{ - u32 timeout = 50000; - u32 ret; - - do { - ret = lcdc_irq_handler(); - udelay(1000); - --timeout; - } while (!(ret & event) && timeout); - - if (!(ret & event)) { - printf("%s: event %d not hit\n", __func__, event); - return -1; - } - - return 0; - -} - -void *video_hw_init(void) -{ - struct da8xx_fb_par *par; - u32 size; - u32 rev; - char *p; - - if (!lcd_panel) { - printf("Display not initialized\n"); - return NULL; - } - gpanel.winSizeX = lcd_panel->width; - gpanel.winSizeY = lcd_panel->height; - gpanel.plnSizeX = lcd_panel->width; - gpanel.plnSizeY = lcd_panel->height; - - switch (bits_x_pixel) { - case 32: - gpanel.gdfBytesPP = 4; - gpanel.gdfIndex = GDF_32BIT_X888RGB; - break; - case 24: - gpanel.gdfBytesPP = 4; - gpanel.gdfIndex = GDF_32BIT_X888RGB; - break; - case 16: - gpanel.gdfBytesPP = 2; - gpanel.gdfIndex = GDF_16BIT_565RGB; - break; - default: - gpanel.gdfBytesPP = 1; - gpanel.gdfIndex = GDF__8BIT_INDEX; - break; - } - - da8xx_fb_reg_base = (struct da8xx_lcd_regs *)DA8XX_LCD_CNTL_BASE; - - /* Determine LCD IP Version */ - rev = lcdc_read(&da8xx_fb_reg_base->revid); - switch (rev) { - case 0x4C100102: - lcd_revision = LCD_VERSION_1; - break; - case 0x4F200800: - case 0x4F201000: - lcd_revision = LCD_VERSION_2; - break; - default: - printf("Unknown PID Reg value 0x%x, defaulting to LCD revision 1\n", - rev); - lcd_revision = LCD_VERSION_1; - break; - } - - debug("rev: 0x%x Resolution: %dx%d %d\n", rev, - gpanel.winSizeX, - gpanel.winSizeY, - da8xx_lcd_cfg->bpp); - - size = sizeof(struct fb_info) + sizeof(struct da8xx_fb_par); - da8xx_fb_info = malloc_cache_aligned(size); - debug("da8xx_fb_info at %x\n", (unsigned int)da8xx_fb_info); - - if (!da8xx_fb_info) { - printf("Memory allocation failed for fb_info\n"); - return NULL; - } - memset(da8xx_fb_info, 0, size); - p = (char *)da8xx_fb_info; - da8xx_fb_info->par = p + sizeof(struct fb_info); - debug("da8xx_par at %x\n", (unsigned int)da8xx_fb_info->par); - - par = da8xx_fb_info->par; - par->pxl_clk = lcd_panel->pxl_clk; - - if (lcd_init(par, da8xx_lcd_cfg, lcd_panel) < 0) { - printf("lcd_init failed\n"); - goto err_release_fb; - } - - /* allocate frame buffer */ - par->vram_size = lcd_panel->width * lcd_panel->height * - da8xx_lcd_cfg->bpp; - par->vram_size = par->vram_size * LCD_NUM_BUFFERS / 8; - - par->vram_virt = malloc_cache_aligned(par->vram_size); - - par->vram_phys = (dma_addr_t) par->vram_virt; - debug("Requesting 0x%x bytes for framebuffer at 0x%x\n", - (unsigned int)par->vram_size, - (unsigned int)par->vram_virt); - if (!par->vram_virt) { - printf("GLCD: malloc for frame buffer failed\n"); - goto err_release_fb; - } - gd->fb_base = (int)par->vram_virt; - - gpanel.frameAdrs = (unsigned int)par->vram_virt; - da8xx_fb_info->screen_base = (char *) par->vram_virt; - da8xx_fb_fix.smem_start = gpanel.frameAdrs; - da8xx_fb_fix.smem_len = par->vram_size; - da8xx_fb_fix.line_length = (lcd_panel->width * da8xx_lcd_cfg->bpp) / 8; - - par->dma_start = par->vram_phys; - par->dma_end = par->dma_start + lcd_panel->height * - da8xx_fb_fix.line_length - 1; - - /* allocate palette buffer */ - par->v_palette_base = malloc_cache_aligned(PALETTE_SIZE); - if (!par->v_palette_base) { - printf("GLCD: malloc for palette buffer failed\n"); - goto err_release_fb_mem; - } - memset(par->v_palette_base, 0, PALETTE_SIZE); - par->p_palette_base = (unsigned int)par->v_palette_base; - - /* Initialize par */ - da8xx_fb_info->var.bits_per_pixel = da8xx_lcd_cfg->bpp; - - da8xx_fb_var.xres = lcd_panel->width; - da8xx_fb_var.xres_virtual = lcd_panel->width; - - da8xx_fb_var.yres = lcd_panel->height; - da8xx_fb_var.yres_virtual = lcd_panel->height * LCD_NUM_BUFFERS; - - da8xx_fb_var.grayscale = - da8xx_lcd_cfg->p_disp_panel->panel_shade == MONOCHROME ? 1 : 0; - da8xx_fb_var.bits_per_pixel = da8xx_lcd_cfg->bpp; - - da8xx_fb_var.hsync_len = lcd_panel->hsw; - da8xx_fb_var.vsync_len = lcd_panel->vsw; - - /* Initialize fbinfo */ - da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT; - da8xx_fb_info->fix = da8xx_fb_fix; - da8xx_fb_info->var = da8xx_fb_var; - da8xx_fb_info->pseudo_palette = par->pseudo_palette; - da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ? - FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - - /* Clear interrupt */ - memset((void *)par->vram_virt, 0, par->vram_size); - lcd_disable_raster(NO_WAIT_FOR_FRAME_DONE); - if (lcd_revision == LCD_VERSION_1) - lcdc_write(0xFFFF, &da8xx_fb_reg_base->stat); - else - lcdc_write(0xFFFF, &da8xx_fb_reg_base->masked_stat); - debug("Palette at 0x%x size %d\n", par->p_palette_base, - par->palette_sz); - lcdc_dma_start(); - - /* Load a default palette */ - fb_setcolreg(0, 0, 0, 0, 0xffff, da8xx_fb_info); - - /* Check that the palette is loaded */ - wait_for_event(LCD_PL_LOAD_DONE); - - /* Wait until DMA is working */ - wait_for_event(LCD_END_OF_FRAME0); - - return (void *)&gpanel; - -err_release_fb_mem: - free(par->vram_virt); - -err_release_fb: - free(da8xx_fb_info); - - return NULL; -} - -void da8xx_video_init(const struct da8xx_panel *panel, - const struct lcd_ctrl_config *lcd_cfg, int bits_pixel) -{ - lcd_panel = panel; - da8xx_lcd_cfg = lcd_cfg; - bits_x_pixel = bits_pixel; -} |