Subversion Repositories freemyipod

Rev

Rev 648 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 648 Rev 669
Line 1... Line 1...
1
//
1
//
2
//
2
//
3
//    Copyright 2010 TheSeven
3
//    Copyright 2010 TheSeven
4
//
4
//
5
//
5
//
6
//    This file is part of emCORE.
6
//    This file is part of emCORE.
7
//
7
//
8
//    emCORE is free software: you can redistribute it and/or
8
//    emCORE is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
11
//    License, or (at your option) any later version.
12
//
12
//
13
//    emCORE is distributed in the hope that it will be useful,
13
//    emCORE is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
16
//    See the GNU General Public License for more details.
17
//
17
//
18
//    You should have received a copy of the GNU General Public License along
18
//    You should have received a copy of the GNU General Public License along
19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
20
//
20
//
21
//
21
//
22
 
22
 
23
 
23
 
24
#include "global.h"
24
#include "global.h"
25
#include "thread.h"
25
#include "thread.h"
26
#include "s5l8701.h"
26
#include "s5l8701.h"
27
#include "util.h"
27
#include "util.h"
28
 
28
 
29
 
29
 
30
static struct mutex lcd_mutex IDATA_ATTR;
30
static struct mutex lcd_mutex IDATA_ATTR;
31
static struct wakeup lcd_wakeup IDATA_ATTR;
31
static struct wakeup lcd_wakeup IDATA_ATTR;
32
 
32
 
33
static bool lcd_dma_busy IDATA_ATTR;
33
static bool lcd_dma_busy IDATA_ATTR;
34
static bool lcd_in_irq IDATA_ATTR;
34
static bool lcd_in_irq IDATA_ATTR;
35
 
35
 
36
 
36
 
37
void lcd_init()
37
void lcd_init()
38
{
38
{
39
    mutex_init(&lcd_mutex);
39
    mutex_init(&lcd_mutex);
40
    wakeup_init(&lcd_wakeup);
40
    wakeup_init(&lcd_wakeup);
41
    DMACON8 = 0x20590000;
41
    DMACON8 = 0x20590000;
42
    LCDCON = 0xd01;
42
    LCDCON = 0xd01;
43
    LCDPHTIME = 0;
43
    LCDPHTIME = 0;
44
    lcd_in_irq = false;
44
    lcd_in_irq = false;
45
    lcd_dma_busy = false;
45
    lcd_dma_busy = false;
46
}
46
}
47
 
47
 
48
int lcd_get_width()
48
int lcd_get_width()
49
{
49
{
50
    return LCD_WIDTH;
50
    return LCD_WIDTH;
51
}
51
}
52
 
52
 
53
int lcd_get_height()
53
int lcd_get_height()
54
{
54
{
55
    return LCD_HEIGHT;
55
    return LCD_HEIGHT;
56
}
56
}
57
 
57
 
58
int lcd_get_bytes_per_pixel()
58
int lcd_get_bytes_per_pixel()
59
{
59
{
60
    return LCD_BYTESPERPIXEL;
60
    return LCD_BYTESPERPIXEL;
61
}
61
}
62
 
62
 
63
int lcd_get_format()
63
int lcd_get_format()
64
{
64
{
65
    return LCD_FORMAT;
65
    return LCD_FORMAT;
66
}
66
}
67
 
67
 
68
static void lcd_send_cmd(uint16_t cmd) ICODE_ATTR __attribute__((noinline));
68
static void lcd_send_cmd(uint16_t cmd) ICODE_ATTR __attribute__((noinline));
69
static void lcd_send_cmd(uint16_t cmd)
69
static void lcd_send_cmd(uint16_t cmd)
70
{
70
{
71
    while (LCDSTATUS & 0x10);
71
    while (LCDSTATUS & 0x10);
72
    LCDWCMD = cmd;
72
    LCDWCMD = cmd;
73
}
73
}
74
 
74
 
75
static void lcd_send_data(uint16_t data) ICODE_ATTR __attribute__((noinline));
75
static void lcd_send_data(uint16_t data) ICODE_ATTR __attribute__((noinline));
76
static void lcd_send_data(uint16_t data)
76
static void lcd_send_data(uint16_t data)
77
{
77
{
78
    while (LCDSTATUS & 0x10);
78
    while (LCDSTATUS & 0x10);
79
    LCDWDATA = data;
79
    LCDWDATA = data;
80
}
80
}
81
 
81
 
