Subversion Repositories freemyipod

Rev

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

Rev 648 Rev 650
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 "s5l8720.h"
26
#include "s5l8720.h"
27
#include "util.h"
27
#include "util.h"
28
#include "clockgates-target.h"
28
#include "clockgates-target.h"
29
 
29
 
30
 
30
 
31
static struct dma_lli lcd_lli[(LCD_WIDTH * LCD_HEIGHT - 1) / 0xfff]
31
static struct dma_lli lcd_lli[(LCD_WIDTH * LCD_HEIGHT - 1) / 0xfff]
32
    IDATA_ATTR __attribute__((aligned(16)));
32
    IDATA_ATTR __attribute__((aligned(16)));
33
 
33
 
34
static uint16_t lcd_color IDATA_ATTR;
34
static uint16_t lcd_color IDATA_ATTR;
35
 
35
 
36
static struct mutex lcd_mutex IDATA_ATTR;
36
static struct mutex lcd_mutex IDATA_ATTR;
37
static struct wakeup lcd_wakeup IDATA_ATTR;
37
static struct wakeup lcd_wakeup IDATA_ATTR;
38
 
38
 
39
static bool lcd_dma_busy IDATA_ATTR;
39
static bool lcd_dma_busy IDATA_ATTR;
40
static bool lcd_in_irq IDATA_ATTR;
40
static bool lcd_in_irq IDATA_ATTR;
41
 
41
 
42
 
42
 
43
void lcd_init()
43
void lcd_init()
44
{
44
{
45
    mutex_init(&lcd_mutex);
45
    mutex_init(&lcd_mutex);
46
    wakeup_init(&lcd_wakeup);
46
    wakeup_init(&lcd_wakeup);
47
    lcd_in_irq = false;
47
    lcd_in_irq = false;
48
    lcd_dma_busy = true;
48
    lcd_dma_busy = true;
49
    clockgate_dma(0, 4, true);
49
    clockgate_dma(0, 4, true);
50
    if (!(DMAC0C4CONFIG & 1))
50
    if (!(DMAC0C4CONFIG & 1))
51
    {
51
    {
52
        lcd_dma_busy = false;
52
        lcd_dma_busy = false;
53
        clockgate_dma(0, 4, false);
53
        clockgate_dma(0, 4, false);
54
    }
54
    }
55
}
55
}
56
 
56
 
57
int lcd_get_width()
57
int lcd_get_width()
58
{
58
{
59
    return LCD_WIDTH;
59
    return LCD_WIDTH;
60
}
60
}
61
 
61
 
62
int lcd_get_height()
62
int lcd_get_height()
63
{
63
{
64
    return LCD_HEIGHT;
64
    return LCD_HEIGHT;
65
}
65
}
66
 
66
 
67
int lcd_get_bytes_per_pixel()
67
int lcd_get_bytes_per_pixel()
68
{
68
{
69
    return LCD_BYTESPERPIXEL;
69
    return LCD_BYTESPERPIXEL;
70
}
70
}
71
 
71
 
72
int lcd_get_format()
72
int lcd_get_format()
73
{
73
{
74
    return LCD_FORMAT;
74
    return LCD_FORMAT;
75
}
75
}
76
 
76
 
77
static void lcd_send_cmd(uint16_t cmd) ICODE_ATTR __attribute__((noinline));
77
static void lcd_send_cmd(uint16_t cmd) ICODE_ATTR __attribute__((noinline));
78
static void lcd_send_cmd(uint16_t cmd)
78
static void lcd_send_cmd(uint16_t cmd)
79
{
79
{
80
    while (LCDSTATUS & 0x10);
80
    while (LCDSTATUS & 0x10);
81
    LCDWCMD = cmd;
81
    LCDWCMD = cmd;
82
}
82
}
83
 
83
 
