1*0c99f6abSGuennadi Liakhovetski /* 2*0c99f6abSGuennadi Liakhovetski * Copyright (C) 2009 3*0c99f6abSGuennadi Liakhovetski * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de> 4*0c99f6abSGuennadi Liakhovetski * 5*0c99f6abSGuennadi Liakhovetski * See file CREDITS for list of people who contributed to this 6*0c99f6abSGuennadi Liakhovetski * project. 7*0c99f6abSGuennadi Liakhovetski * 8*0c99f6abSGuennadi Liakhovetski * This program is free software; you can redistribute it and/or 9*0c99f6abSGuennadi Liakhovetski * modify it under the terms of the GNU General Public License as 10*0c99f6abSGuennadi Liakhovetski * published by the Free Software Foundation; either version 2 of 11*0c99f6abSGuennadi Liakhovetski * the License, or (at your option) any later version. 12*0c99f6abSGuennadi Liakhovetski * 13*0c99f6abSGuennadi Liakhovetski * This program is distributed in the hope that it will be useful, 14*0c99f6abSGuennadi Liakhovetski * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*0c99f6abSGuennadi Liakhovetski * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*0c99f6abSGuennadi Liakhovetski * GNU General Public License for more details. 17*0c99f6abSGuennadi Liakhovetski * 18*0c99f6abSGuennadi Liakhovetski * You should have received a copy of the GNU General Public License 19*0c99f6abSGuennadi Liakhovetski * along with this program; if not, write to the Free Software 20*0c99f6abSGuennadi Liakhovetski * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21*0c99f6abSGuennadi Liakhovetski * MA 02111-1307 USA 22*0c99f6abSGuennadi Liakhovetski */ 23*0c99f6abSGuennadi Liakhovetski #include <common.h> 24*0c99f6abSGuennadi Liakhovetski #include <lcd.h> 25*0c99f6abSGuennadi Liakhovetski #include <asm/arch/mx31.h> 26*0c99f6abSGuennadi Liakhovetski #include <asm/arch/mx31-regs.h> 27*0c99f6abSGuennadi Liakhovetski #include <asm/errno.h> 28*0c99f6abSGuennadi Liakhovetski 29*0c99f6abSGuennadi Liakhovetski DECLARE_GLOBAL_DATA_PTR; 30*0c99f6abSGuennadi Liakhovetski 31*0c99f6abSGuennadi Liakhovetski void *lcd_base; /* Start of framebuffer memory */ 32*0c99f6abSGuennadi Liakhovetski void *lcd_console_address; /* Start of console buffer */ 33*0c99f6abSGuennadi Liakhovetski 34*0c99f6abSGuennadi Liakhovetski int lcd_line_length; 35*0c99f6abSGuennadi Liakhovetski int lcd_color_fg; 36*0c99f6abSGuennadi Liakhovetski int lcd_color_bg; 37*0c99f6abSGuennadi Liakhovetski 38*0c99f6abSGuennadi Liakhovetski short console_col; 39*0c99f6abSGuennadi Liakhovetski short console_row; 40*0c99f6abSGuennadi Liakhovetski 41*0c99f6abSGuennadi Liakhovetski void lcd_initcolregs(void) 42*0c99f6abSGuennadi Liakhovetski { 43*0c99f6abSGuennadi Liakhovetski } 44*0c99f6abSGuennadi Liakhovetski 45*0c99f6abSGuennadi Liakhovetski void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) 46*0c99f6abSGuennadi Liakhovetski { 47*0c99f6abSGuennadi Liakhovetski } 48*0c99f6abSGuennadi Liakhovetski 49*0c99f6abSGuennadi Liakhovetski void lcd_disable(void) 50*0c99f6abSGuennadi Liakhovetski { 51*0c99f6abSGuennadi Liakhovetski } 52*0c99f6abSGuennadi Liakhovetski 53*0c99f6abSGuennadi Liakhovetski void lcd_panel_disable(void) 54*0c99f6abSGuennadi Liakhovetski { 55*0c99f6abSGuennadi Liakhovetski } 56*0c99f6abSGuennadi Liakhovetski 57*0c99f6abSGuennadi Liakhovetski #define msleep(a) udelay(a * 1000) 58*0c99f6abSGuennadi Liakhovetski 59*0c99f6abSGuennadi Liakhovetski #define XRES 240 60*0c99f6abSGuennadi Liakhovetski #define YRES 320 61*0c99f6abSGuennadi Liakhovetski #define PANEL_TYPE IPU_PANEL_TFT 62*0c99f6abSGuennadi Liakhovetski #define PIXEL_CLK 185925 63*0c99f6abSGuennadi Liakhovetski #define PIXEL_FMT IPU_PIX_FMT_RGB666 64*0c99f6abSGuennadi Liakhovetski #define H_START_WIDTH 9 /* left_margin */ 65*0c99f6abSGuennadi Liakhovetski #define H_SYNC_WIDTH 1 /* hsync_len */ 66*0c99f6abSGuennadi Liakhovetski #define H_END_WIDTH (16 + 1) /* right_margin + hsync_len */ 67*0c99f6abSGuennadi Liakhovetski #define V_START_WIDTH 7 /* upper_margin */ 68*0c99f6abSGuennadi Liakhovetski #define V_SYNC_WIDTH 1 /* vsync_len */ 69*0c99f6abSGuennadi Liakhovetski #define V_END_WIDTH (9 + 1) /* lower_margin + vsync_len */ 70*0c99f6abSGuennadi Liakhovetski #define SIG_POL (DI_D3_DRDY_SHARP_POL | DI_D3_CLK_POL) 71*0c99f6abSGuennadi Liakhovetski #define IF_CONF 0 72*0c99f6abSGuennadi Liakhovetski #define IF_CLK_DIV 0x175 73*0c99f6abSGuennadi Liakhovetski 74*0c99f6abSGuennadi Liakhovetski #define LCD_COLOR_IPU LCD_COLOR16 75*0c99f6abSGuennadi Liakhovetski 76*0c99f6abSGuennadi Liakhovetski static ushort colormap[256]; 77*0c99f6abSGuennadi Liakhovetski 78*0c99f6abSGuennadi Liakhovetski vidinfo_t panel_info = { 79*0c99f6abSGuennadi Liakhovetski .vl_col = XRES, 80*0c99f6abSGuennadi Liakhovetski .vl_row = YRES, 81*0c99f6abSGuennadi Liakhovetski .vl_bpix = LCD_COLOR_IPU, 82*0c99f6abSGuennadi Liakhovetski .cmap = colormap, 83*0c99f6abSGuennadi Liakhovetski }; 84*0c99f6abSGuennadi Liakhovetski 85*0c99f6abSGuennadi Liakhovetski #define BIT_PER_PIXEL NBITS(LCD_COLOR_IPU) 86*0c99f6abSGuennadi Liakhovetski 87*0c99f6abSGuennadi Liakhovetski /* IPU DMA Controller channel definitions. */ 88*0c99f6abSGuennadi Liakhovetski enum ipu_channel { 89*0c99f6abSGuennadi Liakhovetski IDMAC_IC_0 = 0, /* IC (encoding task) to memory */ 90*0c99f6abSGuennadi Liakhovetski IDMAC_IC_1 = 1, /* IC (viewfinder task) to memory */ 91*0c99f6abSGuennadi Liakhovetski IDMAC_ADC_0 = 1, 92*0c99f6abSGuennadi Liakhovetski IDMAC_IC_2 = 2, 93*0c99f6abSGuennadi Liakhovetski IDMAC_ADC_1 = 2, 94*0c99f6abSGuennadi Liakhovetski IDMAC_IC_3 = 3, 95*0c99f6abSGuennadi Liakhovetski IDMAC_IC_4 = 4, 96*0c99f6abSGuennadi Liakhovetski IDMAC_IC_5 = 5, 97*0c99f6abSGuennadi Liakhovetski IDMAC_IC_6 = 6, 98*0c99f6abSGuennadi Liakhovetski IDMAC_IC_7 = 7, /* IC (sensor data) to memory */ 99*0c99f6abSGuennadi Liakhovetski IDMAC_IC_8 = 8, 100*0c99f6abSGuennadi Liakhovetski IDMAC_IC_9 = 9, 101*0c99f6abSGuennadi Liakhovetski IDMAC_IC_10 = 10, 102*0c99f6abSGuennadi Liakhovetski IDMAC_IC_11 = 11, 103*0c99f6abSGuennadi Liakhovetski IDMAC_IC_12 = 12, 104*0c99f6abSGuennadi Liakhovetski IDMAC_IC_13 = 13, 105*0c99f6abSGuennadi Liakhovetski IDMAC_SDC_0 = 14, /* Background synchronous display data */ 106*0c99f6abSGuennadi Liakhovetski IDMAC_SDC_1 = 15, /* Foreground data (overlay) */ 107*0c99f6abSGuennadi Liakhovetski IDMAC_SDC_2 = 16, 108*0c99f6abSGuennadi Liakhovetski IDMAC_SDC_3 = 17, 109*0c99f6abSGuennadi Liakhovetski IDMAC_ADC_2 = 18, 110*0c99f6abSGuennadi Liakhovetski IDMAC_ADC_3 = 19, 111*0c99f6abSGuennadi Liakhovetski IDMAC_ADC_4 = 20, 112*0c99f6abSGuennadi Liakhovetski IDMAC_ADC_5 = 21, 113*0c99f6abSGuennadi Liakhovetski IDMAC_ADC_6 = 22, 114*0c99f6abSGuennadi Liakhovetski IDMAC_ADC_7 = 23, 115*0c99f6abSGuennadi Liakhovetski IDMAC_PF_0 = 24, 116*0c99f6abSGuennadi Liakhovetski IDMAC_PF_1 = 25, 117*0c99f6abSGuennadi Liakhovetski IDMAC_PF_2 = 26, 118*0c99f6abSGuennadi Liakhovetski IDMAC_PF_3 = 27, 119*0c99f6abSGuennadi Liakhovetski IDMAC_PF_4 = 28, 120*0c99f6abSGuennadi Liakhovetski IDMAC_PF_5 = 29, 121*0c99f6abSGuennadi Liakhovetski IDMAC_PF_6 = 30, 122*0c99f6abSGuennadi Liakhovetski IDMAC_PF_7 = 31, 123*0c99f6abSGuennadi Liakhovetski }; 124*0c99f6abSGuennadi Liakhovetski 125*0c99f6abSGuennadi Liakhovetski /* More formats can be copied from the Linux driver if needed */ 126*0c99f6abSGuennadi Liakhovetski enum pixel_fmt { 127*0c99f6abSGuennadi Liakhovetski /* 2 bytes */ 128*0c99f6abSGuennadi Liakhovetski IPU_PIX_FMT_RGB565, 129*0c99f6abSGuennadi Liakhovetski IPU_PIX_FMT_RGB666, 130*0c99f6abSGuennadi Liakhovetski IPU_PIX_FMT_BGR666, 131*0c99f6abSGuennadi Liakhovetski /* 3 bytes */ 132*0c99f6abSGuennadi Liakhovetski IPU_PIX_FMT_RGB24, 133*0c99f6abSGuennadi Liakhovetski }; 134*0c99f6abSGuennadi Liakhovetski 135*0c99f6abSGuennadi Liakhovetski struct pixel_fmt_cfg { 136*0c99f6abSGuennadi Liakhovetski u32 b0; 137*0c99f6abSGuennadi Liakhovetski u32 b1; 138*0c99f6abSGuennadi Liakhovetski u32 b2; 139*0c99f6abSGuennadi Liakhovetski u32 acc; 140*0c99f6abSGuennadi Liakhovetski }; 141*0c99f6abSGuennadi Liakhovetski 142*0c99f6abSGuennadi Liakhovetski static struct pixel_fmt_cfg fmt_cfg[] = { 143*0c99f6abSGuennadi Liakhovetski [IPU_PIX_FMT_RGB24] = { 144*0c99f6abSGuennadi Liakhovetski 0x1600AAAA, 0x00E05555, 0x00070000, 3, 145*0c99f6abSGuennadi Liakhovetski }, 146*0c99f6abSGuennadi Liakhovetski [IPU_PIX_FMT_RGB666] = { 147*0c99f6abSGuennadi Liakhovetski 0x0005000F, 0x000B000F, 0x0011000F, 1, 148*0c99f6abSGuennadi Liakhovetski }, 149*0c99f6abSGuennadi Liakhovetski [IPU_PIX_FMT_BGR666] = { 150*0c99f6abSGuennadi Liakhovetski 0x0011000F, 0x000B000F, 0x0005000F, 1, 151*0c99f6abSGuennadi Liakhovetski }, 152*0c99f6abSGuennadi Liakhovetski [IPU_PIX_FMT_RGB565] = { 153*0c99f6abSGuennadi Liakhovetski 0x0004003F, 0x000A000F, 0x000F003F, 1, 154*0c99f6abSGuennadi Liakhovetski } 155*0c99f6abSGuennadi Liakhovetski }; 156*0c99f6abSGuennadi Liakhovetski 157*0c99f6abSGuennadi Liakhovetski enum ipu_panel { 158*0c99f6abSGuennadi Liakhovetski IPU_PANEL_SHARP_TFT, 159*0c99f6abSGuennadi Liakhovetski IPU_PANEL_TFT, 160*0c99f6abSGuennadi Liakhovetski }; 161*0c99f6abSGuennadi Liakhovetski 162*0c99f6abSGuennadi Liakhovetski /* IPU Common registers */ 163*0c99f6abSGuennadi Liakhovetski /* IPU_CONF and its bits already defined in mx31-regs.h */ 164*0c99f6abSGuennadi Liakhovetski #define IPU_CHA_BUF0_RDY (0x04 + IPU_BASE) 165*0c99f6abSGuennadi Liakhovetski #define IPU_CHA_BUF1_RDY (0x08 + IPU_BASE) 166*0c99f6abSGuennadi Liakhovetski #define IPU_CHA_DB_MODE_SEL (0x0C + IPU_BASE) 167*0c99f6abSGuennadi Liakhovetski #define IPU_CHA_CUR_BUF (0x10 + IPU_BASE) 168*0c99f6abSGuennadi Liakhovetski #define IPU_FS_PROC_FLOW (0x14 + IPU_BASE) 169*0c99f6abSGuennadi Liakhovetski #define IPU_FS_DISP_FLOW (0x18 + IPU_BASE) 170*0c99f6abSGuennadi Liakhovetski #define IPU_TASKS_STAT (0x1C + IPU_BASE) 171*0c99f6abSGuennadi Liakhovetski #define IPU_IMA_ADDR (0x20 + IPU_BASE) 172*0c99f6abSGuennadi Liakhovetski #define IPU_IMA_DATA (0x24 + IPU_BASE) 173*0c99f6abSGuennadi Liakhovetski #define IPU_INT_CTRL_1 (0x28 + IPU_BASE) 174*0c99f6abSGuennadi Liakhovetski #define IPU_INT_CTRL_2 (0x2C + IPU_BASE) 175*0c99f6abSGuennadi Liakhovetski #define IPU_INT_CTRL_3 (0x30 + IPU_BASE) 176*0c99f6abSGuennadi Liakhovetski #define IPU_INT_CTRL_4 (0x34 + IPU_BASE) 177*0c99f6abSGuennadi Liakhovetski #define IPU_INT_CTRL_5 (0x38 + IPU_BASE) 178*0c99f6abSGuennadi Liakhovetski #define IPU_INT_STAT_1 (0x3C + IPU_BASE) 179*0c99f6abSGuennadi Liakhovetski #define IPU_INT_STAT_2 (0x40 + IPU_BASE) 180*0c99f6abSGuennadi Liakhovetski #define IPU_INT_STAT_3 (0x44 + IPU_BASE) 181*0c99f6abSGuennadi Liakhovetski #define IPU_INT_STAT_4 (0x48 + IPU_BASE) 182*0c99f6abSGuennadi Liakhovetski #define IPU_INT_STAT_5 (0x4C + IPU_BASE) 183*0c99f6abSGuennadi Liakhovetski #define IPU_BRK_CTRL_1 (0x50 + IPU_BASE) 184*0c99f6abSGuennadi Liakhovetski #define IPU_BRK_CTRL_2 (0x54 + IPU_BASE) 185*0c99f6abSGuennadi Liakhovetski #define IPU_BRK_STAT (0x58 + IPU_BASE) 186*0c99f6abSGuennadi Liakhovetski #define IPU_DIAGB_CTRL (0x5C + IPU_BASE) 187*0c99f6abSGuennadi Liakhovetski 188*0c99f6abSGuennadi Liakhovetski /* Image Converter Registers */ 189*0c99f6abSGuennadi Liakhovetski #define IC_CONF (0x88 + IPU_BASE) 190*0c99f6abSGuennadi Liakhovetski #define IC_PRP_ENC_RSC (0x8C + IPU_BASE) 191*0c99f6abSGuennadi Liakhovetski #define IC_PRP_VF_RSC (0x90 + IPU_BASE) 192*0c99f6abSGuennadi Liakhovetski #define IC_PP_RSC (0x94 + IPU_BASE) 193*0c99f6abSGuennadi Liakhovetski #define IC_CMBP_1 (0x98 + IPU_BASE) 194*0c99f6abSGuennadi Liakhovetski #define IC_CMBP_2 (0x9C + IPU_BASE) 195*0c99f6abSGuennadi Liakhovetski #define PF_CONF (0xA0 + IPU_BASE) 196*0c99f6abSGuennadi Liakhovetski #define IDMAC_CONF (0xA4 + IPU_BASE) 197*0c99f6abSGuennadi Liakhovetski #define IDMAC_CHA_EN (0xA8 + IPU_BASE) 198*0c99f6abSGuennadi Liakhovetski #define IDMAC_CHA_PRI (0xAC + IPU_BASE) 199*0c99f6abSGuennadi Liakhovetski #define IDMAC_CHA_BUSY (0xB0 + IPU_BASE) 200*0c99f6abSGuennadi Liakhovetski 201*0c99f6abSGuennadi Liakhovetski /* Image Converter Register bits */ 202*0c99f6abSGuennadi Liakhovetski #define IC_CONF_PRPENC_EN 0x00000001 203*0c99f6abSGuennadi Liakhovetski #define IC_CONF_PRPENC_CSC1 0x00000002 204*0c99f6abSGuennadi Liakhovetski #define IC_CONF_PRPENC_ROT_EN 0x00000004 205*0c99f6abSGuennadi Liakhovetski #define IC_CONF_PRPVF_EN 0x00000100 206*0c99f6abSGuennadi Liakhovetski #define IC_CONF_PRPVF_CSC1 0x00000200 207*0c99f6abSGuennadi Liakhovetski #define IC_CONF_PRPVF_CSC2 0x00000400 208*0c99f6abSGuennadi Liakhovetski #define IC_CONF_PRPVF_CMB 0x00000800 209*0c99f6abSGuennadi Liakhovetski #define IC_CONF_PRPVF_ROT_EN 0x00001000 210*0c99f6abSGuennadi Liakhovetski #define IC_CONF_PP_EN 0x00010000 211*0c99f6abSGuennadi Liakhovetski #define IC_CONF_PP_CSC1 0x00020000 212*0c99f6abSGuennadi Liakhovetski #define IC_CONF_PP_CSC2 0x00040000 213*0c99f6abSGuennadi Liakhovetski #define IC_CONF_PP_CMB 0x00080000 214*0c99f6abSGuennadi Liakhovetski #define IC_CONF_PP_ROT_EN 0x00100000 215*0c99f6abSGuennadi Liakhovetski #define IC_CONF_IC_GLB_LOC_A 0x10000000 216*0c99f6abSGuennadi Liakhovetski #define IC_CONF_KEY_COLOR_EN 0x20000000 217*0c99f6abSGuennadi Liakhovetski #define IC_CONF_RWS_EN 0x40000000 218*0c99f6abSGuennadi Liakhovetski #define IC_CONF_CSI_MEM_WR_EN 0x80000000 219*0c99f6abSGuennadi Liakhovetski 220*0c99f6abSGuennadi Liakhovetski /* SDC Registers */ 221*0c99f6abSGuennadi Liakhovetski #define SDC_COM_CONF (0xB4 + IPU_BASE) 222*0c99f6abSGuennadi Liakhovetski #define SDC_GW_CTRL (0xB8 + IPU_BASE) 223*0c99f6abSGuennadi Liakhovetski #define SDC_FG_POS (0xBC + IPU_BASE) 224*0c99f6abSGuennadi Liakhovetski #define SDC_BG_POS (0xC0 + IPU_BASE) 225*0c99f6abSGuennadi Liakhovetski #define SDC_CUR_POS (0xC4 + IPU_BASE) 226*0c99f6abSGuennadi Liakhovetski #define SDC_PWM_CTRL (0xC8 + IPU_BASE) 227*0c99f6abSGuennadi Liakhovetski #define SDC_CUR_MAP (0xCC + IPU_BASE) 228*0c99f6abSGuennadi Liakhovetski #define SDC_HOR_CONF (0xD0 + IPU_BASE) 229*0c99f6abSGuennadi Liakhovetski #define SDC_VER_CONF (0xD4 + IPU_BASE) 230*0c99f6abSGuennadi Liakhovetski #define SDC_SHARP_CONF_1 (0xD8 + IPU_BASE) 231*0c99f6abSGuennadi Liakhovetski #define SDC_SHARP_CONF_2 (0xDC + IPU_BASE) 232*0c99f6abSGuennadi Liakhovetski 233*0c99f6abSGuennadi Liakhovetski /* Register bits */ 234*0c99f6abSGuennadi Liakhovetski #define SDC_COM_TFT_COLOR 0x00000001UL 235*0c99f6abSGuennadi Liakhovetski #define SDC_COM_FG_EN 0x00000010UL 236*0c99f6abSGuennadi Liakhovetski #define SDC_COM_GWSEL 0x00000020UL 237*0c99f6abSGuennadi Liakhovetski #define SDC_COM_GLB_A 0x00000040UL 238*0c99f6abSGuennadi Liakhovetski #define SDC_COM_KEY_COLOR_G 0x00000080UL 239*0c99f6abSGuennadi Liakhovetski #define SDC_COM_BG_EN 0x00000200UL 240*0c99f6abSGuennadi Liakhovetski #define SDC_COM_SHARP 0x00001000UL 241*0c99f6abSGuennadi Liakhovetski 242*0c99f6abSGuennadi Liakhovetski #define SDC_V_SYNC_WIDTH_L 0x00000001UL 243*0c99f6abSGuennadi Liakhovetski 244*0c99f6abSGuennadi Liakhovetski /* Display Interface registers */ 245*0c99f6abSGuennadi Liakhovetski #define DI_DISP_IF_CONF (0x0124 + IPU_BASE) 246*0c99f6abSGuennadi Liakhovetski #define DI_DISP_SIG_POL (0x0128 + IPU_BASE) 247*0c99f6abSGuennadi Liakhovetski #define DI_SER_DISP1_CONF (0x012C + IPU_BASE) 248*0c99f6abSGuennadi Liakhovetski #define DI_SER_DISP2_CONF (0x0130 + IPU_BASE) 249*0c99f6abSGuennadi Liakhovetski #define DI_HSP_CLK_PER (0x0134 + IPU_BASE) 250*0c99f6abSGuennadi Liakhovetski #define DI_DISP0_TIME_CONF_1 (0x0138 + IPU_BASE) 251*0c99f6abSGuennadi Liakhovetski #define DI_DISP0_TIME_CONF_2 (0x013C + IPU_BASE) 252*0c99f6abSGuennadi Liakhovetski #define DI_DISP0_TIME_CONF_3 (0x0140 + IPU_BASE) 253*0c99f6abSGuennadi Liakhovetski #define DI_DISP1_TIME_CONF_1 (0x0144 + IPU_BASE) 254*0c99f6abSGuennadi Liakhovetski #define DI_DISP1_TIME_CONF_2 (0x0148 + IPU_BASE) 255*0c99f6abSGuennadi Liakhovetski #define DI_DISP1_TIME_CONF_3 (0x014C + IPU_BASE) 256*0c99f6abSGuennadi Liakhovetski #define DI_DISP2_TIME_CONF_1 (0x0150 + IPU_BASE) 257*0c99f6abSGuennadi Liakhovetski #define DI_DISP2_TIME_CONF_2 (0x0154 + IPU_BASE) 258*0c99f6abSGuennadi Liakhovetski #define DI_DISP2_TIME_CONF_3 (0x0158 + IPU_BASE) 259*0c99f6abSGuennadi Liakhovetski #define DI_DISP3_TIME_CONF (0x015C + IPU_BASE) 260*0c99f6abSGuennadi Liakhovetski #define DI_DISP0_DB0_MAP (0x0160 + IPU_BASE) 261*0c99f6abSGuennadi Liakhovetski #define DI_DISP0_DB1_MAP (0x0164 + IPU_BASE) 262*0c99f6abSGuennadi Liakhovetski #define DI_DISP0_DB2_MAP (0x0168 + IPU_BASE) 263*0c99f6abSGuennadi Liakhovetski #define DI_DISP0_CB0_MAP (0x016C + IPU_BASE) 264*0c99f6abSGuennadi Liakhovetski #define DI_DISP0_CB1_MAP (0x0170 + IPU_BASE) 265*0c99f6abSGuennadi Liakhovetski #define DI_DISP0_CB2_MAP (0x0174 + IPU_BASE) 266*0c99f6abSGuennadi Liakhovetski #define DI_DISP1_DB0_MAP (0x0178 + IPU_BASE) 267*0c99f6abSGuennadi Liakhovetski #define DI_DISP1_DB1_MAP (0x017C + IPU_BASE) 268*0c99f6abSGuennadi Liakhovetski #define DI_DISP1_DB2_MAP (0x0180 + IPU_BASE) 269*0c99f6abSGuennadi Liakhovetski #define DI_DISP1_CB0_MAP (0x0184 + IPU_BASE) 270*0c99f6abSGuennadi Liakhovetski #define DI_DISP1_CB1_MAP (0x0188 + IPU_BASE) 271*0c99f6abSGuennadi Liakhovetski #define DI_DISP1_CB2_MAP (0x018C + IPU_BASE) 272*0c99f6abSGuennadi Liakhovetski #define DI_DISP2_DB0_MAP (0x0190 + IPU_BASE) 273*0c99f6abSGuennadi Liakhovetski #define DI_DISP2_DB1_MAP (0x0194 + IPU_BASE) 274*0c99f6abSGuennadi Liakhovetski #define DI_DISP2_DB2_MAP (0x0198 + IPU_BASE) 275*0c99f6abSGuennadi Liakhovetski #define DI_DISP2_CB0_MAP (0x019C + IPU_BASE) 276*0c99f6abSGuennadi Liakhovetski #define DI_DISP2_CB1_MAP (0x01A0 + IPU_BASE) 277*0c99f6abSGuennadi Liakhovetski #define DI_DISP2_CB2_MAP (0x01A4 + IPU_BASE) 278*0c99f6abSGuennadi Liakhovetski #define DI_DISP3_B0_MAP (0x01A8 + IPU_BASE) 279*0c99f6abSGuennadi Liakhovetski #define DI_DISP3_B1_MAP (0x01AC + IPU_BASE) 280*0c99f6abSGuennadi Liakhovetski #define DI_DISP3_B2_MAP (0x01B0 + IPU_BASE) 281*0c99f6abSGuennadi Liakhovetski #define DI_DISP_ACC_CC (0x01B4 + IPU_BASE) 282*0c99f6abSGuennadi Liakhovetski #define DI_DISP_LLA_CONF (0x01B8 + IPU_BASE) 283*0c99f6abSGuennadi Liakhovetski #define DI_DISP_LLA_DATA (0x01BC + IPU_BASE) 284*0c99f6abSGuennadi Liakhovetski 285*0c99f6abSGuennadi Liakhovetski /* DI_DISP_SIG_POL bits */ 286*0c99f6abSGuennadi Liakhovetski #define DI_D3_VSYNC_POL (1 << 28) 287*0c99f6abSGuennadi Liakhovetski #define DI_D3_HSYNC_POL (1 << 27) 288*0c99f6abSGuennadi Liakhovetski #define DI_D3_DRDY_SHARP_POL (1 << 26) 289*0c99f6abSGuennadi Liakhovetski #define DI_D3_CLK_POL (1 << 25) 290*0c99f6abSGuennadi Liakhovetski #define DI_D3_DATA_POL (1 << 24) 291*0c99f6abSGuennadi Liakhovetski 292*0c99f6abSGuennadi Liakhovetski /* DI_DISP_IF_CONF bits */ 293*0c99f6abSGuennadi Liakhovetski #define DI_D3_CLK_IDLE (1 << 26) 294*0c99f6abSGuennadi Liakhovetski #define DI_D3_CLK_SEL (1 << 25) 295*0c99f6abSGuennadi Liakhovetski #define DI_D3_DATAMSK (1 << 24) 296*0c99f6abSGuennadi Liakhovetski 297*0c99f6abSGuennadi Liakhovetski #define IOMUX_PADNUM_MASK 0x1ff 298*0c99f6abSGuennadi Liakhovetski #define IOMUX_GPIONUM_SHIFT 9 299*0c99f6abSGuennadi Liakhovetski #define IOMUX_GPIONUM_MASK (0xff << IOMUX_GPIONUM_SHIFT) 300*0c99f6abSGuennadi Liakhovetski 301*0c99f6abSGuennadi Liakhovetski #define IOMUX_PIN(gpionum, padnum) ((padnum) & IOMUX_PADNUM_MASK) 302*0c99f6abSGuennadi Liakhovetski 303*0c99f6abSGuennadi Liakhovetski #define IOMUX_MODE_L(pin, mode) IOMUX_MODE(((pin) + 0xc) ^ 3, mode) 304*0c99f6abSGuennadi Liakhovetski 305*0c99f6abSGuennadi Liakhovetski enum lcd_pin { 306*0c99f6abSGuennadi Liakhovetski MX31_PIN_D3_SPL = IOMUX_PIN(0xff, 19), 307*0c99f6abSGuennadi Liakhovetski MX31_PIN_D3_CLS = IOMUX_PIN(0xff, 20), 308*0c99f6abSGuennadi Liakhovetski MX31_PIN_D3_REV = IOMUX_PIN(0xff, 21), 309*0c99f6abSGuennadi Liakhovetski MX31_PIN_CONTRAST = IOMUX_PIN(0xff, 22), 310*0c99f6abSGuennadi Liakhovetski MX31_PIN_VSYNC3 = IOMUX_PIN(0xff, 23), 311*0c99f6abSGuennadi Liakhovetski 312*0c99f6abSGuennadi Liakhovetski MX31_PIN_DRDY0 = IOMUX_PIN(0xff, 33), 313*0c99f6abSGuennadi Liakhovetski MX31_PIN_FPSHIFT = IOMUX_PIN(0xff, 34), 314*0c99f6abSGuennadi Liakhovetski MX31_PIN_HSYNC = IOMUX_PIN(0xff, 35), 315*0c99f6abSGuennadi Liakhovetski 316*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD17 = IOMUX_PIN(0xff, 37), 317*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD16 = IOMUX_PIN(0xff, 38), 318*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD15 = IOMUX_PIN(0xff, 39), 319*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD14 = IOMUX_PIN(0xff, 40), 320*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD13 = IOMUX_PIN(0xff, 41), 321*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD12 = IOMUX_PIN(0xff, 42), 322*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD11 = IOMUX_PIN(0xff, 43), 323*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD10 = IOMUX_PIN(0xff, 44), 324*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD9 = IOMUX_PIN(0xff, 45), 325*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD8 = IOMUX_PIN(0xff, 46), 326*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD7 = IOMUX_PIN(0xff, 47), 327*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD6 = IOMUX_PIN(0xff, 48), 328*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD5 = IOMUX_PIN(0xff, 49), 329*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD4 = IOMUX_PIN(0xff, 50), 330*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD3 = IOMUX_PIN(0xff, 51), 331*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD2 = IOMUX_PIN(0xff, 52), 332*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD1 = IOMUX_PIN(0xff, 53), 333*0c99f6abSGuennadi Liakhovetski MX31_PIN_LD0 = IOMUX_PIN(0xff, 54), 334*0c99f6abSGuennadi Liakhovetski }; 335*0c99f6abSGuennadi Liakhovetski 336*0c99f6abSGuennadi Liakhovetski struct chan_param_mem_planar { 337*0c99f6abSGuennadi Liakhovetski /* Word 0 */ 338*0c99f6abSGuennadi Liakhovetski u32 xv:10; 339*0c99f6abSGuennadi Liakhovetski u32 yv:10; 340*0c99f6abSGuennadi Liakhovetski u32 xb:12; 341*0c99f6abSGuennadi Liakhovetski 342*0c99f6abSGuennadi Liakhovetski u32 yb:12; 343*0c99f6abSGuennadi Liakhovetski u32 res1:2; 344*0c99f6abSGuennadi Liakhovetski u32 nsb:1; 345*0c99f6abSGuennadi Liakhovetski u32 lnpb:6; 346*0c99f6abSGuennadi Liakhovetski u32 ubo_l:11; 347*0c99f6abSGuennadi Liakhovetski 348*0c99f6abSGuennadi Liakhovetski u32 ubo_h:15; 349*0c99f6abSGuennadi Liakhovetski u32 vbo_l:17; 350*0c99f6abSGuennadi Liakhovetski 351*0c99f6abSGuennadi Liakhovetski u32 vbo_h:9; 352*0c99f6abSGuennadi Liakhovetski u32 res2:3; 353*0c99f6abSGuennadi Liakhovetski u32 fw:12; 354*0c99f6abSGuennadi Liakhovetski u32 fh_l:8; 355*0c99f6abSGuennadi Liakhovetski 356*0c99f6abSGuennadi Liakhovetski u32 fh_h:4; 357*0c99f6abSGuennadi Liakhovetski u32 res3:28; 358*0c99f6abSGuennadi Liakhovetski 359*0c99f6abSGuennadi Liakhovetski /* Word 1 */ 360*0c99f6abSGuennadi Liakhovetski u32 eba0; 361*0c99f6abSGuennadi Liakhovetski 362*0c99f6abSGuennadi Liakhovetski u32 eba1; 363*0c99f6abSGuennadi Liakhovetski 364*0c99f6abSGuennadi Liakhovetski u32 bpp:3; 365*0c99f6abSGuennadi Liakhovetski u32 sl:14; 366*0c99f6abSGuennadi Liakhovetski u32 pfs:3; 367*0c99f6abSGuennadi Liakhovetski u32 bam:3; 368*0c99f6abSGuennadi Liakhovetski u32 res4:2; 369*0c99f6abSGuennadi Liakhovetski u32 npb:6; 370*0c99f6abSGuennadi Liakhovetski u32 res5:1; 371*0c99f6abSGuennadi Liakhovetski 372*0c99f6abSGuennadi Liakhovetski u32 sat:2; 373*0c99f6abSGuennadi Liakhovetski u32 res6:30; 374*0c99f6abSGuennadi Liakhovetski } __attribute__ ((packed)); 375*0c99f6abSGuennadi Liakhovetski 376*0c99f6abSGuennadi Liakhovetski struct chan_param_mem_interleaved { 377*0c99f6abSGuennadi Liakhovetski /* Word 0 */ 378*0c99f6abSGuennadi Liakhovetski u32 xv:10; 379*0c99f6abSGuennadi Liakhovetski u32 yv:10; 380*0c99f6abSGuennadi Liakhovetski u32 xb:12; 381*0c99f6abSGuennadi Liakhovetski 382*0c99f6abSGuennadi Liakhovetski u32 yb:12; 383*0c99f6abSGuennadi Liakhovetski u32 sce:1; 384*0c99f6abSGuennadi Liakhovetski u32 res1:1; 385*0c99f6abSGuennadi Liakhovetski u32 nsb:1; 386*0c99f6abSGuennadi Liakhovetski u32 lnpb:6; 387*0c99f6abSGuennadi Liakhovetski u32 sx:10; 388*0c99f6abSGuennadi Liakhovetski u32 sy_l:1; 389*0c99f6abSGuennadi Liakhovetski 390*0c99f6abSGuennadi Liakhovetski u32 sy_h:9; 391*0c99f6abSGuennadi Liakhovetski u32 ns:10; 392*0c99f6abSGuennadi Liakhovetski u32 sm:10; 393*0c99f6abSGuennadi Liakhovetski u32 sdx_l:3; 394*0c99f6abSGuennadi Liakhovetski 395*0c99f6abSGuennadi Liakhovetski u32 sdx_h:2; 396*0c99f6abSGuennadi Liakhovetski u32 sdy:5; 397*0c99f6abSGuennadi Liakhovetski u32 sdrx:1; 398*0c99f6abSGuennadi Liakhovetski u32 sdry:1; 399*0c99f6abSGuennadi Liakhovetski u32 sdr1:1; 400*0c99f6abSGuennadi Liakhovetski u32 res2:2; 401*0c99f6abSGuennadi Liakhovetski u32 fw:12; 402*0c99f6abSGuennadi Liakhovetski u32 fh_l:8; 403*0c99f6abSGuennadi Liakhovetski 404*0c99f6abSGuennadi Liakhovetski u32 fh_h:4; 405*0c99f6abSGuennadi Liakhovetski u32 res3:28; 406*0c99f6abSGuennadi Liakhovetski 407*0c99f6abSGuennadi Liakhovetski /* Word 1 */ 408*0c99f6abSGuennadi Liakhovetski u32 eba0; 409*0c99f6abSGuennadi Liakhovetski 410*0c99f6abSGuennadi Liakhovetski u32 eba1; 411*0c99f6abSGuennadi Liakhovetski 412*0c99f6abSGuennadi Liakhovetski u32 bpp:3; 413*0c99f6abSGuennadi Liakhovetski u32 sl:14; 414*0c99f6abSGuennadi Liakhovetski u32 pfs:3; 415*0c99f6abSGuennadi Liakhovetski u32 bam:3; 416*0c99f6abSGuennadi Liakhovetski u32 res4:2; 417*0c99f6abSGuennadi Liakhovetski u32 npb:6; 418*0c99f6abSGuennadi Liakhovetski u32 res5:1; 419*0c99f6abSGuennadi Liakhovetski 420*0c99f6abSGuennadi Liakhovetski u32 sat:2; 421*0c99f6abSGuennadi Liakhovetski u32 scc:1; 422*0c99f6abSGuennadi Liakhovetski u32 ofs0:5; 423*0c99f6abSGuennadi Liakhovetski u32 ofs1:5; 424*0c99f6abSGuennadi Liakhovetski u32 ofs2:5; 425*0c99f6abSGuennadi Liakhovetski u32 ofs3:5; 426*0c99f6abSGuennadi Liakhovetski u32 wid0:3; 427*0c99f6abSGuennadi Liakhovetski u32 wid1:3; 428*0c99f6abSGuennadi Liakhovetski u32 wid2:3; 429*0c99f6abSGuennadi Liakhovetski 430*0c99f6abSGuennadi Liakhovetski u32 wid3:3; 431*0c99f6abSGuennadi Liakhovetski u32 dec_sel:1; 432*0c99f6abSGuennadi Liakhovetski u32 res6:28; 433*0c99f6abSGuennadi Liakhovetski } __attribute__ ((packed)); 434*0c99f6abSGuennadi Liakhovetski 435*0c99f6abSGuennadi Liakhovetski union chan_param_mem { 436*0c99f6abSGuennadi Liakhovetski struct chan_param_mem_planar pp; 437*0c99f6abSGuennadi Liakhovetski struct chan_param_mem_interleaved ip; 438*0c99f6abSGuennadi Liakhovetski }; 439*0c99f6abSGuennadi Liakhovetski 440*0c99f6abSGuennadi Liakhovetski static inline u32 reg_read(unsigned long reg) 441*0c99f6abSGuennadi Liakhovetski { 442*0c99f6abSGuennadi Liakhovetski return __REG(reg); 443*0c99f6abSGuennadi Liakhovetski } 444*0c99f6abSGuennadi Liakhovetski 445*0c99f6abSGuennadi Liakhovetski static inline void reg_write(u32 value, unsigned long reg) 446*0c99f6abSGuennadi Liakhovetski { 447*0c99f6abSGuennadi Liakhovetski __REG(reg) = value; 448*0c99f6abSGuennadi Liakhovetski } 449*0c99f6abSGuennadi Liakhovetski 450*0c99f6abSGuennadi Liakhovetski /* 451*0c99f6abSGuennadi Liakhovetski * sdc_init_panel() - initialize a synchronous LCD panel. 452*0c99f6abSGuennadi Liakhovetski * @width: width of panel in pixels. 453*0c99f6abSGuennadi Liakhovetski * @height: height of panel in pixels. 454*0c99f6abSGuennadi Liakhovetski * @pixel_fmt: pixel format of buffer as FOURCC ASCII code. 455*0c99f6abSGuennadi Liakhovetski * @return: 0 on success or negative error code on failure. 456*0c99f6abSGuennadi Liakhovetski */ 457*0c99f6abSGuennadi Liakhovetski static int sdc_init_panel(u16 width, u16 height, enum pixel_fmt pixel_fmt) 458*0c99f6abSGuennadi Liakhovetski { 459*0c99f6abSGuennadi Liakhovetski u32 reg; 460*0c99f6abSGuennadi Liakhovetski uint32_t old_conf; 461*0c99f6abSGuennadi Liakhovetski 462*0c99f6abSGuennadi Liakhovetski /* Init panel size and blanking periods */ 463*0c99f6abSGuennadi Liakhovetski reg = ((H_SYNC_WIDTH - 1) << 26) | 464*0c99f6abSGuennadi Liakhovetski ((u32)(width + H_START_WIDTH + H_END_WIDTH - 1) << 16); 465*0c99f6abSGuennadi Liakhovetski reg_write(reg, SDC_HOR_CONF); 466*0c99f6abSGuennadi Liakhovetski 467*0c99f6abSGuennadi Liakhovetski reg = ((V_SYNC_WIDTH - 1) << 26) | SDC_V_SYNC_WIDTH_L | 468*0c99f6abSGuennadi Liakhovetski ((u32)(height + V_START_WIDTH + V_END_WIDTH - 1) << 16); 469*0c99f6abSGuennadi Liakhovetski reg_write(reg, SDC_VER_CONF); 470*0c99f6abSGuennadi Liakhovetski 471*0c99f6abSGuennadi Liakhovetski switch (PANEL_TYPE) { 472*0c99f6abSGuennadi Liakhovetski case IPU_PANEL_SHARP_TFT: 473*0c99f6abSGuennadi Liakhovetski reg_write(0x00FD0102L, SDC_SHARP_CONF_1); 474*0c99f6abSGuennadi Liakhovetski reg_write(0x00F500F4L, SDC_SHARP_CONF_2); 475*0c99f6abSGuennadi Liakhovetski reg_write(SDC_COM_SHARP | SDC_COM_TFT_COLOR, SDC_COM_CONF); 476*0c99f6abSGuennadi Liakhovetski break; 477*0c99f6abSGuennadi Liakhovetski case IPU_PANEL_TFT: 478*0c99f6abSGuennadi Liakhovetski reg_write(SDC_COM_TFT_COLOR, SDC_COM_CONF); 479*0c99f6abSGuennadi Liakhovetski break; 480*0c99f6abSGuennadi Liakhovetski default: 481*0c99f6abSGuennadi Liakhovetski return -EINVAL; 482*0c99f6abSGuennadi Liakhovetski } 483*0c99f6abSGuennadi Liakhovetski 484*0c99f6abSGuennadi Liakhovetski /* Init clocking */ 485*0c99f6abSGuennadi Liakhovetski 486*0c99f6abSGuennadi Liakhovetski /* 487*0c99f6abSGuennadi Liakhovetski * Calculate divider: fractional part is 4 bits so simply multiple by 488*0c99f6abSGuennadi Liakhovetski * 2^4 to get fractional part, as long as we stay under ~250MHz and on 489*0c99f6abSGuennadi Liakhovetski * i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz 490*0c99f6abSGuennadi Liakhovetski */ 491*0c99f6abSGuennadi Liakhovetski 492*0c99f6abSGuennadi Liakhovetski reg_write((((IF_CLK_DIV / 8) - 1) << 22) | 493*0c99f6abSGuennadi Liakhovetski IF_CLK_DIV, DI_DISP3_TIME_CONF); 494*0c99f6abSGuennadi Liakhovetski 495*0c99f6abSGuennadi Liakhovetski /* DI settings */ 496*0c99f6abSGuennadi Liakhovetski old_conf = reg_read(DI_DISP_IF_CONF) & 0x78FFFFFF; 497*0c99f6abSGuennadi Liakhovetski reg_write(old_conf | IF_CONF, DI_DISP_IF_CONF); 498*0c99f6abSGuennadi Liakhovetski 499*0c99f6abSGuennadi Liakhovetski old_conf = reg_read(DI_DISP_SIG_POL) & 0xE0FFFFFF; 500*0c99f6abSGuennadi Liakhovetski reg_write(old_conf | SIG_POL, DI_DISP_SIG_POL); 501*0c99f6abSGuennadi Liakhovetski 502*0c99f6abSGuennadi Liakhovetski reg_write(fmt_cfg[pixel_fmt].b0, DI_DISP3_B0_MAP); 503*0c99f6abSGuennadi Liakhovetski reg_write(fmt_cfg[pixel_fmt].b1, DI_DISP3_B1_MAP); 504*0c99f6abSGuennadi Liakhovetski reg_write(fmt_cfg[pixel_fmt].b2, DI_DISP3_B2_MAP); 505*0c99f6abSGuennadi Liakhovetski reg_write(reg_read(DI_DISP_ACC_CC) | 506*0c99f6abSGuennadi Liakhovetski ((fmt_cfg[pixel_fmt].acc - 1) << 12), DI_DISP_ACC_CC); 507*0c99f6abSGuennadi Liakhovetski 508*0c99f6abSGuennadi Liakhovetski return 0; 509*0c99f6abSGuennadi Liakhovetski } 510*0c99f6abSGuennadi Liakhovetski 511*0c99f6abSGuennadi Liakhovetski static void ipu_ch_param_set_size(union chan_param_mem *params, 512*0c99f6abSGuennadi Liakhovetski uint32_t pixel_fmt, uint16_t width, 513*0c99f6abSGuennadi Liakhovetski uint16_t height, uint16_t stride) 514*0c99f6abSGuennadi Liakhovetski { 515*0c99f6abSGuennadi Liakhovetski params->pp.fw = width - 1; 516*0c99f6abSGuennadi Liakhovetski params->pp.fh_l = height - 1; 517*0c99f6abSGuennadi Liakhovetski params->pp.fh_h = (height - 1) >> 8; 518*0c99f6abSGuennadi Liakhovetski params->pp.sl = stride - 1; 519*0c99f6abSGuennadi Liakhovetski 520*0c99f6abSGuennadi Liakhovetski /* See above, for further formats see the Linux driver */ 521*0c99f6abSGuennadi Liakhovetski switch (pixel_fmt) { 522*0c99f6abSGuennadi Liakhovetski case IPU_PIX_FMT_RGB565: 523*0c99f6abSGuennadi Liakhovetski params->ip.bpp = 2; 524*0c99f6abSGuennadi Liakhovetski params->ip.pfs = 4; 525*0c99f6abSGuennadi Liakhovetski params->ip.npb = 7; 526*0c99f6abSGuennadi Liakhovetski params->ip.sat = 2; /* SAT = 32-bit access */ 527*0c99f6abSGuennadi Liakhovetski params->ip.ofs0 = 0; /* Red bit offset */ 528*0c99f6abSGuennadi Liakhovetski params->ip.ofs1 = 5; /* Green bit offset */ 529*0c99f6abSGuennadi Liakhovetski params->ip.ofs2 = 11; /* Blue bit offset */ 530*0c99f6abSGuennadi Liakhovetski params->ip.ofs3 = 16; /* Alpha bit offset */ 531*0c99f6abSGuennadi Liakhovetski params->ip.wid0 = 4; /* Red bit width - 1 */ 532*0c99f6abSGuennadi Liakhovetski params->ip.wid1 = 5; /* Green bit width - 1 */ 533*0c99f6abSGuennadi Liakhovetski params->ip.wid2 = 4; /* Blue bit width - 1 */ 534*0c99f6abSGuennadi Liakhovetski break; 535*0c99f6abSGuennadi Liakhovetski case IPU_PIX_FMT_RGB24: 536*0c99f6abSGuennadi Liakhovetski params->ip.bpp = 1; /* 24 BPP & RGB PFS */ 537*0c99f6abSGuennadi Liakhovetski params->ip.pfs = 4; 538*0c99f6abSGuennadi Liakhovetski params->ip.npb = 7; 539*0c99f6abSGuennadi Liakhovetski params->ip.sat = 2; /* SAT = 32-bit access */ 540*0c99f6abSGuennadi Liakhovetski params->ip.ofs0 = 16; /* Red bit offset */ 541*0c99f6abSGuennadi Liakhovetski params->ip.ofs1 = 8; /* Green bit offset */ 542*0c99f6abSGuennadi Liakhovetski params->ip.ofs2 = 0; /* Blue bit offset */ 543*0c99f6abSGuennadi Liakhovetski params->ip.ofs3 = 24; /* Alpha bit offset */ 544*0c99f6abSGuennadi Liakhovetski params->ip.wid0 = 7; /* Red bit width - 1 */ 545*0c99f6abSGuennadi Liakhovetski params->ip.wid1 = 7; /* Green bit width - 1 */ 546*0c99f6abSGuennadi Liakhovetski params->ip.wid2 = 7; /* Blue bit width - 1 */ 547*0c99f6abSGuennadi Liakhovetski break; 548*0c99f6abSGuennadi Liakhovetski default: 549*0c99f6abSGuennadi Liakhovetski break; 550*0c99f6abSGuennadi Liakhovetski } 551*0c99f6abSGuennadi Liakhovetski 552*0c99f6abSGuennadi Liakhovetski params->pp.nsb = 1; 553*0c99f6abSGuennadi Liakhovetski } 554*0c99f6abSGuennadi Liakhovetski 555*0c99f6abSGuennadi Liakhovetski static void ipu_ch_param_set_buffer(union chan_param_mem *params, 556*0c99f6abSGuennadi Liakhovetski void *buf0, void *buf1) 557*0c99f6abSGuennadi Liakhovetski { 558*0c99f6abSGuennadi Liakhovetski params->pp.eba0 = (u32)buf0; 559*0c99f6abSGuennadi Liakhovetski params->pp.eba1 = (u32)buf1; 560*0c99f6abSGuennadi Liakhovetski } 561*0c99f6abSGuennadi Liakhovetski 562*0c99f6abSGuennadi Liakhovetski static void ipu_write_param_mem(uint32_t addr, uint32_t *data, 563*0c99f6abSGuennadi Liakhovetski uint32_t num_words) 564*0c99f6abSGuennadi Liakhovetski { 565*0c99f6abSGuennadi Liakhovetski for (; num_words > 0; num_words--) { 566*0c99f6abSGuennadi Liakhovetski reg_write(addr, IPU_IMA_ADDR); 567*0c99f6abSGuennadi Liakhovetski reg_write(*data++, IPU_IMA_DATA); 568*0c99f6abSGuennadi Liakhovetski addr++; 569*0c99f6abSGuennadi Liakhovetski if ((addr & 0x7) == 5) { 570*0c99f6abSGuennadi Liakhovetski addr &= ~0x7; /* set to word 0 */ 571*0c99f6abSGuennadi Liakhovetski addr += 8; /* increment to next row */ 572*0c99f6abSGuennadi Liakhovetski } 573*0c99f6abSGuennadi Liakhovetski } 574*0c99f6abSGuennadi Liakhovetski } 575*0c99f6abSGuennadi Liakhovetski 576*0c99f6abSGuennadi Liakhovetski static uint32_t bpp_to_pixfmt(int bpp) 577*0c99f6abSGuennadi Liakhovetski { 578*0c99f6abSGuennadi Liakhovetski switch (bpp) { 579*0c99f6abSGuennadi Liakhovetski case 16: 580*0c99f6abSGuennadi Liakhovetski return IPU_PIX_FMT_RGB565; 581*0c99f6abSGuennadi Liakhovetski default: 582*0c99f6abSGuennadi Liakhovetski return 0; 583*0c99f6abSGuennadi Liakhovetski } 584*0c99f6abSGuennadi Liakhovetski } 585*0c99f6abSGuennadi Liakhovetski 586*0c99f6abSGuennadi Liakhovetski static uint32_t dma_param_addr(enum ipu_channel channel) 587*0c99f6abSGuennadi Liakhovetski { 588*0c99f6abSGuennadi Liakhovetski /* Channel Parameter Memory */ 589*0c99f6abSGuennadi Liakhovetski return 0x10000 | (channel << 4); 590*0c99f6abSGuennadi Liakhovetski } 591*0c99f6abSGuennadi Liakhovetski 592*0c99f6abSGuennadi Liakhovetski static void ipu_init_channel_buffer(enum ipu_channel channel, void *fbmem) 593*0c99f6abSGuennadi Liakhovetski { 594*0c99f6abSGuennadi Liakhovetski union chan_param_mem params = {}; 595*0c99f6abSGuennadi Liakhovetski uint32_t reg; 596*0c99f6abSGuennadi Liakhovetski uint32_t stride_bytes; 597*0c99f6abSGuennadi Liakhovetski 598*0c99f6abSGuennadi Liakhovetski stride_bytes = (XRES * ((BIT_PER_PIXEL + 7) / 8) + 3) & ~3; 599*0c99f6abSGuennadi Liakhovetski 600*0c99f6abSGuennadi Liakhovetski /* Build parameter memory data for DMA channel */ 601*0c99f6abSGuennadi Liakhovetski ipu_ch_param_set_size(¶ms, bpp_to_pixfmt(BIT_PER_PIXEL), 602*0c99f6abSGuennadi Liakhovetski XRES, YRES, stride_bytes); 603*0c99f6abSGuennadi Liakhovetski ipu_ch_param_set_buffer(¶ms, fbmem, NULL); 604*0c99f6abSGuennadi Liakhovetski params.pp.bam = 0; 605*0c99f6abSGuennadi Liakhovetski /* Some channels (rotation) have restriction on burst length */ 606*0c99f6abSGuennadi Liakhovetski 607*0c99f6abSGuennadi Liakhovetski switch (channel) { 608*0c99f6abSGuennadi Liakhovetski case IDMAC_SDC_0: 609*0c99f6abSGuennadi Liakhovetski /* In original code only IPU_PIX_FMT_RGB565 was setting burst */ 610*0c99f6abSGuennadi Liakhovetski params.pp.npb = 16 - 1; 611*0c99f6abSGuennadi Liakhovetski break; 612*0c99f6abSGuennadi Liakhovetski default: 613*0c99f6abSGuennadi Liakhovetski break; 614*0c99f6abSGuennadi Liakhovetski } 615*0c99f6abSGuennadi Liakhovetski 616*0c99f6abSGuennadi Liakhovetski ipu_write_param_mem(dma_param_addr(channel), (uint32_t *)¶ms, 10); 617*0c99f6abSGuennadi Liakhovetski 618*0c99f6abSGuennadi Liakhovetski /* Disable double-buffering */ 619*0c99f6abSGuennadi Liakhovetski reg = reg_read(IPU_CHA_DB_MODE_SEL); 620*0c99f6abSGuennadi Liakhovetski reg &= ~(1UL << channel); 621*0c99f6abSGuennadi Liakhovetski reg_write(reg, IPU_CHA_DB_MODE_SEL); 622*0c99f6abSGuennadi Liakhovetski } 623*0c99f6abSGuennadi Liakhovetski 624*0c99f6abSGuennadi Liakhovetski static void ipu_channel_set_priority(enum ipu_channel channel, 625*0c99f6abSGuennadi Liakhovetski int prio) 626*0c99f6abSGuennadi Liakhovetski { 627*0c99f6abSGuennadi Liakhovetski u32 reg = reg_read(IDMAC_CHA_PRI); 628*0c99f6abSGuennadi Liakhovetski 629*0c99f6abSGuennadi Liakhovetski if (prio) 630*0c99f6abSGuennadi Liakhovetski reg |= 1UL << channel; 631*0c99f6abSGuennadi Liakhovetski else 632*0c99f6abSGuennadi Liakhovetski reg &= ~(1UL << channel); 633*0c99f6abSGuennadi Liakhovetski 634*0c99f6abSGuennadi Liakhovetski reg_write(reg, IDMAC_CHA_PRI); 635*0c99f6abSGuennadi Liakhovetski } 636*0c99f6abSGuennadi Liakhovetski 637*0c99f6abSGuennadi Liakhovetski /* 638*0c99f6abSGuennadi Liakhovetski * ipu_enable_channel() - enable an IPU channel. 639*0c99f6abSGuennadi Liakhovetski * @channel: channel ID. 640*0c99f6abSGuennadi Liakhovetski * @return: 0 on success or negative error code on failure. 641*0c99f6abSGuennadi Liakhovetski */ 642*0c99f6abSGuennadi Liakhovetski static int ipu_enable_channel(enum ipu_channel channel) 643*0c99f6abSGuennadi Liakhovetski { 644*0c99f6abSGuennadi Liakhovetski uint32_t reg; 645*0c99f6abSGuennadi Liakhovetski 646*0c99f6abSGuennadi Liakhovetski /* Reset to buffer 0 */ 647*0c99f6abSGuennadi Liakhovetski reg_write(1UL << channel, IPU_CHA_CUR_BUF); 648*0c99f6abSGuennadi Liakhovetski 649*0c99f6abSGuennadi Liakhovetski switch (channel) { 650*0c99f6abSGuennadi Liakhovetski case IDMAC_SDC_0: 651*0c99f6abSGuennadi Liakhovetski ipu_channel_set_priority(channel, 1); 652*0c99f6abSGuennadi Liakhovetski break; 653*0c99f6abSGuennadi Liakhovetski default: 654*0c99f6abSGuennadi Liakhovetski break; 655*0c99f6abSGuennadi Liakhovetski } 656*0c99f6abSGuennadi Liakhovetski 657*0c99f6abSGuennadi Liakhovetski reg = reg_read(IDMAC_CHA_EN); 658*0c99f6abSGuennadi Liakhovetski reg_write(reg | (1UL << channel), IDMAC_CHA_EN); 659*0c99f6abSGuennadi Liakhovetski 660*0c99f6abSGuennadi Liakhovetski return 0; 661*0c99f6abSGuennadi Liakhovetski } 662*0c99f6abSGuennadi Liakhovetski 663*0c99f6abSGuennadi Liakhovetski static int ipu_update_channel_buffer(enum ipu_channel channel, void *buf) 664*0c99f6abSGuennadi Liakhovetski { 665*0c99f6abSGuennadi Liakhovetski uint32_t reg; 666*0c99f6abSGuennadi Liakhovetski 667*0c99f6abSGuennadi Liakhovetski reg = reg_read(IPU_CHA_BUF0_RDY); 668*0c99f6abSGuennadi Liakhovetski if (reg & (1UL << channel)) 669*0c99f6abSGuennadi Liakhovetski return -EACCES; 670*0c99f6abSGuennadi Liakhovetski 671*0c99f6abSGuennadi Liakhovetski /* 44.3.3.1.9 - Row Number 1 (WORD1, offset 0) */ 672*0c99f6abSGuennadi Liakhovetski reg_write(dma_param_addr(channel) + 0x0008UL, IPU_IMA_ADDR); 673*0c99f6abSGuennadi Liakhovetski reg_write((u32)buf, IPU_IMA_DATA); 674*0c99f6abSGuennadi Liakhovetski 675*0c99f6abSGuennadi Liakhovetski return 0; 676*0c99f6abSGuennadi Liakhovetski } 677*0c99f6abSGuennadi Liakhovetski 678*0c99f6abSGuennadi Liakhovetski static int idmac_tx_submit(enum ipu_channel channel, void *buf) 679*0c99f6abSGuennadi Liakhovetski { 680*0c99f6abSGuennadi Liakhovetski int ret; 681*0c99f6abSGuennadi Liakhovetski 682*0c99f6abSGuennadi Liakhovetski ipu_init_channel_buffer(channel, buf); 683*0c99f6abSGuennadi Liakhovetski 684*0c99f6abSGuennadi Liakhovetski 685*0c99f6abSGuennadi Liakhovetski /* ipu_idmac.c::ipu_submit_channel_buffers() */ 686*0c99f6abSGuennadi Liakhovetski ret = ipu_update_channel_buffer(channel, buf); 687*0c99f6abSGuennadi Liakhovetski if (ret < 0) 688*0c99f6abSGuennadi Liakhovetski return ret; 689*0c99f6abSGuennadi Liakhovetski 690*0c99f6abSGuennadi Liakhovetski /* ipu_idmac.c::ipu_select_buffer() */ 691*0c99f6abSGuennadi Liakhovetski /* Mark buffer 0 as ready. */ 692*0c99f6abSGuennadi Liakhovetski reg_write(1UL << channel, IPU_CHA_BUF0_RDY); 693*0c99f6abSGuennadi Liakhovetski 694*0c99f6abSGuennadi Liakhovetski 695*0c99f6abSGuennadi Liakhovetski ret = ipu_enable_channel(channel); 696*0c99f6abSGuennadi Liakhovetski return ret; 697*0c99f6abSGuennadi Liakhovetski } 698*0c99f6abSGuennadi Liakhovetski 699*0c99f6abSGuennadi Liakhovetski static void sdc_enable_channel(void *fbmem) 700*0c99f6abSGuennadi Liakhovetski { 701*0c99f6abSGuennadi Liakhovetski int ret; 702*0c99f6abSGuennadi Liakhovetski u32 reg; 703*0c99f6abSGuennadi Liakhovetski 704*0c99f6abSGuennadi Liakhovetski ret = idmac_tx_submit(IDMAC_SDC_0, fbmem); 705*0c99f6abSGuennadi Liakhovetski 706*0c99f6abSGuennadi Liakhovetski /* mx3fb.c::sdc_fb_init() */ 707*0c99f6abSGuennadi Liakhovetski if (ret >= 0) { 708*0c99f6abSGuennadi Liakhovetski reg = reg_read(SDC_COM_CONF); 709*0c99f6abSGuennadi Liakhovetski reg_write(reg | SDC_COM_BG_EN, SDC_COM_CONF); 710*0c99f6abSGuennadi Liakhovetski } 711*0c99f6abSGuennadi Liakhovetski 712*0c99f6abSGuennadi Liakhovetski /* 713*0c99f6abSGuennadi Liakhovetski * Attention! Without this msleep the channel keeps generating 714*0c99f6abSGuennadi Liakhovetski * interrupts. Next sdc_set_brightness() is going to be called 715*0c99f6abSGuennadi Liakhovetski * from mx3fb_blank(). 716*0c99f6abSGuennadi Liakhovetski */ 717*0c99f6abSGuennadi Liakhovetski msleep(2); 718*0c99f6abSGuennadi Liakhovetski } 719*0c99f6abSGuennadi Liakhovetski 720*0c99f6abSGuennadi Liakhovetski /* 721*0c99f6abSGuennadi Liakhovetski * mx3fb_set_par() - set framebuffer parameters and change the operating mode. 722*0c99f6abSGuennadi Liakhovetski * @return: 0 on success or negative error code on failure. 723*0c99f6abSGuennadi Liakhovetski */ 724*0c99f6abSGuennadi Liakhovetski static int mx3fb_set_par(void) 725*0c99f6abSGuennadi Liakhovetski { 726*0c99f6abSGuennadi Liakhovetski int ret; 727*0c99f6abSGuennadi Liakhovetski 728*0c99f6abSGuennadi Liakhovetski ret = sdc_init_panel(XRES, YRES, PIXEL_FMT); 729*0c99f6abSGuennadi Liakhovetski if (ret < 0) 730*0c99f6abSGuennadi Liakhovetski return ret; 731*0c99f6abSGuennadi Liakhovetski 732*0c99f6abSGuennadi Liakhovetski reg_write((H_START_WIDTH << 16) | V_START_WIDTH, SDC_BG_POS); 733*0c99f6abSGuennadi Liakhovetski 734*0c99f6abSGuennadi Liakhovetski return 0; 735*0c99f6abSGuennadi Liakhovetski } 736*0c99f6abSGuennadi Liakhovetski 737*0c99f6abSGuennadi Liakhovetski /* References in this function refer to respective Linux kernel sources */ 738*0c99f6abSGuennadi Liakhovetski void lcd_enable(void) 739*0c99f6abSGuennadi Liakhovetski { 740*0c99f6abSGuennadi Liakhovetski u32 reg; 741*0c99f6abSGuennadi Liakhovetski 742*0c99f6abSGuennadi Liakhovetski /* pcm037.c::mxc_board_init() */ 743*0c99f6abSGuennadi Liakhovetski 744*0c99f6abSGuennadi Liakhovetski /* Display Interface #3 */ 745*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD0, MUX_CTL_FUNC)); 746*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD1, MUX_CTL_FUNC)); 747*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD2, MUX_CTL_FUNC)); 748*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD3, MUX_CTL_FUNC)); 749*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD4, MUX_CTL_FUNC)); 750*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD5, MUX_CTL_FUNC)); 751*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD6, MUX_CTL_FUNC)); 752*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD7, MUX_CTL_FUNC)); 753*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD8, MUX_CTL_FUNC)); 754*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD9, MUX_CTL_FUNC)); 755*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD10, MUX_CTL_FUNC)); 756*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD11, MUX_CTL_FUNC)); 757*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD12, MUX_CTL_FUNC)); 758*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD13, MUX_CTL_FUNC)); 759*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD14, MUX_CTL_FUNC)); 760*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD15, MUX_CTL_FUNC)); 761*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD16, MUX_CTL_FUNC)); 762*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD17, MUX_CTL_FUNC)); 763*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_VSYNC3, MUX_CTL_FUNC)); 764*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_HSYNC, MUX_CTL_FUNC)); 765*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_FPSHIFT, MUX_CTL_FUNC)); 766*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_DRDY0, MUX_CTL_FUNC)); 767*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_D3_REV, MUX_CTL_FUNC)); 768*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_CONTRAST, MUX_CTL_FUNC)); 769*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_D3_SPL, MUX_CTL_FUNC)); 770*0c99f6abSGuennadi Liakhovetski mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_D3_CLS, MUX_CTL_FUNC)); 771*0c99f6abSGuennadi Liakhovetski 772*0c99f6abSGuennadi Liakhovetski 773*0c99f6abSGuennadi Liakhovetski /* ipu_idmac.c::ipu_probe() */ 774*0c99f6abSGuennadi Liakhovetski 775*0c99f6abSGuennadi Liakhovetski /* Start the clock */ 776*0c99f6abSGuennadi Liakhovetski __REG(CCM_CGR1) = __REG(CCM_CGR1) | (3 << 22); 777*0c99f6abSGuennadi Liakhovetski 778*0c99f6abSGuennadi Liakhovetski 779*0c99f6abSGuennadi Liakhovetski /* ipu_idmac.c::ipu_idmac_init() */ 780*0c99f6abSGuennadi Liakhovetski 781*0c99f6abSGuennadi Liakhovetski /* Service request counter to maximum - shouldn't be needed */ 782*0c99f6abSGuennadi Liakhovetski reg_write(0x00000070, IDMAC_CONF); 783*0c99f6abSGuennadi Liakhovetski 784*0c99f6abSGuennadi Liakhovetski 785*0c99f6abSGuennadi Liakhovetski /* ipu_idmac.c::ipu_init_channel() */ 786*0c99f6abSGuennadi Liakhovetski 787*0c99f6abSGuennadi Liakhovetski /* Enable IPU sub modules */ 788*0c99f6abSGuennadi Liakhovetski reg = reg_read(IPU_CONF) | IPU_CONF_SDC_EN | IPU_CONF_DI_EN; 789*0c99f6abSGuennadi Liakhovetski reg_write(reg, IPU_CONF); 790*0c99f6abSGuennadi Liakhovetski 791*0c99f6abSGuennadi Liakhovetski 792*0c99f6abSGuennadi Liakhovetski /* mx3fb.c::init_fb_chan() */ 793*0c99f6abSGuennadi Liakhovetski 794*0c99f6abSGuennadi Liakhovetski /* set Display Interface clock period */ 795*0c99f6abSGuennadi Liakhovetski reg_write(0x00100010L, DI_HSP_CLK_PER); 796*0c99f6abSGuennadi Liakhovetski /* Might need to trigger HSP clock change - see 44.3.3.8.5 */ 797*0c99f6abSGuennadi Liakhovetski 798*0c99f6abSGuennadi Liakhovetski 799*0c99f6abSGuennadi Liakhovetski /* mx3fb.c::sdc_set_brightness() */ 800*0c99f6abSGuennadi Liakhovetski 801*0c99f6abSGuennadi Liakhovetski /* This might be board-specific */ 802*0c99f6abSGuennadi Liakhovetski reg_write(0x03000000UL | 255 << 16, SDC_PWM_CTRL); 803*0c99f6abSGuennadi Liakhovetski 804*0c99f6abSGuennadi Liakhovetski 805*0c99f6abSGuennadi Liakhovetski /* mx3fb.c::sdc_set_global_alpha() */ 806*0c99f6abSGuennadi Liakhovetski 807*0c99f6abSGuennadi Liakhovetski /* Use global - not per-pixel - Alpha-blending */ 808*0c99f6abSGuennadi Liakhovetski reg = reg_read(SDC_GW_CTRL) & 0x00FFFFFFL; 809*0c99f6abSGuennadi Liakhovetski reg_write(reg | ((uint32_t) 0xff << 24), SDC_GW_CTRL); 810*0c99f6abSGuennadi Liakhovetski 811*0c99f6abSGuennadi Liakhovetski reg = reg_read(SDC_COM_CONF); 812*0c99f6abSGuennadi Liakhovetski reg_write(reg | SDC_COM_GLB_A, SDC_COM_CONF); 813*0c99f6abSGuennadi Liakhovetski 814*0c99f6abSGuennadi Liakhovetski 815*0c99f6abSGuennadi Liakhovetski /* mx3fb.c::sdc_set_color_key() */ 816*0c99f6abSGuennadi Liakhovetski 817*0c99f6abSGuennadi Liakhovetski /* Disable colour-keying for background */ 818*0c99f6abSGuennadi Liakhovetski reg = reg_read(SDC_COM_CONF) & 819*0c99f6abSGuennadi Liakhovetski ~(SDC_COM_GWSEL | SDC_COM_KEY_COLOR_G); 820*0c99f6abSGuennadi Liakhovetski reg_write(reg, SDC_COM_CONF); 821*0c99f6abSGuennadi Liakhovetski 822*0c99f6abSGuennadi Liakhovetski 823*0c99f6abSGuennadi Liakhovetski mx3fb_set_par(); 824*0c99f6abSGuennadi Liakhovetski 825*0c99f6abSGuennadi Liakhovetski sdc_enable_channel(lcd_base); 826*0c99f6abSGuennadi Liakhovetski 827*0c99f6abSGuennadi Liakhovetski /* 828*0c99f6abSGuennadi Liakhovetski * Linux driver calls sdc_set_brightness() here again, 829*0c99f6abSGuennadi Liakhovetski * once is enough for us 830*0c99f6abSGuennadi Liakhovetski */ 831*0c99f6abSGuennadi Liakhovetski } 832*0c99f6abSGuennadi Liakhovetski 833*0c99f6abSGuennadi Liakhovetski void lcd_ctrl_init(void *lcdbase) 834*0c99f6abSGuennadi Liakhovetski { 835*0c99f6abSGuennadi Liakhovetski u32 mem_len = XRES * YRES * BIT_PER_PIXEL / 8; 836*0c99f6abSGuennadi Liakhovetski /* 837*0c99f6abSGuennadi Liakhovetski * We rely on lcdbase being a physical address, i.e., either MMU off, 838*0c99f6abSGuennadi Liakhovetski * or 1-to-1 mapping. Might want to add some virt2phys here. 839*0c99f6abSGuennadi Liakhovetski */ 840*0c99f6abSGuennadi Liakhovetski if (!lcdbase) 841*0c99f6abSGuennadi Liakhovetski return; 842*0c99f6abSGuennadi Liakhovetski 843*0c99f6abSGuennadi Liakhovetski memset(lcdbase, 0, mem_len); 844*0c99f6abSGuennadi Liakhovetski } 845*0c99f6abSGuennadi Liakhovetski 846*0c99f6abSGuennadi Liakhovetski ulong calc_fbsize(void) 847*0c99f6abSGuennadi Liakhovetski { 848*0c99f6abSGuennadi Liakhovetski return ((panel_info.vl_col * panel_info.vl_row * 849*0c99f6abSGuennadi Liakhovetski NBITS(panel_info.vl_bpix)) / 8) + PAGE_SIZE; 850*0c99f6abSGuennadi Liakhovetski } 851*0c99f6abSGuennadi Liakhovetski 852*0c99f6abSGuennadi Liakhovetski int overwrite_console(void) 853*0c99f6abSGuennadi Liakhovetski { 854*0c99f6abSGuennadi Liakhovetski /* Keep stdout / stderr on serial, our LCD is for splashscreen only */ 855*0c99f6abSGuennadi Liakhovetski return 1; 856*0c99f6abSGuennadi Liakhovetski } 857