Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
Marcin Bukat | 082c7d3 | 2010-10-22 12:28:43 +0000 | [diff] [blame^] | 8 | * $Id$ |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 9 | * |
| 10 | * Copyright (C) 2010 Marcin Bukat |
Marcin Bukat | 88baa4d | 2010-04-30 14:13:52 +0000 | [diff] [blame] | 11 | * based on lcd-as-m3.S by Jens Arnold |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 12 | * |
| 13 | * This program is free software; you can redistribute it and/or |
| 14 | * modify it under the terms of the GNU General Public License |
| 15 | * as published by the Free Software Foundation; either version 2 |
| 16 | * of the License, or (at your option) any later version. |
| 17 | * |
| 18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 19 | * KIND, either express or implied. |
| 20 | * |
| 21 | ****************************************************************************/ |
| 22 | |
| 23 | #include "config.h" |
| 24 | #include "cpu.h" |
| 25 | |
| 26 | |
| 27 | #define LCD_BASE_ADDRESS 0xf0000000 |
| 28 | |
| 29 | .section .icode,"ax",@progbits |
| 30 | |
| 31 | .align 2 |
| 32 | .global lcd_write_command |
| 33 | .type lcd_write_command,@function |
| 34 | |
| 35 | lcd_write_command: |
| 36 | move.l (4, %sp), %d0 |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 37 | move.b %d0, LCD_BASE_ADDRESS /* transfers 1 byte to LCD */ |
| 38 | |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 39 | rts |
| 40 | .wc_end: |
| 41 | .size lcd_write_command,.wc_end-lcd_write_command |
| 42 | |
| 43 | |
| 44 | .align 2 |
| 45 | .global lcd_write_command_e |
| 46 | .type lcd_write_command_e,@function |
| 47 | |
| 48 | lcd_write_command_e: |
| 49 | lea.l LCD_BASE_ADDRESS, %a0 |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 50 | move.l (4, %sp), %d0 /* Command */ |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 51 | move.b %d0, (%a0) |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 52 | move.l (8, %sp), %d0 /* Data */ |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 53 | move.b %d0, (%a0) /* Write to LCD */ |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 54 | |
| 55 | rts |
| 56 | .wce_end: |
| 57 | .size lcd_write_command_e,.wce_end-lcd_write_command_e |
| 58 | |
| 59 | |
| 60 | .align 2 |
| 61 | .global lcd_write_data |
| 62 | .type lcd_write_data,@function |
| 63 | |
| 64 | /* PIXELFORMAT = VERTICAL_INTERLEAVED |
| 65 | * this means that data is packed verticaly in 8 pixels columns |
| 66 | * first byte is lsb of 2bit color in column |
| 67 | * second byte is msb of 2bit color in column |
| 68 | * so one word of data equals 8 pixels i 2bits color depth packed |
| 69 | * verticaly |
| 70 | */ |
| 71 | lcd_write_data: |
| 72 | movem.l (4, %sp), %a0 /* Data pointer */ |
| 73 | move.l (8, %sp), %d0 /* Length i in words */ |
Marcin Bukat | cce9c17 | 2010-05-17 12:34:59 +0000 | [diff] [blame] | 74 | lea.l LCD_BASE_ADDRESS+2, %a1 /* LCD data port address */ |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 75 | |
| 76 | btst #0, %d0 /* longwords multiply? */ |
Marcin Bukat | cce9c17 | 2010-05-17 12:34:59 +0000 | [diff] [blame] | 77 | jeq .l_write |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 78 | |
| 79 | .w_write: |
| 80 | move.w (%a0)+, %d1 /* load data 3 cycles*/ |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 81 | move.b %d1, (%a1) /* first byte 1 cycle*/ |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 82 | lsr.l #8, %d1 /* load second byte 1 cycle*/ |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 83 | move.b %d1, (%a1) /* transfer 1 cycle*/ |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 84 | subq.l #1, %d0 /* decrement counter 1 cycle*/ |
Marcin Bukat | cce9c17 | 2010-05-17 12:34:59 +0000 | [diff] [blame] | 85 | jeq .write_end |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 86 | |
| 87 | .l_write: |
| 88 | move.l (%a0)+, %d1 /* load data 2 cycles*/ |
| 89 | swap %d1 /* 1 cycle */ |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 90 | move.b %d1, (%a1) /* first byte 1 cycle*/ |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 91 | lsr.l #8, %d1 /* 1 cycle */ |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 92 | move.b %d1, (%a1) /* second byte 1 cycle*/ |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 93 | lsr.l #8, %d1 /* 1 cycle */ |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 94 | move.b %d1, (%a1) /* third byte 1 cycle*/ |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 95 | lsr.l #8, %d1 /* 1 cycle */ |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 96 | move.b %d1, (%a1) /* forth byte 1 cycle*/ |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 97 | subq.l #2, %d0 /* decrement counter 1 cycle*/ |
Marcin Bukat | cce9c17 | 2010-05-17 12:34:59 +0000 | [diff] [blame] | 98 | bne.s .l_write |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 99 | |
| 100 | .write_end: |
| 101 | rts |
Marcin Bukat | 88baa4d | 2010-04-30 14:13:52 +0000 | [diff] [blame] | 102 | .wd_end: |
Marcin Bukat | 28d54c6 | 2010-04-26 21:40:16 +0000 | [diff] [blame] | 103 | .size lcd_write_data,.wd_end-lcd_write_data |
| 104 | |
Marcin Bukat | 88baa4d | 2010-04-30 14:13:52 +0000 | [diff] [blame] | 105 | .global lcd_mono_data |
| 106 | .type lcd_mono_data, @function |
| 107 | |
| 108 | lcd_mono_data: |
| 109 | move.l (4, %sp), %a0 /* p_bytes */ |
| 110 | move.l (8, %sp), %d0 /* count */ |
| 111 | lea.l LCD_BASE_ADDRESS+2, %a1 /* LCD data port address */ |
| 112 | |
| 113 | .md_loop: |
| 114 | move.b (%a0)+, %d1 |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 115 | move.b %d1, (%a1) /* byte transfers */ |
| 116 | move.b %d1, (%a1) |
Marcin Bukat | 88baa4d | 2010-04-30 14:13:52 +0000 | [diff] [blame] | 117 | subq.l #1, %d0 |
| 118 | bne.s .md_loop |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 119 | |
Marcin Bukat | 88baa4d | 2010-04-30 14:13:52 +0000 | [diff] [blame] | 120 | rts |
| 121 | .md_end: |
| 122 | .size lcd_mono_data,.md_end-lcd_mono_data |
| 123 | |
| 124 | .global lcd_grey_data |
| 125 | .type lcd_grey_data,@function |
| 126 | |
| 127 | lcd_grey_data: |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 128 | lea.l (-11*4, %sp), %sp |
| 129 | movem.l %d2-%d7/%a2-%a6, (%sp) /* save some registers */ |
| 130 | movem.l (11*4+4, %sp), %a0-%a2 /* values, phases, length */ |
Marcin Bukat | 88baa4d | 2010-04-30 14:13:52 +0000 | [diff] [blame] | 131 | add.l %a2, %a2 |
| 132 | lea.l (%a1, %a2.l*4), %a2 /* end address */ |
| 133 | lea.l LCD_BASE_ADDRESS+2, %a3 /* LCD data port address */ |
Jens Arnold | f053b0d | 2010-06-11 19:53:17 +0000 | [diff] [blame] | 134 | moveq.l #24, %d4 /* shift count */ |
| 135 | move.l #0x204081, %d5 /* bit shuffle factor */ |
| 136 | |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 137 | moveq.l #8, %d2 |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 138 | add.l %a1, %d2 |
| 139 | and.l #0xfffffff0, %d2 /* first line bound */ |
| 140 | cmp.l %d2, %a2 /* end address lower than first line bound? */ |
| 141 | bhs.s 1f |
| 142 | move.l %a2, %d2 /* -> adjust end address of head loop */ |
| 143 | 1: |
| 144 | cmp.l %a1, %d2 |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 145 | bls.s .g_hend |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 146 | |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 147 | /* process head pixels */ |
Jens Arnold | f053b0d | 2010-06-11 19:53:17 +0000 | [diff] [blame] | 148 | movem.l (%a1), %d0-%d1 /* fetch 8 pixel phases */ |
Marcin Bukat | 88baa4d | 2010-04-30 14:13:52 +0000 | [diff] [blame] | 149 | |
Jens Arnold | f053b0d | 2010-06-11 19:53:17 +0000 | [diff] [blame] | 150 | move.l %d0, %d2 |
| 151 | and.l #0x80808080, %d2 /* %d2 = 0.......1.......2.......3....... */ |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 152 | eor.l %d2, %d0 |
Jens Arnold | f053b0d | 2010-06-11 19:53:17 +0000 | [diff] [blame] | 153 | add.l (%a0)+, %d0 /* add values to first 4 phases */ |
Marcin Bukat | 88baa4d | 2010-04-30 14:13:52 +0000 | [diff] [blame] | 154 | |
Jens Arnold | f053b0d | 2010-06-11 19:53:17 +0000 | [diff] [blame] | 155 | move.l %d1, %d3 |
| 156 | and.l #0x80808080, %d3 /* %d3 = 4.......5.......6.......7....... */ |
| 157 | eor.l %d3, %d1 |
| 158 | add.l (%a0)+, %d1 /* add values to second 4 phases */ |
Marcin Bukat | 88baa4d | 2010-04-30 14:13:52 +0000 | [diff] [blame] | 159 | |
Jens Arnold | f053b0d | 2010-06-11 19:53:17 +0000 | [diff] [blame] | 160 | lsr.l #4, %d3 /* %d3 = ....4.......5.......6.......7... */ |
| 161 | or.l %d3, %d2 /* %d2 = 0...4...1...5...2...6...3...7... */ |
| 162 | mulu.l %d5, %d2 /* %d2 = 01234567123.567.23..67..3...7... */ |
| 163 | not.l %d2 /* negate bits */ |
| 164 | lsr.l %d4, %d2 /* %d2 = ........................01234567 */ |
| 165 | |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 166 | move.b %d2, (%a3) /* transfer first LCD byte */ |
Jens Arnold | f053b0d | 2010-06-11 19:53:17 +0000 | [diff] [blame] | 167 | |
| 168 | movem.l %d0-%d1, (%a1) /* store 8 new pixel phases */ |
| 169 | addq.l #8, %a1 |
| 170 | |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 171 | move.b %d2, (%a3) /* transfer second LCD byte */ |
Marcin Bukat | 88baa4d | 2010-04-30 14:13:52 +0000 | [diff] [blame] | 172 | |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 173 | .g_hend: |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 174 | cmp.l %a1, %a2 |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 175 | bls.w .g_tend |
| 176 | subq.l #8, %a2 |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 177 | cmp.l %a1, %a2 |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 178 | bls.s .g_lend |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 179 | |
| 180 | .g_line_loop: |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 181 | /* loop that utilizes line transfers */ |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 182 | movem.l (%a1), %d0-%d3 /* fetch 2 * 8 pixels phases */ |
| 183 | |
| 184 | move.l %d0, %d6 |
| 185 | and.l #0x80808080, %d6 /* %d6 = 0.......1.......2.......3....... */ |
| 186 | eor.l %d6, %d0 |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 187 | |
| 188 | move.l %d1, %d7 |
| 189 | and.l #0x80808080, %d7 /* %d7 = 4.......5.......6.......7....... */ |
| 190 | eor.l %d7, %d1 |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 191 | |
| 192 | lsr.l #4, %d7 /* %d7 = ....4.......5.......6.......7... */ |
| 193 | or.l %d7, %d6 /* %d6 = 0...4...1...5...2...6...3...7... */ |
| 194 | mulu.l %d5, %d6 /* %d6 = 01234567123.567.23..67..3...7... */ |
| 195 | not.l %d6 /* negate bits */ |
| 196 | lsr.l %d4, %d6 /* %d6 = ........................01234567 */ |
| 197 | |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 198 | move.b %d6, (%a3) /* transfer first LCD byte */ |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 199 | |
| 200 | movem.l (%a0), %d7/%a4-%a6 /* fetch 2 * 8 pixel values */ |
| 201 | lea.l (16, %a0), %a0 |
| 202 | |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 203 | move.b %d6, (%a3) /* transfer second LCD byte */ |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 204 | |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 205 | add.l %d7, %d0 |
| 206 | add.l %a4, %d1 |
| 207 | |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 208 | move.l %d2, %d6 |
| 209 | and.l #0x80808080, %d6 /* %d6 = 0.......1.......2.......3....... */ |
| 210 | eor.l %d6, %d2 |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 211 | |
| 212 | move.l %d3, %d7 |
| 213 | and.l #0x80808080, %d7 /* %d7 = 4.......5.......6.......7....... */ |
| 214 | eor.l %d7, %d3 |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 215 | |
| 216 | lsr.l #4, %d7 /* %d7 = ....4.......5.......6.......7... */ |
| 217 | or.l %d7, %d6 /* %d6 = 0...4...1...5...2...6...3...7... */ |
| 218 | mulu.l %d5, %d6 /* %d6 = 01234567123.567.23..67..3...7... */ |
| 219 | not.l %d6 /* negate bits */ |
| 220 | lsr.l %d4, %d6 /* %d6 = ........................01234567 */ |
| 221 | |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 222 | add.l %a5, %d2 |
| 223 | add.l %a6, %d3 |
| 224 | |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 225 | move.b %d6, (%a3) /* transfer first LCD byte */ |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 226 | |
| 227 | movem.l %d0-%d3, (%a1) /* store 2 * 8 new pixel phases */ |
| 228 | lea.l (16, %a1), %a1 /* advance pointer */ |
| 229 | |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 230 | move.b %d6, (%a3) /* transfer second LCD byte */ |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 231 | |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 232 | cmp.l %a2, %a1 |
| 233 | bls.s .g_line_loop |
| 234 | |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 235 | .g_lend: |
| 236 | addq.l #8, %a2 |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 237 | cmp.l %a1, %a2 |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 238 | bls.s .g_tend |
Marcin Bukat | a316ebe | 2010-06-15 10:41:43 +0000 | [diff] [blame] | 239 | |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 240 | /* process tail pixels */ |
| 241 | movem.l (%a1), %d0-%d1 /* fetch 8 pixel phases */ |
| 242 | |
| 243 | move.l %d0, %d2 |
| 244 | and.l #0x80808080, %d2 /* %d2 = 0.......1.......2.......3....... */ |
| 245 | eor.l %d2, %d0 |
| 246 | add.l (%a0)+, %d0 /* add values to first 4 phases */ |
| 247 | |
| 248 | move.l %d1, %d3 |
| 249 | and.l #0x80808080, %d3 /* %d3 = 4.......5.......6.......7....... */ |
| 250 | eor.l %d3, %d1 |
| 251 | add.l (%a0)+, %d1 /* add values to second 4 phases */ |
| 252 | |
| 253 | lsr.l #4, %d3 /* %d3 = ....4.......5.......6.......7... */ |
| 254 | or.l %d3, %d2 /* %d2 = 0...4...1...5...2...6...3...7... */ |
| 255 | mulu.l %d5, %d2 /* %d2 = 01234567123.567.23..67..3...7... */ |
| 256 | not.l %d2 /* negate bits */ |
| 257 | lsr.l %d4, %d2 /* %d2 = ........................01234567 */ |
| 258 | |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 259 | move.b %d2, (%a3) /* transfer first LCD byte */ |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 260 | |
| 261 | movem.l %d0-%d1, (%a1) /* store 8 new pixel phases */ |
| 262 | /* addq.l #8, %a1 not needed anymore */ |
| 263 | |
Marcin Bukat | 5b5275a | 2010-07-16 07:24:08 +0000 | [diff] [blame] | 264 | move.b %d2, (%a3) /* transfer second LCD byte */ |
Jens Arnold | 701dafd | 2010-07-16 07:08:39 +0000 | [diff] [blame] | 265 | |
| 266 | .g_tend: |
| 267 | movem.l (%sp), %d2-%d7/%a2-%a6 |
| 268 | lea.l (11*4, %sp), %sp |
Marcin Bukat | 88baa4d | 2010-04-30 14:13:52 +0000 | [diff] [blame] | 269 | rts |
| 270 | .grey_end: |
| 271 | .size lcd_grey_data,.grey_end-lcd_grey_data |