2 * Copyright (C) 2010 Freescale Semiconductor, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Based on STMP378X LCDIF
21 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
26 #include <linux/list.h>
27 #include <linux/err.h>
28 #include <linux/types.h>
29 #include <asm/arch/mx50.h>
31 #include "mxc_epdc_fb.h"
34 extern int setup_waveform_file();
35 extern void epdc_power_on();
36 extern void epdc_power_off();
38 DECLARE_GLOBAL_DATA_PTR;
40 void *lcd_base; /* Start of framebuffer memory */
41 void *lcd_console_address; /* Start of console buffer */
50 void lcd_initcolregs(void)
54 void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
58 #define TEMP_USE_DEFAULT 8
60 #define UPDATE_MODE_PARTIAL 0x0
61 #define UPDATE_MODE_FULL 0x1
66 #define msleep(a) udelay(a * 1000)
69 /********************************************************
70 * Start Low-Level EPDC Functions
71 ********************************************************/
73 static inline void epdc_set_screen_res(u32 width, u32 height)
75 u32 val = (height << EPDC_RES_VERTICAL_OFFSET) | width;
77 REG_WR(EPDC_BASE, EPDC_RES, val);
80 static inline void epdc_set_update_coord(u32 x, u32 y)
82 u32 val = (y << EPDC_UPD_CORD_YCORD_OFFSET) | x;
84 REG_WR(EPDC_BASE, EPDC_UPD_CORD, val);
87 static inline void epdc_set_update_dimensions(u32 width, u32 height)
89 u32 val = (height << EPDC_UPD_SIZE_HEIGHT_OFFSET) | width;
91 REG_WR(EPDC_BASE, EPDC_UPD_SIZE, val);
94 static void epdc_submit_update(u32 lut_num, u32 waveform_mode, u32 update_mode,
95 int use_test_mode, u32 np_val)
101 ((np_val << EPDC_UPD_FIXED_FIXNP_OFFSET) &
102 EPDC_UPD_FIXED_FIXNP_MASK) | EPDC_UPD_FIXED_FIXNP_EN;
104 REG_WR(EPDC_BASE, EPDC_UPD_FIXED, reg_val);
106 reg_val = EPDC_UPD_CTRL_USE_FIXED;
108 REG_WR(EPDC_BASE, EPDC_UPD_FIXED, reg_val);
112 ((lut_num << EPDC_UPD_CTRL_LUT_SEL_OFFSET) &
113 EPDC_UPD_CTRL_LUT_SEL_MASK) |
114 ((waveform_mode << EPDC_UPD_CTRL_WAVEFORM_MODE_OFFSET) &
115 EPDC_UPD_CTRL_WAVEFORM_MODE_MASK) |
118 REG_WR(EPDC_BASE, EPDC_UPD_CTRL, reg_val);
121 static inline int epdc_is_lut_active(u32 lut_num)
123 u32 val = REG_RD(EPDC_BASE, EPDC_STATUS_LUTS);
124 int is_active = val & (1 << lut_num) ? TRUE : FALSE;
129 static void epdc_set_horizontal_timing(u32 horiz_start, u32 horiz_end,
130 u32 hsync_width, u32 hsync_line_length)
133 ((hsync_width << EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_OFFSET) &
134 EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_MASK)
135 | ((hsync_line_length << EPDC_TCE_HSCAN1_LINE_SYNC_OFFSET) &
136 EPDC_TCE_HSCAN1_LINE_SYNC_MASK);
137 REG_WR(EPDC_BASE, EPDC_TCE_HSCAN1, reg_val);
140 ((horiz_start << EPDC_TCE_HSCAN2_LINE_BEGIN_OFFSET) &
141 EPDC_TCE_HSCAN2_LINE_BEGIN_MASK)
142 | ((horiz_end << EPDC_TCE_HSCAN2_LINE_END_OFFSET) &
143 EPDC_TCE_HSCAN2_LINE_END_MASK);
144 REG_WR(EPDC_BASE, EPDC_TCE_HSCAN2, reg_val);
147 static void epdc_set_vertical_timing(u32 vert_start, u32 vert_end,
151 ((vert_start << EPDC_TCE_VSCAN_FRAME_BEGIN_OFFSET) &
152 EPDC_TCE_VSCAN_FRAME_BEGIN_MASK)
153 | ((vert_end << EPDC_TCE_VSCAN_FRAME_END_OFFSET) &
154 EPDC_TCE_VSCAN_FRAME_END_MASK)
155 | ((vsync_width << EPDC_TCE_VSCAN_FRAME_SYNC_OFFSET) &
156 EPDC_TCE_VSCAN_FRAME_SYNC_MASK);
157 REG_WR(EPDC_BASE, EPDC_TCE_VSCAN, reg_val);
160 static void epdc_init_settings(void)
165 reg_val = REG_RD(EPDC_BASE, EPDC_CTRL);
166 reg_val &= ~EPDC_CTRL_UPD_DATA_SWIZZLE_MASK;
167 reg_val |= EPDC_CTRL_UPD_DATA_SWIZZLE_NO_SWAP;
168 reg_val &= ~EPDC_CTRL_LUT_DATA_SWIZZLE_MASK;
169 reg_val |= EPDC_CTRL_LUT_DATA_SWIZZLE_NO_SWAP;
170 REG_SET(EPDC_BASE, EPDC_CTRL, reg_val);
172 /* EPDC_FORMAT - 2bit TFT and 4bit Buf pixel format */
173 reg_val = EPDC_FORMAT_TFT_PIXEL_FORMAT_2BIT
174 | EPDC_FORMAT_BUF_PIXEL_FORMAT_P4N
175 | ((0x0 << EPDC_FORMAT_DEFAULT_TFT_PIXEL_OFFSET) &
176 EPDC_FORMAT_DEFAULT_TFT_PIXEL_MASK);
177 REG_WR(EPDC_BASE, EPDC_FORMAT, reg_val);
179 /* EPDC_FIFOCTRL (disabled) */
181 ((100 << EPDC_FIFOCTRL_FIFO_INIT_LEVEL_OFFSET) &
182 EPDC_FIFOCTRL_FIFO_INIT_LEVEL_MASK)
183 | ((200 << EPDC_FIFOCTRL_FIFO_H_LEVEL_OFFSET) &
184 EPDC_FIFOCTRL_FIFO_H_LEVEL_MASK)
185 | ((100 << EPDC_FIFOCTRL_FIFO_L_LEVEL_OFFSET) &
186 EPDC_FIFOCTRL_FIFO_L_LEVEL_MASK);
187 REG_WR(EPDC_BASE, EPDC_FIFOCTRL, reg_val);
189 /* EPDC_TEMP - Use default temperature */
190 REG_WR(EPDC_BASE, EPDC_TEMP, TEMP_USE_DEFAULT);
193 epdc_set_screen_res(panel_info.vl_col, panel_info.vl_row);
200 * DDR_MODE = DISABLED
201 * LVDS_MODE_CE = DISABLED
202 * LVDS_MODE = DISABLED
203 * DUAL_SCAN = DISABLED
205 * PIXELS_PER_SDCLK = 4
208 ((4 << EPDC_TCE_CTRL_VSCAN_HOLDOFF_OFFSET) &
209 EPDC_TCE_CTRL_VSCAN_HOLDOFF_MASK)
210 | EPDC_TCE_CTRL_PIXELS_PER_SDCLK_4;
211 REG_WR(EPDC_BASE, EPDC_TCE_CTRL, reg_val);
214 epdc_set_horizontal_timing(panel_info.vl_left_margin,
215 panel_info.vl_right_margin,
217 panel_info.vl_hsync);
220 epdc_set_vertical_timing(panel_info.vl_upper_margin,
221 panel_info.vl_lower_margin,
222 panel_info.vl_vsync);
226 ((10 << EPDC_TCE_OE_SDOED_WIDTH_OFFSET) &
227 EPDC_TCE_OE_SDOED_WIDTH_MASK)
228 | ((20 << EPDC_TCE_OE_SDOED_DLY_OFFSET) &
229 EPDC_TCE_OE_SDOED_DLY_MASK)
230 | ((10 << EPDC_TCE_OE_SDOEZ_WIDTH_OFFSET) &
231 EPDC_TCE_OE_SDOEZ_WIDTH_MASK)
232 | ((20 << EPDC_TCE_OE_SDOEZ_DLY_OFFSET) &
233 EPDC_TCE_OE_SDOEZ_DLY_MASK);
234 REG_WR(EPDC_BASE, EPDC_TCE_OE, reg_val);
236 /* EPDC_TCE_TIMING1 */
237 REG_WR(EPDC_BASE, EPDC_TCE_TIMING1, 0x0);
239 /* EPDC_TCE_TIMING2 */
241 ((480 << EPDC_TCE_TIMING2_GDCLK_HP_OFFSET) &
242 EPDC_TCE_TIMING2_GDCLK_HP_MASK)
243 | ((20 << EPDC_TCE_TIMING2_GDSP_OFFSET_OFFSET) &
244 EPDC_TCE_TIMING2_GDSP_OFFSET_MASK);
245 REG_WR(EPDC_BASE, EPDC_TCE_TIMING2, reg_val);
247 /* EPDC_TCE_TIMING3 */
249 ((0 << EPDC_TCE_TIMING3_GDOE_OFFSET_OFFSET) &
250 EPDC_TCE_TIMING3_GDOE_OFFSET_MASK)
251 | ((1 << EPDC_TCE_TIMING3_GDCLK_OFFSET_OFFSET) &
252 EPDC_TCE_TIMING3_GDCLK_OFFSET_MASK);
253 REG_WR(EPDC_BASE, EPDC_TCE_TIMING3, reg_val);
260 * SDDO_REFORMAT = FLIP_PIXELS
261 * SDDO_INVERT = DISABLED
262 * PIXELS_PER_CE = display horizontal resolution
264 reg_val = EPDC_TCE_SDCFG_SDCLK_HOLD | EPDC_TCE_SDCFG_SDSHR
265 | ((1 << EPDC_TCE_SDCFG_NUM_CE_OFFSET) & EPDC_TCE_SDCFG_NUM_CE_MASK)
266 | EPDC_TCE_SDCFG_SDDO_REFORMAT_FLIP_PIXELS
267 | ((panel_info.vl_col << EPDC_TCE_SDCFG_PIXELS_PER_CE_OFFSET) &
268 EPDC_TCE_SDCFG_PIXELS_PER_CE_MASK);
269 REG_WR(EPDC_BASE, EPDC_TCE_SDCFG, reg_val);
277 reg_val = EPDC_TCE_SDCFG_GDRL;
278 REG_WR(EPDC_BASE, EPDC_TCE_GDCFG, reg_val);
282 * SDCE_POL = ACTIVE LOW
283 * SDLE_POL = ACTIVE HIGH
284 * SDOE_POL = ACTIVE HIGH
285 * GDOE_POL = ACTIVE HIGH
286 * GDSP_POL = ACTIVE LOW
288 reg_val = EPDC_TCE_POLARITY_SDLE_POL_ACTIVE_HIGH
289 | EPDC_TCE_POLARITY_SDOE_POL_ACTIVE_HIGH
290 | EPDC_TCE_POLARITY_GDOE_POL_ACTIVE_HIGH;
291 REG_WR(EPDC_BASE, EPDC_TCE_POLARITY, reg_val);
294 REG_WR(EPDC_BASE, EPDC_IRQ_MASK,
295 EPDC_IRQ_TCE_UNDERRUN_IRQ);
303 reg_val = ((0 << EPDC_GPIO_PWRCTRL_OFFSET) & EPDC_GPIO_PWRCTRL_MASK)
304 | ((0 << EPDC_GPIO_BDR_OFFSET) & EPDC_GPIO_BDR_MASK);
305 REG_WR(EPDC_BASE, EPDC_GPIO, reg_val);
308 static void draw_mode0(void)
312 /* Program EPDC update to process buffer */
313 epdc_set_update_coord(0, 0);
314 epdc_set_update_dimensions(panel_info.vl_col, panel_info.vl_row);
315 epdc_submit_update(0, panel_info.epdc_data.wv_modes.mode_init,
316 UPDATE_MODE_FULL, FALSE, 0);
318 debug("Mode0 update - Waiting for LUT to complete...\n");
320 /* Will timeout after ~4-5 seconds */
322 for (i = 0; i < 40; i++) {
323 if (!epdc_is_lut_active(0)) {
324 debug("Mode0 init complete\n");
330 debug("Mode0 init failed!\n");
334 static void draw_splash_screen(void)
339 /* Program EPDC update to process buffer */
340 epdc_set_update_coord(0, 0);
341 epdc_set_update_dimensions(panel_info.vl_col, panel_info.vl_row);
342 epdc_submit_update(lut_num, panel_info.epdc_data.wv_modes.mode_gc16,
343 UPDATE_MODE_FULL, FALSE, 0);
345 for (i = 0; i < 40; i++) {
346 if (!epdc_is_lut_active(lut_num)) {
347 debug("Splash screen update complete\n");
352 debug("Splash screen update failed!\n");
356 void lcd_enable(void)
362 /* Draw black border around framebuffer*/
363 memset(lcd_base, 0xFF, panel_info.vl_col * panel_info.vl_row);
364 memset(lcd_base, 0x0, 24 * panel_info.vl_col);
365 for (i = 24; i < (panel_info.vl_row - 24); i++) {
366 memset((u8 *)lcd_base + i * panel_info.vl_col, 0x00, 24);
367 memset((u8 *)lcd_base + i * panel_info.vl_col
368 + panel_info.vl_col - 24, 0x00, 24);
370 memset((u8 *)lcd_base + panel_info.vl_col * (panel_info.vl_row - 24),
371 0x00, 24 * panel_info.vl_col);
373 /* Draw data to display */
376 draw_splash_screen();
379 void lcd_disable(void)
381 debug("lcd_disable\n");
383 /* Disable clocks to EPDC */
384 REG_SET(EPDC_BASE, EPDC_CTRL, EPDC_CTRL_CLKGATE);
387 void lcd_panel_disable(void)
392 void lcd_ctrl_init(void *lcdbase)
395 * We rely on lcdbase being a physical address, i.e., either MMU off,
396 * or 1-to-1 mapping. Might want to add some virt2phys here.
405 REG_SET(EPDC_BASE, EPDC_CTRL, EPDC_CTRL_SFTRST);
406 while (!(REG_RD(EPDC_BASE, EPDC_CTRL) & EPDC_CTRL_CLKGATE))
408 REG_CLR(EPDC_BASE, EPDC_CTRL, EPDC_CTRL_SFTRST);
410 /* Enable clock gating (clear to enable) */
411 REG_CLR(EPDC_BASE, EPDC_CTRL, EPDC_CTRL_CLKGATE);
412 while (REG_RD(EPDC_BASE, EPDC_CTRL) &
413 (EPDC_CTRL_SFTRST | EPDC_CTRL_CLKGATE))
416 debug("resolution %dx%d, bpp %d\n", (int)panel_info.vl_col,
417 (int)panel_info.vl_row, NBITS(panel_info.vl_bpix));
419 /* Set framebuffer pointer */
420 REG_WR(EPDC_BASE, EPDC_UPD_ADDR, (u32)lcdbase);
422 /* Set Working Buffer pointer */
423 REG_WR(EPDC_BASE, EPDC_WB_ADDR, panel_info.epdc_data.working_buf_addr);
425 /* Get waveform data address and offset */
426 if (setup_waveform_file()) {
427 printf("Can't load waveform data!\n");
431 /* Set Waveform Buffer pointer */
432 REG_WR(EPDC_BASE, EPDC_WVADDR,
433 panel_info.epdc_data.waveform_buf_addr);
435 /* Initialize EPDC, passing pointer to EPDC registers */
436 epdc_init_settings();
441 ulong calc_fbsize(void)
443 return panel_info.vl_row * panel_info.vl_col * 2 \
444 * NBITS(panel_info.vl_bpix) / 8;