84
static void lcd_send_data(uint16_t data) ICODE_ATTR __attribute__((noinline));
84
static void lcd_send_data(uint16_t data) ICODE_ATTR __attribute__((noinline));
85
static void lcd_send_data(uint16_t data)
85
static void lcd_send_data(uint16_t data)
86
{
86
{
87
    while (LCDSTATUS & 0x10);
87
    while (LCDSTATUS & 0x10);
88
    LCDWDATA = (data & 0xff) | ((data & 0x7f00) << 1);
88
    LCDWDATA = (data & 0xff) | ((data & 0x7f00) << 1);
89
}
89
}
90
 
90
 
91
void lcd_shutdown()
91
void lcd_shutdown()
92
{
92
{
93
}
93
}
94
 
94
 
95
bool displaylcd_busy() ICODE_ATTR;
95
bool displaylcd_busy() ICODE_ATTR;
96
bool displaylcd_busy()
96
bool displaylcd_busy()
97
{
97
{
98
    return lcd_dma_busy;
98
    return lcd_dma_busy;
99
}
99
}
100
 
100
 
101
bool displaylcd_safe()
101
bool displaylcd_safe()
102
{
102
{
103
    lcd_in_irq = true;
103
    lcd_in_irq = true;
104
    if (!lcd_dma_busy) return true;
104
    if (!lcd_dma_busy) return true;
105
    return !(DMAC0C4CONFIG & 1);
105
    return !(DMAC0C4CONFIG & 1);
106
}
106
}
107
 
107
 
108
void displaylcd_sync() ICODE_ATTR;
108
void displaylcd_sync() ICODE_ATTR;
109
void displaylcd_sync()
109
void displaylcd_sync()
110
{
110
{
111
    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
111
    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
112
    while (displaylcd_busy()) wakeup_wait(&lcd_wakeup, TIMEOUT_BLOCK);
112
    while (displaylcd_busy()) wakeup_wait(&lcd_wakeup, TIMEOUT_BLOCK);
113
    mutex_unlock(&lcd_mutex);
113
    mutex_unlock(&lcd_mutex);
114
}
114
}
115
 
115
 
116
void displaylcd_setup(unsigned int startx, unsigned int endx,
116
void displaylcd_setup(unsigned int startx, unsigned int endx,
117
                      unsigned int starty, unsigned int endy) ICODE_ATTR;
117
                      unsigned int starty, unsigned int endy) ICODE_ATTR;
118
void displaylcd_setup(unsigned int startx, unsigned int endx,
118
void displaylcd_setup(unsigned int startx, unsigned int endx,
119
                      unsigned int starty, unsigned int endy)
119
                      unsigned int starty, unsigned int endy)
120
{
120
{
121
    if (!lcd_in_irq)
121
    if (!lcd_in_irq)
122
    {
122
    {
123
        mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
123
        mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
124
        displaylcd_sync();
124
        displaylcd_sync();
125
    }
125
    }
126
    lcd_send_cmd(0x2a);
126
    lcd_send_cmd(0x2a);
127
    lcd_send_data(startx);
127
    lcd_send_data(startx);
128
    lcd_send_data(endx);
128
    lcd_send_data(endx);
129
    lcd_send_cmd(0x2b);
129
    lcd_send_cmd(0x2b);
130
    lcd_send_data(starty);
130
    lcd_send_data(starty);
131
    lcd_send_data(endy);
131
    lcd_send_data(endy);
132
    lcd_send_cmd(0x2c);
132
    lcd_send_cmd(0x2c);
133
}
133
}
134
 
134
 
