]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/video/mxc_epdc_fb.c
applied patches from Freescale and Ka-Ro
[karo-tx-uboot.git] / drivers / video / mxc_epdc_fb.c
1 /*
2  * Copyright (C) 2010 Freescale Semiconductor, Inc.
3  *
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.
8  *
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.
13  *
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
17  *
18  */
19 /*
20  * Based on STMP378X LCDIF
21  * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
22  */
23
24 #include <common.h>
25 #include <lcd.h>
26 #include <linux/list.h>
27 #include <linux/err.h>
28 #include <linux/types.h>
29 #include <asm/arch/mx50.h>
30
31 #include "mxc_epdc_fb.h"
32
33
34 extern int setup_waveform_file();
35 extern void epdc_power_on();
36 extern void epdc_power_off();
37
38 DECLARE_GLOBAL_DATA_PTR;
39
40 void *lcd_base;                 /* Start of framebuffer memory  */
41 void *lcd_console_address;      /* Start of console buffer      */
42
43 int lcd_line_length;
44 int lcd_color_fg;
45 int lcd_color_bg;
46
47 short console_col;
48 short console_row;
49
50 void lcd_initcolregs(void)
51 {
52 }
53
54 void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
55 {
56 }
57
58 #define TEMP_USE_DEFAULT 8
59
60 #define UPDATE_MODE_PARTIAL                     0x0
61 #define UPDATE_MODE_FULL                        0x1
62
63 #define TRUE 1
64 #define FALSE 0
65
66 #define msleep(a)       udelay(a * 1000)
67
68
69 /********************************************************
70  * Start Low-Level EPDC Functions
71  ********************************************************/
72
73 static inline void epdc_set_screen_res(u32 width, u32 height)
74 {
75         u32 val = (height << EPDC_RES_VERTICAL_OFFSET) | width;
76
77         REG_WR(EPDC_BASE, EPDC_RES, val);
78 }
79
80 static inline void epdc_set_update_coord(u32 x, u32 y)
81 {
82         u32 val = (y << EPDC_UPD_CORD_YCORD_OFFSET) | x;
83
84         REG_WR(EPDC_BASE, EPDC_UPD_CORD, val);
85 }
86
87 static inline void epdc_set_update_dimensions(u32 width, u32 height)
88 {
89         u32 val = (height << EPDC_UPD_SIZE_HEIGHT_OFFSET) | width;
90
91         REG_WR(EPDC_BASE, EPDC_UPD_SIZE, val);
92 }
93
94 static void epdc_submit_update(u32 lut_num, u32 waveform_mode, u32 update_mode,
95                                int use_test_mode, u32 np_val)
96 {
97         u32 reg_val = 0;
98
99         if (use_test_mode) {
100                 reg_val |=
101                         ((np_val << EPDC_UPD_FIXED_FIXNP_OFFSET) &
102                         EPDC_UPD_FIXED_FIXNP_MASK) | EPDC_UPD_FIXED_FIXNP_EN;
103
104                 REG_WR(EPDC_BASE, EPDC_UPD_FIXED, reg_val);
105
106                 reg_val = EPDC_UPD_CTRL_USE_FIXED;
107         } else {
108                 REG_WR(EPDC_BASE, EPDC_UPD_FIXED, reg_val);
109         }
110
111         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) |
116                 update_mode;
117
118         REG_WR(EPDC_BASE, EPDC_UPD_CTRL, reg_val);
119 }
120
121 static inline int epdc_is_lut_active(u32 lut_num)
122 {
123         u32 val = REG_RD(EPDC_BASE, EPDC_STATUS_LUTS);
124         int is_active = val & (1 << lut_num) ? TRUE : FALSE;
125
126         return is_active;
127 }
128
129 static void epdc_set_horizontal_timing(u32 horiz_start, u32 horiz_end,
130                                        u32 hsync_width, u32 hsync_line_length)
131 {
132         u32 reg_val =
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);
138
139         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);
145 }
146
147 static void epdc_set_vertical_timing(u32 vert_start, u32 vert_end,
148                                         u32 vsync_width)
149 {
150         u32 reg_val =
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);
158 }
159
160 static void epdc_init_settings(void)
161 {
162         u32 reg_val;
163
164         /* EPDC_CTRL */
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);
171
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);
178
179         /* EPDC_FIFOCTRL (disabled) */
180         reg_val =
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);
188
189         /* EPDC_TEMP - Use default temperature */
190         REG_WR(EPDC_BASE, EPDC_TEMP, TEMP_USE_DEFAULT);
191
192         /* EPDC_RES */
193         epdc_set_screen_res(panel_info.vl_col, panel_info.vl_row);
194
195         /*
196          * EPDC_TCE_CTRL
197          * VSCAN_HOLDOFF = 4
198          * VCOM_MODE = MANUAL
199          * VCOM_VAL = 0
200          * DDR_MODE = DISABLED
201          * LVDS_MODE_CE = DISABLED
202          * LVDS_MODE = DISABLED
203          * DUAL_SCAN = DISABLED
204          * SDDO_WIDTH = 8bit
205          * PIXELS_PER_SDCLK = 4
206          */
207         reg_val =
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);
212
213         /* EPDC_TCE_HSCAN */
214         epdc_set_horizontal_timing(panel_info.vl_left_margin,
215                                 panel_info.vl_right_margin,
216                                 panel_info.vl_hsync,
217                                 panel_info.vl_hsync);
218
219         /* EPDC_TCE_VSCAN */
220         epdc_set_vertical_timing(panel_info.vl_upper_margin,
221                                  panel_info.vl_lower_margin,
222                                  panel_info.vl_vsync);
223
224         /* EPDC_TCE_OE */
225         reg_val =
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);
235
236         /* EPDC_TCE_TIMING1 */
237         REG_WR(EPDC_BASE, EPDC_TCE_TIMING1, 0x0);
238
239         /* EPDC_TCE_TIMING2 */
240         reg_val =
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);
246
247         /* EPDC_TCE_TIMING3 */
248         reg_val =
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);
254
255         /*
256          * EPDC_TCE_SDCFG
257          * SDCLK_HOLD = 1
258          * SDSHR = 1
259          * NUM_CE = 1
260          * SDDO_REFORMAT = FLIP_PIXELS
261          * SDDO_INVERT = DISABLED
262          * PIXELS_PER_CE = display horizontal resolution
263          */
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);
270
271         /*
272          * EPDC_TCE_GDCFG
273          * GDRL = 1
274          * GDOE_MODE = 0;
275          * GDSP_MODE = 0;
276          */
277         reg_val = EPDC_TCE_SDCFG_GDRL;
278         REG_WR(EPDC_BASE, EPDC_TCE_GDCFG, reg_val);
279
280         /*
281          * EPDC_TCE_POLARITY
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
287          */
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);
292
293         /* EPDC_IRQ_MASK */
294         REG_WR(EPDC_BASE, EPDC_IRQ_MASK,
295                 EPDC_IRQ_TCE_UNDERRUN_IRQ);
296
297         /*
298          * EPDC_GPIO
299          * PWRCOM = ?
300          * PWRCTRL = ?
301          * BDR = ?
302          */
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);
306 }
307
308 static void draw_mode0(void)
309 {
310         int i;
311
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);
317
318         debug("Mode0 update - Waiting for LUT to complete...\n");
319
320         /* Will timeout after ~4-5 seconds */
321
322         for (i = 0; i < 40; i++) {
323                 if (!epdc_is_lut_active(0)) {
324                         debug("Mode0 init complete\n");
325                         return;
326                 }
327                 msleep(100);
328         }
329
330         debug("Mode0 init failed!\n");
331
332 }
333
334 static void draw_splash_screen(void)
335 {
336         int i;
337         int lut_num = 0;
338
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);
344
345         for (i = 0; i < 40; i++) {
346                 if (!epdc_is_lut_active(lut_num)) {
347                         debug("Splash screen update complete\n");
348                         return;
349                 }
350                 msleep(100);
351         }
352         debug("Splash screen update failed!\n");
353
354 }
355
356 void lcd_enable(void)
357 {
358         int i;
359
360         epdc_power_on();
361
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);
369         }
370         memset((u8 *)lcd_base + panel_info.vl_col * (panel_info.vl_row - 24),
371                 0x00, 24 * panel_info.vl_col);
372
373         /* Draw data to display */
374         draw_mode0();
375
376         draw_splash_screen();
377 }
378
379 void lcd_disable(void)
380 {
381         debug("lcd_disable\n");
382
383         /* Disable clocks to EPDC */
384         REG_SET(EPDC_BASE, EPDC_CTRL, EPDC_CTRL_CLKGATE);
385 }
386
387 void lcd_panel_disable(void)
388 {
389         epdc_power_off();
390 }
391
392 void lcd_ctrl_init(void *lcdbase)
393 {
394         /*
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.
397          */
398         if (!lcdbase)
399                 return;
400
401         lcd_color_fg = 0xFF;
402         lcd_color_bg = 0xFF;
403
404         /* Reset */
405         REG_SET(EPDC_BASE, EPDC_CTRL, EPDC_CTRL_SFTRST);
406         while (!(REG_RD(EPDC_BASE, EPDC_CTRL) & EPDC_CTRL_CLKGATE))
407                 ;
408         REG_CLR(EPDC_BASE, EPDC_CTRL, EPDC_CTRL_SFTRST);
409
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))
414                 ;
415
416         debug("resolution %dx%d, bpp %d\n", (int)panel_info.vl_col,
417                 (int)panel_info.vl_row, NBITS(panel_info.vl_bpix));
418
419         /* Set framebuffer pointer */
420         REG_WR(EPDC_BASE, EPDC_UPD_ADDR, (u32)lcdbase);
421
422         /* Set Working Buffer pointer */
423         REG_WR(EPDC_BASE, EPDC_WB_ADDR, panel_info.epdc_data.working_buf_addr);
424
425         /* Get waveform data address and offset */
426         if (setup_waveform_file()) {
427                 printf("Can't load waveform data!\n");
428                 return;
429         }
430
431         /* Set Waveform Buffer pointer */
432         REG_WR(EPDC_BASE, EPDC_WVADDR,
433                 panel_info.epdc_data.waveform_buf_addr);
434
435         /* Initialize EPDC, passing pointer to EPDC registers */
436         epdc_init_settings();
437
438         return;
439 }
440
441 ulong calc_fbsize(void)
442 {
443         return panel_info.vl_row * panel_info.vl_col * 2 \
444                 * NBITS(panel_info.vl_bpix) / 8;
445 }
446