1*14f88c43SAnatolij Gustschin /* 2*14f88c43SAnatolij Gustschin * Copyright 2007, 2010 Freescale Semiconductor, Inc. 3*14f88c43SAnatolij Gustschin * York Sun <yorksun@freescale.com> 4*14f88c43SAnatolij Gustschin * 5*14f88c43SAnatolij Gustschin * FSL DIU Framebuffer driver 6*14f88c43SAnatolij Gustschin * 7*14f88c43SAnatolij Gustschin * See file CREDITS for list of people who contributed to this 8*14f88c43SAnatolij Gustschin * project. 9*14f88c43SAnatolij Gustschin * 10*14f88c43SAnatolij Gustschin * This program is free software; you can redistribute it and/or 11*14f88c43SAnatolij Gustschin * modify it under the terms of the GNU General Public License as 12*14f88c43SAnatolij Gustschin * published by the Free Software Foundation; either version 2 of 13*14f88c43SAnatolij Gustschin * the License, or (at your option) any later version. 14*14f88c43SAnatolij Gustschin * 15*14f88c43SAnatolij Gustschin * This program is distributed in the hope that it will be useful, 16*14f88c43SAnatolij Gustschin * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*14f88c43SAnatolij Gustschin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*14f88c43SAnatolij Gustschin * GNU General Public License for more details. 19*14f88c43SAnatolij Gustschin * 20*14f88c43SAnatolij Gustschin * You should have received a copy of the GNU General Public License 21*14f88c43SAnatolij Gustschin * along with this program; if not, write to the Free Software 22*14f88c43SAnatolij Gustschin * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 23*14f88c43SAnatolij Gustschin * MA 02111-1307 USA 24*14f88c43SAnatolij Gustschin */ 25*14f88c43SAnatolij Gustschin 26*14f88c43SAnatolij Gustschin #include <common.h> 27*14f88c43SAnatolij Gustschin #include <i2c.h> 28*14f88c43SAnatolij Gustschin #include <malloc.h> 29*14f88c43SAnatolij Gustschin #include <asm/io.h> 30*14f88c43SAnatolij Gustschin 31*14f88c43SAnatolij Gustschin #include <fsl_diu_fb.h> 32*14f88c43SAnatolij Gustschin 33*14f88c43SAnatolij Gustschin struct fb_videomode { 34*14f88c43SAnatolij Gustschin const char *name; /* optional */ 35*14f88c43SAnatolij Gustschin unsigned int refresh; /* optional */ 36*14f88c43SAnatolij Gustschin unsigned int xres; 37*14f88c43SAnatolij Gustschin unsigned int yres; 38*14f88c43SAnatolij Gustschin unsigned int pixclock; 39*14f88c43SAnatolij Gustschin unsigned int left_margin; 40*14f88c43SAnatolij Gustschin unsigned int right_margin; 41*14f88c43SAnatolij Gustschin unsigned int upper_margin; 42*14f88c43SAnatolij Gustschin unsigned int lower_margin; 43*14f88c43SAnatolij Gustschin unsigned int hsync_len; 44*14f88c43SAnatolij Gustschin unsigned int vsync_len; 45*14f88c43SAnatolij Gustschin unsigned int sync; 46*14f88c43SAnatolij Gustschin unsigned int vmode; 47*14f88c43SAnatolij Gustschin unsigned int flag; 48*14f88c43SAnatolij Gustschin }; 49*14f88c43SAnatolij Gustschin 50*14f88c43SAnatolij Gustschin #define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */ 51*14f88c43SAnatolij Gustschin #define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */ 52*14f88c43SAnatolij Gustschin #define FB_VMODE_NONINTERLACED 0 /* non interlaced */ 53*14f88c43SAnatolij Gustschin 54*14f88c43SAnatolij Gustschin /* This setting is used for the ifm pdm360ng with PRIMEVIEW PM070WL3 */ 55*14f88c43SAnatolij Gustschin static struct fb_videomode fsl_diu_mode_800 = { 56*14f88c43SAnatolij Gustschin .refresh = 60, 57*14f88c43SAnatolij Gustschin .xres = 800, 58*14f88c43SAnatolij Gustschin .yres = 480, 59*14f88c43SAnatolij Gustschin .pixclock = 31250, 60*14f88c43SAnatolij Gustschin .left_margin = 86, 61*14f88c43SAnatolij Gustschin .right_margin = 42, 62*14f88c43SAnatolij Gustschin .upper_margin = 33, 63*14f88c43SAnatolij Gustschin .lower_margin = 10, 64*14f88c43SAnatolij Gustschin .hsync_len = 128, 65*14f88c43SAnatolij Gustschin .vsync_len = 2, 66*14f88c43SAnatolij Gustschin .sync = 0, 67*14f88c43SAnatolij Gustschin .vmode = FB_VMODE_NONINTERLACED 68*14f88c43SAnatolij Gustschin }; 69*14f88c43SAnatolij Gustschin 70*14f88c43SAnatolij Gustschin /* 71*14f88c43SAnatolij Gustschin * These parameters give default parameters 72*14f88c43SAnatolij Gustschin * for video output 1024x768, 73*14f88c43SAnatolij Gustschin * FIXME - change timing to proper amounts 74*14f88c43SAnatolij Gustschin * hsync 31.5kHz, vsync 60Hz 75*14f88c43SAnatolij Gustschin */ 76*14f88c43SAnatolij Gustschin static struct fb_videomode fsl_diu_mode_1024 = { 77*14f88c43SAnatolij Gustschin .refresh = 60, 78*14f88c43SAnatolij Gustschin .xres = 1024, 79*14f88c43SAnatolij Gustschin .yres = 768, 80*14f88c43SAnatolij Gustschin .pixclock = 15385, 81*14f88c43SAnatolij Gustschin .left_margin = 160, 82*14f88c43SAnatolij Gustschin .right_margin = 24, 83*14f88c43SAnatolij Gustschin .upper_margin = 29, 84*14f88c43SAnatolij Gustschin .lower_margin = 3, 85*14f88c43SAnatolij Gustschin .hsync_len = 136, 86*14f88c43SAnatolij Gustschin .vsync_len = 6, 87*14f88c43SAnatolij Gustschin .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 88*14f88c43SAnatolij Gustschin .vmode = FB_VMODE_NONINTERLACED 89*14f88c43SAnatolij Gustschin }; 90*14f88c43SAnatolij Gustschin 91*14f88c43SAnatolij Gustschin static struct fb_videomode fsl_diu_mode_1280 = { 92*14f88c43SAnatolij Gustschin .name = "1280x1024-60", 93*14f88c43SAnatolij Gustschin .refresh = 60, 94*14f88c43SAnatolij Gustschin .xres = 1280, 95*14f88c43SAnatolij Gustschin .yres = 1024, 96*14f88c43SAnatolij Gustschin .pixclock = 9375, 97*14f88c43SAnatolij Gustschin .left_margin = 38, 98*14f88c43SAnatolij Gustschin .right_margin = 128, 99*14f88c43SAnatolij Gustschin .upper_margin = 2, 100*14f88c43SAnatolij Gustschin .lower_margin = 7, 101*14f88c43SAnatolij Gustschin .hsync_len = 216, 102*14f88c43SAnatolij Gustschin .vsync_len = 37, 103*14f88c43SAnatolij Gustschin .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 104*14f88c43SAnatolij Gustschin .vmode = FB_VMODE_NONINTERLACED 105*14f88c43SAnatolij Gustschin }; 106*14f88c43SAnatolij Gustschin 107*14f88c43SAnatolij Gustschin /* 108*14f88c43SAnatolij Gustschin * These are the fields of area descriptor(in DDR memory) for every plane 109*14f88c43SAnatolij Gustschin */ 110*14f88c43SAnatolij Gustschin struct diu_ad { 111*14f88c43SAnatolij Gustschin /* Word 0(32-bit) in DDR memory */ 112*14f88c43SAnatolij Gustschin unsigned int pix_fmt; /* hard coding pixel format */ 113*14f88c43SAnatolij Gustschin /* Word 1(32-bit) in DDR memory */ 114*14f88c43SAnatolij Gustschin unsigned int addr; 115*14f88c43SAnatolij Gustschin /* Word 2(32-bit) in DDR memory */ 116*14f88c43SAnatolij Gustschin unsigned int src_size_g_alpha; 117*14f88c43SAnatolij Gustschin /* Word 3(32-bit) in DDR memory */ 118*14f88c43SAnatolij Gustschin unsigned int aoi_size; 119*14f88c43SAnatolij Gustschin /* Word 4(32-bit) in DDR memory */ 120*14f88c43SAnatolij Gustschin unsigned int offset_xyi; 121*14f88c43SAnatolij Gustschin /* Word 5(32-bit) in DDR memory */ 122*14f88c43SAnatolij Gustschin unsigned int offset_xyd; 123*14f88c43SAnatolij Gustschin /* Word 6(32-bit) in DDR memory */ 124*14f88c43SAnatolij Gustschin unsigned int ckmax_r:8; 125*14f88c43SAnatolij Gustschin unsigned int ckmax_g:8; 126*14f88c43SAnatolij Gustschin unsigned int ckmax_b:8; 127*14f88c43SAnatolij Gustschin unsigned int res9:8; 128*14f88c43SAnatolij Gustschin /* Word 7(32-bit) in DDR memory */ 129*14f88c43SAnatolij Gustschin unsigned int ckmin_r:8; 130*14f88c43SAnatolij Gustschin unsigned int ckmin_g:8; 131*14f88c43SAnatolij Gustschin unsigned int ckmin_b:8; 132*14f88c43SAnatolij Gustschin unsigned int res10:8; 133*14f88c43SAnatolij Gustschin /* Word 8(32-bit) in DDR memory */ 134*14f88c43SAnatolij Gustschin unsigned int next_ad; 135*14f88c43SAnatolij Gustschin /* Word 9(32-bit) in DDR memory, just for 64-bit aligned */ 136*14f88c43SAnatolij Gustschin unsigned int res1; 137*14f88c43SAnatolij Gustschin unsigned int res2; 138*14f88c43SAnatolij Gustschin unsigned int res3; 139*14f88c43SAnatolij Gustschin }__attribute__ ((packed)); 140*14f88c43SAnatolij Gustschin 141*14f88c43SAnatolij Gustschin /* 142*14f88c43SAnatolij Gustschin * DIU register map 143*14f88c43SAnatolij Gustschin */ 144*14f88c43SAnatolij Gustschin struct diu { 145*14f88c43SAnatolij Gustschin unsigned int desc[3]; 146*14f88c43SAnatolij Gustschin unsigned int gamma; 147*14f88c43SAnatolij Gustschin unsigned int pallete; 148*14f88c43SAnatolij Gustschin unsigned int cursor; 149*14f88c43SAnatolij Gustschin unsigned int curs_pos; 150*14f88c43SAnatolij Gustschin unsigned int diu_mode; 151*14f88c43SAnatolij Gustschin unsigned int bgnd; 152*14f88c43SAnatolij Gustschin unsigned int bgnd_wb; 153*14f88c43SAnatolij Gustschin unsigned int disp_size; 154*14f88c43SAnatolij Gustschin unsigned int wb_size; 155*14f88c43SAnatolij Gustschin unsigned int wb_mem_addr; 156*14f88c43SAnatolij Gustschin unsigned int hsyn_para; 157*14f88c43SAnatolij Gustschin unsigned int vsyn_para; 158*14f88c43SAnatolij Gustschin unsigned int syn_pol; 159*14f88c43SAnatolij Gustschin unsigned int thresholds; 160*14f88c43SAnatolij Gustschin unsigned int int_status; 161*14f88c43SAnatolij Gustschin unsigned int int_mask; 162*14f88c43SAnatolij Gustschin unsigned int colorbar[8]; 163*14f88c43SAnatolij Gustschin unsigned int filling; 164*14f88c43SAnatolij Gustschin unsigned int plut; 165*14f88c43SAnatolij Gustschin } __attribute__ ((packed)); 166*14f88c43SAnatolij Gustschin 167*14f88c43SAnatolij Gustschin struct diu_hw { 168*14f88c43SAnatolij Gustschin struct diu *diu_reg; 169*14f88c43SAnatolij Gustschin volatile unsigned int mode; /* DIU operation mode */ 170*14f88c43SAnatolij Gustschin }; 171*14f88c43SAnatolij Gustschin 172*14f88c43SAnatolij Gustschin struct diu_addr { 173*14f88c43SAnatolij Gustschin unsigned char * paddr; /* Virtual address */ 174*14f88c43SAnatolij Gustschin unsigned int offset; 175*14f88c43SAnatolij Gustschin }; 176*14f88c43SAnatolij Gustschin 177*14f88c43SAnatolij Gustschin /* 178*14f88c43SAnatolij Gustschin * Modes of operation of DIU 179*14f88c43SAnatolij Gustschin */ 180*14f88c43SAnatolij Gustschin #define MFB_MODE0 0 /* DIU off */ 181*14f88c43SAnatolij Gustschin #define MFB_MODE1 1 /* All three planes output to display */ 182*14f88c43SAnatolij Gustschin #define MFB_MODE2 2 /* Plane 1 to display, 183*14f88c43SAnatolij Gustschin * planes 2+3 written back to memory */ 184*14f88c43SAnatolij Gustschin #define MFB_MODE3 3 /* All three planes written back to memory */ 185*14f88c43SAnatolij Gustschin #define MFB_MODE4 4 /* Color bar generation */ 186*14f88c43SAnatolij Gustschin 187*14f88c43SAnatolij Gustschin #define MAX_CURS 32 188*14f88c43SAnatolij Gustschin 189*14f88c43SAnatolij Gustschin static struct fb_info fsl_fb_info; 190*14f88c43SAnatolij Gustschin static struct diu_addr gamma, cursor; 191*14f88c43SAnatolij Gustschin static struct diu_ad fsl_diu_fb_ad __attribute__ ((aligned(32))); 192*14f88c43SAnatolij Gustschin static struct diu_ad dummy_ad __attribute__ ((aligned(32))); 193*14f88c43SAnatolij Gustschin static unsigned char *dummy_fb; 194*14f88c43SAnatolij Gustschin static struct diu_hw dr = { 195*14f88c43SAnatolij Gustschin .mode = MFB_MODE1, 196*14f88c43SAnatolij Gustschin }; 197*14f88c43SAnatolij Gustschin 198*14f88c43SAnatolij Gustschin int fb_enabled = 0; 199*14f88c43SAnatolij Gustschin int fb_initialized = 0; 200*14f88c43SAnatolij Gustschin const int default_xres = 1280; 201*14f88c43SAnatolij Gustschin const int default_pixel_format = 0x88882317; 202*14f88c43SAnatolij Gustschin 203*14f88c43SAnatolij Gustschin static int map_video_memory(struct fb_info *info, unsigned long bytes_align); 204*14f88c43SAnatolij Gustschin static void enable_lcdc(void); 205*14f88c43SAnatolij Gustschin static void disable_lcdc(void); 206*14f88c43SAnatolij Gustschin static int fsl_diu_enable_panel(struct fb_info *info); 207*14f88c43SAnatolij Gustschin static int fsl_diu_disable_panel(struct fb_info *info); 208*14f88c43SAnatolij Gustschin static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align); 209*14f88c43SAnatolij Gustschin void diu_set_pixel_clock(unsigned int pixclock); 210*14f88c43SAnatolij Gustschin 211*14f88c43SAnatolij Gustschin int fsl_diu_init(int xres, unsigned int pixel_format, int gamma_fix) 212*14f88c43SAnatolij Gustschin { 213*14f88c43SAnatolij Gustschin struct fb_videomode *fsl_diu_mode_db; 214*14f88c43SAnatolij Gustschin struct diu_ad *ad = &fsl_diu_fb_ad; 215*14f88c43SAnatolij Gustschin struct diu *hw; 216*14f88c43SAnatolij Gustschin struct fb_info *info = &fsl_fb_info; 217*14f88c43SAnatolij Gustschin struct fb_var_screeninfo *var = &info->var; 218*14f88c43SAnatolij Gustschin unsigned char *gamma_table_base; 219*14f88c43SAnatolij Gustschin unsigned int i, j; 220*14f88c43SAnatolij Gustschin 221*14f88c43SAnatolij Gustschin debug("Enter fsl_diu_init\n"); 222*14f88c43SAnatolij Gustschin dr.diu_reg = (struct diu *) (CONFIG_SYS_DIU_ADDR); 223*14f88c43SAnatolij Gustschin hw = (struct diu *) dr.diu_reg; 224*14f88c43SAnatolij Gustschin 225*14f88c43SAnatolij Gustschin disable_lcdc(); 226*14f88c43SAnatolij Gustschin 227*14f88c43SAnatolij Gustschin switch (xres) { 228*14f88c43SAnatolij Gustschin case 800: 229*14f88c43SAnatolij Gustschin fsl_diu_mode_db = &fsl_diu_mode_800; 230*14f88c43SAnatolij Gustschin break; 231*14f88c43SAnatolij Gustschin case 1280: 232*14f88c43SAnatolij Gustschin fsl_diu_mode_db = &fsl_diu_mode_1280; 233*14f88c43SAnatolij Gustschin break; 234*14f88c43SAnatolij Gustschin default: 235*14f88c43SAnatolij Gustschin fsl_diu_mode_db = &fsl_diu_mode_1024; 236*14f88c43SAnatolij Gustschin } 237*14f88c43SAnatolij Gustschin 238*14f88c43SAnatolij Gustschin if (0 == fb_initialized) { 239*14f88c43SAnatolij Gustschin allocate_buf(&gamma, 768, 32); 240*14f88c43SAnatolij Gustschin debug("gamma is allocated @ 0x%x\n", 241*14f88c43SAnatolij Gustschin (unsigned int)gamma.paddr); 242*14f88c43SAnatolij Gustschin allocate_buf(&cursor, MAX_CURS * MAX_CURS * 2, 32); 243*14f88c43SAnatolij Gustschin debug("curosr is allocated @ 0x%x\n", 244*14f88c43SAnatolij Gustschin (unsigned int)cursor.paddr); 245*14f88c43SAnatolij Gustschin 246*14f88c43SAnatolij Gustschin /* create a dummy fb and dummy ad */ 247*14f88c43SAnatolij Gustschin dummy_fb = malloc(64); 248*14f88c43SAnatolij Gustschin if (NULL == dummy_fb) { 249*14f88c43SAnatolij Gustschin printf("Cannot allocate dummy fb\n"); 250*14f88c43SAnatolij Gustschin return -1; 251*14f88c43SAnatolij Gustschin } 252*14f88c43SAnatolij Gustschin dummy_ad.addr = cpu_to_le32((unsigned int)dummy_fb); 253*14f88c43SAnatolij Gustschin dummy_ad.pix_fmt = 0x88882317; 254*14f88c43SAnatolij Gustschin dummy_ad.src_size_g_alpha = 0x04400000; /* alpha = 0 */ 255*14f88c43SAnatolij Gustschin dummy_ad.aoi_size = 0x02000400; 256*14f88c43SAnatolij Gustschin dummy_ad.offset_xyi = 0; 257*14f88c43SAnatolij Gustschin dummy_ad.offset_xyd = 0; 258*14f88c43SAnatolij Gustschin dummy_ad.next_ad = 0; 259*14f88c43SAnatolij Gustschin /* Memory allocation for framebuffer */ 260*14f88c43SAnatolij Gustschin if (map_video_memory(info, 32)) { 261*14f88c43SAnatolij Gustschin printf("Unable to allocate fb memory 1\n"); 262*14f88c43SAnatolij Gustschin return -1; 263*14f88c43SAnatolij Gustschin } 264*14f88c43SAnatolij Gustschin } 265*14f88c43SAnatolij Gustschin 266*14f88c43SAnatolij Gustschin memset(info->screen_base, 0, info->smem_len); 267*14f88c43SAnatolij Gustschin 268*14f88c43SAnatolij Gustschin out_be32(&dr.diu_reg->desc[0], (int)&dummy_ad); 269*14f88c43SAnatolij Gustschin out_be32(&dr.diu_reg->desc[1], (int)&dummy_ad); 270*14f88c43SAnatolij Gustschin out_be32(&dr.diu_reg->desc[2], (int)&dummy_ad); 271*14f88c43SAnatolij Gustschin debug("dummy dr.diu_reg->desc[0] = 0x%x\n", dr.diu_reg->desc[0]); 272*14f88c43SAnatolij Gustschin debug("dummy desc[0] = 0x%x\n", hw->desc[0]); 273*14f88c43SAnatolij Gustschin 274*14f88c43SAnatolij Gustschin /* read mode info */ 275*14f88c43SAnatolij Gustschin var->xres = fsl_diu_mode_db->xres; 276*14f88c43SAnatolij Gustschin var->yres = fsl_diu_mode_db->yres; 277*14f88c43SAnatolij Gustschin var->bits_per_pixel = 32; 278*14f88c43SAnatolij Gustschin var->pixclock = fsl_diu_mode_db->pixclock; 279*14f88c43SAnatolij Gustschin var->left_margin = fsl_diu_mode_db->left_margin; 280*14f88c43SAnatolij Gustschin var->right_margin = fsl_diu_mode_db->right_margin; 281*14f88c43SAnatolij Gustschin var->upper_margin = fsl_diu_mode_db->upper_margin; 282*14f88c43SAnatolij Gustschin var->lower_margin = fsl_diu_mode_db->lower_margin; 283*14f88c43SAnatolij Gustschin var->hsync_len = fsl_diu_mode_db->hsync_len; 284*14f88c43SAnatolij Gustschin var->vsync_len = fsl_diu_mode_db->vsync_len; 285*14f88c43SAnatolij Gustschin var->sync = fsl_diu_mode_db->sync; 286*14f88c43SAnatolij Gustschin var->vmode = fsl_diu_mode_db->vmode; 287*14f88c43SAnatolij Gustschin info->line_length = var->xres * var->bits_per_pixel / 8; 288*14f88c43SAnatolij Gustschin 289*14f88c43SAnatolij Gustschin ad->pix_fmt = pixel_format; 290*14f88c43SAnatolij Gustschin ad->addr = cpu_to_le32((unsigned int)info->screen_base); 291*14f88c43SAnatolij Gustschin ad->src_size_g_alpha 292*14f88c43SAnatolij Gustschin = cpu_to_le32((var->yres << 12) | var->xres); 293*14f88c43SAnatolij Gustschin /* fix me. AOI should not be greater than display size */ 294*14f88c43SAnatolij Gustschin ad->aoi_size = cpu_to_le32(( var->yres << 16) | var->xres); 295*14f88c43SAnatolij Gustschin ad->offset_xyi = 0; 296*14f88c43SAnatolij Gustschin ad->offset_xyd = 0; 297*14f88c43SAnatolij Gustschin 298*14f88c43SAnatolij Gustschin /* Disable chroma keying function */ 299*14f88c43SAnatolij Gustschin ad->ckmax_r = 0; 300*14f88c43SAnatolij Gustschin ad->ckmax_g = 0; 301*14f88c43SAnatolij Gustschin ad->ckmax_b = 0; 302*14f88c43SAnatolij Gustschin 303*14f88c43SAnatolij Gustschin ad->ckmin_r = 255; 304*14f88c43SAnatolij Gustschin ad->ckmin_g = 255; 305*14f88c43SAnatolij Gustschin ad->ckmin_b = 255; 306*14f88c43SAnatolij Gustschin 307*14f88c43SAnatolij Gustschin gamma_table_base = gamma.paddr; 308*14f88c43SAnatolij Gustschin debug("gamma_table_base is allocated @ 0x%x\n", 309*14f88c43SAnatolij Gustschin (unsigned int)gamma_table_base); 310*14f88c43SAnatolij Gustschin 311*14f88c43SAnatolij Gustschin /* Prep for DIU init - gamma table */ 312*14f88c43SAnatolij Gustschin 313*14f88c43SAnatolij Gustschin for (i = 0; i <= 2; i++) 314*14f88c43SAnatolij Gustschin for (j = 0; j <= 255; j++) 315*14f88c43SAnatolij Gustschin *gamma_table_base++ = j; 316*14f88c43SAnatolij Gustschin 317*14f88c43SAnatolij Gustschin if (gamma_fix == 1) { /* fix the gamma */ 318*14f88c43SAnatolij Gustschin debug("Fix gamma table\n"); 319*14f88c43SAnatolij Gustschin gamma_table_base = gamma.paddr; 320*14f88c43SAnatolij Gustschin for (i = 0; i < 256*3; i++) { 321*14f88c43SAnatolij Gustschin gamma_table_base[i] = (gamma_table_base[i] << 2) 322*14f88c43SAnatolij Gustschin | ((gamma_table_base[i] >> 6) & 0x03); 323*14f88c43SAnatolij Gustschin } 324*14f88c43SAnatolij Gustschin } 325*14f88c43SAnatolij Gustschin 326*14f88c43SAnatolij Gustschin debug("update-lcdc: HW - %p\n Disabling DIU\n", hw); 327*14f88c43SAnatolij Gustschin 328*14f88c43SAnatolij Gustschin /* Program DIU registers */ 329*14f88c43SAnatolij Gustschin 330*14f88c43SAnatolij Gustschin out_be32(&hw->gamma, (int)gamma.paddr); 331*14f88c43SAnatolij Gustschin out_be32(&hw->cursor, (int)cursor.paddr); 332*14f88c43SAnatolij Gustschin out_be32(&hw->bgnd, 0x007F7F7F); 333*14f88c43SAnatolij Gustschin out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ 334*14f88c43SAnatolij Gustschin out_be32(&hw->disp_size, var->yres << 16 | var->xres); /* DISP SIZE */ 335*14f88c43SAnatolij Gustschin out_be32(&hw->wb_size, 0); /* WB SIZE */ 336*14f88c43SAnatolij Gustschin out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */ 337*14f88c43SAnatolij Gustschin out_be32(&hw->hsyn_para, var->left_margin << 22 | /* BP_H */ 338*14f88c43SAnatolij Gustschin var->hsync_len << 11 | /* PW_H */ 339*14f88c43SAnatolij Gustschin var->right_margin); /* FP_H */ 340*14f88c43SAnatolij Gustschin 341*14f88c43SAnatolij Gustschin out_be32(&hw->vsyn_para, var->upper_margin << 22 | /* BP_V */ 342*14f88c43SAnatolij Gustschin var->vsync_len << 11 | /* PW_V */ 343*14f88c43SAnatolij Gustschin var->lower_margin); /* FP_V */ 344*14f88c43SAnatolij Gustschin 345*14f88c43SAnatolij Gustschin out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */ 346*14f88c43SAnatolij Gustschin out_be32(&hw->thresholds, 0x00037800); /* The Thresholds */ 347*14f88c43SAnatolij Gustschin out_be32(&hw->int_status, 0); /* INTERRUPT STATUS */ 348*14f88c43SAnatolij Gustschin out_be32(&hw->int_mask, 0); /* INT MASK */ 349*14f88c43SAnatolij Gustschin out_be32(&hw->plut, 0x01F5F666); 350*14f88c43SAnatolij Gustschin /* Pixel Clock configuration */ 351*14f88c43SAnatolij Gustschin debug("DIU pixclock in ps - %d\n", var->pixclock); 352*14f88c43SAnatolij Gustschin diu_set_pixel_clock(var->pixclock); 353*14f88c43SAnatolij Gustschin 354*14f88c43SAnatolij Gustschin fb_initialized = 1; 355*14f88c43SAnatolij Gustschin 356*14f88c43SAnatolij Gustschin /* Enable the DIU */ 357*14f88c43SAnatolij Gustschin fsl_diu_enable_panel(info); 358*14f88c43SAnatolij Gustschin enable_lcdc(); 359*14f88c43SAnatolij Gustschin 360*14f88c43SAnatolij Gustschin return 0; 361*14f88c43SAnatolij Gustschin } 362*14f88c43SAnatolij Gustschin 363*14f88c43SAnatolij Gustschin char *fsl_fb_open(struct fb_info **info) 364*14f88c43SAnatolij Gustschin { 365*14f88c43SAnatolij Gustschin *info = &fsl_fb_info; 366*14f88c43SAnatolij Gustschin return fsl_fb_info.screen_base; 367*14f88c43SAnatolij Gustschin } 368*14f88c43SAnatolij Gustschin 369*14f88c43SAnatolij Gustschin void fsl_diu_close(void) 370*14f88c43SAnatolij Gustschin { 371*14f88c43SAnatolij Gustschin struct fb_info *info = &fsl_fb_info; 372*14f88c43SAnatolij Gustschin fsl_diu_disable_panel(info); 373*14f88c43SAnatolij Gustschin } 374*14f88c43SAnatolij Gustschin 375*14f88c43SAnatolij Gustschin static int fsl_diu_enable_panel(struct fb_info *info) 376*14f88c43SAnatolij Gustschin { 377*14f88c43SAnatolij Gustschin struct diu *hw = dr.diu_reg; 378*14f88c43SAnatolij Gustschin struct diu_ad *ad = &fsl_diu_fb_ad; 379*14f88c43SAnatolij Gustschin 380*14f88c43SAnatolij Gustschin debug("Entered: enable_panel\n"); 381*14f88c43SAnatolij Gustschin if (in_be32(&hw->desc[0]) != (unsigned)ad) 382*14f88c43SAnatolij Gustschin out_be32(&hw->desc[0], (unsigned)ad); 383*14f88c43SAnatolij Gustschin debug("desc[0] = 0x%x\n", hw->desc[0]); 384*14f88c43SAnatolij Gustschin return 0; 385*14f88c43SAnatolij Gustschin } 386*14f88c43SAnatolij Gustschin 387*14f88c43SAnatolij Gustschin static int fsl_diu_disable_panel(struct fb_info *info) 388*14f88c43SAnatolij Gustschin { 389*14f88c43SAnatolij Gustschin struct diu *hw = dr.diu_reg; 390*14f88c43SAnatolij Gustschin 391*14f88c43SAnatolij Gustschin debug("Entered: disable_panel\n"); 392*14f88c43SAnatolij Gustschin if (in_be32(&hw->desc[0]) != (unsigned)&dummy_ad) 393*14f88c43SAnatolij Gustschin out_be32(&hw->desc[0], (unsigned)&dummy_ad); 394*14f88c43SAnatolij Gustschin return 0; 395*14f88c43SAnatolij Gustschin } 396*14f88c43SAnatolij Gustschin 397*14f88c43SAnatolij Gustschin static int map_video_memory(struct fb_info *info, unsigned long bytes_align) 398*14f88c43SAnatolij Gustschin { 399*14f88c43SAnatolij Gustschin unsigned long offset; 400*14f88c43SAnatolij Gustschin unsigned long mask; 401*14f88c43SAnatolij Gustschin 402*14f88c43SAnatolij Gustschin debug("Entered: map_video_memory\n"); 403*14f88c43SAnatolij Gustschin /* allocate maximum 1280*1024 with 32bpp */ 404*14f88c43SAnatolij Gustschin info->smem_len = 1280 * 4 *1024 + bytes_align; 405*14f88c43SAnatolij Gustschin debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->smem_len); 406*14f88c43SAnatolij Gustschin info->screen_base = malloc(info->smem_len); 407*14f88c43SAnatolij Gustschin if (info->screen_base == NULL) { 408*14f88c43SAnatolij Gustschin printf("Unable to allocate fb memory\n"); 409*14f88c43SAnatolij Gustschin return -1; 410*14f88c43SAnatolij Gustschin } 411*14f88c43SAnatolij Gustschin info->smem_start = (unsigned int) info->screen_base; 412*14f88c43SAnatolij Gustschin mask = bytes_align - 1; 413*14f88c43SAnatolij Gustschin offset = (unsigned long)info->screen_base & mask; 414*14f88c43SAnatolij Gustschin if (offset) { 415*14f88c43SAnatolij Gustschin info->screen_base += (bytes_align - offset); 416*14f88c43SAnatolij Gustschin info->smem_len = info->smem_len - (bytes_align - offset); 417*14f88c43SAnatolij Gustschin } else 418*14f88c43SAnatolij Gustschin info->smem_len = info->smem_len - bytes_align; 419*14f88c43SAnatolij Gustschin 420*14f88c43SAnatolij Gustschin info->screen_size = info->smem_len; 421*14f88c43SAnatolij Gustschin 422*14f88c43SAnatolij Gustschin debug("Allocated fb @ 0x%08lx, size=%d.\n", 423*14f88c43SAnatolij Gustschin info->smem_start, info->smem_len); 424*14f88c43SAnatolij Gustschin 425*14f88c43SAnatolij Gustschin return 0; 426*14f88c43SAnatolij Gustschin } 427*14f88c43SAnatolij Gustschin 428*14f88c43SAnatolij Gustschin static void enable_lcdc(void) 429*14f88c43SAnatolij Gustschin { 430*14f88c43SAnatolij Gustschin struct diu *hw = dr.diu_reg; 431*14f88c43SAnatolij Gustschin 432*14f88c43SAnatolij Gustschin debug("Entered: enable_lcdc, fb_enabled = %d\n", fb_enabled); 433*14f88c43SAnatolij Gustschin if (!fb_enabled) { 434*14f88c43SAnatolij Gustschin out_be32(&hw->diu_mode, dr.mode); 435*14f88c43SAnatolij Gustschin fb_enabled++; 436*14f88c43SAnatolij Gustschin } 437*14f88c43SAnatolij Gustschin debug("diu_mode = %d\n", hw->diu_mode); 438*14f88c43SAnatolij Gustschin } 439*14f88c43SAnatolij Gustschin 440*14f88c43SAnatolij Gustschin static void disable_lcdc(void) 441*14f88c43SAnatolij Gustschin { 442*14f88c43SAnatolij Gustschin struct diu *hw = dr.diu_reg; 443*14f88c43SAnatolij Gustschin 444*14f88c43SAnatolij Gustschin debug("Entered: disable_lcdc, fb_enabled = %d\n", fb_enabled); 445*14f88c43SAnatolij Gustschin if (fb_enabled) { 446*14f88c43SAnatolij Gustschin out_be32(&hw->diu_mode, 0); 447*14f88c43SAnatolij Gustschin fb_enabled = 0; 448*14f88c43SAnatolij Gustschin } 449*14f88c43SAnatolij Gustschin } 450*14f88c43SAnatolij Gustschin 451*14f88c43SAnatolij Gustschin /* 452*14f88c43SAnatolij Gustschin * Align to 64-bit(8-byte), 32-byte, etc. 453*14f88c43SAnatolij Gustschin */ 454*14f88c43SAnatolij Gustschin static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align) 455*14f88c43SAnatolij Gustschin { 456*14f88c43SAnatolij Gustschin u32 offset, ssize; 457*14f88c43SAnatolij Gustschin u32 mask; 458*14f88c43SAnatolij Gustschin 459*14f88c43SAnatolij Gustschin debug("Entered: allocate_buf\n"); 460*14f88c43SAnatolij Gustschin ssize = size + bytes_align; 461*14f88c43SAnatolij Gustschin buf->paddr = malloc(ssize); 462*14f88c43SAnatolij Gustschin if (!buf->paddr) 463*14f88c43SAnatolij Gustschin return -1; 464*14f88c43SAnatolij Gustschin 465*14f88c43SAnatolij Gustschin memset(buf->paddr, 0, ssize); 466*14f88c43SAnatolij Gustschin mask = bytes_align - 1; 467*14f88c43SAnatolij Gustschin offset = (u32)buf->paddr & mask; 468*14f88c43SAnatolij Gustschin if (offset) { 469*14f88c43SAnatolij Gustschin buf->offset = bytes_align - offset; 470*14f88c43SAnatolij Gustschin buf->paddr = (unsigned char *) ((u32)buf->paddr + offset); 471*14f88c43SAnatolij Gustschin } else 472*14f88c43SAnatolij Gustschin buf->offset = 0; 473*14f88c43SAnatolij Gustschin return 0; 474*14f88c43SAnatolij Gustschin } 475*14f88c43SAnatolij Gustschin 476*14f88c43SAnatolij Gustschin #if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) 477*14f88c43SAnatolij Gustschin #include <stdio_dev.h> 478*14f88c43SAnatolij Gustschin #include <video_fb.h> 479*14f88c43SAnatolij Gustschin /* 480*14f88c43SAnatolij Gustschin * The Graphic Device 481*14f88c43SAnatolij Gustschin */ 482*14f88c43SAnatolij Gustschin static GraphicDevice ctfb; 483*14f88c43SAnatolij Gustschin 484*14f88c43SAnatolij Gustschin void *video_hw_init(void) 485*14f88c43SAnatolij Gustschin { 486*14f88c43SAnatolij Gustschin struct fb_info *info; 487*14f88c43SAnatolij Gustschin 488*14f88c43SAnatolij Gustschin if (platform_diu_init(&ctfb.winSizeX, &ctfb.winSizeY) < 0) 489*14f88c43SAnatolij Gustschin return NULL; 490*14f88c43SAnatolij Gustschin 491*14f88c43SAnatolij Gustschin /* fill in Graphic device struct */ 492*14f88c43SAnatolij Gustschin sprintf(ctfb.modeIdent, "%ix%ix%i %ikHz %iHz", 493*14f88c43SAnatolij Gustschin ctfb.winSizeX, ctfb.winSizeY, 32, 64, 60); 494*14f88c43SAnatolij Gustschin 495*14f88c43SAnatolij Gustschin ctfb.frameAdrs = (unsigned int)fsl_fb_open(&info); 496*14f88c43SAnatolij Gustschin ctfb.plnSizeX = ctfb.winSizeX; 497*14f88c43SAnatolij Gustschin ctfb.plnSizeY = ctfb.winSizeY; 498*14f88c43SAnatolij Gustschin 499*14f88c43SAnatolij Gustschin ctfb.gdfBytesPP = 4; 500*14f88c43SAnatolij Gustschin ctfb.gdfIndex = GDF_32BIT_X888RGB; 501*14f88c43SAnatolij Gustschin 502*14f88c43SAnatolij Gustschin ctfb.isaBase = 0; 503*14f88c43SAnatolij Gustschin ctfb.pciBase = 0; 504*14f88c43SAnatolij Gustschin ctfb.memSize = info->screen_size; 505*14f88c43SAnatolij Gustschin 506*14f88c43SAnatolij Gustschin /* Cursor Start Address */ 507*14f88c43SAnatolij Gustschin ctfb.dprBase = 0; 508*14f88c43SAnatolij Gustschin ctfb.vprBase = 0; 509*14f88c43SAnatolij Gustschin ctfb.cprBase = 0; 510*14f88c43SAnatolij Gustschin 511*14f88c43SAnatolij Gustschin return &ctfb; 512*14f88c43SAnatolij Gustschin } 513*14f88c43SAnatolij Gustschin #endif /* defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) */ 514