lcd drivers: Convert lcd_[remote_]framebuffer to a pointer
[maemo-rb.git] / firmware / target / coldfire / mpio / hd200 / lcd-hd200.c
blob3c009597459eea0efaf8664ff2f0772e799ddbda
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2010 Marcin Bukat
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "config.h"
24 #include "system.h"
25 #include "kernel.h"
26 #include "lcd.h"
28 /*** definitions ***/
29 /* TOMATO LSI 0350 - definitions and slightly tweaked functions
30 * taken from lcd-remote-iaudio.c
33 #define LCD_SET_DUTY_RATIO 0x48
34 #define LCD_SELECT_ADC 0xa0
35 #define LCD_SELECT_SHL 0xc0
36 #define LCD_SET_COM0 0x44
37 #define LCD_OSC_ON 0xab
38 #define LCD_SELECT_DCDC 0x64
39 #define LCD_SELECT_RES 0x20
40 #define LCD_SET_VOLUME 0x81
41 #define LCD_SET_BIAS 0x50
42 #define LCD_CONTROL_POWER 0x28
43 #define LCD_DISPLAY_ON 0xae
44 #define LCD_SET_INITLINE 0x40
45 #define LCD_SET_COLUMN 0x10
46 #define LCD_SET_PAGE 0xb0
47 #define LCD_SET_GRAY 0x88
48 #define LCD_SET_PWM_FRC 0x90
49 #define LCD_SET_POWER_SAVE 0xa8
50 #define LCD_REVERSE 0xa6
51 #define LCD_RESET 0xe2
53 /* cached settings */
54 static bool cached_invert = false;
55 static bool cached_flip = false;
56 static int cached_contrast = DEFAULT_CONTRAST_SETTING;
58 static struct mutex lcd_mtx; /* The update functions use DMA and yield */
60 volatile unsigned char page IBSS_ATTR;
61 unsigned char column IBSS_ATTR;
62 unsigned int dma_len IBSS_ATTR;
63 volatile unsigned long dma_count IBSS_ATTR;
65 /*** hardware configuration ***/
66 int lcd_default_contrast(void)
68 return DEFAULT_CONTRAST_SETTING;
71 void lcd_powersave(bool on)
73 if (on)
74 /* enter power saving mode
75 * this turns off lcd without controller reset
76 * probably ~1mA saving
78 lcd_write_command(LCD_SET_POWER_SAVE | 1);
79 else
80 /* leave lcd power saving mode
81 * no need to reset and initialize controller
83 lcd_write_command(LCD_SET_POWER_SAVE | 0);
86 void lcd_set_contrast(int val)
88 if (val < MIN_CONTRAST_SETTING)
89 val = MIN_CONTRAST_SETTING;
90 else if (val > MAX_CONTRAST_SETTING)
91 val = MAX_CONTRAST_SETTING;
93 cached_contrast = val;
94 lcd_write_command_e(LCD_SET_VOLUME, val);
97 void lcd_set_invert_display(bool yesno)
99 cached_invert = yesno;
100 lcd_write_command(LCD_REVERSE | yesno);
104 /* turn the display upside down (call lcd_update() afterwards) */
105 void lcd_set_flip(bool yesno)
107 cached_flip = yesno;
108 if(yesno)
110 lcd_write_command(LCD_SELECT_ADC | 1);
111 lcd_write_command(LCD_SELECT_SHL | 0);
112 lcd_write_command_e(LCD_SET_COM0, 0);
114 else
116 lcd_write_command(LCD_SELECT_ADC | 0);
117 lcd_write_command(LCD_SELECT_SHL | 8);
118 lcd_write_command_e(LCD_SET_COM0, 0);
122 void lcd_shutdown(void)
124 /* Set power save -> Power OFF (VDD - VSS) .. that's it */
125 lcd_write_command(LCD_SET_POWER_SAVE | 1);
128 void lcd_init_device(void)
130 and_l(~0x00000800, &GPIO_FUNCTION); /* CS3 line */
132 /* LCD Reset GPO34 */
133 or_l(0x00000004, &GPIO1_ENABLE); /* set as output */
134 or_l(0x00000004, &GPIO1_FUNCTION); /* switch to secondary function - GPIO */
136 and_l(~0x00000004, &GPIO1_OUT); /* RESET low */
137 sleep(1); /* delay at least 1000 ns */
138 or_l(0x00000004, &GPIO1_OUT); /* RESET high */
139 sleep(1);
141 /* parameters setup taken from original firmware */
142 lcd_write_command(LCD_RESET);
143 lcd_write_command_e(LCD_SET_DUTY_RATIO,0x80); /* 1/128 */
144 lcd_write_command(LCD_OSC_ON);
145 lcd_write_command(LCD_SELECT_DCDC | 3); /* DC/DC 6xboost */
146 lcd_write_command(LCD_SELECT_RES | 7); /* Regulator resistor: 7.2 */
147 lcd_write_command(LCD_SET_BIAS | 6); /* 1/11 */
148 lcd_write_command(LCD_SET_PWM_FRC | 6); /* 3FRC + 12PWM */
149 lcd_write_command_e(LCD_SET_GRAY | 0, 0x00);
150 lcd_write_command_e(LCD_SET_GRAY | 1, 0x00);
151 lcd_write_command_e(LCD_SET_GRAY | 2, 0x0c);
152 lcd_write_command_e(LCD_SET_GRAY | 3, 0x00);
153 lcd_write_command_e(LCD_SET_GRAY | 4, 0xc4);
154 lcd_write_command_e(LCD_SET_GRAY | 5, 0x00);
155 lcd_write_command_e(LCD_SET_GRAY | 6, 0xcc);
156 lcd_write_command_e(LCD_SET_GRAY | 7, 0x00);
158 lcd_write_command(LCD_CONTROL_POWER | 7); /* All circuits ON */
159 lcd_write_command(LCD_DISPLAY_ON | 1); /* display on */
161 lcd_set_flip(cached_flip);
162 lcd_set_contrast(cached_contrast);
163 lcd_set_invert_display(cached_invert);
165 /* Configure DMA3 */
166 DAR3 = 0xf0000002;
167 DSR3 = 1;
168 DIVR3 = 57; /* DMA3 is mapped into vector 57 in system.c */
169 ICR9 = (6 << 2); /* Enable DMA3 interrupt at level 6, priority 0 */
170 coldfire_imr_mod(0, 1 << 17);
172 mutex_init(&lcd_mtx);
174 lcd_update();
177 /* LCD DMA ISR */
178 void DMA3(void) __attribute__ ((interrupt_handler, section(".icode")));
179 void DMA3(void)
181 DSR3 = 1;
183 if (--dma_count > 0)
185 /* Setup write address in lcd controller ram*/
186 lcd_write_command(LCD_SET_PAGE | ++page);
187 lcd_write_command_e(LCD_SET_COLUMN | ((column >> 4) & 0xf),
188 column & 0x0f);
190 SAR3 = (unsigned long)FBADDR(column,page);
191 BCR3 = dma_len;
192 DCR3 = DMA_INT | DMA_AA | DMA_BWC(1)
193 | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE)
194 | DMA_DSIZE(DMA_SIZE_BYTE) | DMA_START;
199 /* Update the display.
200 This must be called after all other LCD functions that change the display. */
201 void lcd_update(void) ICODE_ATTR;
202 void lcd_update(void)
204 mutex_lock(&lcd_mtx);
206 /* Setup initial address in lcd controller */
207 lcd_write_command(LCD_SET_PAGE | 0);
208 lcd_write_command_e(LCD_SET_COLUMN, 0);
210 /* Initial lcd ram address */
211 page = 0;
212 column = 0;
214 /* Number of pages to address */
215 dma_count = LCD_FBHEIGHT;
217 /* Transfer size in bytes to the given page */
218 dma_len = LCD_WIDTH*2;
220 /* Initialize DMA transfer */
221 SAR3 = (unsigned long)lcd_framebuffer;
222 BCR3 = LCD_WIDTH*2;
223 DCR3 = DMA_INT | DMA_AA | DMA_BWC(1)
224 | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE)
225 | DMA_DSIZE(DMA_SIZE_BYTE) | DMA_START;
227 while (dma_count > 0)
228 yield();
230 mutex_unlock(&lcd_mtx);
233 /* Update a fraction of the display. */
234 void lcd_update_rect(int, int, int, int) ICODE_ATTR;
235 void lcd_update_rect(int x, int y, int width, int height)
237 int ymax;
239 /* The Y coordinates have to work on even 8 pixel rows */
240 ymax = (y + height-1) >> 3;
241 y >>= 3;
243 if (x + width > LCD_WIDTH)
244 width = LCD_WIDTH - x;
246 if (width <= 0)
247 return; /* nothing left to do, 0 is harmful to lcd_write_data() */
249 mutex_lock(&lcd_mtx);
251 if (ymax >= LCD_FBHEIGHT)
252 ymax = LCD_FBHEIGHT-1;
254 /* Initial lcd ram address*/
255 lcd_write_command(LCD_SET_PAGE | y );
256 lcd_write_command_e(LCD_SET_COLUMN | ((x >> 4) & 0xf), x & 0x0f);
258 page = y;
259 column = x;
260 dma_len = width*2;
261 dma_count = ymax - y + 1;
263 /* Initialize DMA transfer */
264 SAR3 = (unsigned long)FBADDR(column,page);
265 BCR3 = dma_len;
266 DCR3 = DMA_INT | DMA_AA | DMA_BWC(1)
267 | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE)
268 | DMA_DSIZE(DMA_SIZE_BYTE) | DMA_START;
270 while (dma_count > 0)
271 yield();
273 mutex_unlock(&lcd_mtx);
277 /* Helper function. */
278 void lcd_mono_data(const unsigned char *data, int count);
280 /* Performance function that works with an external buffer
281 note that by and bheight are in 8-pixel units! */
282 void lcd_blit_mono(const unsigned char *data, int x, int by, int width,
283 int bheight, int stride)
285 while (bheight--)
287 lcd_write_command(LCD_SET_PAGE | (by & 0xf));
288 lcd_write_command_e(LCD_SET_COLUMN | ((x >> 4) & 0xf), x & 0xf);
290 lcd_mono_data(data, width);
291 data += stride;
292 by++;
296 /* Helper function for lcd_grey_phase_blit(). */
297 void lcd_grey_data(unsigned char *values, unsigned char *phases, int count);
299 /* Performance function that works with an external buffer
300 note that by and bheight are in 8-pixel units! */
301 void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases,
302 int x, int by, int width, int bheight, int stride)
304 stride <<= 3; /* 8 pixels per block */
306 while (bheight--)
308 lcd_write_command(LCD_SET_PAGE | (by & 0xf));
309 lcd_write_command_e(LCD_SET_COLUMN | ((x >> 4) & 0xf), x & 0xf);
311 lcd_grey_data(values, phases, width);
312 values += stride;
313 phases += stride;
314 by++;