Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
273 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
427 farthen 6
//    This file is part of emCORE.
273 theseven 7
//
427 farthen 8
//    emCORE is free software: you can redistribute it and/or
273 theseven 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
11
//    License, or (at your option) any later version.
12
//
427 farthen 13
//    emCORE is distributed in the hope that it will be useful,
273 theseven 14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
427 farthen 19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
273 theseven 20
//
21
//
22
 
23
 
24
#include "global.h"
25
#include "thread.h"
26
#include "s5l8702.h"
27
#include "util.h"
28
 
29
 
278 theseven 30
static struct dma_lli lcd_lli[(LCD_WIDTH * LCD_HEIGHT - 1) / 0xfff]
31
    IDATA_ATTR __attribute__((aligned(16)));
273 theseven 32
 
33
static uint16_t lcd_color IDATA_ATTR;
34
 
492 theseven 35
static struct mutex lcd_mutex;
273 theseven 36
 
492 theseven 37
 
273 theseven 38
void lcd_init()
39
{
40
}
41
 
42
int lcd_get_width()
43
{
44
    return LCD_WIDTH;
45
}
46
 
47
int lcd_get_height()
48
{
49
    return LCD_HEIGHT;
50
}
51
 
52
int lcd_get_bytes_per_pixel()
53
{
54
    return LCD_BYTESPERPIXEL;
55
}
56
 
489 theseven 57
int lcd_get_format()
58
{
59
    return LCD_FORMAT;
60
}
61
 
492 theseven 62
static void lcd_send_cmd(uint16_t cmd) ICODE_ATTR __attribute__((noinline));
273 theseven 63
static void lcd_send_cmd(uint16_t cmd)
64
{
65
    while (LCDSTATUS & 0x10);
66
    LCDWCMD = cmd;
67
}
68
 
492 theseven 69
static void lcd_send_data(uint16_t data) ICODE_ATTR __attribute__((noinline));
273 theseven 70
static void lcd_send_data(uint16_t data)
71
{
72
    while (LCDSTATUS & 0x10);
419 theseven 73
    LCDWDATA = (data & 0xff) | ((data & 0x7f00) << 1);
273 theseven 74
}
75
 
492 theseven 76
static uint32_t lcd_detect() ICODE_ATTR;
273 theseven 77
static uint32_t lcd_detect()
78
{
79
    return (PDAT6 & 0x30) >> 4;
80
}
81
 
492 theseven 82
bool displaylcd_busy() ICODE_ATTR;
273 theseven 83
bool displaylcd_busy()
84
{
388 theseven 85
    return DMAC0C4CONFIG & 1;
273 theseven 86
}
87
 
88
bool displaylcd_safe()
89
{
388 theseven 90
    return !(DMAC0C4CONFIG & 1);
273 theseven 91
}
92
 
492 theseven 93
void displaylcd_sync() ICODE_ATTR;
273 theseven 94
void displaylcd_sync()
95
{
492 theseven 96
    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
273 theseven 97
    while (displaylcd_busy()) sleep(100);
492 theseven 98
    mutex_unlock(&lcd_mutex);
273 theseven 99
}
100
 
492 theseven 101
void displaylcd_setup(unsigned int startx, unsigned int endx,
102
                      unsigned int starty, unsigned int endy) ICODE_ATTR;
103
void displaylcd_setup(unsigned int startx, unsigned int endx,
104
                      unsigned int starty, unsigned int endy)
273 theseven 105
{
492 theseven 106
    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
273 theseven 107
    displaylcd_sync();
378 theseven 108
    if (lcd_detect() & 2)
273 theseven 109
    {
110
        lcd_send_cmd(0x210);
111
        lcd_send_data(startx);
112
        lcd_send_cmd(0x211);
113
        lcd_send_data(endx);
114
        lcd_send_cmd(0x212);
115
        lcd_send_data(starty);
116
        lcd_send_cmd(0x213);
117
        lcd_send_data(endy);
118
        lcd_send_cmd(0x200);
119
        lcd_send_data(startx);
120
        lcd_send_cmd(0x201);
121
        lcd_send_data(starty);
122
        lcd_send_cmd(0x202);
123
    }
124
    else
125
    {
126
        lcd_send_cmd(0x2a);
127
        lcd_send_data(startx >> 8);
128
        lcd_send_data(startx & 0xff);
129
        lcd_send_data(endx >> 8);
130
        lcd_send_data(endx & 0xff);
131
        lcd_send_cmd(0x2b);
132
        lcd_send_data(starty >> 8);
133
        lcd_send_data(starty & 0xff);
134
        lcd_send_data(endy >> 8);
135
        lcd_send_data(endy & 0xff);
136
        lcd_send_cmd(0x2c);
137
    }
492 theseven 138
}
139
 
