1 /* 2 * Ben NanoNote LCD initialisation, based on uboot-xburst and xburst-tools. 3 * 4 * Copyright (C) 2001-2002 Wolfgang Denk, DENX Software Engineering, <wd@denx.de> 5 * Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk> 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "board-display.h" 22 23 #include "xburst_types.h" 24 #include "jzlcd.h" 25 #include "sdram.h" 26 #include "board.h" 27 28 extern vidinfo_t panel_info; 29 static unsigned long lcd_base; 30 31 static unsigned int get_line_length() 32 { 33 return ALIGN((panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8, sizeof(u32)); 34 } 35 36 static u32 *get_pixel32(unsigned short h, unsigned short v) 37 { 38 return (u32 *) (lcd_base + v * get_line_length()) + h; 39 } 40 41 static u16 *get_pixel16(unsigned short h, unsigned short v) 42 { 43 return (u16 *) (lcd_base + v * get_line_length()) + h; 44 } 45 46 static u8 *get_pixel8(unsigned short h, unsigned short v) 47 { 48 return (u8 *) (lcd_base + v * get_line_length()) + h; 49 } 50 51 static u8 *get_pixel4(unsigned short h, unsigned short v) 52 { 53 return (u8 *) (lcd_base + v * get_line_length()) + h / 2; 54 } 55 56 static inline unsigned short div(unsigned short num, unsigned short denom, unsigned short scale) 57 { 58 return (scale * num) / denom; 59 } 60 61 static unsigned long pixel(u8 r, u8 g, u8 b, u8 rmax, u8 gmax, u8 bmax, u8 rshift, u8 gshift, u8 bshift) 62 { 63 return (div(r, 255, rmax) << rshift) | (div(g, 255, gmax) << gshift) | (div(b, 255, bmax) << bshift); 64 } 65 66 static void get_colour(unsigned short h, unsigned short v, u8 rgb[], unsigned short pixel_type) 67 { 68 unsigned short v_max = panel_info.vl_row; 69 unsigned short h_max = panel_info.vl_col; 70 71 rgb[(pixel_type - 1) % 3] = div(h, h_max, 255); 72 rgb[pixel_type % 3] = div(v, v_max, 255); 73 rgb[(pixel_type + 1) % 3] = (rgb[0] + rgb[1]) / 2; 74 } 75 76 static void test_pixel32(unsigned short h, unsigned short v, unsigned short pixel_type) 77 { 78 u32 *pix = get_pixel32(h, v); 79 u8 rgb[3]; 80 81 get_colour(h, v, rgb, pixel_type); 82 *pix = (u32) pixel(rgb[0], rgb[1], rgb[2], 255, 255, 255, 16, 8, 0); 83 } 84 85 static void test_pixel16_565(unsigned short h, unsigned short v, unsigned short pixel_type) 86 { 87 u16 *pix = get_pixel16(h, v); 88 u8 rgb[3]; 89 90 get_colour(h, v, rgb, pixel_type); 91 *pix = (u16) pixel(rgb[0], rgb[1], rgb[2], 31, 63, 31, 11, 5, 0); 92 } 93 94 static void test_pixel8(unsigned short h, unsigned short v, unsigned short pixel_type) 95 { 96 u8 *pix = get_pixel8(h, v); 97 u8 rgb[3]; 98 99 get_colour(h, v, rgb, pixel_type); 100 *pix = (u8) pixel(rgb[0], rgb[1], rgb[2], 7, 7, 3, 5, 2, 0); 101 } 102 103 static void test_pixel4(unsigned short h, unsigned short v, unsigned short pixel_type) 104 { 105 u8 *pix = get_pixel4(h, v); 106 u8 mask = h & 1 ? 0xf0 : 0x0f; 107 u8 rgb[3]; 108 109 get_colour(h, v, rgb, pixel_type); 110 *pix = (*pix & mask) | ((u8) pixel(rgb[0], rgb[1], rgb[2], 1, 2, 1, 3, 1, 0) << (h & 1 ? 0 : 4)); 111 } 112 113 void test_pixel(unsigned short h, unsigned short v, unsigned short pixel_type) 114 { 115 switch (panel_info.vl_bpix) 116 { 117 case LCD_COLOR32: 118 test_pixel32(h, v, pixel_type); 119 break; 120 121 case LCD_COLOR8: 122 test_pixel8(h, v, pixel_type); 123 break; 124 125 case LCD_COLOR4: 126 test_pixel4(h, v, pixel_type); 127 break; 128 129 case LCD_COLOR16: 130 default: 131 test_pixel16_565(h, v, pixel_type); 132 break; 133 } 134 } 135 136 void clear_pixel32(unsigned short h, unsigned short v) 137 { 138 u32 *pix = get_pixel32(h, v); 139 *pix = 0; 140 } 141 142 void clear_pixel16(unsigned short h, unsigned short v) 143 { 144 u16 *pix = get_pixel16(h, v); 145 *pix = 0; 146 } 147 148 void clear_pixel8(unsigned short h, unsigned short v) 149 { 150 u8 *pix = get_pixel8(h, v); 151 *pix = 0; 152 } 153 154 void clear_pixel4(unsigned short h, unsigned short v) 155 { 156 u8 *pix = get_pixel4(h, v); 157 u8 mask = h & 1 ? 0xf0 : 0x0f; 158 *pix = *pix & mask; 159 } 160 161 void clear_pixel(unsigned short h, unsigned short v) 162 { 163 switch (panel_info.vl_bpix) 164 { 165 case LCD_COLOR32: 166 clear_pixel32(h, v); 167 break; 168 169 case LCD_COLOR8: 170 clear_pixel8(h, v); 171 break; 172 173 case LCD_COLOR4: 174 clear_pixel4(h, v); 175 break; 176 177 case LCD_COLOR16: 178 default: 179 clear_pixel16(h, v); 180 break; 181 } 182 } 183 184 void test_pattern() 185 { 186 unsigned short v_max = panel_info.vl_row; 187 unsigned short h_max = panel_info.vl_col; 188 unsigned short v, h; 189 190 for (v = 0; v < v_max; v += 1) { 191 for (h = 0; h < h_max; h += 1) { 192 test_pixel(h, v, 1); 193 } 194 } 195 } 196 197 void lcd_clear(unsigned long lcd_base) 198 { 199 unsigned short v_max = panel_info.vl_row; 200 unsigned short h_max = panel_info.vl_col; 201 unsigned short v, h; 202 unsigned long *pix = (unsigned long *)lcd_base; 203 204 for (v = 0; v < v_max; v += 1) { 205 for (h = 0; h < h_max; h += 1) { 206 *pix++ = 0; 207 } 208 } 209 } 210 211 /* LCD initialisation. */ 212 213 void lcd_init(void) 214 { 215 __lcd_display_pin_init(); 216 __lcd_display_on(); 217 218 lcd_base = lcd_ctrl_init(); 219 lcd_clear(lcd_base); 220 lcd_enable(); 221 }