diff options
Diffstat (limited to 'firmware/target/arm/olympus/mrobe-100/lcd-mr100.c')
-rw-r--r-- | firmware/target/arm/olympus/mrobe-100/lcd-mr100.c | 268 |
1 files changed, 175 insertions, 93 deletions
diff --git a/firmware/target/arm/olympus/mrobe-100/lcd-mr100.c b/firmware/target/arm/olympus/mrobe-100/lcd-mr100.c index 9fb6790cc4..d3c913f4d7 100644 --- a/firmware/target/arm/olympus/mrobe-100/lcd-mr100.c +++ b/firmware/target/arm/olympus/mrobe-100/lcd-mr100.c | |||
@@ -22,18 +22,109 @@ | |||
22 | #include "kernel.h" | 22 | #include "kernel.h" |
23 | #include "system.h" | 23 | #include "system.h" |
24 | 24 | ||
25 | /* send LCD data */ | 25 | /* The m:robe 100 display has a register set that is very similar to the |
26 | static void lcd_send_data(unsigned data) | 26 | Solomon SSD1815 */ |
27 | |||
28 | /*** definitions ***/ | ||
29 | |||
30 | #define LCD_SET_LOWER_COLUMN_ADDRESS ((char)0x00) | ||
31 | #define LCD_SET_HIGHER_COLUMN_ADDRESS ((char)0x10) | ||
32 | #define LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO ((char)0x20) | ||
33 | #define LCD_SET_POWER_CONTROL_REGISTER ((char)0x28) | ||
34 | #define LCD_SET_DISPLAY_START_LINE ((char)0x40) | ||
35 | #define LCD_SET_CONTRAST_CONTROL_REGISTER ((char)0x81) | ||
36 | #define LCD_SET_SEGMENT_REMAP ((char)0xA0) | ||
37 | #define LCD_SET_LCD_BIAS ((char)0xA2) | ||
38 | #define LCD_SET_ENTIRE_DISPLAY_OFF ((char)0xA4) | ||
39 | #define LCD_SET_ENTIRE_DISPLAY_ON ((char)0xA5) | ||
40 | #define LCD_SET_NORMAL_DISPLAY ((char)0xA6) | ||
41 | #define LCD_SET_REVERSE_DISPLAY ((char)0xA7) | ||
42 | #define LCD_SET_MULTIPLEX_RATIO ((char)0xA8) | ||
43 | #define LCD_SET_BIAS_TC_OSC ((char)0xA9) | ||
44 | #define LCD_SET_1OVER4_BIAS_RATIO ((char)0xAA) | ||
45 | #define LCD_SET_INDICATOR_OFF ((char)0xAC) | ||
46 | #define LCD_SET_INDICATOR_ON ((char)0xAD) | ||
47 | #define LCD_SET_DISPLAY_OFF ((char)0xAE) | ||
48 | #define LCD_SET_DISPLAY_ON ((char)0xAF) | ||
49 | #define LCD_SET_PAGE_ADDRESS ((char)0xB0) | ||
50 | #define LCD_SET_COM_OUTPUT_SCAN_DIRECTION ((char)0xC0) | ||
51 | #define LCD_SET_TOTAL_FRAME_PHASES ((char)0xD2) | ||
52 | #define LCD_SET_DISPLAY_OFFSET ((char)0xD3) | ||
53 | #define LCD_SET_READ_MODIFY_WRITE_MODE ((char)0xE0) | ||
54 | #define LCD_SOFTWARE_RESET ((char)0xE2) | ||
55 | #define LCD_NOP ((char)0xE3) | ||
56 | #define LCD_SET_END_OF_READ_MODIFY_WRITE_MODE ((char)0xEE) | ||
57 | |||
58 | /* LCD command codes */ | ||
59 | |||
60 | #define LCD_CNTL_RESET 0xe2 /* Software reset */ | ||
61 | #define LCD_CNTL_POWER 0x2f /* Power control */ | ||
62 | #define LCD_CNTL_CONTRAST 0x81 /* Contrast */ | ||
63 | #define LCD_CNTL_OUTSCAN 0xc8 /* Output scan direction */ | ||
64 | #define LCD_CNTL_SEGREMAP 0xa1 /* Segment remap */ | ||
65 | #define LCD_CNTL_DISPON 0xaf /* Display on */ | ||
66 | |||
67 | #define LCD_CNTL_PAGE 0xb0 /* Page address */ | ||
68 | #define LCD_CNTL_HIGHCOL 0x10 /* Upper column address */ | ||
69 | #define LCD_CNTL_LOWCOL 0x00 /* Lower column address */ | ||
70 | |||
71 | /* send LCD command */ | ||
72 | |||
73 | void lcd_write_command(int byte) | ||
27 | { | 74 | { |
28 | while (LCD1_CONTROL & LCD1_BUSY_MASK); /* wait for LCD */ | 75 | while (LCD1_CONTROL & LCD1_BUSY_MASK); /* wait for LCD */ |
29 | LCD1_DATA = data; | 76 | LCD1_CMD = byte; |
30 | } | 77 | } |
31 | 78 | ||
32 | /* send LCD command */ | 79 | /* send LCD data */ |
33 | static void lcd_send_command(unsigned cmd) | 80 | |
81 | void lcd_write_data(const fb_data* p_bytes, int count) | ||
34 | { | 82 | { |
35 | while (LCD1_CONTROL & LCD1_BUSY_MASK); /* wait for LCD */ | 83 | while (count--) |
36 | LCD1_CMD = cmd; | 84 | { |
85 | while (LCD1_CONTROL & LCD1_BUSY_MASK); /* wait for LCD */ | ||
86 | LCD1_DATA = *(p_bytes++); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static int xoffset; /* needed for flip */ | ||
91 | |||
92 | /*** hardware configuration ***/ | ||
93 | |||
94 | int lcd_default_contrast(void) | ||
95 | { | ||
96 | return DEFAULT_CONTRAST_SETTING; | ||
97 | } | ||
98 | |||
99 | void lcd_set_contrast(int val) | ||
100 | { | ||
101 | lcd_write_command(LCD_CNTL_CONTRAST); | ||
102 | lcd_write_command(val); | ||
103 | } | ||
104 | |||
105 | void lcd_set_invert_display(bool yesno) | ||
106 | { | ||
107 | if (yesno) | ||
108 | lcd_write_command(LCD_SET_REVERSE_DISPLAY); | ||
109 | else | ||
110 | lcd_write_command(LCD_SET_NORMAL_DISPLAY); | ||
111 | } | ||
112 | |||
113 | /* turn the display upside down (call lcd_update() afterwards) */ | ||
114 | void lcd_set_flip(bool yesno) | ||
115 | { | ||
116 | if (!yesno) | ||
117 | { | ||
118 | /* normal */ | ||
119 | lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION | 0xc); | ||
120 | xoffset = 240 - LCD_WIDTH; /* 240 colums minus the 160 we have */ | ||
121 | } | ||
122 | else | ||
123 | { | ||
124 | /* upside-down */ | ||
125 | lcd_write_command(LCD_SET_COM_OUTPUT_SCAN_DIRECTION); | ||
126 | xoffset = 0; | ||
127 | } | ||
37 | } | 128 | } |
38 | 129 | ||
39 | /* LCD init */ | 130 | /* LCD init */ |
@@ -59,83 +150,67 @@ void lcd_init_device(void) | |||
59 | LCD1_CONTROL = 0x694; | 150 | LCD1_CONTROL = 0x694; |
60 | 151 | ||
61 | /* OF just reads these */ | 152 | /* OF just reads these */ |
62 | i = LCD1_CONTROL; | 153 | LCD1_CONTROL; |
63 | i = inl(0x70003004); | 154 | inl(0x70003004); |
64 | i = LCD1_CMD; | 155 | LCD1_CMD; |
65 | i = inl(0x7000300c); | 156 | inl(0x7000300c); |
66 | |||
67 | #if 0 | ||
68 | /* this is skipped in the OF */ | ||
69 | LCD1_CONTROL &= ~0x200; | ||
70 | LCD1_CONTROL &= ~0x800; | ||
71 | LCD1_CONTROL &= ~0x400; | ||
72 | #endif | ||
73 | 157 | ||
74 | LCD1_CONTROL |= 0x1; | 158 | LCD1_CONTROL |= 0x1; |
75 | udelay(15000); | 159 | udelay(15000); |
76 | 160 | ||
77 | lcd_send_command(0xe2); | 161 | lcd_write_command(LCD_SOFTWARE_RESET); /* 0xE2 */ |
78 | lcd_send_command(0x2f); | 162 | lcd_write_command(LCD_SET_POWER_CONTROL_REGISTER + 7); /* 0x2F */ |
79 | lcd_send_command(0x26); | 163 | /* power control register: op-amp=1, regulator=1, booster=1 */ |
80 | lcd_send_command(0xcc); | 164 | lcd_write_command(LCD_SET_INTERNAL_REGULATOR_RESISTOR_RATIO + 6); /* 0x26 */ |
81 | lcd_send_command(0xe8); | ||
82 | lcd_send_command(0x81); | ||
83 | lcd_send_command(0); | ||
84 | lcd_send_command(0x40); | ||
85 | lcd_send_command(0xa6); | ||
86 | lcd_send_command(0x88); | ||
87 | lcd_send_command(0xb0); | ||
88 | lcd_send_command(0x10); | ||
89 | lcd_send_command(0); | ||
90 | } | ||
91 | 165 | ||
92 | /*** hardware configuration ***/ | 166 | lcd_set_flip(false); /* 0xCC */ |
93 | int lcd_default_contrast(void) | ||
94 | { | ||
95 | return DEFAULT_CONTRAST_SETTING; | ||
96 | } | ||
97 | 167 | ||
98 | void lcd_set_contrast(int val) | 168 | lcd_write_command(0xe8); |
99 | { | ||
100 | lcd_send_command(0x81); | ||
101 | lcd_send_command(val); | ||
102 | } | ||
103 | 169 | ||
104 | void lcd_set_invert_display(bool yesno) | 170 | lcd_set_contrast(lcd_default_contrast()); /* 0x80, 0x00 */ |
105 | { | ||
106 | /* TODO: Implement lcd_set_invert_display() */ | ||
107 | (void)yesno; | ||
108 | } | ||
109 | 171 | ||
110 | /* turn the display upside down (call lcd_update() afterwards) */ | 172 | lcd_write_command(LCD_SET_DISPLAY_START_LINE + 0); /* 0x40 */ |
111 | void lcd_set_flip(bool yesno) | 173 | lcd_write_command(LCD_SET_NORMAL_DISPLAY); /* 0xA6 */ |
112 | { | 174 | |
113 | /* TODO: Implement lcd_set_flip() */ | 175 | lcd_write_command(0x88); |
114 | (void)yesno; | 176 | |
177 | lcd_write_command(LCD_SET_PAGE_ADDRESS); /* 0xB0 */ | ||
178 | lcd_write_command(LCD_SET_HIGHER_COLUMN_ADDRESS + 0); /* 0x10 */ | ||
179 | lcd_write_command(LCD_SET_LOWER_COLUMN_ADDRESS + 0); /* 0x00 */ | ||
180 | |||
181 | lcd_write_command(LCD_SET_DISPLAY_ON); /* 0xAF */ | ||
115 | } | 182 | } |
116 | 183 | ||
117 | /*** update functions ***/ | 184 | /*** update functions ***/ |
118 | 185 | ||
119 | /* Performance function that works with an external buffer | 186 | /* Performance function that works with an external buffer |
120 | note that by and bheight are in 8-pixel units! */ | 187 | note that by and bheight are in 8-pixel units! */ |
121 | void lcd_blit_mono(const unsigned char *data, int x, int by, int width, | 188 | void lcd_blit_mono(const unsigned char* data, int x, int by, int width, |
122 | int bheight, int stride) | 189 | int bheight, int stride) |
123 | { | 190 | { |
124 | /* TODO: Implement lcd_blit() */ | 191 | int cmd1, cmd2; |
125 | (void)data; | 192 | |
126 | (void)x; | 193 | cmd1 = LCD_CNTL_HIGHCOL | (((x + xoffset) >> 4) & 0xf); |
127 | (void)by; | 194 | cmd2 = LCD_CNTL_LOWCOL | ((x + xoffset) & 0xf); |
128 | (void)width; | 195 | |
129 | (void)bheight; | 196 | /* Copy display bitmap to hardware */ |
130 | (void)stride; | 197 | while (bheight--) |
198 | { | ||
199 | lcd_write_command(LCD_CNTL_PAGE | (by++ & 0xff)); | ||
200 | lcd_write_command(cmd1); | ||
201 | lcd_write_command(cmd2); | ||
202 | |||
203 | lcd_write_data(data, width); | ||
204 | |||
205 | data += stride; | ||
206 | } | ||
131 | } | 207 | } |
132 | 208 | ||
133 | /* Performance function that works with an external buffer | 209 | /* Performance function that works with an external buffer |
134 | note that by and bheight are in 4-pixel units! */ | 210 | note that by and bheight are in 8-pixel units! */ |
135 | void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, | 211 | void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, |
136 | int x, int by, int width, int bheight, int stride) | 212 | int x, int by, int width, int bheight, int stride) |
137 | { | 213 | { |
138 | /* TODO: Implement lcd_grey_phase_blit() */ | ||
139 | (void)values; | 214 | (void)values; |
140 | (void)phases; | 215 | (void)phases; |
141 | (void)x; | 216 | (void)x; |
@@ -144,49 +219,56 @@ void lcd_blit_grey_phase(unsigned char *values, unsigned char *phases, | |||
144 | (void)bheight; | 219 | (void)bheight; |
145 | (void)stride; | 220 | (void)stride; |
146 | } | 221 | } |
147 | 222 | ||
148 | /* Update the display. | 223 | /* Update the display. |
149 | This must be called after all other LCD functions that change the display. */ | 224 | This must be called after all other LCD functions that change the display. */ |
225 | void lcd_update(void) ICODE_ATTR; | ||
150 | void lcd_update(void) | 226 | void lcd_update(void) |
151 | { | 227 | { |
152 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | 228 | int y, cmd1, cmd2; |
229 | |||
230 | cmd1 = LCD_CNTL_HIGHCOL | (((xoffset) >> 4) & 0xf); | ||
231 | cmd2 = LCD_CNTL_LOWCOL | ((xoffset) & 0xf); | ||
232 | |||
233 | /* Copy display bitmap to hardware */ | ||
234 | for (y = 0; y < LCD_FBHEIGHT; y++) | ||
235 | { | ||
236 | lcd_write_command (LCD_CNTL_PAGE | (y & 0xf)); | ||
237 | lcd_write_command(cmd1); | ||
238 | lcd_write_command(cmd2); | ||
239 | |||
240 | lcd_write_data (lcd_framebuffer[y], LCD_WIDTH); | ||
241 | } | ||
153 | } | 242 | } |
154 | 243 | ||
155 | /* Update a fraction of the display. */ | 244 | /* Update a fraction of the display. */ |
156 | void lcd_update_rect(int x0, int y0, int width, int height) | 245 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; |
246 | void lcd_update_rect(int x, int y, int width, int height) | ||
157 | { | 247 | { |
158 | unsigned char *addr; | 248 | int ymax, cmd1, cmd2; |
159 | unsigned int cmd0, cmd1, cmd2; | ||
160 | int r, c, x1, y1, start_row, last_row; | ||
161 | 249 | ||
162 | x1 = (x0 + width) - 1; | 250 | /* The Y coordinates have to work on even 8 pixel rows */ |
163 | y1 = (y0 + height) - 1; | 251 | ymax = (y + height - 1) >> 3; |
164 | if ((x1 <= 0) || (y1 <= 0)) | 252 | y >>= 3; |
165 | return; | ||
166 | 253 | ||
167 | if(x1 >= LCD_WIDTH) | 254 | if(x + width > LCD_WIDTH) |
168 | x1 = LCD_WIDTH - 1; | 255 | width = LCD_WIDTH - x; |
256 | if (width <= 0) | ||
257 | return; /* nothing left to do, 0 is harmful to lcd_write_data() */ | ||
258 | if(ymax >= LCD_FBHEIGHT) | ||
259 | ymax = LCD_FBHEIGHT-1; | ||
169 | 260 | ||
170 | if(y1 >= LCD_HEIGHT) | ||
171 | y1 = LCD_HEIGHT - 1; | ||
172 | 261 | ||
173 | start_row = y0/8; | 262 | cmd1 = LCD_CNTL_HIGHCOL | (((x + xoffset) >> 4) & 0xf); |
174 | last_row = y1/8; | 263 | cmd2 = LCD_CNTL_LOWCOL | ((x + xoffset) & 0xf); |
175 | 264 | ||
176 | cmd1 = (x0 & 0xff) >> 4; | 265 | /* Copy specified rectange bitmap to hardware */ |
177 | cmd1 = (cmd1 + 5) | 0x10; | 266 | for (; y <= ymax; y++) |
178 | cmd2 = x0 & 0xf; | 267 | { |
268 | lcd_write_command(LCD_CNTL_PAGE | (y & 0xf)); | ||
269 | lcd_write_command(cmd1); | ||
270 | lcd_write_command(cmd2); | ||
179 | 271 | ||
180 | for (r = start_row; r <= last_row; r++) { | 272 | lcd_write_data (&lcd_framebuffer[y][x], width); |
181 | cmd0 = (r & 0xff) | 0xb0; | ||
182 | lcd_send_command(cmd0); | ||
183 | lcd_send_command(cmd1); | ||
184 | lcd_send_command(cmd2); | ||
185 | |||
186 | addr = (unsigned char*)&lcd_framebuffer[r][x0]; | ||
187 | for (c = x0; c <= x1; c++) | ||
188 | lcd_send_data(*(addr++)); | ||
189 | } | 273 | } |
190 | |||
191 | lcd_send_command(0xaf); | ||
192 | } | 274 | } |