135
static void displaylcd_dma(void* data, int pixels, bool solid) ICODE_ATTR;
135
static void displaylcd_dma(void* data, int pixels, bool solid) ICODE_ATTR;
136
static void displaylcd_dma(void* data, int pixels, bool solid)
136
static void displaylcd_dma(void* data, int pixels, bool solid)
137
{
137
{
138
    int i;
138
    int i;
139
    lcd_dma_busy = true;
139
    lcd_dma_busy = true;
140
    clockgate_dma(0, 4, true);
140
    clockgate_dma(0, 4, true);
141
    for (i = -1; i < (int)ARRAYLEN(lcd_lli) && pixels > 0; i++, pixels -= 0xfff)
141
    for (i = -1; i < (int)ARRAYLEN(lcd_lli) && pixels > 0; i++, pixels -= 0xfff)
142
    {
142
    {
143
        bool last = i + 1 >= ARRAYLEN(lcd_lli) || pixels <= 0xfff;
143
        bool last = i + 1 >= ARRAYLEN(lcd_lli) || pixels <= 0xfff;
144
        struct dma_lli* lli = i < 0 ? (struct dma_lli*)((int)&DMAC0C4LLI) : &lcd_lli[i];
144
        struct dma_lli* lli = i < 0 ? (struct dma_lli*)((int)&DMAC0C4LLI) : &lcd_lli[i];
145
        lli->srcaddr = data;
145
        lli->srcaddr = data;
146
        lli->dstaddr = (void*)((int)&LCDWDATA);
146
        lli->dstaddr = (void*)((int)&LCDWDATA);
147
        lli->nextlli = last ? NULL : &lcd_lli[i + 1];
147
        lli->nextlli = last ? NULL : &lcd_lli[i + 1];
148
        lli->control = 0x70240000 | (last ? pixels : 0xfff)
148
        lli->control = 0x70240000 | (last ? pixels : 0xfff)
149
                     | (last ? 0x80000000 : 0) | (solid ? 0 : 0x4000000);
149
                     | (last ? 0x80000000 : 0) | (solid ? 0 : 0x4000000);
150
        if (!solid) data = (void*)(((uint32_t)data) + 0x1ffe);
150
        if (!solid) data = (void*)(((uint32_t)data) + 0x1ffe);
151
    }
151
    }
152
    clean_dcache();
152
    clean_dcache();
153
    DMAC0C4CONFIG = 0x88c1;
153
    DMAC0C4CONFIG = 0x88c1;
154
}
154
}
155
 
155
 
156
void displaylcd_native(unsigned int startx, unsigned int endx,
156
void displaylcd_native(unsigned int startx, unsigned int endx,
157
                       unsigned int starty, unsigned int endy, void* data)
157
                       unsigned int starty, unsigned int endy, void* data)
158
{
158
{
159
    int pixels = (endx - startx + 1) * (endy - starty + 1);
159
    int pixels = (endx - startx + 1) * (endy - starty + 1);
160
    if (pixels <= 0) return;
160
    if (pixels <= 0) return;
161
    displaylcd_setup(startx, endx, starty, endy);
161
    displaylcd_setup(startx, endx, starty, endy);
162
    displaylcd_dma(data, pixels, false);
162
    displaylcd_dma(data, pixels, false);
163
    if (!lcd_in_irq) mutex_unlock(&lcd_mutex);
163
    if (!lcd_in_irq) mutex_unlock(&lcd_mutex);
164
}
164
}
165
 
165
 
166
void filllcd_native(unsigned int startx, unsigned int endx,
166
void filllcd_native(unsigned int startx, unsigned int endx,
167
                    unsigned int starty, unsigned int endy, int color)
167
                    unsigned int starty, unsigned int endy, int color)
168
{
168
{
169
    int pixels = (endx - startx + 1) * (endy - starty + 1);
169
    int pixels = (endx - startx + 1) * (endy - starty + 1);
170
    if (pixels <= 0) return;
170
    if (pixels <= 0) return;
171
    displaylcd_setup(startx, endx, starty, endy);
171
    displaylcd_setup(startx, endx, starty, endy);
172
    lcd_color = color;
172
    lcd_color = color;
173
    displaylcd_dma(&lcd_color, pixels, true);
173
    displaylcd_dma(&lcd_color, pixels, true);
174
    if (!lcd_in_irq) mutex_unlock(&lcd_mutex);
174
    if (!lcd_in_irq) mutex_unlock(&lcd_mutex);
175
}
175
}
176
 
176
 
177
void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width,
177
void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width,
178
                       unsigned int height, void* data, unsigned int datax,
178
                       unsigned int height, void* data, unsigned int datax,