82
static uint32_t lcd_detect() ICODE_ATTR;
82
static uint32_t lcd_detect() ICODE_ATTR;
83
static uint32_t lcd_detect()
83
static uint32_t lcd_detect()
84
{
84
{
85
    return (PDAT13 & 1) | (PDAT14 & 2);
85
    return (PDAT13 & 1) | (PDAT14 & 2);
86
}
86
}
87
 
87
 
88
bool displaylcd_busy() ICODE_ATTR;
88
bool displaylcd_busy() ICODE_ATTR;
89
bool displaylcd_busy()
89
bool displaylcd_busy()
90
{
90
{
91
    return lcd_dma_busy;
91
    return lcd_dma_busy;
92
}
92
}
93
 
93
 
94
bool displaylcd_safe()
94
bool displaylcd_safe()
95
{
95
{
96
    lcd_in_irq = true;
96
    lcd_in_irq = true;
97
    if (!lcd_dma_busy) return true;
97
    if (!lcd_dma_busy) return true;
98
    return !(DMAALLST2 & 0x70000);
98
    return !(DMAALLST2 & 0x70000);
99
}
99
}
100
 
100
 
101
void displaylcd_sync() ICODE_ATTR;
101
void displaylcd_sync() ICODE_ATTR;
102
void displaylcd_sync()
102
void displaylcd_sync()
103
{
103
{
104
    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
104
    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
105
    while (displaylcd_busy()) wakeup_wait(&lcd_wakeup, TIMEOUT_BLOCK);
105
    while (displaylcd_busy()) wakeup_wait(&lcd_wakeup, TIMEOUT_BLOCK);
106
    mutex_unlock(&lcd_mutex);
106
    mutex_unlock(&lcd_mutex);
107
}
107
}
108
 
108
 
109
void displaylcd_setup(unsigned int startx, unsigned int endx,
109
void displaylcd_setup(unsigned int startx, unsigned int endx,
110
                      unsigned int starty, unsigned int endy) ICODE_ATTR;
110
                      unsigned int starty, unsigned int endy) ICODE_ATTR;
111
void displaylcd_setup(unsigned int startx, unsigned int endx,
111
void displaylcd_setup(unsigned int startx, unsigned int endx,
112
                      unsigned int starty, unsigned int endy)
112
                      unsigned int starty, unsigned int endy)
113
{
113
{
114
    if (!lcd_in_irq)
114
    if (!lcd_in_irq)
115
    {
115
    {
116
        mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
116
        mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
117
        displaylcd_sync();
117
        displaylcd_sync();
118
    }
118
    }
119
    if (lcd_detect() == 2)
119
    if (lcd_detect() == 2)
120
    {
120
    {
121
        lcd_send_cmd(0x50);
121
        lcd_send_cmd(0x50);
122
        lcd_send_data(startx);
122
        lcd_send_data(startx);
123
        lcd_send_cmd(0x51);
123
        lcd_send_cmd(0x51);
124
        lcd_send_data(endx);
124
        lcd_send_data(endx);
125
        lcd_send_cmd(0x52);
125
        lcd_send_cmd(0x52);
126
        lcd_send_data(starty);
126
        lcd_send_data(starty);
127
        lcd_send_cmd(0x53);
127
        lcd_send_cmd(0x53);
128
        lcd_send_data(endy);
128
        lcd_send_data(endy);
129
        lcd_send_cmd(0x20);
129
        lcd_send_cmd(0x20);
130
        lcd_send_data(startx);
130
        lcd_send_data(startx);
131
        lcd_send_cmd(0x21);
131
        lcd_send_cmd(0x21);
132
        lcd_send_data(starty);
132
        lcd_send_data(starty);
133
        lcd_send_cmd(0x22);
133
        lcd_send_cmd(0x22);
134
    }
134
    }
135
    else
135
    else
136
    {
136
    {
137
        lcd_send_cmd(0x2a);
137
        lcd_send_cmd(0x2a);
138
        lcd_send_data(startx);
138
        lcd_send_data(startx);
139
        lcd_send_data(endx);
139
        lcd_send_data(endx);
140
        lcd_send_cmd(0x2b);
140
        lcd_send_cmd(0x2b);
141
        lcd_send_data(starty);
141
        lcd_send_data(starty);
142
        lcd_send_data(endy);
142
        lcd_send_data(endy);
143
        lcd_send_cmd(0x2c);
143
        lcd_send_cmd(0x2c);
144
    }
144
    }
145
}
145
}
146
 
