diff options
-rw-r--r-- | firmware/target/coldfire/mpio/hd200/lcd-hd200.c | 102 |
1 files changed, 86 insertions, 16 deletions
diff --git a/firmware/target/coldfire/mpio/hd200/lcd-hd200.c b/firmware/target/coldfire/mpio/hd200/lcd-hd200.c index 8cb4449b57..5983c7af36 100644 --- a/firmware/target/coldfire/mpio/hd200/lcd-hd200.c +++ b/firmware/target/coldfire/mpio/hd200/lcd-hd200.c | |||
@@ -55,6 +55,13 @@ static bool cached_invert = false; | |||
55 | static bool cached_flip = false; | 55 | static bool cached_flip = false; |
56 | static int cached_contrast = DEFAULT_CONTRAST_SETTING; | 56 | static int cached_contrast = DEFAULT_CONTRAST_SETTING; |
57 | 57 | ||
58 | static struct mutex lcd_mtx; /* The update functions use DMA and yield */ | ||
59 | |||
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; | ||
64 | |||
58 | /*** hardware configuration ***/ | 65 | /*** hardware configuration ***/ |
59 | int lcd_default_contrast(void) | 66 | int lcd_default_contrast(void) |
60 | { | 67 | { |
@@ -155,24 +162,72 @@ void lcd_init_device(void) | |||
155 | lcd_set_contrast(cached_contrast); | 162 | lcd_set_contrast(cached_contrast); |
156 | lcd_set_invert_display(cached_invert); | 163 | lcd_set_invert_display(cached_invert); |
157 | 164 | ||
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 | and_l(~(1<<17), &IMR); | ||
171 | |||
172 | mutex_init(&lcd_mtx); | ||
173 | |||
158 | lcd_update(); | 174 | lcd_update(); |
159 | } | 175 | } |
160 | 176 | ||
177 | /* LCD DMA ISR */ | ||
178 | void DMA3(void) __attribute__ ((interrupt_handler, section(".icode"))); | ||
179 | void DMA3(void) | ||
180 | { | ||
181 | DSR3 = 1; | ||
182 | |||
183 | if (--dma_count > 0) | ||
184 | { | ||
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); | ||
189 | |||
190 | SAR3 = (unsigned long)&lcd_framebuffer[page][column]; | ||
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; | ||
195 | |||
196 | } | ||
197 | } | ||
198 | |||
161 | /* Update the display. | 199 | /* Update the display. |
162 | This must be called after all other LCD functions that change the display. */ | 200 | This must be called after all other LCD functions that change the display. */ |
163 | void lcd_update(void) ICODE_ATTR; | 201 | void lcd_update(void) ICODE_ATTR; |
164 | void lcd_update(void) | 202 | void lcd_update(void) |
165 | { | 203 | { |
166 | int y; | 204 | mutex_lock(&lcd_mtx); |
167 | 205 | ||
168 | for(y = 0;y < LCD_FBHEIGHT;y++) | 206 | /* Setup initial address in lcd controller */ |
169 | { | 207 | lcd_write_command(LCD_SET_PAGE | 0); |
170 | lcd_write_command(LCD_SET_PAGE | y); | 208 | lcd_write_command_e(LCD_SET_COLUMN, 0); |
171 | lcd_write_command_e(LCD_SET_COLUMN, 0); | 209 | |
172 | lcd_write_data(lcd_framebuffer[y], LCD_WIDTH); | 210 | /* Initial lcd ram address */ |
173 | } | 211 | page = 0; |
212 | column = 0; | ||
213 | |||
214 | /* Number of pages to address */ | ||
215 | dma_count = LCD_FBHEIGHT; | ||
174 | 216 | ||
217 | /* Transfer size in bytes to the given page */ | ||
218 | dma_len = LCD_WIDTH*2; | ||
219 | |||
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; | ||
226 | |||
227 | while (dma_count > 0) | ||
228 | yield(); | ||
175 | 229 | ||
230 | mutex_unlock(&lcd_mtx); | ||
176 | } | 231 | } |
177 | 232 | ||
178 | /* Update a fraction of the display. */ | 233 | /* Update a fraction of the display. */ |
@@ -191,17 +246,32 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
191 | if (width <= 0) | 246 | if (width <= 0) |
192 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ | 247 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ |
193 | 248 | ||
249 | mutex_lock(&lcd_mtx); | ||
250 | |||
194 | if (ymax >= LCD_FBHEIGHT) | 251 | if (ymax >= LCD_FBHEIGHT) |
195 | ymax = LCD_FBHEIGHT-1; | 252 | ymax = LCD_FBHEIGHT-1; |
196 | 253 | ||
197 | /* Copy specified rectange bitmap to hardware */ | 254 | /* Initial lcd ram address*/ |
198 | for (; y <= ymax; y++) | 255 | lcd_write_command(LCD_SET_PAGE | y ); |
199 | { | 256 | lcd_write_command_e(LCD_SET_COLUMN | ((x >> 4) & 0xf), x & 0x0f); |
200 | lcd_write_command(LCD_SET_PAGE | y ); | 257 | |
201 | lcd_write_command_e(LCD_SET_COLUMN | ((x >> 4) & 0xf), x & 0x0f); | 258 | page = y; |
202 | lcd_write_data (&lcd_framebuffer[y][x], width); | 259 | column = x; |
203 | } | 260 | dma_len = width*2; |
204 | 261 | dma_count = ymax - y + 1; | |
262 | |||
263 | /* Initialize DMA transfer */ | ||
264 | SAR3 = (unsigned long)&lcd_framebuffer[page][column]; | ||
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; | ||
269 | |||
270 | while (dma_count > 0) | ||
271 | yield(); | ||
272 | |||
273 | mutex_unlock(&lcd_mtx); | ||
274 | |||
205 | } | 275 | } |
206 | 276 | ||
207 | /* Helper function. */ | 277 | /* Helper function. */ |