| /*************************************************************************** |
| * __________ __ ___. |
| * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| * \/ \/ \/ \/ \/ |
| * $Id:$ |
| * |
| * Copyright (C) 2010 Marcin Bukat |
| * based on lcd-as-m3.S by Jens Arnold |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version 2 |
| * of the License, or (at your option) any later version. |
| * |
| * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| * KIND, either express or implied. |
| * |
| ****************************************************************************/ |
| |
| #include "config.h" |
| #include "cpu.h" |
| |
| |
| #define LCD_BASE_ADDRESS 0xf0000000 |
| |
| .section .icode,"ax",@progbits |
| |
| .align 2 |
| .global lcd_write_command |
| .type lcd_write_command,@function |
| |
| lcd_write_command: |
| move.l (4, %sp), %d0 |
| move.w %d0, LCD_BASE_ADDRESS /* data is 1byte but CF uses word |
| * transfers only */ |
| rts |
| .wc_end: |
| .size lcd_write_command,.wc_end-lcd_write_command |
| |
| |
| .align 2 |
| .global lcd_write_command_e |
| .type lcd_write_command_e,@function |
| |
| lcd_write_command_e: |
| lea.l LCD_BASE_ADDRESS, %a0 |
| |
| move.l (4, %sp), %d0 /* Command */ |
| move.w %d0, (%a0) |
| move.l (8, %sp), %d0 /* Data */ |
| move.w %d0, (%a0) /* Write to LCD */ |
| |
| rts |
| .wce_end: |
| .size lcd_write_command_e,.wce_end-lcd_write_command_e |
| |
| |
| .align 2 |
| .global lcd_write_data |
| .type lcd_write_data,@function |
| |
| /* PIXELFORMAT = VERTICAL_INTERLEAVED |
| * this means that data is packed verticaly in 8 pixels columns |
| * first byte is lsb of 2bit color in column |
| * second byte is msb of 2bit color in column |
| * so one word of data equals 8 pixels i 2bits color depth packed |
| * verticaly |
| */ |
| lcd_write_data: |
| movem.l (4, %sp), %a0 /* Data pointer */ |
| move.l (8, %sp), %d0 /* Length i in words */ |
| lea.l LCD_BASE_ADDRESS+2, %a1 /* LCD data port address */ |
| |
| btst #0, %d0 /* longwords multiply? */ |
| jeq .l_write |
| |
| .w_write: |
| move.w (%a0)+, %d1 /* load data 3 cycles*/ |
| move.w %d1, (%a1) /* first byte 1 cycle*/ |
| lsr.l #8, %d1 /* load second byte 1 cycle*/ |
| move.w %d1, (%a1) /* transfer 1 cycle*/ |
| subq.l #1, %d0 /* decrement counter 1 cycle*/ |
| jeq .write_end |
| |
| .l_write: |
| move.l (%a0)+, %d1 /* load data 2 cycles*/ |
| swap %d1 /* 1 cycle */ |
| move.w %d1, (%a1) /* first byte 1 cycle*/ |
| lsr.l #8, %d1 /* 1 cycle */ |
| move.w %d1, (%a1) /* second byte 1 cycle*/ |
| lsr.l #8, %d1 /* 1 cycle */ |
| move.w %d1, (%a1) /* third byte 1 cycle*/ |
| lsr.l #8, %d1 /* 1 cycle */ |
| move.w %d1, (%a1) /* forth byte 1 cycle*/ |
| subq.l #2, %d0 /* decrement counter 1 cycle*/ |
| bne.s .l_write |
| |
| .write_end: |
| rts |
| .wd_end: |
| .size lcd_write_data,.wd_end-lcd_write_data |
| |
| .global lcd_mono_data |
| .type lcd_mono_data, @function |
| |
| lcd_mono_data: |
| move.l (4, %sp), %a0 /* p_bytes */ |
| move.l (8, %sp), %d0 /* count */ |
| lea.l LCD_BASE_ADDRESS+2, %a1 /* LCD data port address */ |
| |
| .md_loop: |
| move.b (%a0)+, %d1 |
| move.w %d1, (%a1) /* byte transfers actually */ |
| move.w %d1, (%a1) |
| subq.l #1, %d0 |
| bne.s .md_loop |
| rts |
| .md_end: |
| .size lcd_mono_data,.md_end-lcd_mono_data |
| |
| .global lcd_grey_data |
| .type lcd_grey_data,@function |
| |
| lcd_grey_data: |
| lea.l (-2*4, %sp), %sp |
| movem.l %a2-%a3, (%sp) |
| movem.l (2*4+4, %sp), %a0-%a2 /* values, phases, length */ |
| add.l %a2, %a2 |
| lea.l (%a1, %a2.l*4), %a2 /* end address */ |
| lea.l LCD_BASE_ADDRESS+2, %a3 /* LCD data port address */ |
| .ph_loop: |
| clr.l %d1 |
| move.l (%a1), %d0 /* fetch 4 pixel phases */ |
| bclr.l #31, %d0 /* Z = !(p0 & 0x80); p0 &= ~0x80; */ |
| seq.b %d1 /* %d1 = ........................00000000 */ |
| lsl.l #1, %d1 /* %d1 = .......................00000000. */ |
| bclr.l #23, %d0 /* Z = !(p1 & 0x80); p1 &= ~0x80; */ |
| seq.b %d1 /* %d1 = .......................011111111 */ |
| lsl.l #1, %d1 /* %d1 = ......................011111111. */ |
| bclr.l #15, %d0 /* Z = !(p2 & 0x80); p2 &= ~0x80; */ |
| seq.b %d1 /* %d1 = ......................0122222222 */ |
| lsl.l #1, %d1 /* %d1 = .....................0122222222. */ |
| bclr.l #7, %d0 /* Z = !(p3 & 0x80); p3 &= ~0x80; */ |
| seq.b %d1 /* %d1 = .....................01233333333 */ |
| lsl.l #1, %d1 /* %d1 = ....................01233333333. */ |
| add.l (%a0)+, %d0 /* add 4 pixel values to the phases */ |
| move.l %d0, (%a1)+ /* store new phases, advance pointer */ |
| |
| move.l (%a1), %d0 /* fetch 4 pixel phases */ |
| bclr.l #31, %d0 /* Z = !(p0 & 0x80); p0 &= ~0x80; */ |
| seq.b %d1 /* %d1 = ....................012344444444 */ |
| lsl.l #1, %d1 /* %d1 = ...................012344444444. */ |
| bclr.l #23, %d0 /* Z = !(p1 & 0x80); p1 &= ~0x80; */ |
| seq.b %d1 /* %d1 = ...................0123455555555 */ |
| lsl.l #1, %d1 /* %d1 = ..................0123455555555. */ |
| bclr.l #15, %d0 /* Z = !(p2 & 0x80); p2 &= ~0x80; */ |
| seq.b %d1 /* %d1 = ..................01234566666666 */ |
| lsl.l #1, %d1 /* %d1 = .................01234566666666. */ |
| bclr.l #7, %d0 /* Z = !(p3 & 0x80); p3 &= ~0x80; */ |
| seq.b %d1 /* %d1 = .................012345677777777 */ |
| lsr.l #7, %d1 /* %d1 = ........................01234567 */ |
| add.l (%a0)+, %d0 /* add 4 pixel values to the phases */ |
| move.l %d0, (%a1)+ /* store new phases, advance pointer */ |
| |
| move.w %d1, (%a3) /* transfer to lcd */ |
| move.w %d1, (%a3) /* transfer to lcd */ |
| |
| cmp.l %a2, %a1 |
| bls.s .ph_loop |
| |
| movem.l (%sp), %a2-%a3 |
| lea.l (2*4, %sp), %sp |
| rts |
| .grey_end: |
| .size lcd_grey_data,.grey_end-lcd_grey_data |