140
static void displaylcd_dma(void* data, int pixels, bool solid) ICODE_ATTR;
141
static void displaylcd_dma(void* data, int pixels, bool solid)
142
{
273 theseven 143
    int i;
278 theseven 144
    for (i = -1; i < (int)ARRAYLEN(lcd_lli) && pixels > 0; i++, pixels -= 0xfff)
273 theseven 145
    {
278 theseven 146
        bool last = i + 1 >= ARRAYLEN(lcd_lli) || pixels <= 0xfff;
388 theseven 147
        struct dma_lli* lli = i < 0 ? (struct dma_lli*)((int)&DMAC0C4LLI) : &lcd_lli[i];
492 theseven 148
        lli->srcaddr = data;
278 theseven 149
        lli->dstaddr = (void*)((int)&LCDWDATA);
150
        lli->nextlli = last ? NULL : &lcd_lli[i + 1];
151
        lli->control = 0x70240000 | (last ? pixels : 0xfff)
152
                     | (last ? 0x80000000 : 0) | (solid ? 0 : 0x4000000);
273 theseven 153
        data = (void*)(((uint32_t)data) + 0x1ffe);
154
    }
155
    clean_dcache();
388 theseven 156
    DMAC0C4CONFIG = 0x88c1;
273 theseven 157
}
158
 
492 theseven 159
void displaylcd_native(unsigned int startx, unsigned int endx,
160
                       unsigned int starty, unsigned int endy, void* data)
161
{
162
    int pixels = (endx - startx + 1) * (endy - starty + 1);
163
    if (pixels <= 0) return;
164
    displaylcd_setup(startx, endx, starty, endy);
165
    displaylcd_dma(data, pixels, false);
166
    mutex_unlock(&lcd_mutex);
167
}
168
 
169
void filllcd_native(unsigned int startx, unsigned int endx,
170
                    unsigned int starty, unsigned int endy, int color)
171
{
172
    int pixels = (endx - startx + 1) * (endy - starty + 1);
173
    if (pixels <= 0) return;
174
    displaylcd_setup(startx, endx, starty, endy);
175
    lcd_color = color;
176
    displaylcd_dma(&lcd_color, pixels, true);
177
    mutex_unlock(&lcd_mutex);
178
}
179
 
180
void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width,
181
                       unsigned int height, void* data, unsigned int datax,
182
                       unsigned int datay, unsigned int stride, bool solid) ICODE_ATTR;
183
void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width,
184
                       unsigned int height, void* data, unsigned int datax,
185
                       unsigned int datay, unsigned int stride, bool solid)
186
{
187
    int pixels = width * height;
188
    if (pixels <= 0) return;
189
    displaylcd_setup(x, x + width - 1, y, y + height - 1);
190
    int corrsize = width * 3;
191
    signed char* corr = (signed char*)malloc(corrsize);
192
    if (!corr)
193
    {
194
        mutex_unlock(&lcd_mutex);
195
        return;
196
    }
197
    memset(corr, 0, corrsize);
198
    unsigned char* in = (unsigned char*)data + (stride * datay + datax) * 3;
199
    for (y = 0; y < height; y++)
200
    {
201
        int i;
202
        signed char* corrptr = corr;
203
        signed char lastcorr[3] = {0};
204
        for (x = 0; x < width; x++)
205
        {
206
            unsigned int pixel = 0;
207
            signed char* lastcorrptr = lastcorr;
208
            int orig = *in++ + *corrptr + *lastcorrptr;
209
            orig = MAX(0, MIN(255, orig));
210
            unsigned int real = orig >> 3;
211
            pixel |= real << 11;
212
            int err = orig - ((real << 3) | (real >> 2));
213
            *corrptr++ = (*lastcorrptr >> 1) + err >> 2;
214
            *lastcorrptr++ = err >> 1;
215
            orig = *in++ + *corrptr + *lastcorrptr;
216
            orig = MAX(0, MIN(255, orig));
217
            real = orig >> 2;
218
            pixel |= real << 5;
219
            err = orig - ((real << 2) | (real >> 4));
220
            *corrptr++ = (*lastcorrptr >> 1) + err >> 2;
221
            *lastcorrptr++ = err >> 1;
222
            orig = *in++ + *corrptr + *lastcorrptr;
223
            orig = MAX(0, MIN(255, orig));
224
            real = orig >> 3;
225
            pixel |= real;
226
            err = orig - ((real << 3) | (real >> 2));
227
            *corrptr++ = (*lastcorrptr >> 1) + err >> 2;
228
            *lastcorrptr++ = err >> 1;
229
            while (LCDSTATUS & 0x10);
230
            LCDWDATA = pixel;
231
            if (solid) in -= 3;
232
        }
233
        if (solid) in += stride * 3;
234
        else in += (stride - width) * 3;
235
    }
236
    free(corr);
237
    mutex_unlock(&lcd_mutex);
238
}
239
 