179
                       unsigned int datay, unsigned int stride, bool solid)
179
                       unsigned int datay, unsigned int stride, bool solid)
180
     ICODE_ATTR __attribute__((naked,noinline));
180
     ICODE_ATTR __attribute__((naked,noinline));
181
void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width,
181
void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width,
182
                       unsigned int height, void* data, unsigned int datax,
182
                       unsigned int height, void* data, unsigned int datax,
183
                       unsigned int datay, unsigned int stride, bool solid)
183
                       unsigned int datay, unsigned int stride, bool solid)
184
{
184
{
185
//TODO: This is ARMv5E optimized assembly, should be converted to ARMv6
185
//TODO: This is ARMv5E optimized assembly, should be converted to ARMv6
186
    __asm__ volatile("    muls r12, r2, r3             \n");
186
    __asm__ volatile("    muls r12, r2, r3             \n");
187
    __asm__ volatile("    bxeq lr                      \n");
187
    __asm__ volatile("    bxeq lr                      \n");
188
    __asm__ volatile("    stmfd sp!, {r2-r11,lr}       \n");
188
    __asm__ volatile("    stmfd sp!, {r2-r11,lr}       \n");
189
    __asm__ volatile("    mov r12, r2                  \n");
189
    __asm__ volatile("    mov r12, r2                  \n");
190
    __asm__ volatile("    add r8, r2, r2,lsl#1         \n");
190
    __asm__ volatile("    add r8, r2, r2,lsl#1         \n");
191
    __asm__ volatile("    add r3, r1, r3               \n");
191
    __asm__ volatile("    add r3, r1, r3               \n");
192
    __asm__ volatile("    sub r3, r3, #1               \n");
192
    __asm__ volatile("    sub r3, r3, #1               \n");
193
    __asm__ volatile("    mov r2, r1                   \n");
193
    __asm__ volatile("    mov r2, r1                   \n");
194
    __asm__ volatile("    add r1, r0, r12              \n");
194
    __asm__ volatile("    add r1, r0, r12              \n");
195
    __asm__ volatile("    sub r1, r1, #1               \n");
195
    __asm__ volatile("    sub r1, r1, #1               \n");
196
    __asm__ volatile("    bl displaylcd_setup          \n");
196
    __asm__ volatile("    bl displaylcd_setup          \n");
197
    __asm__ volatile("    mov r0, r8                   \n");
197
    __asm__ volatile("    mov r0, r8                   \n");
198
    __asm__ volatile("    bl malloc                    \n");
198
    __asm__ volatile("    bl malloc                    \n");
199
    __asm__ volatile("    cmp r0, #0                   \n");
199
    __asm__ volatile("    cmp r0, #0                   \n");
200
    __asm__ volatile("    beq displaylcd_dither_unlock \n");
200
    __asm__ volatile("    beq displaylcd_dither_unlock \n");
201
    __asm__ volatile("    mov r2, r8                   \n");
201
    __asm__ volatile("    mov r2, r8                   \n");
202
    __asm__ volatile("    mov r1, #0                   \n");
202
    __asm__ volatile("    mov r1, #0                   \n");
203
    __asm__ volatile("    mov r8, r0                   \n");
203
    __asm__ volatile("    mov r8, r0                   \n");
204
    __asm__ volatile("    bl memset                    \n");
204
    __asm__ volatile("    bl memset                    \n");
205
    __asm__ volatile("    ldr r0, [sp,#0x30]           \n");
205
    __asm__ volatile("    ldr r0, [sp,#0x30]           \n");
206
    __asm__ volatile("    ldr r1, [sp,#0x34]           \n");
206
    __asm__ volatile("    ldr r1, [sp,#0x34]           \n");
207
    __asm__ volatile("    ldr r11, [sp,#0x38]          \n");
207
    __asm__ volatile("    ldr r11, [sp,#0x38]          \n");
208
    __asm__ volatile("    ldr r3, [sp,#0x2c]           \n");
208
    __asm__ volatile("    ldr r3, [sp,#0x2c]           \n");
209
    __asm__ volatile("    mla r0, r1, r11, r0          \n");
209
    __asm__ volatile("    mla r0, r1, r11, r0          \n");
210
    __asm__ volatile("    ldr r12, [sp,#0x04]          \n");
210
    __asm__ volatile("    ldr r12, [sp,#0x04]          \n");
211
    __asm__ volatile("    ldr r2, [sp,#0x3c]           \n");
211
    __asm__ volatile("    ldr r2, [sp,#0x3c]           \n");
212
    __asm__ volatile("    add r3, r3, r0,lsl#1         \n");
212
    __asm__ volatile("    add r3, r3, r0,lsl#1         \n");
213
    __asm__ volatile("    cmp r2, #0                   \n");
213
    __asm__ volatile("    cmp r2, #0                   \n");
214
    __asm__ volatile("    ldreq r1, [sp]               \n");
214
    __asm__ volatile("    ldreq r1, [sp]               \n");
215
    __asm__ volatile("    add r3, r3, r0               \n");
215
    __asm__ volatile("    add r3, r3, r0               \n");
216
    __asm__ volatile("    subeq r11, r11, r1           \n");
216
    __asm__ volatile("    subeq r11, r11, r1           \n");
217
    __asm__ volatile("    add r11, r11, r11,lsl#1      \n");
217
    __asm__ volatile("    add r11, r11, r11,lsl#1      \n");
218
    __asm__ volatile("    movne r10, #3                \n");
218
    __asm__ volatile("    movne r10, #3                \n");
219
    __asm__ volatile("    moveq r10, #0                \n");
219
    __asm__ volatile("    moveq r10, #0                \n");
220
    __asm__ volatile("    ldr r9, =0x38300040          \n");
220
    __asm__ volatile("    ldr r9, =0x38300040          \n");
221
    __asm__ volatile("displaylcd_dither_y:             \n");
221
    __asm__ volatile("displaylcd_dither_y:             \n");
222
    __asm__ volatile("    ldr lr, [sp]                 \n");
222
    __asm__ volatile("    ldr lr, [sp]                 \n");
223
    __asm__ volatile("    mov r4, #0                   \n");
223
    __asm__ volatile("    mov r4, #0                   \n");
224
    __asm__ volatile("    mov r5, #0                   \n");
224
    __asm__ volatile("    mov r5, #0                   \n");
225
    __asm__ volatile("    mov r6, #0                   \n");
225
    __asm__ volatile("    mov r6, #0                   \n");
226
    __asm__ volatile("    mov r7, r8                   \n");
226
    __asm__ volatile("    mov r7, r8                   \n");
227
    __asm__ volatile("displaylcd_dither_x:             \n");
227
    __asm__ volatile("displaylcd_dither_x:             \n");
228
    __asm__ volatile("    mov r2, #0                   \n");
228
    __asm__ volatile("    mov r2, #0                   \n");
229
    __asm__ volatile("    ldrb r1, [r3], #1            \n");
229
    __asm__ volatile("    ldrb r1, [r3], #1            \n");
230
    __asm__ volatile("    ldrsb r0, [r7]               \n");
230
    __asm__ volatile("    ldrsb r0, [r7]               \n");
231
    __asm__ volatile("    add r1, r1, r4               \n");
231
    __asm__ volatile("    add r1, r1, r4               \n");
232
    __asm__ volatile("    add r1, r1, r0               \n");
232
    __asm__ volatile("    add r1, r1, r0               \n");
233
    __asm__ volatile("    cmp r1, #0xff                \n");
233
    __asm__ volatile("    cmp r1, #0xff                \n");
234
    __asm__ volatile("    mvnhi r1, r1,asr#31          \n");
234
    __asm__ volatile("    mvnhi r1, r1,asr#31          \n");
235
    __asm__ volatile("    andhi r1, r1, #0xff          \n");
235
    __asm__ volatile("    andhi r1, r1, #0xff          \n");
236
    __asm__ volatile("    mov r0, r1,lsr#3             \n");
236
    __asm__ volatile("    mov r0, r1,lsr#3             \n");
237
    __asm__ volatile("    orr r2, r0,lsl#11            \n");
237
    __asm__ volatile("    orr r2, r0,lsl#11            \n");
238
    __asm__ volatile("    sub r1, r1, r0,lsl#3         \n");
238
    __asm__ volatile("    sub r1, r1, r0,lsl#3         \n");
239
    __asm__ volatile("    sub r1, r1, r0,lsr#2         \n");
239
    __asm__ volatile("    sub r1, r1, r0,lsr#2         \n");
240
    __asm__ volatile("    mov r4, r4,lsr#1             \n");
240
    __asm__ volatile("    mov r4, r4,lsr#1             \n");
241
    __asm__ volatile("    add r4, r4, r1,lsr#2         \n");
241
    __asm__ volatile("    add r4, r4, r1,lsr#2         \n");
242
    __asm__ volatile("    strb r4, [r7], #1            \n");
242
    __asm__ volatile("    strb r4, [r7], #1            \n");
243
    __asm__ volatile("    mov r4, r1,asr#1             \n");
243
    __asm__ volatile("    mov r4, r1,asr#1             \n");
244
    __asm__ volatile("    ldrb r1, [r3], #1            \n");
244
    __asm__ volatile("    ldrb r1, [r3], #1            \n");
245
    __asm__ volatile("    ldrsb r0, [r7]               \n");
245
    __asm__ volatile("    ldrsb r0, [r7]               \n");
246
    __asm__ volatile("    add r1, r1, r5               \n");
246
    __asm__ volatile("    add r1, r1, r5               \n");
247
    __asm__ volatile("    add r1, r1, r0               \n");
247
    __asm__ volatile("    add r1, r1, r0               \n");
248
    __asm__ volatile("    cmp r1, #0xff                \n");
248
    __asm__ volatile("    cmp r1, #0xff                \n");
249
    __asm__ volatile("    mvnhi r1, r1,asr#31          \n");
249
    __asm__ volatile("    mvnhi r1, r1,asr#31          \n");
250
    __asm__ volatile("    andhi r1, r1, #0xff          \n");
250
    __asm__ volatile("    andhi r1, r1, #0xff          \n");
251
    __asm__ volatile("    mov r0, r1,lsr#2             \n");
251
    __asm__ volatile("    mov r0, r1,lsr#2             \n");
252
    __asm__ volatile("    orr r2, r0,lsl#5             \n");
252
    __asm__ volatile("    orr r2, r0,lsl#5             \n");
253
    __asm__ volatile("    sub r1, r1, r0,lsl#2         \n");
253
    __asm__ volatile("    sub r1, r1, r0,lsl#2         \n");
254
    __asm__ volatile("    sub r1, r1, r0,lsr#4         \n");
254
    __asm__ volatile("    sub r1, r1, r0,lsr#4         \n");
255
    __asm__ volatile("    mov r5, r5,lsr#1             \n");
255
    __asm__ volatile("    mov r5, r5,lsr#1             \n");
256
    __asm__ volatile("    add r5, r5, r1,lsr#2         \n");
256
    __asm__ volatile("    add r5, r5, r1,lsr#2         \n");
257
    __asm__ volatile("    strb r5, [r7], #1            \n");
257
    __asm__ volatile("    strb r5, [r7], #1            \n");
258
    __asm__ volatile("    mov r5, r1,asr#1             \n");
258
    __asm__ volatile("    mov r5, r1,asr#1             \n");
259
    __asm__ volatile("    ldrb r1, [r3], #1            \n");
259
    __asm__ volatile("    ldrb r1, [r3], #1            \n");
260
    __asm__ volatile("    ldrsb r0, [r7]               \n");
260
    __asm__ volatile("    ldrsb r0, [r7]               \n");
261
    __asm__ volatile("    add r1, r1, r6               \n");
261
    __asm__ volatile("    add r1, r1, r6               \n");
262
    __asm__ volatile("    add r1, r1, r0               \n");
262
    __asm__ volatile("    add r1, r1, r0               \n");
263
    __asm__ volatile("    cmp r1, #0xff                \n");
263
    __asm__ volatile("    cmp r1, #0xff                \n");
264
    __asm__ volatile("    mvnhi r1, r1,asr#31          \n");
264
    __asm__ volatile("    mvnhi r1, r1,asr#31          \n");
265
    __asm__ volatile("    andhi r1, r1, #0xff          \n");
265
    __asm__ volatile("    andhi r1, r1, #0xff          \n");
266
    __asm__ volatile("    mov r0, r1,lsr#3             \n");
266
    __asm__ volatile("    mov r0, r1,lsr#3             \n");
267
    __asm__ volatile("    orr r2, r0                   \n");
267
    __asm__ volatile("    orr r2, r0                   \n");
268
    __asm__ volatile("    sub r1, r1, r0,lsl#3         \n");
268
    __asm__ volatile("    sub r1, r1, r0,lsl#3         \n");
269
    __asm__ volatile("    sub r1, r1, r0,lsr#2         \n");
269
    __asm__ volatile("    sub r1, r1, r0,lsr#2         \n");
270
    __asm__ volatile("    mov r6, r6,lsr#1             \n");
270
    __asm__ volatile("    mov r6, r6,lsr#1             \n");
271
    __asm__ volatile("    add r6, r6, r1,lsr#2         \n");
271
    __asm__ volatile("    add r6, r6, r1,lsr#2         \n");
272
    __asm__ volatile("    strb r6, [r7], #1            \n");
272
    __asm__ volatile("    strb r6, [r7], #1            \n");
273
    __asm__ volatile("displaylcd_dither_waitlcd:       \n");
273
    __asm__ volatile("displaylcd_dither_waitlcd:       \n");
274
    __asm__ volatile("    ldr r0, [r9,#-0x24]          \n");
274
    __asm__ volatile("    ldr r0, [r9,#-0x24]          \n");
275
    __asm__ volatile("    mov r6, r1,asr#1             \n");
275
    __asm__ volatile("    mov r6, r1,asr#1             \n");
276
    __asm__ volatile("    tst r0, #0x10                \n");
276
    __asm__ volatile("    tst r0, #0x10                \n");
277
    __asm__ volatile("    bne displaylcd_dither_waitlcd\n");
277
    __asm__ volatile("    bne displaylcd_dither_waitlcd\n");
278
    __asm__ volatile("    str r2, [r9]                 \n");
278
    __asm__ volatile("    str r2, [r9]                 \n");
279
    __asm__ volatile("    sub r3, r3, r10              \n");
279
    __asm__ volatile("    sub r3, r3, r10              \n");
280
    __asm__ volatile("    subs lr, lr, #1              \n");
280
    __asm__ volatile("    subs lr, lr, #1              \n");
281
    __asm__ volatile("    bne displaylcd_dither_x      \n");
281
    __asm__ volatile("    bne displaylcd_dither_x      \n");
282
    __asm__ volatile("    add r3, r3, r11              \n");
282
    __asm__ volatile("    add r3, r3, r11              \n");
283
    __asm__ volatile("    subs r12, r12, #1            \n");
283
    __asm__ volatile("    subs r12, r12, #1            \n");
284
    __asm__ volatile("    bne displaylcd_dither_y      \n");
284
    __asm__ volatile("    bne displaylcd_dither_y      \n");
285
    __asm__ volatile("displaylcd_dither_free:          \n");
285
    __asm__ volatile("displaylcd_dither_free:          \n");
286
    __asm__ volatile("    mov r0, r8                   \n");
286
    __asm__ volatile("    mov r0, r8                   \n");
287
    __asm__ volatile("    bl free                      \n");
287
    __asm__ volatile("    bl free                      \n");
288
    __asm__ volatile("displaylcd_dither_unlock:        \n");
288
    __asm__ volatile("displaylcd_dither_unlock:        \n");
289
    __asm__ volatile("    ldr r0, =lcd_mutex           \n");
289
    __asm__ volatile("    ldr r0, =lcd_mutex           \n");
290
    __asm__ volatile("    bl mutex_unlock              \n");
290
    __asm__ volatile("    bl mutex_unlock              \n");
291
    __asm__ volatile("    ldmfd sp!, {r2-r11,pc}       \n");
291
    __asm__ volatile("    ldmfd sp!, {r2-r11,pc}       \n");
292
}
292
}
293
 