146
 
147
static void displaylcd_dma(void* data, int pixels) ICODE_ATTR;
147
static void displaylcd_dma(void* data, int pixels) ICODE_ATTR;
148
static void displaylcd_dma(void* data, int pixels)
148
static void displaylcd_dma(void* data, int pixels)
149
{
149
{
150
    uint16_t* in = (uint16_t*)data;
150
    uint16_t* in = (uint16_t*)data;
151
    while (LCDSTATUS & 8);
151
    while (LCDSTATUS & 8);
152
    while (pixels & 3)
152
    while (pixels & 3)
153
	{
153
	{
154
        LCDWDATA = *in++;
154
        LCDWDATA = *in++;
155
        pixels--;
155
        pixels--;
156
	}
156
	}
157
    lcd_dma_busy = true;
157
    lcd_dma_busy = true;
158
    DMABASE8 = in;
158
    DMABASE8 = in;
159
    DMACON8 = 0x20590000;
159
    DMACON8 = 0x20590000;
160
    DMATCNT8 = pixels / 4;
160
    DMATCNT8 = pixels / 4;
161
    clean_dcache();
161
    clean_dcache();
162
    DMACOM8 = 4;
162
    DMACOM8 = 4;
163
}
163
}
164
 
164
 
165
static void displaylcd_solid(uint16_t data, int pixels) ICODE_ATTR;
165
static void displaylcd_solid(uint16_t data, int pixels) ICODE_ATTR;
166
static void displaylcd_solid(uint16_t data, int pixels)
166
static void displaylcd_solid(uint16_t data, int pixels)
167
{
167
{
168
    while (pixels >= 4)
168
    while (pixels >= 4)
169
    {
169
    {
170
        while (LCDSTATUS & 8);
170
        while (LCDSTATUS & 8);
171
        LCDWDATA = data;
171
        LCDWDATA = data;
172
        LCDWDATA = data;
172
        LCDWDATA = data;
173
        LCDWDATA = data;
173
        LCDWDATA = data;
174
        LCDWDATA = data;
174
        LCDWDATA = data;
175
        pixels -= 4;
175
        pixels -= 4;
176
    }
176
    }
177
    while (LCDSTATUS & 8);
177
    while (LCDSTATUS & 8);
178
    while (pixels & 3)
178
    while (pixels & 3)
179
	{
179
	{
180
        LCDWDATA = data;
180
        LCDWDATA = data;
181
        pixels--;
181
        pixels--;
182
	}
182
	}
183
}
183
}
184
 
184
 
185
void displaylcd_native(unsigned int startx, unsigned int endx,
185
void displaylcd_native(unsigned int startx, unsigned int endx,
186
                       unsigned int starty, unsigned int endy, void* data)
186
                       unsigned int starty, unsigned int endy, void* data)
187
{
187
{
188
    int pixels = (endx - startx + 1) * (endy - starty + 1);
188
    int pixels = (endx - startx + 1) * (endy - starty + 1);
189
    if (pixels <= 0) return;
189
    if (pixels <= 0) return;
190
    displaylcd_setup(startx, endx, starty, endy);
190
    displaylcd_setup(startx, endx, starty, endy);
191
    displaylcd_dma(data, pixels);
191
    displaylcd_dma(data, pixels);
192
    if (!lcd_in_irq) mutex_unlock(&lcd_mutex);
192
    if (!lcd_in_irq) mutex_unlock(&lcd_mutex);
193
}
193
}
194
 
194
 
195
void filllcd_native(unsigned int startx, unsigned int endx,
195
void filllcd_native(unsigned int startx, unsigned int endx,
196
                    unsigned int starty, unsigned int endy, int color)
196
                    unsigned int starty, unsigned int endy, int color)
197
{
197
{
198
    int pixels = (endx - startx + 1) * (endy - starty + 1);
198
    int pixels = (endx - startx + 1) * (endy - starty + 1);
199
    if (pixels <= 0) return;
199
    if (pixels <= 0) return;
200
    displaylcd_setup(startx, endx, starty, endy);
200
    displaylcd_setup(startx, endx, starty, endy);
201
    displaylcd_solid(color, pixels);
201
    displaylcd_solid(color, pixels);
202
    if (!lcd_in_irq) mutex_unlock(&lcd_mutex);
202
    if (!lcd_in_irq) mutex_unlock(&lcd_mutex);
203
}
203
}
204
 
