summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootloader/h10.c22
-rw-r--r--firmware/export/config-h10.h6
-rw-r--r--firmware/target/arm/iriver/h10/lcd-h10.c398
3 files changed, 169 insertions, 257 deletions
diff --git a/bootloader/h10.c b/bootloader/h10.c
index d7942c9583..86d3c33a17 100644
--- a/bootloader/h10.c
+++ b/bootloader/h10.c
@@ -115,15 +115,19 @@ void main(void)
115 ); 115 );
116 */ 116 */
117 117
118 int i; 118 /*int i;
119 int rc; 119 int rc;
120 int btn; 120 int btn;
121 int fd; 121 int fd;*/
122 char buffer[24]; 122 char buffer[24];
123
124 snprintf(buffer, 24, "Hello World");
125 lcd_puts(0, 0, buffer);
126 lcd_update();
123 127
124 i=ata_init(); 128 /*i=ata_init();
125 disk_init(); 129 disk_init();
126 rc = disk_mount_all(); 130 rc = disk_mount_all();*/
127 131
128 /* Load original iriver firmware. Uses load_iriver(buf) to load the 132 /* Load original iriver firmware. Uses load_iriver(buf) to load the
129 decrypted mi4 file from disk to DRAM. This then copies that part of DRAM 133 decrypted mi4 file from disk to DRAM. This then copies that part of DRAM
@@ -139,7 +143,7 @@ void main(void)
139 143
140 144
141 /* This assumes that /test.txt exists */ 145 /* This assumes that /test.txt exists */
142 fd=open("/test.txt",O_RDWR); 146 /*fd=open("/test.txt",O_RDWR);*/
143 147
144 148
145 /* 149 /*
@@ -223,16 +227,16 @@ void main(void)
223 227
224 228
225 /* Apparently necessary for the data to be actually written to file */ 229 /* Apparently necessary for the data to be actually written to file */
226 fsync(fd); 230 /*fsync(fd);
227 udelay(1000000); 231 udelay(1000000);*/
228 232
229 /* This causes the device to shut off instantly 233 /* This causes the device to shut off instantly
230 234
231 GPIOF_OUTPUT_VAL = 0; 235 GPIOF_OUTPUT_VAL = 0;
232 */ 236 */
233 237
234 close(fd); 238 /*close(fd);*/
235 udelay(1000000); 239 udelay(100000000);
236} 240}
237 241
238/* These functions are present in the firmware library, but we reimplement 242/* These functions are present in the firmware library, but we reimplement
diff --git a/firmware/export/config-h10.h b/firmware/export/config-h10.h
index 39f8a85a35..099df0d715 100644
--- a/firmware/export/config-h10.h
+++ b/firmware/export/config-h10.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * This config file is for the iriver H10 2 * This config file is for the iriver H10 20Gb
3 */ 3 */
4 4
5#define TARGET_TREE /* this target is using the target tree system */ 5#define TARGET_TREE /* this target is using the target tree system */
@@ -96,8 +96,8 @@
96/* TODO: this is probably wrong */ 96/* TODO: this is probably wrong */
97#define CPU_FREQ 11289600 97#define CPU_FREQ 11289600
98 98
99/* Type of LCD TODO: hopefully the same as the x5 but check this*/ 99/* Type of LCD */
100#define CONFIG_LCD LCD_X5 100#define CONFIG_LCD LCD_H10
101 101
102/* Offset ( in the firmware file's header ) to the file length */ 102/* Offset ( in the firmware file's header ) to the file length */
103#define FIRMWARE_OFFSET_FILE_LENGTH 0 103#define FIRMWARE_OFFSET_FILE_LENGTH 0
diff --git a/firmware/target/arm/iriver/h10/lcd-h10.c b/firmware/target/arm/iriver/h10/lcd-h10.c
index 3640aa1ba1..022dc22208 100644
--- a/firmware/target/arm/iriver/h10/lcd-h10.c
+++ b/firmware/target/arm/iriver/h10/lcd-h10.c
@@ -16,252 +16,133 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19
20/* The H10 display possibly identical to that of the X5, so that code was used here
21 but left #if 0'ed out for the moment */
22
23#include "config.h" 19#include "config.h"
24
25#include "cpu.h" 20#include "cpu.h"
26#include "lcd.h" 21#include "lcd.h"
27#include "kernel.h" 22#include "kernel.h"
28#include "thread.h"
29#include <string.h>
30#include <stdlib.h>
31#include "file.h"
32#include "debug.h"
33#include "system.h" 23#include "system.h"
34#include "font.h"
35#include "bidi.h"
36 24
37static bool display_on=false; /* is the display turned on? */ 25/* check if number of useconds has past */
26static inline bool timer_check(int clock_start, int usecs)
27{
28 return ((int)(USEC_TIMER - clock_start)) >= usecs;
29}
38 30
39#define LCD_CMD *(volatile unsigned short *)0x70003008 /* or maybe 0x70008a0c */ 31/* Hardware address of LCD. Bits are:
40#define LCD_DATA *(volatile unsigned short *)0x70003010 32 * 31 - set to write, poll for completion.
33 * 24 - 0 for command, 1 for data
34 * 7..0 - command/data to send
35 * Commands/Data are always sent in 16-bits, msb first.
36 */
37#define LCD_BASE *(volatile unsigned int *)0x70008a0c
38#define LCD_BUSY_MASK 0x80000000
39#define LCD_CMD 0x80000000
40#define LCD_DATA 0x81000000
41 41
42/* register defines for the Renesas HD66773R */ 42/* register defines for the Renesas HD66773R */
43#define R_HORIZ_RAM_ADDR_POS 0x16 43#define R_START_OSC 0x00
44#define R_VERT_RAM_ADDR_POS 0x17 44#define R_DEVICE_CODE_READ 0x00
45#define R_DRV_OUTPUT_CONTROL 0x01
46#define R_DRV_AC_CONTROL 0x02
47#define R_POWER_CONTROL1 0x03
48#define R_POWER_CONTROL2 0x04
49#define R_ENTRY_MODE 0x05
50#define R_COMPARE_REG 0x06
51#define R_DISP_CONTROL 0x07
52#define R_FRAME_CYCLE_CONTROL 0x0b
53#define R_POWER_CONTROL3 0x0c
54#define R_POWER_CONTROL4 0x0d
55#define R_POWER_CONTROL5 0x0e
56#define R_GATE_SCAN_START_POS 0x0f
57#define R_VERT_SCROLL_CONTROL 0x11
58#define R_1ST_SCR_DRV_POS 0x14
59#define R_2ND_SCR_DRV_POS 0x15
60#define R_HORIZ_RAM_ADDR_POS 0x44
61#define R_VERT_RAM_ADDR_POS 0x45
62#define R_RAM_WRITE_DATA_MASK 0x20
45#define R_RAM_ADDR_SET 0x21 63#define R_RAM_ADDR_SET 0x21
46#define R_WRITE_DATA_2_GRAM 0x22 64#define R_WRITE_DATA_2_GRAM 0x22
65#define R_RAM_READ_DATA 0x22
66#define R_GAMMA_FINE_ADJ_POS1 0x30
67#define R_GAMMA_FINE_ADJ_POS2 0x31
68#define R_GAMMA_FINE_ADJ_POS3 0x32
69#define R_GAMMA_GRAD_ADJ_POS 0x33
70#define R_GAMMA_FINE_ADJ_NEG1 0x34
71#define R_GAMMA_FINE_ADJ_NEG2 0x35
72#define R_GAMMA_FINE_ADJ_NEG3 0x36
73#define R_GAMMA_GRAD_ADJ_NEG 0x37
74#define R_GAMMA_AMP_ADJ_POS 0x3a
75#define R_GAMMA_AMP_ADJ_NEG 0x3b
76
77
78static void lcd_wait_write(void)
79{
80 if ((LCD_BASE & LCD_BUSY_MASK) != 0) {
81 int start = USEC_TIMER;
47 82
48/***************************************************** 83 do {
49The table below was generated by the following script: 84 if ((LCD_BASE & LCD_BUSY_MASK) == 0) break;
50 85 } while (timer_check(start, 1000) == 0);
51#!/usr/bin/perl
52
53# high byte table
54print "short high8to9[] = {\n";
55$str = " ";
56for my $m (0 .. 255) {
57 # RRRRRGGG => RRRRR0GGG
58 my $v = (($m & 0xF8) << 1) | ($m & 0x07);
59 if(length($str) > 75) {
60 print "$str\n";
61 $str=" ";
62 } 86 }
63 $str .= sprintf("0x%03x, ", $v);
64} 87}
65print "$str\n};\n"; 88
66 89/* Send command */
67*****************************************************/ 90static void lcd_send_cmd(int v)
68
69/* Lookup table for 16->18bit conversion, high byte. The low byte is just
70 shifted. */
71const short high8to9[] ICONST_ATTR = {
72 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x010, 0x011, 0x012,
73 0x013, 0x014, 0x015, 0x016, 0x017, 0x020, 0x021, 0x022, 0x023, 0x024, 0x025,
74 0x026, 0x027, 0x030, 0x031, 0x032, 0x033, 0x034, 0x035, 0x036, 0x037, 0x040,
75 0x041, 0x042, 0x043, 0x044, 0x045, 0x046, 0x047, 0x050, 0x051, 0x052, 0x053,
76 0x054, 0x055, 0x056, 0x057, 0x060, 0x061, 0x062, 0x063, 0x064, 0x065, 0x066,
77 0x067, 0x070, 0x071, 0x072, 0x073, 0x074, 0x075, 0x076, 0x077, 0x080, 0x081,
78 0x082, 0x083, 0x084, 0x085, 0x086, 0x087, 0x090, 0x091, 0x092, 0x093, 0x094,
79 0x095, 0x096, 0x097, 0x0a0, 0x0a1, 0x0a2, 0x0a3, 0x0a4, 0x0a5, 0x0a6, 0x0a7,
80 0x0b0, 0x0b1, 0x0b2, 0x0b3, 0x0b4, 0x0b5, 0x0b6, 0x0b7, 0x0c0, 0x0c1, 0x0c2,
81 0x0c3, 0x0c4, 0x0c5, 0x0c6, 0x0c7, 0x0d0, 0x0d1, 0x0d2, 0x0d3, 0x0d4, 0x0d5,
82 0x0d6, 0x0d7, 0x0e0, 0x0e1, 0x0e2, 0x0e3, 0x0e4, 0x0e5, 0x0e6, 0x0e7, 0x0f0,
83 0x0f1, 0x0f2, 0x0f3, 0x0f4, 0x0f5, 0x0f6, 0x0f7, 0x100, 0x101, 0x102, 0x103,
84 0x104, 0x105, 0x106, 0x107, 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116,
85 0x117, 0x120, 0x121, 0x122, 0x123, 0x124, 0x125, 0x126, 0x127, 0x130, 0x131,
86 0x132, 0x133, 0x134, 0x135, 0x136, 0x137, 0x140, 0x141, 0x142, 0x143, 0x144,
87 0x145, 0x146, 0x147, 0x150, 0x151, 0x152, 0x153, 0x154, 0x155, 0x156, 0x157,
88 0x160, 0x161, 0x162, 0x163, 0x164, 0x165, 0x166, 0x167, 0x170, 0x171, 0x172,
89 0x173, 0x174, 0x175, 0x176, 0x177, 0x180, 0x181, 0x182, 0x183, 0x184, 0x185,
90 0x186, 0x187, 0x190, 0x191, 0x192, 0x193, 0x194, 0x195, 0x196, 0x197, 0x1a0,
91 0x1a1, 0x1a2, 0x1a3, 0x1a4, 0x1a5, 0x1a6, 0x1a7, 0x1b0, 0x1b1, 0x1b2, 0x1b3,
92 0x1b4, 0x1b5, 0x1b6, 0x1b7, 0x1c0, 0x1c1, 0x1c2, 0x1c3, 0x1c4, 0x1c5, 0x1c6,
93 0x1c7, 0x1d0, 0x1d1, 0x1d2, 0x1d3, 0x1d4, 0x1d5, 0x1d6, 0x1d7, 0x1e0, 0x1e1,
94 0x1e2, 0x1e3, 0x1e4, 0x1e5, 0x1e6, 0x1e7, 0x1f0, 0x1f1, 0x1f2, 0x1f3, 0x1f4,
95 0x1f5, 0x1f6, 0x1f7,
96};
97
98/* called very frequently - inline! */
99inline void lcd_write_reg(int reg, int val)
100{ 91{
101 LCD_CMD = (reg >> 8) << 1; 92 lcd_wait_write();
102 LCD_CMD = (reg & 0xff) << 1; 93 LCD_BASE = 0x00000000 | LCD_CMD;
103 LCD_DATA = (val >> 8) << 1; 94 LCD_BASE = v | LCD_CMD;
104 LCD_DATA = (val & 0xff) << 1;
105} 95}
106 96
107/* called very frequently - inline! */ 97/* Send 16-bit data */
108inline void lcd_begin_write_gram(void) 98static void lcd_send_data(int v)
109{ 99{
110 LCD_CMD = (R_WRITE_DATA_2_GRAM >> 8) << 1; 100 lcd_wait_write();
111 LCD_CMD = (R_WRITE_DATA_2_GRAM & 0xff) << 1; 101 LCD_BASE = ( v & 0xff) | LCD_DATA; /* Send MSB first */
102 LCD_BASE = ((v>>8) & 0xff) | LCD_DATA;
112} 103}
113 104
114/* called very frequently - inline! */ 105/* Send two 16-bit data */
115inline void lcd_write_data(const unsigned short* p_bytes, int count) ICODE_ATTR; 106static void lcd_send_data2(int v)
116inline void lcd_write_data(const unsigned short* p_bytes, int count)
117{ 107{
118 unsigned int tmp; 108 unsigned int vsr = v;
119 unsigned int *ptr = (unsigned int *)p_bytes; 109 lcd_send_data(vsr);
120 bool extra; 110 vsr = v >> 16;
121 111 lcd_send_data(vsr);
122 /* if there's on odd number of pixels, remmber this and output the
123 trailing pixel after the loop */
124 extra = (count&1)?true:false;
125
126 count >>= 1;
127 while(count--) {
128 tmp = *ptr++;
129 LCD_DATA = high8to9[tmp >> 24];
130 LCD_DATA = tmp>>15;
131 LCD_DATA = high8to9[(tmp >> 8)&255];
132 LCD_DATA = tmp<<1;
133 }
134 if(extra) {
135 /* the final "spare" pixel */
136 unsigned short read = *(unsigned short *)ptr;
137 LCD_DATA = high8to9[read >> 8];
138 LCD_DATA = read<<1;
139 }
140} 112}
141 113
142/*** hardware configuration ***/
143 114
144int lcd_default_contrast(void) 115/*** hardware configuration ***/
145{
146 return 16;
147}
148 116
149void lcd_set_contrast(int val) 117void lcd_set_contrast(int val)
150{ 118{
151 if (val >= 15) // val must'nt be 15 or 31 119 /* TODO: Implement lcd_set_contrast() */
152 ++val; 120 (void)val;
153 if (val > 30)
154 return;
155
156 lcd_write_reg(0x0e, 0x201e + (val << 8));
157} 121}
158 122
159void lcd_set_invert_display(bool yesno) 123void lcd_set_invert_display(bool yesno)
160{ 124{
161 (void)yesno; 125 /* TODO: Implement lcd_set_invert_display() */
126 (void)yesno;
162} 127}
163 128
164/* turn the display upside down (call lcd_update() afterwards) */ 129/* turn the display upside down (call lcd_update() afterwards) */
165void lcd_set_flip(bool yesno) 130void lcd_set_flip(bool yesno)
166{ 131{
167 (void)yesno; 132 /* TODO: Implement lcd_set_flip() */
168} 133 (void)yesno;
169
170/* Rolls up the lcd display by the specified amount of lines.
171 * Lines that are rolled out over the top of the screen are
172 * rolled in from the bottom again. This is a hardware
173 * remapping only and all operations on the lcd are affected.
174 * ->
175 * @param int lines - The number of lines that are rolled.
176 * The value must be 0 <= pixels < LCD_HEIGHT. */
177void lcd_roll(int lines)
178{
179 (void)lines;
180} 134}
181 135
182/* LCD init 136/* LCD init */
183 * These settings are taken from the original X5 firmware
184 */
185void lcd_init_device(void) 137void lcd_init_device(void)
186{ 138{
187 display_on=true; 139 /* H10 LCD is initialised by the bootloader */
188
189#if 0
190 /* LCD Reset */
191 and_l(~0x00000010, &GPIO1_OUT);
192 or_l(0x00000010, &GPIO1_ENABLE);
193 or_l(0x00000010, &GPIO1_FUNCTION);
194 sleep(HZ/100);
195 or_l(0x00000010, &GPIO1_OUT);
196
197 sleep(HZ/100);
198
199 lcd_write_reg(0, 0x0001);
200
201 sleep(HZ/50);
202
203 lcd_write_reg(0x0d, 0x0401);
204 lcd_write_reg(0x0e, 0x321e);
205 lcd_write_reg(0x01, 0x0313);
206 lcd_write_reg(0x02, 0x0700);
207 lcd_write_reg(0x05, 0x9038);
208 lcd_write_reg(0x06, 0x0000);
209 lcd_write_reg(0x0b, 0x4000);
210
211 sleep(HZ/100);
212
213 lcd_write_reg(0x21,0x0000);
214 lcd_write_reg(0x30,0x0003);
215 lcd_write_reg(0x31,0x0400);
216 lcd_write_reg(0x32,0x0407);
217 lcd_write_reg(0x33,0x0305);
218 lcd_write_reg(0x34,0x0003);
219 lcd_write_reg(0x35,0x0704);
220 lcd_write_reg(0x36,0x0407);
221 lcd_write_reg(0x37,0x0503);
222 lcd_write_reg(0x0f,0x0002);
223 lcd_write_reg(0x11,0x0000);
224 lcd_write_reg(0x14,0x9f00);
225 lcd_write_reg(0x15,0x5c00);
226 lcd_write_reg(0x16,0x7f00);
227 lcd_write_reg(0x17,0x9f00);
228 lcd_write_reg(0x3a,0x1409);
229 lcd_write_reg(0x3b,0x0602);
230
231 lcd_write_reg(0x0c,0x0001);
232
233 sleep(HZ/25);
234
235 lcd_write_reg(0x03,0x002c);
236 lcd_write_reg(0x04,0x8000);
237
238 sleep(HZ/25);
239
240 lcd_write_reg(0x0e,0x3318);
241
242 sleep(HZ/25);
243
244 lcd_write_reg(0x0d,0x0411);
245
246 sleep(HZ/100);
247
248 lcd_write_reg(0x07,0x0006);
249 lcd_write_reg(0x07,0x036);
250 lcd_write_reg(0x07,0x037);
251 lcd_write_reg(0x07,0x0037);
252 return;
253#endif
254}
255
256void lcd_enable(bool on)
257{
258 display_on = on;
259} 140}
260 141
261/*** update functions ***/ 142/*** update functions ***/
262 143
263/* Performance function that works with an external buffer 144/* Performance function that works with an external buffer
264 note that by and bheight are in 8-pixel units! */ 145 note that by and bheight are in 4-pixel units! */
265void lcd_blit(const fb_data* data, int x, int by, int width, 146void lcd_blit(const fb_data* data, int x, int by, int width,
266 int bheight, int stride) 147 int bheight, int stride)
267{ 148{
@@ -272,56 +153,83 @@ void lcd_blit(const fb_data* data, int x, int by, int width,
272 (void)width; 153 (void)width;
273 (void)bheight; 154 (void)bheight;
274 (void)stride; 155 (void)stride;
275 /*if(display_on)*/
276} 156}
277 157
278 158
279/* Update the display.
280 This must be called after all other LCD functions that change the display. */
281void lcd_update(void) ICODE_ATTR;
282void lcd_update(void)
283{
284 if(display_on){
285 159
286 /* Copy display bitmap to hardware */
287 lcd_write_reg(R_RAM_ADDR_SET, 0x0000);
288 lcd_begin_write_gram();
289 lcd_write_data((unsigned short *)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT);
290 }
291}
292 160
293/* Update a fraction of the display. */ 161/* Update a fraction of the display. */
294void lcd_update_rect(int, int, int, int) ICODE_ATTR;
295void lcd_update_rect(int x, int y, int width, int height) 162void lcd_update_rect(int x, int y, int width, int height)
296{ 163{
297 if(display_on) { 164 int y0, x0, y1, x1;
298 int ymax = y + height; 165 int newx,newwidth;
299 166
300 if(x + width > LCD_WIDTH) 167 unsigned long *addr = (unsigned long *)lcd_framebuffer;
301 width = LCD_WIDTH - x; 168
302 if (width <= 0) 169 /* Ensure x and width are both even - so we can read 32-bit aligned
303 return; /* nothing left to do, 0 is harmful to lcd_write_data() */ 170 data from lcd_framebuffer */
304 if(ymax >= LCD_HEIGHT) 171 /*newx=x&~1;
305 ymax = LCD_HEIGHT-1; 172 newwidth=width&~1;
306 173 if (newx+newwidth < x+width) { newwidth+=2; }
307 /* set update window */ 174 x=newx; width=newwidth;*/
308 175
309 /* horiz ram addr */ 176 /* calculate the drawing region */
310 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (ymax<<8) | y); 177 y0 = x; /* start horiz */
311 178 x0 = y; /* start vert */
312 /* vert ram addr */ 179 y1 = (x + width) - 1; /* max horiz */
313 lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+width-1)<<8) | x); 180 x1 = (y + height) - 1; /* max vert */
314 lcd_write_reg(R_RAM_ADDR_SET, (x<<8) | y); 181
315 lcd_begin_write_gram(); 182
316 183 /* swap max horiz < start horiz */
317 /* Copy specified rectangle bitmap to hardware */ 184 if (y1 < y0) {
318 for (; y <= ymax; y++) 185 int t;
319 { 186 t = y0;
320 lcd_write_data ((unsigned short *)&lcd_framebuffer[y][x], width); 187 y0 = y1;
321 } 188 y1 = t;
322 189 }
323 /* reset update window */ 190
324 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0x7f00); 191 /* swap max vert < start vert */
325 lcd_write_reg(R_VERT_RAM_ADDR_POS, 0x9f00); 192 if (x1 < x0) {
193 int t;
194 t = x0;
195 x0 = x1;
196 x1 = t;
326 } 197 }
198
199 /* max horiz << 8 | start horiz */
200 lcd_send_cmd(R_HORIZ_RAM_ADDR_POS);
201 lcd_send_data((y0 << 8) | y1);
202 /* max vert << 8 | start vert */
203 lcd_send_cmd(R_VERT_RAM_ADDR_POS);
204 lcd_send_data((x0 << 8) | x1);
205
206 /* position cursor (set AD0-AD15) */
207 /* start vert << 8 | start horiz */
208 lcd_send_cmd(R_RAM_ADDR_SET);
209 lcd_send_data(((x0 << 8) | y0));
210
211 /* start drawing */
212 lcd_send_cmd(R_WRITE_DATA_2_GRAM);
213
214 addr = (unsigned long*)&lcd_framebuffer[y][x];
215
216 int c, r;
217
218 /* for each row */
219 for (r = 0; r < height; r++) {
220 /* for each column */
221 for (c = 0; c < width; c += 2) {
222 /* output 2 pixels */
223 lcd_send_data2(*(addr++));
224 }
225
226 addr += (LCD_WIDTH - width)/2;
227 }
228}
229
230/* Update the display.
231 This must be called after all other LCD functions that change the display. */
232void lcd_update(void)
233{
234 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
327} 235}