293
 
294
void displaylcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height,
294
void displaylcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height,
295
                void* data, unsigned int datax, unsigned int datay, unsigned int stride)
295
                void* data, unsigned int datax, unsigned int datay, unsigned int stride)
296
{
296
{
297
    displaylcd_dither(x, y, width, height, data, datax, datay, stride, false);
297
    displaylcd_dither(x, y, width, height, data, datax, datay, stride, false);
298
}
298
}
299
 
299
 
300
void filllcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int color)
300
void filllcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int color)
301
{
301
{
302
    if (width * height <= 0) return;
302
    if (width * height <= 0) return;
303
    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
303
    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
304
    displaylcd_sync();
304
    displaylcd_sync();
305
    lcd_color = color;
305
    lcd_color = color;
306
    displaylcd_dither(x, y, width, height, &lcd_color, 0, 0, 0, true);
306
    displaylcd_dither(x, y, width, height, &lcd_color, 0, 0, 0, true);
307
    mutex_unlock(&lcd_mutex);
307
    mutex_unlock(&lcd_mutex);
308
}
308
}
309
 
309
 
310
void INT_DMAC0C4()
310
void INT_DMAC0C4()
311
{
311
{
312
    DMAC0INTTCCLR = 0x10;
312
    DMAC0INTTCCLR = 0x10;
313
    lcd_in_irq = true;
313
    lcd_in_irq = true;
314
    lcd_dma_busy = false;
314
    lcd_dma_busy = false;
315
    clockgate_dma(0, 4, false);
315
    clockgate_dma(0, 4, false);
316
    lcdconsole_callback();
316
    lcdconsole_callback();
317
    wakeup_signal(&lcd_wakeup);
317
    wakeup_signal(&lcd_wakeup);
318
    lcd_in_irq = false;
318
    lcd_in_irq = false;
319
}
319
}
320
 
