113402868SStefano Babic /* 213402868SStefano Babic * Porting to u-boot: 313402868SStefano Babic * 413402868SStefano Babic * (C) Copyright 2011 513402868SStefano Babic * Stefano Babic, DENX Software Engineering, sbabic@denx.de. 613402868SStefano Babic * 713402868SStefano Babic * Copyright (C) 2008-2009 MontaVista Software Inc. 813402868SStefano Babic * Copyright (C) 2008-2009 Texas Instruments Inc 913402868SStefano Babic * 1013402868SStefano Babic * Based on the LCD driver for TI Avalanche processors written by 1113402868SStefano Babic * Ajay Singh and Shalom Hai. 1213402868SStefano Babic * 131a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 1413402868SStefano Babic */ 1513402868SStefano Babic 1613402868SStefano Babic #include <common.h> 1713402868SStefano Babic #include <malloc.h> 1813402868SStefano Babic #include <video_fb.h> 1913402868SStefano Babic #include <linux/list.h> 2013402868SStefano Babic #include <linux/fb.h> 2113402868SStefano Babic 2213402868SStefano Babic #include <asm/errno.h> 2313402868SStefano Babic #include <asm/io.h> 2413402868SStefano Babic #include <asm/arch/hardware.h> 2513402868SStefano Babic 2613402868SStefano Babic #include "videomodes.h" 27*0017f9eeSHeiko Schocher #include "da8xx-fb.h" 2813402868SStefano Babic 2913402868SStefano Babic #define DRIVER_NAME "da8xx_lcdc" 3013402868SStefano Babic 3113402868SStefano Babic /* LCD Status Register */ 3213402868SStefano Babic #define LCD_END_OF_FRAME1 (1 << 9) 3313402868SStefano Babic #define LCD_END_OF_FRAME0 (1 << 8) 3413402868SStefano Babic #define LCD_PL_LOAD_DONE (1 << 6) 3513402868SStefano Babic #define LCD_FIFO_UNDERFLOW (1 << 5) 3613402868SStefano Babic #define LCD_SYNC_LOST (1 << 2) 3713402868SStefano Babic 3813402868SStefano Babic /* LCD DMA Control Register */ 3913402868SStefano Babic #define LCD_DMA_BURST_SIZE(x) ((x) << 4) 4013402868SStefano Babic #define LCD_DMA_BURST_1 0x0 4113402868SStefano Babic #define LCD_DMA_BURST_2 0x1 4213402868SStefano Babic #define LCD_DMA_BURST_4 0x2 4313402868SStefano Babic #define LCD_DMA_BURST_8 0x3 4413402868SStefano Babic #define LCD_DMA_BURST_16 0x4 4513402868SStefano Babic #define LCD_END_OF_FRAME_INT_ENA (1 << 2) 4613402868SStefano Babic #define LCD_DUAL_FRAME_BUFFER_ENABLE (1 << 0) 4713402868SStefano Babic 4813402868SStefano Babic /* LCD Control Register */ 4913402868SStefano Babic #define LCD_CLK_DIVISOR(x) ((x) << 8) 5013402868SStefano Babic #define LCD_RASTER_MODE 0x01 5113402868SStefano Babic 5213402868SStefano Babic /* LCD Raster Control Register */ 5313402868SStefano Babic #define LCD_PALETTE_LOAD_MODE(x) ((x) << 20) 5413402868SStefano Babic #define PALETTE_AND_DATA 0x00 5513402868SStefano Babic #define PALETTE_ONLY 0x01 5613402868SStefano Babic #define DATA_ONLY 0x02 5713402868SStefano Babic 5813402868SStefano Babic #define LCD_MONO_8BIT_MODE (1 << 9) 5913402868SStefano Babic #define LCD_RASTER_ORDER (1 << 8) 6013402868SStefano Babic #define LCD_TFT_MODE (1 << 7) 6113402868SStefano Babic #define LCD_UNDERFLOW_INT_ENA (1 << 6) 6213402868SStefano Babic #define LCD_PL_ENABLE (1 << 4) 6313402868SStefano Babic #define LCD_MONOCHROME_MODE (1 << 1) 6413402868SStefano Babic #define LCD_RASTER_ENABLE (1 << 0) 6513402868SStefano Babic #define LCD_TFT_ALT_ENABLE (1 << 23) 6613402868SStefano Babic #define LCD_STN_565_ENABLE (1 << 24) 6713402868SStefano Babic 6813402868SStefano Babic /* LCD Raster Timing 2 Register */ 6913402868SStefano Babic #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) 7013402868SStefano Babic #define LCD_AC_BIAS_FREQUENCY(x) ((x) << 8) 7113402868SStefano Babic #define LCD_SYNC_CTRL (1 << 25) 7213402868SStefano Babic #define LCD_SYNC_EDGE (1 << 24) 7313402868SStefano Babic #define LCD_INVERT_PIXEL_CLOCK (1 << 22) 7413402868SStefano Babic #define LCD_INVERT_LINE_CLOCK (1 << 21) 7513402868SStefano Babic #define LCD_INVERT_FRAME_CLOCK (1 << 20) 7613402868SStefano Babic 7713402868SStefano Babic /* LCD Block */ 7813402868SStefano Babic struct da8xx_lcd_regs { 7913402868SStefano Babic u32 revid; 8013402868SStefano Babic u32 ctrl; 8113402868SStefano Babic u32 stat; 8213402868SStefano Babic u32 lidd_ctrl; 8313402868SStefano Babic u32 lidd_cs0_conf; 8413402868SStefano Babic u32 lidd_cs0_addr; 8513402868SStefano Babic u32 lidd_cs0_data; 8613402868SStefano Babic u32 lidd_cs1_conf; 8713402868SStefano Babic u32 lidd_cs1_addr; 8813402868SStefano Babic u32 lidd_cs1_data; 8913402868SStefano Babic u32 raster_ctrl; 9013402868SStefano Babic u32 raster_timing_0; 9113402868SStefano Babic u32 raster_timing_1; 9213402868SStefano Babic u32 raster_timing_2; 9313402868SStefano Babic u32 raster_subpanel; 9413402868SStefano Babic u32 reserved; 9513402868SStefano Babic u32 dma_ctrl; 9613402868SStefano Babic u32 dma_frm_buf_base_addr_0; 9713402868SStefano Babic u32 dma_frm_buf_ceiling_addr_0; 9813402868SStefano Babic u32 dma_frm_buf_base_addr_1; 9913402868SStefano Babic u32 dma_frm_buf_ceiling_addr_1; 10013402868SStefano Babic }; 10113402868SStefano Babic 10213402868SStefano Babic #define LCD_NUM_BUFFERS 1 10313402868SStefano Babic 10413402868SStefano Babic #define WSI_TIMEOUT 50 10513402868SStefano Babic #define PALETTE_SIZE 256 10613402868SStefano Babic #define LEFT_MARGIN 64 10713402868SStefano Babic #define RIGHT_MARGIN 64 10813402868SStefano Babic #define UPPER_MARGIN 32 10913402868SStefano Babic #define LOWER_MARGIN 32 11013402868SStefano Babic 11113402868SStefano Babic #define calc_fbsize() (panel.plnSizeX * panel.plnSizeY * panel.gdfBytesPP) 11213402868SStefano Babic 11313402868SStefano Babic static struct da8xx_lcd_regs *da8xx_fb_reg_base; 11413402868SStefano Babic 11513402868SStefano Babic DECLARE_GLOBAL_DATA_PTR; 11613402868SStefano Babic 11713402868SStefano Babic /* graphics setup */ 11813402868SStefano Babic static GraphicDevice gpanel; 11913402868SStefano Babic static const struct da8xx_panel *lcd_panel; 12013402868SStefano Babic static struct fb_info *da8xx_fb_info; 12113402868SStefano Babic static int bits_x_pixel; 12213402868SStefano Babic 12313402868SStefano Babic static inline unsigned int lcdc_read(u32 *addr) 12413402868SStefano Babic { 12513402868SStefano Babic return (unsigned int)readl(addr); 12613402868SStefano Babic } 12713402868SStefano Babic 12813402868SStefano Babic static inline void lcdc_write(unsigned int val, u32 *addr) 12913402868SStefano Babic { 13013402868SStefano Babic writel(val, addr); 13113402868SStefano Babic } 13213402868SStefano Babic 13313402868SStefano Babic struct da8xx_fb_par { 13413402868SStefano Babic u32 p_palette_base; 13513402868SStefano Babic unsigned char *v_palette_base; 13613402868SStefano Babic dma_addr_t vram_phys; 13713402868SStefano Babic unsigned long vram_size; 13813402868SStefano Babic void *vram_virt; 13913402868SStefano Babic unsigned int dma_start; 14013402868SStefano Babic unsigned int dma_end; 14113402868SStefano Babic struct clk *lcdc_clk; 14213402868SStefano Babic int irq; 14313402868SStefano Babic unsigned short pseudo_palette[16]; 14413402868SStefano Babic unsigned int palette_sz; 14513402868SStefano Babic unsigned int pxl_clk; 14613402868SStefano Babic int blank; 14713402868SStefano Babic int vsync_flag; 14813402868SStefano Babic int vsync_timeout; 14913402868SStefano Babic }; 15013402868SStefano Babic 15113402868SStefano Babic 15213402868SStefano Babic /* Variable Screen Information */ 15313402868SStefano Babic static struct fb_var_screeninfo da8xx_fb_var = { 15413402868SStefano Babic .xoffset = 0, 15513402868SStefano Babic .yoffset = 0, 15613402868SStefano Babic .transp = {0, 0, 0}, 15713402868SStefano Babic .nonstd = 0, 15813402868SStefano Babic .activate = 0, 15913402868SStefano Babic .height = -1, 16013402868SStefano Babic .width = -1, 16113402868SStefano Babic .pixclock = 46666, /* 46us - AUO display */ 16213402868SStefano Babic .accel_flags = 0, 16313402868SStefano Babic .left_margin = LEFT_MARGIN, 16413402868SStefano Babic .right_margin = RIGHT_MARGIN, 16513402868SStefano Babic .upper_margin = UPPER_MARGIN, 16613402868SStefano Babic .lower_margin = LOWER_MARGIN, 16713402868SStefano Babic .sync = 0, 16813402868SStefano Babic .vmode = FB_VMODE_NONINTERLACED 16913402868SStefano Babic }; 17013402868SStefano Babic 17113402868SStefano Babic static struct fb_fix_screeninfo da8xx_fb_fix = { 17213402868SStefano Babic .id = "DA8xx FB Drv", 17313402868SStefano Babic .type = FB_TYPE_PACKED_PIXELS, 17413402868SStefano Babic .type_aux = 0, 17513402868SStefano Babic .visual = FB_VISUAL_PSEUDOCOLOR, 17613402868SStefano Babic .xpanstep = 0, 17713402868SStefano Babic .ypanstep = 1, 17813402868SStefano Babic .ywrapstep = 0, 17913402868SStefano Babic .accel = FB_ACCEL_NONE 18013402868SStefano Babic }; 18113402868SStefano Babic 18213402868SStefano Babic static const struct display_panel disp_panel = { 18313402868SStefano Babic QVGA, 18413402868SStefano Babic 16, 18513402868SStefano Babic 16, 18613402868SStefano Babic COLOR_ACTIVE, 18713402868SStefano Babic }; 18813402868SStefano Babic 18913402868SStefano Babic static const struct lcd_ctrl_config lcd_cfg = { 19013402868SStefano Babic &disp_panel, 19113402868SStefano Babic .ac_bias = 255, 19213402868SStefano Babic .ac_bias_intrpt = 0, 19313402868SStefano Babic .dma_burst_sz = 16, 19413402868SStefano Babic .bpp = 16, 19513402868SStefano Babic .fdd = 255, 19613402868SStefano Babic .tft_alt_mode = 0, 19713402868SStefano Babic .stn_565_mode = 0, 19813402868SStefano Babic .mono_8bit_mode = 0, 19913402868SStefano Babic .invert_line_clock = 1, 20013402868SStefano Babic .invert_frm_clock = 1, 20113402868SStefano Babic .sync_edge = 0, 20213402868SStefano Babic .sync_ctrl = 1, 20313402868SStefano Babic .raster_order = 0, 20413402868SStefano Babic }; 20513402868SStefano Babic 20613402868SStefano Babic /* Enable the Raster Engine of the LCD Controller */ 20713402868SStefano Babic static inline void lcd_enable_raster(void) 20813402868SStefano Babic { 20913402868SStefano Babic u32 reg; 21013402868SStefano Babic 21113402868SStefano Babic reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl); 21213402868SStefano Babic if (!(reg & LCD_RASTER_ENABLE)) 21313402868SStefano Babic lcdc_write(reg | LCD_RASTER_ENABLE, 21413402868SStefano Babic &da8xx_fb_reg_base->raster_ctrl); 21513402868SStefano Babic } 21613402868SStefano Babic 21713402868SStefano Babic /* Disable the Raster Engine of the LCD Controller */ 21813402868SStefano Babic static inline void lcd_disable_raster(void) 21913402868SStefano Babic { 22013402868SStefano Babic u32 reg; 22113402868SStefano Babic 22213402868SStefano Babic reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl); 22313402868SStefano Babic if (reg & LCD_RASTER_ENABLE) 22413402868SStefano Babic lcdc_write(reg & ~LCD_RASTER_ENABLE, 22513402868SStefano Babic &da8xx_fb_reg_base->raster_ctrl); 22613402868SStefano Babic } 22713402868SStefano Babic 22813402868SStefano Babic static void lcd_blit(int load_mode, struct da8xx_fb_par *par) 22913402868SStefano Babic { 23013402868SStefano Babic u32 start; 23113402868SStefano Babic u32 end; 23213402868SStefano Babic u32 reg_ras; 23313402868SStefano Babic u32 reg_dma; 23413402868SStefano Babic 23513402868SStefano Babic /* init reg to clear PLM (loading mode) fields */ 23613402868SStefano Babic reg_ras = lcdc_read(&da8xx_fb_reg_base->raster_ctrl); 23713402868SStefano Babic reg_ras &= ~(3 << 20); 23813402868SStefano Babic 23913402868SStefano Babic reg_dma = lcdc_read(&da8xx_fb_reg_base->dma_ctrl); 24013402868SStefano Babic 24113402868SStefano Babic if (load_mode == LOAD_DATA) { 24213402868SStefano Babic start = par->dma_start; 24313402868SStefano Babic end = par->dma_end; 24413402868SStefano Babic 24513402868SStefano Babic reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); 24613402868SStefano Babic reg_dma |= LCD_END_OF_FRAME_INT_ENA; 24713402868SStefano Babic 24813402868SStefano Babic #if (LCD_NUM_BUFFERS == 2) 24913402868SStefano Babic reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; 25013402868SStefano Babic lcdc_write(start, &da8xx_fb_reg_base->dma_frm_buf_base_addr_0); 25113402868SStefano Babic lcdc_write(end, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0); 25213402868SStefano Babic lcdc_write(start, &da8xx_fb_reg_base->dma_frm_buf_base_addr_1); 25313402868SStefano Babic lcdc_write(end, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_1); 25413402868SStefano Babic #else 25513402868SStefano Babic reg_dma &= ~LCD_DUAL_FRAME_BUFFER_ENABLE; 25613402868SStefano Babic lcdc_write(start, &da8xx_fb_reg_base->dma_frm_buf_base_addr_0); 25713402868SStefano Babic lcdc_write(end, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0); 25813402868SStefano Babic lcdc_write(0, &da8xx_fb_reg_base->dma_frm_buf_base_addr_1); 25913402868SStefano Babic lcdc_write(0, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_1); 26013402868SStefano Babic #endif 26113402868SStefano Babic 26213402868SStefano Babic } else if (load_mode == LOAD_PALETTE) { 26313402868SStefano Babic start = par->p_palette_base; 26413402868SStefano Babic end = start + par->palette_sz - 1; 26513402868SStefano Babic 26613402868SStefano Babic reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); 26713402868SStefano Babic reg_ras |= LCD_PL_ENABLE; 26813402868SStefano Babic 26913402868SStefano Babic lcdc_write(start, &da8xx_fb_reg_base->dma_frm_buf_base_addr_0); 27013402868SStefano Babic lcdc_write(end, &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0); 27113402868SStefano Babic } 27213402868SStefano Babic 27313402868SStefano Babic lcdc_write(reg_dma, &da8xx_fb_reg_base->dma_ctrl); 27413402868SStefano Babic lcdc_write(reg_ras, &da8xx_fb_reg_base->raster_ctrl); 27513402868SStefano Babic 27613402868SStefano Babic /* 27713402868SStefano Babic * The Raster enable bit must be set after all other control fields are 27813402868SStefano Babic * set. 27913402868SStefano Babic */ 28013402868SStefano Babic lcd_enable_raster(); 28113402868SStefano Babic } 28213402868SStefano Babic 28313402868SStefano Babic /* Configure the Burst Size of DMA */ 28413402868SStefano Babic static int lcd_cfg_dma(int burst_size) 28513402868SStefano Babic { 28613402868SStefano Babic u32 reg; 28713402868SStefano Babic 28813402868SStefano Babic reg = lcdc_read(&da8xx_fb_reg_base->dma_ctrl) & 0x00000001; 28913402868SStefano Babic switch (burst_size) { 29013402868SStefano Babic case 1: 29113402868SStefano Babic reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1); 29213402868SStefano Babic break; 29313402868SStefano Babic case 2: 29413402868SStefano Babic reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2); 29513402868SStefano Babic break; 29613402868SStefano Babic case 4: 29713402868SStefano Babic reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4); 29813402868SStefano Babic break; 29913402868SStefano Babic case 8: 30013402868SStefano Babic reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8); 30113402868SStefano Babic break; 30213402868SStefano Babic case 16: 30313402868SStefano Babic reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16); 30413402868SStefano Babic break; 30513402868SStefano Babic default: 30613402868SStefano Babic return -EINVAL; 30713402868SStefano Babic } 30813402868SStefano Babic lcdc_write(reg, &da8xx_fb_reg_base->dma_ctrl); 30913402868SStefano Babic 31013402868SStefano Babic return 0; 31113402868SStefano Babic } 31213402868SStefano Babic 31313402868SStefano Babic static void lcd_cfg_ac_bias(int period, int transitions_per_int) 31413402868SStefano Babic { 31513402868SStefano Babic u32 reg; 31613402868SStefano Babic 31713402868SStefano Babic /* Set the AC Bias Period and Number of Transisitons per Interrupt */ 31813402868SStefano Babic reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_2) & 0xFFF00000; 31913402868SStefano Babic reg |= LCD_AC_BIAS_FREQUENCY(period) | 32013402868SStefano Babic LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int); 32113402868SStefano Babic lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_2); 32213402868SStefano Babic } 32313402868SStefano Babic 32413402868SStefano Babic static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width, 32513402868SStefano Babic int front_porch) 32613402868SStefano Babic { 32713402868SStefano Babic u32 reg; 32813402868SStefano Babic 32913402868SStefano Babic reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_0) & 0xf; 33013402868SStefano Babic reg |= ((back_porch & 0xff) << 24) 33113402868SStefano Babic | ((front_porch & 0xff) << 16) 33213402868SStefano Babic | ((pulse_width & 0x3f) << 10); 33313402868SStefano Babic lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_0); 33413402868SStefano Babic } 33513402868SStefano Babic 33613402868SStefano Babic static void lcd_cfg_vertical_sync(int back_porch, int pulse_width, 33713402868SStefano Babic int front_porch) 33813402868SStefano Babic { 33913402868SStefano Babic u32 reg; 34013402868SStefano Babic 34113402868SStefano Babic reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_1) & 0x3ff; 34213402868SStefano Babic reg |= ((back_porch & 0xff) << 24) 34313402868SStefano Babic | ((front_porch & 0xff) << 16) 34413402868SStefano Babic | ((pulse_width & 0x3f) << 10); 34513402868SStefano Babic lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_1); 34613402868SStefano Babic } 34713402868SStefano Babic 34813402868SStefano Babic static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) 34913402868SStefano Babic { 35013402868SStefano Babic u32 reg; 35113402868SStefano Babic 35213402868SStefano Babic reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl) & ~(LCD_TFT_MODE | 35313402868SStefano Babic LCD_MONO_8BIT_MODE | 35413402868SStefano Babic LCD_MONOCHROME_MODE); 35513402868SStefano Babic 35613402868SStefano Babic switch (cfg->p_disp_panel->panel_shade) { 35713402868SStefano Babic case MONOCHROME: 35813402868SStefano Babic reg |= LCD_MONOCHROME_MODE; 35913402868SStefano Babic if (cfg->mono_8bit_mode) 36013402868SStefano Babic reg |= LCD_MONO_8BIT_MODE; 36113402868SStefano Babic break; 36213402868SStefano Babic case COLOR_ACTIVE: 36313402868SStefano Babic reg |= LCD_TFT_MODE; 36413402868SStefano Babic if (cfg->tft_alt_mode) 36513402868SStefano Babic reg |= LCD_TFT_ALT_ENABLE; 36613402868SStefano Babic break; 36713402868SStefano Babic 36813402868SStefano Babic case COLOR_PASSIVE: 36913402868SStefano Babic if (cfg->stn_565_mode) 37013402868SStefano Babic reg |= LCD_STN_565_ENABLE; 37113402868SStefano Babic break; 37213402868SStefano Babic 37313402868SStefano Babic default: 37413402868SStefano Babic return -EINVAL; 37513402868SStefano Babic } 37613402868SStefano Babic 37713402868SStefano Babic /* enable additional interrupts here */ 37813402868SStefano Babic reg |= LCD_UNDERFLOW_INT_ENA; 37913402868SStefano Babic 38013402868SStefano Babic lcdc_write(reg, &da8xx_fb_reg_base->raster_ctrl); 38113402868SStefano Babic 38213402868SStefano Babic reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_2); 38313402868SStefano Babic 38413402868SStefano Babic if (cfg->sync_ctrl) 38513402868SStefano Babic reg |= LCD_SYNC_CTRL; 38613402868SStefano Babic else 38713402868SStefano Babic reg &= ~LCD_SYNC_CTRL; 38813402868SStefano Babic 38913402868SStefano Babic if (cfg->sync_edge) 39013402868SStefano Babic reg |= LCD_SYNC_EDGE; 39113402868SStefano Babic else 39213402868SStefano Babic reg &= ~LCD_SYNC_EDGE; 39313402868SStefano Babic 39413402868SStefano Babic if (cfg->invert_line_clock) 39513402868SStefano Babic reg |= LCD_INVERT_LINE_CLOCK; 39613402868SStefano Babic else 39713402868SStefano Babic reg &= ~LCD_INVERT_LINE_CLOCK; 39813402868SStefano Babic 39913402868SStefano Babic if (cfg->invert_frm_clock) 40013402868SStefano Babic reg |= LCD_INVERT_FRAME_CLOCK; 40113402868SStefano Babic else 40213402868SStefano Babic reg &= ~LCD_INVERT_FRAME_CLOCK; 40313402868SStefano Babic 40413402868SStefano Babic lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_2); 40513402868SStefano Babic 40613402868SStefano Babic return 0; 40713402868SStefano Babic } 40813402868SStefano Babic 40913402868SStefano Babic static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, 41013402868SStefano Babic u32 bpp, u32 raster_order) 41113402868SStefano Babic { 41213402868SStefano Babic u32 reg; 41313402868SStefano Babic 41413402868SStefano Babic /* Set the Panel Width */ 41513402868SStefano Babic /* Pixels per line = (PPL + 1)*16 */ 41613402868SStefano Babic /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/ 41713402868SStefano Babic width &= 0x3f0; 41813402868SStefano Babic reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_0); 41913402868SStefano Babic reg &= 0xfffffc00; 42013402868SStefano Babic reg |= ((width >> 4) - 1) << 4; 42113402868SStefano Babic lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_0); 42213402868SStefano Babic 42313402868SStefano Babic /* Set the Panel Height */ 42413402868SStefano Babic reg = lcdc_read(&da8xx_fb_reg_base->raster_timing_1); 42513402868SStefano Babic reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00); 42613402868SStefano Babic lcdc_write(reg, &da8xx_fb_reg_base->raster_timing_1); 42713402868SStefano Babic 42813402868SStefano Babic /* Set the Raster Order of the Frame Buffer */ 42913402868SStefano Babic reg = lcdc_read(&da8xx_fb_reg_base->raster_ctrl) & ~(1 << 8); 43013402868SStefano Babic if (raster_order) 43113402868SStefano Babic reg |= LCD_RASTER_ORDER; 43213402868SStefano Babic lcdc_write(reg, &da8xx_fb_reg_base->raster_ctrl); 43313402868SStefano Babic 43413402868SStefano Babic switch (bpp) { 43513402868SStefano Babic case 1: 43613402868SStefano Babic case 2: 43713402868SStefano Babic case 4: 43813402868SStefano Babic case 16: 43913402868SStefano Babic par->palette_sz = 16 * 2; 44013402868SStefano Babic break; 44113402868SStefano Babic 44213402868SStefano Babic case 8: 44313402868SStefano Babic par->palette_sz = 256 * 2; 44413402868SStefano Babic break; 44513402868SStefano Babic 44613402868SStefano Babic default: 44713402868SStefano Babic return -EINVAL; 44813402868SStefano Babic } 44913402868SStefano Babic 45013402868SStefano Babic return 0; 45113402868SStefano Babic } 45213402868SStefano Babic 45313402868SStefano Babic static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, 45413402868SStefano Babic unsigned blue, unsigned transp, 45513402868SStefano Babic struct fb_info *info) 45613402868SStefano Babic { 45713402868SStefano Babic struct da8xx_fb_par *par = info->par; 45813402868SStefano Babic unsigned short *palette = (unsigned short *) par->v_palette_base; 45913402868SStefano Babic u_short pal; 46013402868SStefano Babic int update_hw = 0; 46113402868SStefano Babic 46213402868SStefano Babic if (regno > 255) 46313402868SStefano Babic return 1; 46413402868SStefano Babic 46513402868SStefano Babic if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) 46613402868SStefano Babic return 1; 46713402868SStefano Babic 46813402868SStefano Babic if (info->var.bits_per_pixel == 8) { 46913402868SStefano Babic red >>= 4; 47013402868SStefano Babic green >>= 8; 47113402868SStefano Babic blue >>= 12; 47213402868SStefano Babic 47313402868SStefano Babic pal = (red & 0x0f00); 47413402868SStefano Babic pal |= (green & 0x00f0); 47513402868SStefano Babic pal |= (blue & 0x000f); 47613402868SStefano Babic 47713402868SStefano Babic if (palette[regno] != pal) { 47813402868SStefano Babic update_hw = 1; 47913402868SStefano Babic palette[regno] = pal; 48013402868SStefano Babic } 48113402868SStefano Babic } else if ((info->var.bits_per_pixel == 16) && regno < 16) { 48213402868SStefano Babic red >>= (16 - info->var.red.length); 48313402868SStefano Babic red <<= info->var.red.offset; 48413402868SStefano Babic 48513402868SStefano Babic green >>= (16 - info->var.green.length); 48613402868SStefano Babic green <<= info->var.green.offset; 48713402868SStefano Babic 48813402868SStefano Babic blue >>= (16 - info->var.blue.length); 48913402868SStefano Babic blue <<= info->var.blue.offset; 49013402868SStefano Babic 49113402868SStefano Babic par->pseudo_palette[regno] = red | green | blue; 49213402868SStefano Babic 49313402868SStefano Babic if (palette[0] != 0x4000) { 49413402868SStefano Babic update_hw = 1; 49513402868SStefano Babic palette[0] = 0x4000; 49613402868SStefano Babic } 49713402868SStefano Babic } 49813402868SStefano Babic 49913402868SStefano Babic /* Update the palette in the h/w as needed. */ 50013402868SStefano Babic if (update_hw) 50113402868SStefano Babic lcd_blit(LOAD_PALETTE, par); 50213402868SStefano Babic 50313402868SStefano Babic return 0; 50413402868SStefano Babic } 50513402868SStefano Babic 50613402868SStefano Babic static void lcd_reset(struct da8xx_fb_par *par) 50713402868SStefano Babic { 50813402868SStefano Babic /* Disable the Raster if previously Enabled */ 50913402868SStefano Babic lcd_disable_raster(); 51013402868SStefano Babic 51113402868SStefano Babic /* DMA has to be disabled */ 51213402868SStefano Babic lcdc_write(0, &da8xx_fb_reg_base->dma_ctrl); 51313402868SStefano Babic lcdc_write(0, &da8xx_fb_reg_base->raster_ctrl); 51413402868SStefano Babic } 51513402868SStefano Babic 51613402868SStefano Babic static void lcd_calc_clk_divider(struct da8xx_fb_par *par) 51713402868SStefano Babic { 51813402868SStefano Babic unsigned int lcd_clk, div; 51913402868SStefano Babic 52013402868SStefano Babic /* Get clock from sysclk2 */ 52113402868SStefano Babic lcd_clk = clk_get(2); 52213402868SStefano Babic 52313402868SStefano Babic div = lcd_clk / par->pxl_clk; 52413402868SStefano Babic debug("LCD Clock: 0x%x Divider: 0x%x PixClk: 0x%x\n", 52513402868SStefano Babic lcd_clk, div, par->pxl_clk); 52613402868SStefano Babic 52713402868SStefano Babic /* Configure the LCD clock divisor. */ 52813402868SStefano Babic lcdc_write(LCD_CLK_DIVISOR(div) | 52913402868SStefano Babic (LCD_RASTER_MODE & 0x1), &da8xx_fb_reg_base->ctrl); 53013402868SStefano Babic } 53113402868SStefano Babic 53213402868SStefano Babic static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, 53313402868SStefano Babic const struct da8xx_panel *panel) 53413402868SStefano Babic { 53513402868SStefano Babic u32 bpp; 53613402868SStefano Babic int ret = 0; 53713402868SStefano Babic 53813402868SStefano Babic lcd_reset(par); 53913402868SStefano Babic 54013402868SStefano Babic /* Calculate the divider */ 54113402868SStefano Babic lcd_calc_clk_divider(par); 54213402868SStefano Babic 54313402868SStefano Babic if (panel->invert_pxl_clk) 54413402868SStefano Babic lcdc_write((lcdc_read(&da8xx_fb_reg_base->raster_timing_2) | 54513402868SStefano Babic LCD_INVERT_PIXEL_CLOCK), 54613402868SStefano Babic &da8xx_fb_reg_base->raster_timing_2); 54713402868SStefano Babic else 54813402868SStefano Babic lcdc_write((lcdc_read(&da8xx_fb_reg_base->raster_timing_2) & 54913402868SStefano Babic ~LCD_INVERT_PIXEL_CLOCK), 55013402868SStefano Babic &da8xx_fb_reg_base->raster_timing_2); 55113402868SStefano Babic 55213402868SStefano Babic /* Configure the DMA burst size. */ 55313402868SStefano Babic ret = lcd_cfg_dma(cfg->dma_burst_sz); 55413402868SStefano Babic if (ret < 0) 55513402868SStefano Babic return ret; 55613402868SStefano Babic 55713402868SStefano Babic /* Configure the AC bias properties. */ 55813402868SStefano Babic lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt); 55913402868SStefano Babic 56013402868SStefano Babic /* Configure the vertical and horizontal sync properties. */ 56113402868SStefano Babic lcd_cfg_vertical_sync(panel->vbp, panel->vsw, panel->vfp); 56213402868SStefano Babic lcd_cfg_horizontal_sync(panel->hbp, panel->hsw, panel->hfp); 56313402868SStefano Babic 56413402868SStefano Babic /* Configure for disply */ 56513402868SStefano Babic ret = lcd_cfg_display(cfg); 56613402868SStefano Babic if (ret < 0) 56713402868SStefano Babic return ret; 56813402868SStefano Babic 56913402868SStefano Babic if (QVGA != cfg->p_disp_panel->panel_type) 57013402868SStefano Babic return -EINVAL; 57113402868SStefano Babic 57213402868SStefano Babic if (cfg->bpp <= cfg->p_disp_panel->max_bpp && 57313402868SStefano Babic cfg->bpp >= cfg->p_disp_panel->min_bpp) 57413402868SStefano Babic bpp = cfg->bpp; 57513402868SStefano Babic else 57613402868SStefano Babic bpp = cfg->p_disp_panel->max_bpp; 57713402868SStefano Babic if (bpp == 12) 57813402868SStefano Babic bpp = 16; 57913402868SStefano Babic ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->width, 58013402868SStefano Babic (unsigned int)panel->height, bpp, 58113402868SStefano Babic cfg->raster_order); 58213402868SStefano Babic if (ret < 0) 58313402868SStefano Babic return ret; 58413402868SStefano Babic 58513402868SStefano Babic /* Configure FDD */ 58613402868SStefano Babic lcdc_write((lcdc_read(&da8xx_fb_reg_base->raster_ctrl) & 0xfff00fff) | 58713402868SStefano Babic (cfg->fdd << 12), &da8xx_fb_reg_base->raster_ctrl); 58813402868SStefano Babic 58913402868SStefano Babic return 0; 59013402868SStefano Babic } 59113402868SStefano Babic 59213402868SStefano Babic static void lcdc_dma_start(void) 59313402868SStefano Babic { 59413402868SStefano Babic struct da8xx_fb_par *par = da8xx_fb_info->par; 59513402868SStefano Babic lcdc_write(par->dma_start, 59613402868SStefano Babic &da8xx_fb_reg_base->dma_frm_buf_base_addr_0); 59713402868SStefano Babic lcdc_write(par->dma_end, 59813402868SStefano Babic &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0); 59913402868SStefano Babic lcdc_write(0, 60013402868SStefano Babic &da8xx_fb_reg_base->dma_frm_buf_base_addr_1); 60113402868SStefano Babic lcdc_write(0, 60213402868SStefano Babic &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_1); 60313402868SStefano Babic } 60413402868SStefano Babic 60513402868SStefano Babic static u32 lcdc_irq_handler(void) 60613402868SStefano Babic { 60713402868SStefano Babic struct da8xx_fb_par *par = da8xx_fb_info->par; 60813402868SStefano Babic u32 stat = lcdc_read(&da8xx_fb_reg_base->stat); 60913402868SStefano Babic u32 reg_ras; 61013402868SStefano Babic 61113402868SStefano Babic if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { 61213402868SStefano Babic debug("LCD_SYNC_LOST\n"); 61313402868SStefano Babic lcd_disable_raster(); 61413402868SStefano Babic lcdc_write(stat, &da8xx_fb_reg_base->stat); 61513402868SStefano Babic lcd_enable_raster(); 61613402868SStefano Babic return LCD_SYNC_LOST; 61713402868SStefano Babic } else if (stat & LCD_PL_LOAD_DONE) { 61813402868SStefano Babic debug("LCD_PL_LOAD_DONE\n"); 61913402868SStefano Babic /* 62013402868SStefano Babic * Must disable raster before changing state of any control bit. 62113402868SStefano Babic * And also must be disabled before clearing the PL loading 62213402868SStefano Babic * interrupt via the following write to the status register. If 62313402868SStefano Babic * this is done after then one gets multiple PL done interrupts. 62413402868SStefano Babic */ 62513402868SStefano Babic lcd_disable_raster(); 62613402868SStefano Babic 62713402868SStefano Babic lcdc_write(stat, &da8xx_fb_reg_base->stat); 62813402868SStefano Babic 62913402868SStefano Babic /* Disable PL completion inerrupt */ 63013402868SStefano Babic reg_ras = lcdc_read(&da8xx_fb_reg_base->raster_ctrl); 63113402868SStefano Babic reg_ras &= ~LCD_PL_ENABLE; 63213402868SStefano Babic lcdc_write(reg_ras, &da8xx_fb_reg_base->raster_ctrl); 63313402868SStefano Babic 63413402868SStefano Babic /* Setup and start data loading mode */ 63513402868SStefano Babic lcd_blit(LOAD_DATA, par); 63613402868SStefano Babic return LCD_PL_LOAD_DONE; 63713402868SStefano Babic } else { 63813402868SStefano Babic lcdc_write(stat, &da8xx_fb_reg_base->stat); 63913402868SStefano Babic 64013402868SStefano Babic if (stat & LCD_END_OF_FRAME0) 64113402868SStefano Babic debug("LCD_END_OF_FRAME0\n"); 64213402868SStefano Babic 64313402868SStefano Babic lcdc_write(par->dma_start, 64413402868SStefano Babic &da8xx_fb_reg_base->dma_frm_buf_base_addr_0); 64513402868SStefano Babic lcdc_write(par->dma_end, 64613402868SStefano Babic &da8xx_fb_reg_base->dma_frm_buf_ceiling_addr_0); 64713402868SStefano Babic par->vsync_flag = 1; 64813402868SStefano Babic return LCD_END_OF_FRAME0; 64913402868SStefano Babic } 65013402868SStefano Babic return stat; 65113402868SStefano Babic } 65213402868SStefano Babic 65313402868SStefano Babic static u32 wait_for_event(u32 event) 65413402868SStefano Babic { 65513402868SStefano Babic u32 timeout = 50000; 65613402868SStefano Babic u32 ret; 65713402868SStefano Babic 65813402868SStefano Babic do { 65913402868SStefano Babic ret = lcdc_irq_handler(); 66013402868SStefano Babic udelay(1000); 66113402868SStefano Babic } while (!(ret & event)); 66213402868SStefano Babic 66313402868SStefano Babic if (timeout <= 0) { 66413402868SStefano Babic printf("%s: event %d not hit\n", __func__, event); 66513402868SStefano Babic return -1; 66613402868SStefano Babic } 66713402868SStefano Babic 66813402868SStefano Babic return 0; 66913402868SStefano Babic 67013402868SStefano Babic } 67113402868SStefano Babic 67213402868SStefano Babic void *video_hw_init(void) 67313402868SStefano Babic { 67413402868SStefano Babic struct da8xx_fb_par *par; 67513402868SStefano Babic u32 size; 67613402868SStefano Babic char *p; 67713402868SStefano Babic 67813402868SStefano Babic if (!lcd_panel) { 67913402868SStefano Babic printf("Display not initialized\n"); 68013402868SStefano Babic return NULL; 68113402868SStefano Babic } 68213402868SStefano Babic gpanel.winSizeX = lcd_panel->width; 68313402868SStefano Babic gpanel.winSizeY = lcd_panel->height; 68413402868SStefano Babic gpanel.plnSizeX = lcd_panel->width; 68513402868SStefano Babic gpanel.plnSizeY = lcd_panel->height; 68613402868SStefano Babic 68713402868SStefano Babic switch (bits_x_pixel) { 68813402868SStefano Babic case 24: 68913402868SStefano Babic gpanel.gdfBytesPP = 4; 69013402868SStefano Babic gpanel.gdfIndex = GDF_32BIT_X888RGB; 69113402868SStefano Babic break; 69213402868SStefano Babic case 16: 69313402868SStefano Babic gpanel.gdfBytesPP = 2; 69413402868SStefano Babic gpanel.gdfIndex = GDF_16BIT_565RGB; 69513402868SStefano Babic break; 69613402868SStefano Babic default: 69713402868SStefano Babic gpanel.gdfBytesPP = 1; 69813402868SStefano Babic gpanel.gdfIndex = GDF__8BIT_INDEX; 69913402868SStefano Babic break; 70013402868SStefano Babic } 70113402868SStefano Babic 70213402868SStefano Babic da8xx_fb_reg_base = (struct da8xx_lcd_regs *)DAVINCI_LCD_CNTL_BASE; 70313402868SStefano Babic 70413402868SStefano Babic debug("Resolution: %dx%d %x\n", 70513402868SStefano Babic gpanel.winSizeX, 70613402868SStefano Babic gpanel.winSizeY, 70713402868SStefano Babic lcd_cfg.bpp); 70813402868SStefano Babic 70913402868SStefano Babic size = sizeof(struct fb_info) + sizeof(struct da8xx_fb_par); 71013402868SStefano Babic da8xx_fb_info = malloc(size); 71113402868SStefano Babic debug("da8xx_fb_info at %x\n", (unsigned int)da8xx_fb_info); 71213402868SStefano Babic 71313402868SStefano Babic if (!da8xx_fb_info) { 71413402868SStefano Babic printf("Memory allocation failed for fb_info\n"); 71513402868SStefano Babic return NULL; 71613402868SStefano Babic } 71713402868SStefano Babic memset(da8xx_fb_info, 0, size); 71813402868SStefano Babic p = (char *)da8xx_fb_info; 71913402868SStefano Babic da8xx_fb_info->par = p + sizeof(struct fb_info); 72013402868SStefano Babic debug("da8xx_par at %x\n", (unsigned int)da8xx_fb_info->par); 72113402868SStefano Babic 72213402868SStefano Babic par = da8xx_fb_info->par; 72313402868SStefano Babic par->pxl_clk = lcd_panel->pxl_clk; 72413402868SStefano Babic 72513402868SStefano Babic if (lcd_init(par, &lcd_cfg, lcd_panel) < 0) { 72613402868SStefano Babic printf("lcd_init failed\n"); 72713402868SStefano Babic goto err_release_fb; 72813402868SStefano Babic } 72913402868SStefano Babic 73013402868SStefano Babic /* allocate frame buffer */ 73113402868SStefano Babic par->vram_size = lcd_panel->width * lcd_panel->height * lcd_cfg.bpp; 73213402868SStefano Babic par->vram_size = par->vram_size * LCD_NUM_BUFFERS / 8; 73313402868SStefano Babic 73413402868SStefano Babic par->vram_virt = malloc(par->vram_size); 73513402868SStefano Babic 73613402868SStefano Babic par->vram_phys = (dma_addr_t) par->vram_virt; 73713402868SStefano Babic debug("Requesting 0x%x bytes for framebuffer at 0x%x\n", 73813402868SStefano Babic (unsigned int)par->vram_size, 73913402868SStefano Babic (unsigned int)par->vram_virt); 74013402868SStefano Babic if (!par->vram_virt) { 74113402868SStefano Babic printf("GLCD: malloc for frame buffer failed\n"); 74213402868SStefano Babic goto err_release_fb; 74313402868SStefano Babic } 74413402868SStefano Babic 74513402868SStefano Babic gpanel.frameAdrs = (unsigned int)par->vram_virt; 74613402868SStefano Babic da8xx_fb_info->screen_base = (char *) par->vram_virt; 74713402868SStefano Babic da8xx_fb_fix.smem_start = gpanel.frameAdrs; 74813402868SStefano Babic da8xx_fb_fix.smem_len = par->vram_size; 74913402868SStefano Babic da8xx_fb_fix.line_length = (lcd_panel->width * lcd_cfg.bpp) / 8; 75013402868SStefano Babic 75113402868SStefano Babic par->dma_start = par->vram_phys; 75213402868SStefano Babic par->dma_end = par->dma_start + lcd_panel->height * 75313402868SStefano Babic da8xx_fb_fix.line_length - 1; 75413402868SStefano Babic 75513402868SStefano Babic /* allocate palette buffer */ 75613402868SStefano Babic par->v_palette_base = malloc(PALETTE_SIZE); 75713402868SStefano Babic if (!par->v_palette_base) { 75813402868SStefano Babic printf("GLCD: malloc for palette buffer failed\n"); 75913402868SStefano Babic goto err_release_fb_mem; 76013402868SStefano Babic } 76113402868SStefano Babic memset(par->v_palette_base, 0, PALETTE_SIZE); 76213402868SStefano Babic par->p_palette_base = (unsigned int)par->v_palette_base; 76313402868SStefano Babic 76413402868SStefano Babic /* Initialize par */ 76513402868SStefano Babic da8xx_fb_info->var.bits_per_pixel = lcd_cfg.bpp; 76613402868SStefano Babic 76713402868SStefano Babic da8xx_fb_var.xres = lcd_panel->width; 76813402868SStefano Babic da8xx_fb_var.xres_virtual = lcd_panel->width; 76913402868SStefano Babic 77013402868SStefano Babic da8xx_fb_var.yres = lcd_panel->height; 77113402868SStefano Babic da8xx_fb_var.yres_virtual = lcd_panel->height * LCD_NUM_BUFFERS; 77213402868SStefano Babic 77313402868SStefano Babic da8xx_fb_var.grayscale = 77413402868SStefano Babic lcd_cfg.p_disp_panel->panel_shade == MONOCHROME ? 1 : 0; 77513402868SStefano Babic da8xx_fb_var.bits_per_pixel = lcd_cfg.bpp; 77613402868SStefano Babic 77713402868SStefano Babic da8xx_fb_var.hsync_len = lcd_panel->hsw; 77813402868SStefano Babic da8xx_fb_var.vsync_len = lcd_panel->vsw; 77913402868SStefano Babic 78013402868SStefano Babic /* Initialize fbinfo */ 78113402868SStefano Babic da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT; 78213402868SStefano Babic da8xx_fb_info->fix = da8xx_fb_fix; 78313402868SStefano Babic da8xx_fb_info->var = da8xx_fb_var; 78413402868SStefano Babic da8xx_fb_info->pseudo_palette = par->pseudo_palette; 78513402868SStefano Babic da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ? 78613402868SStefano Babic FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 78713402868SStefano Babic 78813402868SStefano Babic /* Clear interrupt */ 78913402868SStefano Babic memset((void *)par->vram_virt, 0, par->vram_size); 79013402868SStefano Babic lcd_disable_raster(); 79113402868SStefano Babic lcdc_write(0xFFFF, &da8xx_fb_reg_base->stat); 79213402868SStefano Babic debug("Palette at 0x%x size %d\n", par->p_palette_base, 79313402868SStefano Babic par->palette_sz); 79413402868SStefano Babic lcdc_dma_start(); 79513402868SStefano Babic 79613402868SStefano Babic /* Load a default palette */ 79713402868SStefano Babic fb_setcolreg(0, 0, 0, 0, 0xffff, da8xx_fb_info); 79813402868SStefano Babic 79913402868SStefano Babic /* Check that the palette is loaded */ 80013402868SStefano Babic wait_for_event(LCD_PL_LOAD_DONE); 80113402868SStefano Babic 80213402868SStefano Babic /* Wait until DMA is working */ 80313402868SStefano Babic wait_for_event(LCD_END_OF_FRAME0); 80413402868SStefano Babic 80513402868SStefano Babic return (void *)&gpanel; 80613402868SStefano Babic 80713402868SStefano Babic err_release_fb_mem: 80813402868SStefano Babic free(par->vram_virt); 80913402868SStefano Babic 81013402868SStefano Babic err_release_fb: 81113402868SStefano Babic free(da8xx_fb_info); 81213402868SStefano Babic 81313402868SStefano Babic return NULL; 81413402868SStefano Babic } 81513402868SStefano Babic 81613402868SStefano Babic void video_set_lut(unsigned int index, /* color number */ 81713402868SStefano Babic unsigned char r, /* red */ 81813402868SStefano Babic unsigned char g, /* green */ 81913402868SStefano Babic unsigned char b /* blue */ 82013402868SStefano Babic ) 82113402868SStefano Babic { 82213402868SStefano Babic 82313402868SStefano Babic return; 82413402868SStefano Babic } 82513402868SStefano Babic 82613402868SStefano Babic void da8xx_video_init(const struct da8xx_panel *panel, int bits_pixel) 82713402868SStefano Babic { 82813402868SStefano Babic lcd_panel = panel; 82913402868SStefano Babic bits_x_pixel = bits_pixel; 83013402868SStefano Babic } 831