Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2004 by Linus Nielsen Feltzing |
| 11 | * |
Daniel Stenberg | 2acc0ac | 2008-06-28 18:10:04 +0000 | [diff] [blame^] | 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. |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
| 21 | #include "config.h" |
| 22 | |
| 23 | #include "cpu.h" |
| 24 | #include "lcd.h" |
| 25 | #include "kernel.h" |
| 26 | #include "thread.h" |
| 27 | #include <string.h> |
| 28 | #include <stdlib.h> |
| 29 | #include "file.h" |
| 30 | #include "debug.h" |
| 31 | #include "system.h" |
| 32 | #include "font.h" |
| 33 | #include "bidi.h" |
| 34 | |
Jens Arnold | cb9e316 | 2006-03-17 15:42:06 +0000 | [diff] [blame] | 35 | static bool display_on = false; /* is the display turned on? */ |
| 36 | static bool display_flipped = false; |
| 37 | static int xoffset = 0; /* needed for flip */ |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 38 | |
| 39 | /* register defines */ |
| 40 | #define R_START_OSC 0x00 |
| 41 | #define R_DRV_OUTPUT_CONTROL 0x01 |
| 42 | #define R_DRV_WAVEFORM_CONTROL 0x02 |
| 43 | #define R_ENTRY_MODE 0x03 |
| 44 | #define R_COMPARE_REG1 0x04 |
| 45 | #define R_COMPARE_REG2 0x05 |
| 46 | |
| 47 | #define R_DISP_CONTROL1 0x07 |
| 48 | #define R_DISP_CONTROL2 0x08 |
| 49 | #define R_DISP_CONTROL3 0x09 |
| 50 | |
| 51 | #define R_FRAME_CYCLE_CONTROL 0x0b |
| 52 | #define R_EXT_DISP_IF_CONTROL 0x0c |
| 53 | |
| 54 | #define R_POWER_CONTROL1 0x10 |
| 55 | #define R_POWER_CONTROL2 0x11 |
| 56 | #define R_POWER_CONTROL3 0x12 |
| 57 | #define R_POWER_CONTROL4 0x13 |
| 58 | |
| 59 | #define R_RAM_ADDR_SET 0x21 |
| 60 | #define R_WRITE_DATA_2_GRAM 0x22 |
| 61 | |
| 62 | #define R_GAMMA_FINE_ADJ_POS1 0x30 |
| 63 | #define R_GAMMA_FINE_ADJ_POS2 0x31 |
| 64 | #define R_GAMMA_FINE_ADJ_POS3 0x32 |
| 65 | #define R_GAMMA_GRAD_ADJ_POS 0x33 |
| 66 | |
| 67 | #define R_GAMMA_FINE_ADJ_NEG1 0x34 |
| 68 | #define R_GAMMA_FINE_ADJ_NEG2 0x35 |
| 69 | #define R_GAMMA_FINE_ADJ_NEG3 0x36 |
| 70 | #define R_GAMMA_GRAD_ADJ_NEG 0x37 |
| 71 | |
| 72 | #define R_GAMMA_AMP_ADJ_RES_POS 0x38 |
| 73 | #define R_GAMMA_AMP_AVG_ADJ_RES_NEG 0x39 |
| 74 | |
| 75 | #define R_GATE_SCAN_POS 0x40 |
| 76 | #define R_VERT_SCROLL_CONTROL 0x41 |
| 77 | #define R_1ST_SCR_DRV_POS 0x42 |
| 78 | #define R_2ND_SCR_DRV_POS 0x43 |
| 79 | #define R_HORIZ_RAM_ADDR_POS 0x44 |
| 80 | #define R_VERT_RAM_ADDR_POS 0x45 |
| 81 | |
Jens Arnold | c5a309a | 2006-08-08 13:44:43 +0000 | [diff] [blame] | 82 | #define LCD_CMD (*(volatile unsigned short *)0xf0000000) |
| 83 | #define LCD_DATA (*(volatile unsigned short *)0xf0000002) |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 84 | |
Jens Arnold | 99f9550 | 2007-10-14 23:05:56 +0000 | [diff] [blame] | 85 | #define R_ENTRY_MODE_HORZ 0x7030 |
| 86 | #define R_ENTRY_MODE_VERT 0x7038 |
| 87 | |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 88 | /* called very frequently - inline! */ |
Jens Arnold | f3857ab | 2006-02-05 00:24:08 +0000 | [diff] [blame] | 89 | static inline void lcd_write_reg(int reg, int val) |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 90 | { |
Jens Arnold | c5a309a | 2006-08-08 13:44:43 +0000 | [diff] [blame] | 91 | LCD_CMD = reg; |
| 92 | LCD_DATA = val; |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 93 | } |
| 94 | |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 95 | /* called very frequently - inline! */ |
Jens Arnold | f3857ab | 2006-02-05 00:24:08 +0000 | [diff] [blame] | 96 | static inline void lcd_begin_write_gram(void) |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 97 | { |
Jens Arnold | c5a309a | 2006-08-08 13:44:43 +0000 | [diff] [blame] | 98 | LCD_CMD = R_WRITE_DATA_2_GRAM; |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 99 | } |
| 100 | |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 101 | /*** hardware configuration ***/ |
| 102 | |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 103 | void lcd_set_contrast(int val) |
| 104 | { |
| 105 | (void)val; |
| 106 | } |
| 107 | |
| 108 | void lcd_set_invert_display(bool yesno) |
| 109 | { |
| 110 | (void)yesno; |
| 111 | } |
| 112 | |
Jens Arnold | cb9e316 | 2006-03-17 15:42:06 +0000 | [diff] [blame] | 113 | static void flip_lcd(bool yesno) |
| 114 | { |
| 115 | if (yesno) |
| 116 | { |
| 117 | lcd_write_reg(R_DRV_OUTPUT_CONTROL, 0x031b); /* 224 lines, GS=SS=1 */ |
| 118 | lcd_write_reg(R_GATE_SCAN_POS, 0x0002); /* 16 lines offset */ |
| 119 | lcd_write_reg(R_1ST_SCR_DRV_POS, 0xdf04); /* 4..223 */ |
| 120 | } |
| 121 | else |
| 122 | { |
| 123 | lcd_write_reg(R_DRV_OUTPUT_CONTROL, 0x001b); /* 224 lines, GS=SS=0 */ |
| 124 | lcd_write_reg(R_GATE_SCAN_POS, 0x0000); |
| 125 | lcd_write_reg(R_1ST_SCR_DRV_POS, 0xdb00); /* 0..219 */ |
| 126 | } |
| 127 | } |
| 128 | |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 129 | /* turn the display upside down (call lcd_update() afterwards) */ |
| 130 | void lcd_set_flip(bool yesno) |
| 131 | { |
Jens Arnold | cb9e316 | 2006-03-17 15:42:06 +0000 | [diff] [blame] | 132 | display_flipped = yesno; |
| 133 | xoffset = yesno ? 4 : 0; |
| 134 | |
| 135 | if (display_on) |
| 136 | flip_lcd(yesno); |
| 137 | } |
| 138 | |
| 139 | static void _display_on(void) |
| 140 | { |
| 141 | /** Sequence according to datasheet, p. 132 **/ |
| 142 | |
| 143 | lcd_write_reg(R_START_OSC, 0x0001); /* Start Oscilation */ |
| 144 | sleep(1); |
| 145 | |
| 146 | /* zero everything*/ |
| 147 | lcd_write_reg(R_POWER_CONTROL1, 0x0000); /* STB = 0, SLP = 0 */ |
| 148 | lcd_write_reg(R_DISP_CONTROL1, 0x0000); /* GON = 0, DTE = 0, D1-0 = 00b */ |
| 149 | lcd_write_reg(R_POWER_CONTROL3, 0x0000); /* PON = 0 */ |
| 150 | lcd_write_reg(R_POWER_CONTROL4, 0x0000); /* VCOMG = 0 */ |
| 151 | sleep(1); |
| 152 | |
| 153 | /* initialise power supply */ |
| 154 | |
| 155 | /* DC12-10 = 000b: Step-up1 = clock/8, |
| 156 | * DC02-00 = 000b: Step-up2 = clock/16, |
| 157 | * VC2-0 = 010b: VciOUT = 0.87 * VciLVL */ |
| 158 | lcd_write_reg(R_POWER_CONTROL2, 0x0002); |
| 159 | |
| 160 | /* VRH3-0 = 1000b: Vreg1OUT = REGP * 1.90 */ |
| 161 | lcd_write_reg(R_POWER_CONTROL3, 0x0008); |
| 162 | |
| 163 | /* VDV4-0 = 00110b: VcomA = Vreg1OUT * 0.76, |
| 164 | * VCM4-0 = 10000b: VcomH = Vreg1OUT * 0.70*/ |
| 165 | lcd_write_reg(R_POWER_CONTROL4, 0x0610); |
| 166 | |
| 167 | lcd_write_reg(R_POWER_CONTROL1, 0x0044); /* AP2-0 = 100b, DK = 1 */ |
| 168 | lcd_write_reg(R_POWER_CONTROL3, 0x0018); /* PON = 1 */ |
| 169 | |
| 170 | sleep(4); /* Step-up circuit stabilising time */ |
| 171 | |
| 172 | /* start power supply */ |
| 173 | |
| 174 | lcd_write_reg(R_POWER_CONTROL1, 0x0540); /* BT2-0 = 101b, DK = 0 */ |
| 175 | lcd_write_reg(R_POWER_CONTROL4, 0x2610); /* VCOMG = 1 */ |
| 176 | |
| 177 | /* other settings */ |
| 178 | |
| 179 | /* B/C = 1: n-line inversion form |
| 180 | * EOR = 1: polarity inversion occurs by applying an EOR to odd/even |
| 181 | * frame select signal and an n-line inversion signal. |
| 182 | * FLD = 01b: 1 field interlaced scan, external display iface */ |
| 183 | lcd_write_reg(R_DRV_WAVEFORM_CONTROL, 0x0700); |
| 184 | |
| 185 | /* Address counter updated in vertical direction; left to right; |
| 186 | * vertical increment horizontal increment. |
| 187 | * data format for 8bit transfer or spi = 65k (5,6,5) |
| 188 | * Reverse order of RGB to BGR for 18bit data written to GRAM |
| 189 | * Replace data on writing to GRAM */ |
| 190 | lcd_write_reg(R_ENTRY_MODE, 0x7038); |
| 191 | |
| 192 | flip_lcd(display_flipped); |
| 193 | |
| 194 | lcd_write_reg(R_2ND_SCR_DRV_POS, 0x0000); |
| 195 | lcd_write_reg(R_VERT_SCROLL_CONTROL, 0x0000); |
| 196 | |
| 197 | /* 19 clocks,no equalization */ |
| 198 | lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x0002); |
| 199 | |
| 200 | /* Transfer mode for RGB interface disabled |
| 201 | * internal clock operation; |
| 202 | * System interface/VSYNC interface */ |
| 203 | lcd_write_reg(R_EXT_DISP_IF_CONTROL, 0x0003); |
| 204 | |
| 205 | /* Front porch lines: 8; Back porch lines: 8; */ |
| 206 | lcd_write_reg(R_DISP_CONTROL2, 0x0808); |
| 207 | |
| 208 | /* Scan mode by the gate driver in the non-display area: disabled; |
| 209 | * Cycle of scan by the gate driver - set to 31frames(518ms), |
| 210 | * disabled by above setting */ |
| 211 | lcd_write_reg(R_DISP_CONTROL3, 0x003f); |
| 212 | |
| 213 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS1, 0x0003); |
| 214 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS2, 0x0707); |
| 215 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS3, 0x0007); |
| 216 | lcd_write_reg(R_GAMMA_GRAD_ADJ_POS, 0x0705); |
| 217 | lcd_write_reg(R_GAMMA_FINE_ADJ_NEG1, 0x0007); |
| 218 | lcd_write_reg(R_GAMMA_FINE_ADJ_NEG2, 0x0000); |
| 219 | lcd_write_reg(R_GAMMA_FINE_ADJ_NEG3, 0x0407); |
| 220 | lcd_write_reg(R_GAMMA_GRAD_ADJ_NEG, 0x0507); |
| 221 | lcd_write_reg(R_GAMMA_AMP_ADJ_RES_POS, 0x1d09); |
| 222 | lcd_write_reg(R_GAMMA_AMP_AVG_ADJ_RES_NEG, 0x0303); |
| 223 | |
| 224 | display_on=true; /* must be done before calling lcd_update() */ |
| 225 | lcd_update(); |
| 226 | |
| 227 | sleep(4); /* op-amp stabilising time */ |
| 228 | |
| 229 | /** Sequence according to datasheet, p. 130 **/ |
| 230 | |
| 231 | lcd_write_reg(R_POWER_CONTROL1, 0x4540); /* SAP2-0=100, BT2-0=101, AP2-0=100 */ |
| 232 | lcd_write_reg(R_DISP_CONTROL1, 0x0005); /* GON=0, DTE=0, REV=1, D1-0=01 */ |
| 233 | sleep(2); |
| 234 | |
| 235 | lcd_write_reg(R_DISP_CONTROL1, 0x0025); /* GON=1, DTE=0, REV=1, D1-0=01 */ |
| 236 | lcd_write_reg(R_DISP_CONTROL1, 0x0027); /* GON=1, DTE=0, REV=1, D1-0=11 */ |
| 237 | sleep(2); |
| 238 | |
| 239 | lcd_write_reg(R_DISP_CONTROL1, 0x0037); /* GON=1, DTE=1, REV=1, D1-0=11 */ |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 240 | } |
| 241 | |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 242 | /* LCD init */ |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 243 | void lcd_init_device(void) |
| 244 | { |
| 245 | /* GPO46 is LCD RESET */ |
| 246 | or_l(0x00004000, &GPIO1_OUT); |
| 247 | or_l(0x00004000, &GPIO1_ENABLE); |
| 248 | or_l(0x00004000, &GPIO1_FUNCTION); |
| 249 | |
| 250 | /* Reset LCD */ |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 251 | and_l(~0x00004000, &GPIO1_OUT); |
| 252 | sleep(1); |
| 253 | or_l(0x00004000, &GPIO1_OUT); |
| 254 | sleep(1); |
| 255 | |
Jens Arnold | cb9e316 | 2006-03-17 15:42:06 +0000 | [diff] [blame] | 256 | _display_on(); |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 257 | } |
| 258 | |
| 259 | void lcd_enable(bool on) |
| 260 | { |
| 261 | if(display_on!=on) |
Jens Arnold | cb9e316 | 2006-03-17 15:42:06 +0000 | [diff] [blame] | 262 | { |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 263 | if(on) |
| 264 | { |
Jens Arnold | cb9e316 | 2006-03-17 15:42:06 +0000 | [diff] [blame] | 265 | _display_on(); |
Michael Sevakis | adf2e4c | 2008-05-28 10:17:16 +0000 | [diff] [blame] | 266 | lcd_call_enable_hook(); |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 267 | } |
| 268 | else |
| 269 | { |
Jens Arnold | cb9e316 | 2006-03-17 15:42:06 +0000 | [diff] [blame] | 270 | /** Off sequence according to datasheet, p. 130 **/ |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 271 | |
Jens Arnold | cb9e316 | 2006-03-17 15:42:06 +0000 | [diff] [blame] | 272 | lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x0002); /* EQ=0, 18 clks/line */ |
| 273 | lcd_write_reg(R_DISP_CONTROL1, 0x0036); /* GON=1, DTE=1, REV=1, D1-0=10 */ |
| 274 | sleep(2); |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 275 | |
Jens Arnold | cb9e316 | 2006-03-17 15:42:06 +0000 | [diff] [blame] | 276 | lcd_write_reg(R_DISP_CONTROL1, 0x0026); /* GON=1, DTE=0, REV=1, D1-0=10 */ |
| 277 | sleep(2); |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 278 | |
Jens Arnold | cb9e316 | 2006-03-17 15:42:06 +0000 | [diff] [blame] | 279 | lcd_write_reg(R_DISP_CONTROL1, 0x0000); /* GON=0, DTE=0, D1-0=00 */ |
| 280 | |
| 281 | lcd_write_reg(R_POWER_CONTROL1, 0x0000); /* SAP2-0=000, AP2-0=000 */ |
| 282 | lcd_write_reg(R_POWER_CONTROL3, 0x0000); /* PON=0 */ |
| 283 | lcd_write_reg(R_POWER_CONTROL4, 0x0000); /* VCOMG=0 */ |
| 284 | |
| 285 | /* datasheet p. 131 */ |
| 286 | lcd_write_reg(R_POWER_CONTROL1, 0x0001); /* STB=1: standby mode */ |
| 287 | |
Hristo Kovachev | 9cf5270 | 2006-01-09 16:11:19 +0000 | [diff] [blame] | 288 | display_on=false; |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 289 | } |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 290 | } |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 291 | } |
| 292 | |
Michael Sevakis | 60b01fa | 2007-07-31 12:43:06 +0000 | [diff] [blame] | 293 | bool lcd_enabled(void) |
| 294 | { |
| 295 | return display_on; |
| 296 | } |
| 297 | |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 298 | /*** update functions ***/ |
| 299 | |
Jens Arnold | 9af13c3 | 2006-08-23 17:30:51 +0000 | [diff] [blame] | 300 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. |
Jens Arnold | 99f9550 | 2007-10-14 23:05:56 +0000 | [diff] [blame] | 301 | * y should have two lines of Y back to back, 2nd line first. |
| 302 | * c should contain the Cb and Cr data for the two lines of Y back to back. |
Jens Arnold | f8b1da2 | 2006-11-04 00:42:18 +0000 | [diff] [blame] | 303 | * Needs EMAC set to saturated, signed integer mode. |
Jens Arnold | 9af13c3 | 2006-08-23 17:30:51 +0000 | [diff] [blame] | 304 | */ |
| 305 | extern void lcd_write_yuv420_lines(const unsigned char *y, |
Jens Arnold | 99f9550 | 2007-10-14 23:05:56 +0000 | [diff] [blame] | 306 | const unsigned char *c, int cwidth); |
Jens Arnold | c5a309a | 2006-08-08 13:44:43 +0000 | [diff] [blame] | 307 | |
Jens Arnold | 9af13c3 | 2006-08-23 17:30:51 +0000 | [diff] [blame] | 308 | /* Performance function to blit a YUV bitmap directly to the LCD |
| 309 | * src_x, src_y, width and height should be even |
| 310 | * x, y, width and height have to be within LCD bounds |
| 311 | */ |
Jens Arnold | 68a2168 | 2008-03-24 00:35:53 +0000 | [diff] [blame] | 312 | void lcd_blit_yuv(unsigned char * const src[3], |
Jens Arnold | c5a309a | 2006-08-08 13:44:43 +0000 | [diff] [blame] | 313 | int src_x, int src_y, int stride, |
| 314 | int x, int y, int width, int height) |
| 315 | { |
Jens Arnold | f8b1da2 | 2006-11-04 00:42:18 +0000 | [diff] [blame] | 316 | /* IRAM Y, Cb and Cb buffers. */ |
Jens Arnold | 9af13c3 | 2006-08-23 17:30:51 +0000 | [diff] [blame] | 317 | unsigned char y_ibuf[LCD_WIDTH*2]; |
Jens Arnold | 99f9550 | 2007-10-14 23:05:56 +0000 | [diff] [blame] | 318 | unsigned char c_ibuf[LCD_WIDTH]; |
Jens Arnold | 9af13c3 | 2006-08-23 17:30:51 +0000 | [diff] [blame] | 319 | const unsigned char *ysrc, *usrc, *vsrc; |
| 320 | const unsigned char *ysrc_max; |
| 321 | |
| 322 | if (!display_on) |
| 323 | return; |
| 324 | |
| 325 | width &= ~1; /* stay on the safe side */ |
| 326 | height &= ~1; |
| 327 | |
Jens Arnold | 99f9550 | 2007-10-14 23:05:56 +0000 | [diff] [blame] | 328 | lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_HORZ); |
Jens Arnold | 9af13c3 | 2006-08-23 17:30:51 +0000 | [diff] [blame] | 329 | /* Set start position and window */ |
Jens Arnold | 99f9550 | 2007-10-14 23:05:56 +0000 | [diff] [blame] | 330 | lcd_write_reg(R_VERT_RAM_ADDR_POS, ((xoffset + 219) << 8) | xoffset); |
Jens Arnold | 9af13c3 | 2006-08-23 17:30:51 +0000 | [diff] [blame] | 331 | |
| 332 | ysrc = src[0] + src_y * stride + src_x; |
| 333 | usrc = src[1] + (src_y * stride >> 2) + (src_x >> 1); |
| 334 | vsrc = src[2] + (src_y * stride >> 2) + (src_x >> 1); |
| 335 | ysrc_max = ysrc + height * stride; |
| 336 | |
Jens Arnold | f8b1da2 | 2006-11-04 00:42:18 +0000 | [diff] [blame] | 337 | coldfire_set_macsr(EMAC_SATURATE); |
Jens Arnold | 9af13c3 | 2006-08-23 17:30:51 +0000 | [diff] [blame] | 338 | do |
Jens Arnold | c5a309a | 2006-08-08 13:44:43 +0000 | [diff] [blame] | 339 | { |
Jens Arnold | 99f9550 | 2007-10-14 23:05:56 +0000 | [diff] [blame] | 340 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, ((y + 1) << 8) | y); |
| 341 | lcd_write_reg(R_RAM_ADDR_SET, ((x+xoffset) << 8) | y); |
| 342 | lcd_begin_write_gram(); |
| 343 | |
| 344 | memcpy(y_ibuf + width, ysrc, width); |
| 345 | memcpy(y_ibuf, ysrc + stride, width); |
| 346 | memcpy(c_ibuf, usrc, width >> 1); |
| 347 | memcpy(c_ibuf + (width >> 1), vsrc, width >> 1); |
| 348 | lcd_write_yuv420_lines(y_ibuf, c_ibuf, width >> 1); |
| 349 | |
| 350 | y += 2; |
Jens Arnold | 9af13c3 | 2006-08-23 17:30:51 +0000 | [diff] [blame] | 351 | ysrc += 2 * stride; |
| 352 | usrc += stride >> 1; |
| 353 | vsrc += stride >> 1; |
Jens Arnold | c5a309a | 2006-08-08 13:44:43 +0000 | [diff] [blame] | 354 | } |
Jens Arnold | 9af13c3 | 2006-08-23 17:30:51 +0000 | [diff] [blame] | 355 | while (ysrc < ysrc_max); |
Jens Arnold | c5a309a | 2006-08-08 13:44:43 +0000 | [diff] [blame] | 356 | } |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 357 | |
| 358 | /* Update the display. |
| 359 | This must be called after all other LCD functions that change the display. */ |
| 360 | void lcd_update(void) ICODE_ATTR; |
| 361 | void lcd_update(void) |
| 362 | { |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 363 | if(display_on){ |
Jens Arnold | 99f9550 | 2007-10-14 23:05:56 +0000 | [diff] [blame] | 364 | lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VERT); |
| 365 | /* set start position window */ |
| 366 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 175 << 8); |
Jens Arnold | cb9e316 | 2006-03-17 15:42:06 +0000 | [diff] [blame] | 367 | lcd_write_reg(R_VERT_RAM_ADDR_POS,((xoffset+219)<<8) | xoffset); |
Jens Arnold | cb9e316 | 2006-03-17 15:42:06 +0000 | [diff] [blame] | 368 | lcd_write_reg(R_RAM_ADDR_SET, xoffset << 8); |
Jens Arnold | 99f9550 | 2007-10-14 23:05:56 +0000 | [diff] [blame] | 369 | |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 370 | lcd_begin_write_gram(); |
Jens Arnold | 83aded9 | 2006-11-02 20:50:50 +0000 | [diff] [blame] | 371 | |
| 372 | DAR3 = 0xf0000002; |
| 373 | SAR3 = (unsigned long)lcd_framebuffer; |
| 374 | BCR3 = LCD_WIDTH*LCD_HEIGHT*2; |
| 375 | DCR3 = DMA_AA | DMA_BWC(1) |
| 376 | | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) |
| 377 | | DMA_DSIZE(DMA_SIZE_WORD) | DMA_START; |
| 378 | |
| 379 | while (!(DSR3 & 1)); |
| 380 | DSR3 = 1; |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 381 | } |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 382 | } |
| 383 | |
Jens Arnold | f8b1da2 | 2006-11-04 00:42:18 +0000 | [diff] [blame] | 384 | |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 385 | /* Update a fraction of the display. */ |
| 386 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; |
| 387 | void lcd_update_rect(int x, int y, int width, int height) |
| 388 | { |
Jens Arnold | 83aded9 | 2006-11-02 20:50:50 +0000 | [diff] [blame] | 389 | unsigned long dma_addr; |
| 390 | |
Jens Arnold | c5a309a | 2006-08-08 13:44:43 +0000 | [diff] [blame] | 391 | if(display_on) { |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 392 | |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 393 | if(x + width > LCD_WIDTH) |
| 394 | width = LCD_WIDTH - x; |
Jens Arnold | 83aded9 | 2006-11-02 20:50:50 +0000 | [diff] [blame] | 395 | if(width <= 0) /* nothing to do */ |
| 396 | return; |
| 397 | if(y + height > LCD_HEIGHT) |
| 398 | height = LCD_HEIGHT - y; |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 399 | |
Jens Arnold | 99f9550 | 2007-10-14 23:05:56 +0000 | [diff] [blame] | 400 | lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VERT); |
Jens Arnold | 83aded9 | 2006-11-02 20:50:50 +0000 | [diff] [blame] | 401 | /* set update window */ |
Jens Arnold | 99f9550 | 2007-10-14 23:05:56 +0000 | [diff] [blame] | 402 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 175 << 8); |
Jens Arnold | cb9e316 | 2006-03-17 15:42:06 +0000 | [diff] [blame] | 403 | lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+xoffset+width-1) << 8) | (x+xoffset)); |
| 404 | lcd_write_reg(R_RAM_ADDR_SET, ((x+xoffset) << 8) | y); |
Jens Arnold | 83aded9 | 2006-11-02 20:50:50 +0000 | [diff] [blame] | 405 | lcd_begin_write_gram(); |
| 406 | |
| 407 | DAR3 = 0xf0000002; |
| 408 | dma_addr = (unsigned long)&lcd_framebuffer[y][x]; |
| 409 | width *= 2; |
Linus Nielsen Feltzing | 6ddfac0 | 2005-12-11 00:30:15 +0000 | [diff] [blame] | 410 | |
Jens Arnold | 83aded9 | 2006-11-02 20:50:50 +0000 | [diff] [blame] | 411 | for (; height > 0; height--) |
| 412 | { |
| 413 | SAR3 = dma_addr; |
| 414 | BCR3 = width; |
| 415 | DCR3 = DMA_AA | DMA_BWC(1) |
| 416 | | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) |
| 417 | | DMA_DSIZE(DMA_SIZE_WORD) | DMA_START; |
| 418 | |
| 419 | dma_addr += LCD_WIDTH*2; |
| 420 | |
| 421 | while (!(DSR3 & 1)); |
| 422 | DSR3 = 1; |
| 423 | } |
Linus Nielsen Feltzing | 67f0022 | 2005-12-20 23:15:27 +0000 | [diff] [blame] | 424 | } |
Linus Nielsen Feltzing | dbc8c2c | 2005-11-14 20:41:49 +0000 | [diff] [blame] | 425 | } |