204
 
205
void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width,
205
void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width,
206
                       unsigned int height, void* data, unsigned int datax,
206
                       unsigned int height, void* data, unsigned int datax,
207
                       unsigned int datay, unsigned int stride, bool solid)
207
                       unsigned int datay, unsigned int stride, bool solid)
208
     ICODE_ATTR __attribute__((naked,noinline));
208
     ICODE_ATTR __attribute__((naked,noinline));
209
void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width,
209
void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width,
210
                       unsigned int height, void* data, unsigned int datax,
210
                       unsigned int height, void* data, unsigned int datax,
211
                       unsigned int datay, unsigned int stride, bool solid)
211
                       unsigned int datay, unsigned int stride, bool solid)
212
{
212
{
213
    __asm__ volatile("    muls r12, r2, r3             \n");
213
    __asm__ volatile("    muls r12, r2, r3             \n");
214
    __asm__ volatile("    bxeq lr                      \n");
214
    __asm__ volatile("    bxeq lr                      \n");
215
    __asm__ volatile("    stmfd sp!, {r2-r11,lr}       \n");
215
    __asm__ volatile("    stmfd sp!, {r2-r11,lr}       \n");
216
    __asm__ volatile("    mov r12, r2                  \n");
216
    __asm__ volatile("    mov r12, r2                  \n");
217
    __asm__ volatile("    add r8, r2, r2,lsl#1         \n");
217
    __asm__ volatile("    add r8, r2, r2,lsl#1         \n");
218
    __asm__ volatile("    add r3, r1, r3               \n");
218
    __asm__ volatile("    add r3, r1, r3               \n");
219
    __asm__ volatile("    sub r3, r3, #1               \n");
219
    __asm__ volatile("    sub r3, r3, #1               \n");
220
    __asm__ volatile("    mov r2, r1                   \n");
220
    __asm__ volatile("    mov r2, r1                   \n");
221
    __asm__ volatile("    add r1, r0, r12              \n");
221
    __asm__ volatile("    add r1, r0, r12              \n");
222
    __asm__ volatile("    sub r1, r1, #1               \n");
222
    __asm__ volatile("    sub r1, r1, #1               \n");
223
    __asm__ volatile("    bl displaylcd_setup          \n");
223
    __asm__ volatile("    bl displaylcd_setup          \n");
224
    __asm__ volatile("    mov r0, r8                   \n");
224
    __asm__ volatile("    mov r0, r8                   \n");
225
    __asm__ volatile("    bl malloc                    \n");
225
    __asm__ volatile("    bl malloc                    \n");
226
    __asm__ volatile("    cmp r0, #0                   \n");
226
    __asm__ volatile("    cmp r0, #0                   \n");
227
    __asm__ volatile("    beq displaylcd_dither_unlock \n");
227
    __asm__ volatile("    beq displaylcd_dither_unlock \n");
228
    __asm__ volatile("    mov r2, r8                   \n");
228
    __asm__ volatile("    mov r2, r8                   \n");
229
    __asm__ volatile("    mov r1, #0                   \n");
229
    __asm__ volatile("    mov r1, #0                   \n");
230
    __asm__ volatile("    mov r8, r0                   \n");
230
    __asm__ volatile("    mov r8, r0                   \n");
231
    __asm__ volatile("    bl memset                    \n");
231
    __asm__ volatile("    bl memset                    \n");
232
    __asm__ volatile("    ldr r0, [sp,#0x30]           \n");
232
    __asm__ volatile("    ldr r0, [sp,#0x30]           \n");
233
    __asm__ volatile("    ldr r1, [sp,#0x34]           \n");
233
    __asm__ volatile("    ldr r1, [sp,#0x34]           \n");
234
    __asm__ volatile("    ldr r11, [sp,#0x38]          \n");
234
    __asm__ volatile("    ldr r11, [sp,#0x38]          \n");
235
    __asm__ volatile("    ldr r3, [sp,#0x2c]           \n");
235
    __asm__ volatile("    ldr r3, [sp,#0x2c]           \n");
236
    __asm__ volatile("    mla r0, r1, r11, r0          \n");
236
    __asm__ volatile("    mla r0, r1, r11, r0          \n");
237
    __asm__ volatile("    ldr r12, [sp,#0x04]          \n");
237
    __asm__ volatile("    ldr r12, [sp,#0x04]          \n");
238
    __asm__ volatile("    ldr r2, [sp,#0x3c]           \n");
238
    __asm__ volatile("    ldr r2, [sp,#0x3c]           \n");
239
    __asm__ volatile("    add r3, r3, r0,lsl#1         \n");
239
    __asm__ volatile("    add r3, r3, r0,lsl#1         \n");
240
    __asm__ volatile("    cmp r2, #0                   \n");
240
    __asm__ volatile("    cmp r2, #0                   \n");
241
    __asm__ volatile("    ldreq r1, [sp]               \n");
241
    __asm__ volatile("    ldreq r1, [sp]               \n");
242
    __asm__ volatile("    add r3, r3, r0               \n");
242
    __asm__ volatile("    add r3, r3, r0               \n");
243
    __asm__ volatile("    subeq r11, r11, r1           \n");
243
    __asm__ volatile("    subeq r11, r11, r1           \n");
244
    __asm__ volatile("    add r11, r11, r11,lsl#1      \n");
244
    __asm__ volatile("    add r11, r11, r11,lsl#1      \n");
245
    __asm__ volatile("    movne r10, #3                \n");
245
    __asm__ volatile("    movne r10, #3                \n");
246
    __asm__ volatile("    moveq r10, #0                \n");
246
    __asm__ volatile("    moveq r10, #0                \n");
247
    __asm__ volatile("    ldr r9, =0x38600040          \n");
247
    __asm__ volatile("    ldr r9, =0x38600040          \n");
248
    __asm__ volatile("displaylcd_dither_y:             \n");
248
    __asm__ volatile("displaylcd_dither_y:             \n");
249
    __asm__ volatile("    ldr lr, [sp]                 \n");
249
    __asm__ volatile("    ldr lr, [sp]                 \n");
250
    __asm__ volatile("    mov r4, #0                   \n");
250
    __asm__ volatile("    mov r4, #0                   \n");
251
    __asm__ volatile("    mov r5, #0                   \n");
251
    __asm__ volatile("    mov r5, #0                   \n");
252
    __asm__ volatile("    mov r6, #0                   \n");
252
    __asm__ volatile("    mov r6, #0                   \n");
253
    __asm__ volatile("    mov r7, r8                   \n");
253
    __asm__ volatile("    mov r7, r8                   \n");
254
    __asm__ volatile("displaylcd_dither_x:             \n");
254
    __asm__ volatile("displaylcd_dither_x:             \n");
255
    __asm__ volatile("    mov r2, #0                   \n");
255
    __asm__ volatile("    mov r2, #0                   \n");
256
    __asm__ volatile("    ldrb r1, [r3], #1            \n");
256
    __asm__ volatile("    ldrb r1, [r3], #1            \n");
257
    __asm__ volatile("    ldrsb r0, [r7]               \n");
257
    __asm__ volatile("    ldrsb r0, [r7]               \n");
258
    __asm__ volatile("    add r1, r1, r4               \n");
258
    __asm__ volatile("    add r1, r1, r4               \n");
259
    __asm__ volatile("    add r1, r1, r0               \n");
259
    __asm__ volatile("    add r1, r1, r0               \n");
260
    __asm__ volatile("    cmp r1, #0xff                \n");
260
    __asm__ volatile("    cmp r1, #0xff                \n");
261
    __asm__ volatile("    mvnhi r1, r1,asr#31          \n");
261
    __asm__ volatile("    mvnhi r1, r1,asr#31          \n");
262
    __asm__ volatile("    andhi r1, r1, #0xff          \n");
262
    __asm__ volatile("    andhi r1, r1, #0xff          \n");
263
    __asm__ volatile("    mov r0, r1,lsr#3             \n");
263
    __asm__ volatile("    mov r0, r1,lsr#3             \n");
264
    __asm__ volatile("    orr r2, r0,lsl#11            \n");
264
    __asm__ volatile("    orr r2, r0,lsl#11            \n");
265
    __asm__ volatile("    sub r1, r1, r0,lsl#3         \n");
265
    __asm__ volatile("    sub r1, r1, r0,lsl#3         \n");
266
    __asm__ volatile("    sub r1, r1, r0,lsr#2         \n");
266
    __asm__ volatile("    sub r1, r1, r0,lsr#2         \n");
267
    __asm__ volatile("    mov r4, r4,lsr#1             \n");
267
    __asm__ volatile("    mov r4, r4,lsr#1             \n");
268
    __asm__ volatile("    add r4, r4, r1,lsr#2         \n");
268
    __asm__ volatile("    add r4, r4, r1,lsr#2         \n");
269
    __asm__ volatile("    strb r4, [r7], #1            \n");
269
    __asm__ volatile("    strb r4, [r7], #1            \n");
270
    __asm__ volatile("    mov r4, r1,asr#1             \n");
270
    __asm__ volatile("    mov r4, r1,asr#1             \n");
271
    __asm__ volatile("    ldrb r1, [r3], #1            \n");
271
    __asm__ volatile("    ldrb r1, [r3], #1            \n");
272
    __asm__ volatile("    ldrsb r0, [r7]               \n");
272
    __asm__ volatile("    ldrsb r0, [r7]               \n");
273
    __asm__ volatile("    add r1, r1, r5               \n");
273
    __asm__ volatile("    add r1, r1, r5               \n");
274
    __asm__ volatile("    add r1, r1, r0               \n");
274
    __asm__ volatile("    add r1, r1, r0               \n");
275
    __asm__ volatile("    cmp r1, #0xff                \n");
275
    __asm__ volatile("    cmp r1, #0xff                \n");
276
    __asm__ volatile("    mvnhi r1, r1,asr#31          \n");
276
    __asm__ volatile("    mvnhi r1, r1,asr#31          \n");
277
    __asm__ volatile("    andhi r1, r1, #0xff          \n");
277
    __asm__ volatile("    andhi r1, r1, #0xff          \n");
278
    __asm__ volatile("    mov r0, r1,lsr#2             \n");
278
    __asm__ volatile("    mov r0, r1,lsr#2             \n");
279
    __asm__ volatile("    orr r2, r0,lsl#5             \n");
279
    __asm__ volatile("    orr r2, r0,lsl#5             \n");
280
    __asm__ volatile("    sub r1, r1, r0,lsl#2         \n");
280
    __asm__ volatile("    sub r1, r1, r0,lsl#2         \n");
281
    __asm__ volatile("    sub r1, r1, r0,lsr#4         \n");
281
    __asm__ volatile("    sub r1, r1, r0,lsr#4         \n");
282
    __asm__ volatile("    mov r5, r5,lsr#1             \n");
282
    __asm__ volatile("    mov r5, r5,lsr#1             \n");
283
    __asm__ volatile("    add r5, r5, r1,lsr#2         \n");
283
    __asm__ volatile("    add r5, r5, r1,lsr#2         \n");
284
    __asm__ volatile("    strb r5, [r7], #1            \n");
284
    __asm__ volatile("    strb r5, [r7], #1            \n");
285
    __asm__ volatile("    mov r5, r1,asr#1             \n");
285
    __asm__ volatile("    mov r5, r1,asr#1             \n");
286
    __asm__ volatile("    ldrb r1, [r3], #1            \n");
286
    __asm__ volatile("    ldrb r1, [r3], #1            \n");
287
    __asm__ volatile("    ldrsb r0, [r7]               \n");
287
    __asm__ volatile("    ldrsb r0, [r7]               \n");
288
    __asm__ volatile("    add r1, r1, r6               \n");
288
    __asm__ volatile("    add r1, r1, r6               \n");
289
    __asm__ volatile("    add r1, r1, r0               \n");
289
    __asm__ volatile("    add r1, r1, r0               \n");
290
    __asm__ volatile("    cmp r1, #0xff                \n");
290
    __asm__ volatile("    cmp r1, #0xff                \n");
291
    __asm__ volatile("    mvnhi r1, r1,asr#31          \n");
291
    __asm__ volatile("    mvnhi r1, r1,asr#31          \n");
292
    __asm__ volatile("    andhi r1, r1, #0xff          \n");
292
    __asm__ volatile("    andhi r1, r1, #0xff          \n");
293
    __asm__ volatile("    mov r0, r1,lsr#3             \n");
293
    __asm__ volatile("    mov r0, r1,lsr#3             \n");
294
    __asm__ volatile("    orr r2, r0                   \n");
294
    __asm__ volatile("    orr r2, r0                   \n");
295
    __asm__ volatile("    sub r1, r1, r0,lsl#3         \n");
295
    __asm__ volatile("    sub r1, r1, r0,lsl#3         \n");
296
    __asm__ volatile("    sub r1, r1, r0,lsr#2         \n");
296
    __asm__ volatile("    sub r1, r1, r0,lsr#2         \n");
297
    __asm__ volatile("    mov r6, r6,lsr#1             \n");
297
    __asm__ volatile("    mov r6, r6,lsr#1             \n");
298
    __asm__ volatile("    add r6, r6, r1,lsr#2         \n");
298
    __asm__ volatile("    add r6, r6, r1,lsr#2         \n");
299
    __asm__ volatile("    strb r6, [r7], #1            \n");
299
    __asm__ volatile("    strb r6, [r7], #1            \n");
300
    __asm__ volatile("displaylcd_dither_waitlcd:       \n");
300
    __asm__ volatile("displaylcd_dither_waitlcd:       \n");
301
    __asm__ volatile("    ldr r0, [r9,#-0x24]          \n");
301
    __asm__ volatile("    ldr r0, [r9,#-0x24]          \n");
302
    __asm__ volatile("    mov r6, r1,asr#1             \n");
302
    __asm__ volatile("    mov r6, r1,asr#1             \n");
303
    __asm__ volatile("    tst r0, #0x10                \n");
303
    __asm__ volatile("    tst r0, #0x10                \n");
304
    __asm__ volatile("    bne displaylcd_dither_waitlcd\n");
304
    __asm__ volatile("    bne displaylcd_dither_waitlcd\n");
305
    __asm__ volatile("    str r2, [r9]                 \n");
305
    __asm__ volatile("    str r2, [r9]                 \n");
306
    __asm__ volatile("    sub r3, r3, r10              \n");
306
    __asm__ volatile("    sub r3, r3, r10              \n");
307
    __asm__ volatile("    subs lr, lr, #1              \n");
307
    __asm__ volatile("    subs lr, lr, #1              \n");
308
    __asm__ volatile("    bne displaylcd_dither_x      \n");
308
    __asm__ volatile("    bne displaylcd_dither_x      \n");
309
    __asm__ volatile("    add r3, r3, r11              \n");
309
    __asm__ volatile("    add r3, r3, r11              \n");
310
    __asm__ volatile("    subs r12, r12, #1            \n");
310
    __asm__ volatile("    subs r12, r12, #1            \n");
311
    __asm__ volatile("    bne displaylcd_dither_y      \n");
311
    __asm__ volatile("    bne displaylcd_dither_y      \n");
312
    __asm__ volatile("displaylcd_dither_free:          \n");
312
    __asm__ volatile("displaylcd_dither_free:          \n");
313
    __asm__ volatile("    mov r0, r8                   \n");
313
    __asm__ volatile("    mov r0, r8                   \n");
314
    __asm__ volatile("    bl free                      \n");
314
    __asm__ volatile("    bl free                      \n");
315
    __asm__ volatile("displaylcd_dither_unlock:        \n");
315
    __asm__ volatile("displaylcd_dither_unlock:        \n");
316
    __asm__ volatile("    ldr r0, =lcd_mutex           \n");
316
    __asm__ volatile("    ldr r0, =lcd_mutex           \n");
317
    __asm__ volatile("    bl mutex_unlock              \n");
317
    __asm__ volatile("    bl mutex_unlock              \n");
318
    __asm__ volatile("    ldmfd sp!, {r2-r11,pc}       \n");
318
    __asm__ volatile("    ldmfd sp!, {r2-r11,pc}       \n");
319
}
319
}
320
 