320
 
321
int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
321
int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
322
    ICODE_ATTR __attribute__((naked, noinline));
322
    ICODE_ATTR __attribute__((naked, noinline));
323
int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
323
int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
324
{
324
{
325
    asm volatile(
325
    asm volatile(
326
        "cmp r0, #0xff             \n\t"
326
        "cmp r0, #0xff             \n\t"
327
        "moveq r0, #-1             \n\t"
327
        "moveq r0, #-1             \n\t"
328
        "moveq pc, lr              \n\t"
328
        "moveq pc, lr              \n\t"
329
        "cmp r0, #0                \n\t"
329
        "cmp r0, #0                \n\t"
330
        "movne r0, #0xff000000     \n\t"
330
        "movne r0, #0xff000000     \n\t"
331
        "orrne r0, r0, #0xff0000   \n\t"
331
        "orrne r0, r0, #0xff0000   \n\t"
332
        "mov r2, r2,lsr#2          \n\t"
332
        "mov r2, r2,lsr#2          \n\t"
333
        "orr r0, r0, r3,lsr#3      \n\t"
333
        "orr r0, r0, r3,lsr#3      \n\t"
334
        "mov r1, r1,lsr#3          \n\t"
334
        "mov r1, r1,lsr#3          \n\t"
335
        "orr r0, r0, r2,lsl#5      \n\t"
335
        "orr r0, r0, r2,lsl#5      \n\t"
336
        "orr r0, r0, r1,lsl#11     \n\t"
336
        "orr r0, r0, r1,lsl#11     \n\t"
337
        "mov pc, lr                \n\t"
337
        "mov pc, lr                \n\t"
338
    );
338
    );
339
}
339
}