240
void displaylcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height,
241
                void* data, unsigned int datax, unsigned int datay, unsigned int stride)
242
{
243
    displaylcd_dither(x, y, width, height, data, datax, datay, stride, false);
244
}
245
 
246
void filllcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int color)
247
{
248
    if (width * height <= 0) return;
249
    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
250
    lcd_color = color;
251
    displaylcd_dither(x, y, width, height, &lcd_color, 0, 0, 0, true);
252
    mutex_unlock(&lcd_mutex);
253
}
254
 
309 theseven 255
void lcd_shutdown()
256
{
257
    displaylcd_sync();
319 theseven 258
    uint32_t type = lcd_detect();
419 theseven 259
    if (type & 2)
319 theseven 260
    {
261
        lcd_send_cmd(0x7);
262
        lcd_send_data(0x172);
263
        lcd_send_cmd(0x30);
264
        lcd_send_data(0x3ff);
265
        sleep(90000);
266
        lcd_send_cmd(0x7);
267
        lcd_send_data(0x120);
268
        lcd_send_cmd(0x30);
269
        lcd_send_data(0x0);
270
        lcd_send_cmd(0x100);
271
        lcd_send_data(0x780);
272
        lcd_send_cmd(0x7);
273
        lcd_send_data(0x0);
274
        lcd_send_cmd(0x101);
275
        lcd_send_data(0x260);
276
        lcd_send_cmd(0x102);
277
        lcd_send_data(0xa9);
278
        sleep(30000);
279
        lcd_send_cmd(0x100);
280
        lcd_send_data(0x700);
281
        lcd_send_cmd(0x100);
282
        lcd_send_data(0x704);
283
    }
284
    else if (type == 1)
285
    {
286
        lcd_send_cmd(0x28);
287
        lcd_send_cmd(0x10);
288
        sleep(100000);
289
    }
290
    else
291
    {
292
        lcd_send_cmd(0x28);
293
        sleep(50000);
294
        lcd_send_cmd(0x10);
295
        sleep(50000);
296
    }
309 theseven 297
}
298
 
388 theseven 299
void INT_DMAC0C4()
273 theseven 300
{
388 theseven 301
    DMAC0INTTCCLR = 0x10;
273 theseven 302
    lcdconsole_callback();
303
}
304
 
305
int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
306
    ICODE_ATTR __attribute__((naked, noinline));
307
int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
308
{
309
    asm volatile(
310
        "cmp r0, #0xff             \n\t"
311
        "moveq r0, #-1             \n\t"
312
        "moveq pc, lr              \n\t"
313
        "cmp r0, #0                \n\t"
314
        "movne r0, #0xff000000     \n\t"
315
        "orrne r0, r0, #0xff0000   \n\t"
316
        "mov r2, r2,lsr#2          \n\t"
317
        "orr r0, r0, r3,lsr#3      \n\t"
318
        "mov r1, r1,lsr#3          \n\t"
319
        "orr r0, r0, r2,lsl#5      \n\t"
320
        "orr r0, r0, r1,lsl#11     \n\t"
321
        "mov pc, lr                \n\t"
322
    );
323
}