320
 
321
void displaylcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height,
321
void displaylcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height,
322
                void* data, unsigned int datax, unsigned int datay, unsigned int stride)
322
                void* data, unsigned int datax, unsigned int datay, unsigned int stride)
323
{
323
{
324
    displaylcd_dither(x, y, width, height, data, datax, datay, stride, false);
324
    displaylcd_dither(x, y, width, height, data, datax, datay, stride, false);
325
}
325
}
326
 
326
 
327
void filllcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int color)
327
void filllcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int color)
328
{
328
{
329
    if (width * height <= 0) return;
329
    if (width * height <= 0) return;
330
    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
330
    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
331
    displaylcd_sync();
331
    displaylcd_sync();
332
    displaylcd_dither(x, y, width, height, &color, 0, 0, 0, true);
332
    displaylcd_dither(x, y, width, height, &color, 0, 0, 0, true);
333
    mutex_unlock(&lcd_mutex);
333
    mutex_unlock(&lcd_mutex);
334
}
334
}
335
 
335
 
336
void lcd_shutdown()
336
void lcd_shutdown()
337
{
337
{
338
    displaylcd_sync();
338
    displaylcd_sync();
339
    uint32_t type = lcd_detect();
339
    uint32_t type = lcd_detect();
340
    if (type == 2)
340
    if (type == 2)
341
    {
341
    {
342
        lcd_send_cmd(0x7);
342
        lcd_send_cmd(0x7);
343
        lcd_send_data(0x232);
343
        lcd_send_data(0x232);
344
        lcd_send_cmd(0x13);
344
        lcd_send_cmd(0x13);
345
        lcd_send_data(0x1137);
345
        lcd_send_data(0x1137);
346
        lcd_send_cmd(0x7);
346
        lcd_send_cmd(0x7);
347
        lcd_send_data(0x201);
347
        lcd_send_data(0x201);
348
        lcd_send_cmd(0x13);
348
        lcd_send_cmd(0x13);
349
        lcd_send_data(0x137);
349
        lcd_send_data(0x137);
350
        lcd_send_cmd(0x7);
350
        lcd_send_cmd(0x7);
351
        lcd_send_data(0x200);
351
        lcd_send_data(0x200);
352
        lcd_send_cmd(0x10);
352
        lcd_send_cmd(0x10);
353
        lcd_send_data(0x680);
353
        lcd_send_data(0x680);
354
        lcd_send_cmd(0x12);
354
        lcd_send_cmd(0x12);
355
        lcd_send_data(0x160);
355
        lcd_send_data(0x160);
356
        lcd_send_cmd(0x13);
356
        lcd_send_cmd(0x13);
357
        lcd_send_data(0x127);
357
        lcd_send_data(0x127);
358
        lcd_send_cmd(0x10);
358
        lcd_send_cmd(0x10);
359
        lcd_send_data(0x600);
359
        lcd_send_data(0x600);
360
    }
360
    }
361
    else
361
    else
362
    {
362
    {
363
        lcd_send_cmd(0x28);
363
        lcd_send_cmd(0x28);
364
        lcd_send_cmd(0x10);
364
        lcd_send_cmd(0x10);
365
    }
365
    }
366
    sleep(5000);
366
    sleep(10000);
367
}
367
}
368
 
