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