Subversion Repositories freemyipod

Rev

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

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