368
 
369
void INT_DMA8()
369
void INT_DMA8()
370
{
370
{
371
    DMACOM8 = 7;
371
    DMACOM8 = 7;
372
    lcd_in_irq = true;
372
    lcd_in_irq = true;
373
    lcd_dma_busy = false;
373
    lcd_dma_busy = false;
374
    lcdconsole_callback();
374
    lcdconsole_callback();
375
    wakeup_signal(&lcd_wakeup);
375
    wakeup_signal(&lcd_wakeup);
376
    lcd_in_irq = false;
376
    lcd_in_irq = false;
377
}
377
}
378
 
378
 
379
int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
379
int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
380
    ICODE_ATTR __attribute__((naked, noinline));
380
    ICODE_ATTR __attribute__((naked, noinline));
381
int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
381
int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
382
{
382
{
383
    asm volatile(
383
    asm volatile(
384
        "cmp r0, #0xff             \n\t"
384
        "cmp r0, #0xff             \n\t"
385
        "moveq r0, #-1             \n\t"
385
        "moveq r0, #-1             \n\t"
386
        "moveq pc, lr              \n\t"
386
        "moveq pc, lr              \n\t"
387
        "cmp r0, #0                \n\t"
387
        "cmp r0, #0                \n\t"
388
        "movne r0, #0xff000000     \n\t"
388
        "movne r0, #0xff000000     \n\t"
389
        "orrne r0, r0, #0xff0000   \n\t"
389
        "orrne r0, r0, #0xff0000   \n\t"
390
        "mov r2, r2,lsr#2          \n\t"
390
        "mov r2, r2,lsr#2          \n\t"
391
        "orr r0, r0, r3,lsr#3      \n\t"
391
        "orr r0, r0, r3,lsr#3      \n\t"
392
        "mov r1, r1,lsr#3          \n\t"
392
        "mov r1, r1,lsr#3          \n\t"
393
        "orr r0, r0, r2,lsl#5      \n\t"
393
        "orr r0, r0, r2,lsl#5      \n\t"
394
        "orr r0, r0, r1,lsl#11     \n\t"
394
        "orr r0, r0, r1,lsl#11     \n\t"
395
        "mov pc, lr                \n\t"
395
        "mov pc, lr                \n\t"
396
    );
396
    );
397
}
397
}