blob: ae55dfb2242a6d12d0516b161abd04cde5d505ae [file] [log] [blame]
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006 by Jens Arnold
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "cpu.h"
.section .icode, "ax", @progbits
/* lcd_write_yuv420_lines(), based on lcd-as-x5.S
*
* See http://en.wikipedia.org/wiki/YCbCr
* ITU-R BT.601 (formerly CCIR 601):
* |Y'| | 0.299000 0.587000 0.114000| |R|
* |Pb| = |-0.168736 -0.331264 0.500000| |G| or 0.564334*(B - Y')
* |Pr| | 0.500000 -0.418688 0.081312| |B| or 0.713267*(R - Y')
* Scaled, normalized and rounded:
* |Y'| | 65 129 25| |R| + 16 : 16->235
* |Cb| = |-38 -74 112| |G| + 128 : 16->240
* |Cr| |112 -94 -18| |B| + 128 : 16->240
*
* The inverse:
* |R| |1.000000 0.000000 1.402000| |Y'|
* |G| = |1.000000 -0.334136 -0.714136| |Pb|
* |B| |1.000000 1.772000 0.000000| |Pr|
* Scaled, normalized, rounded and tweaked to yield RGB666, as converting
* directly to RGB565 gives too much roundoff error:
* |R| |74 0 101| |Y' - 16| / 256
* |G| = |74 -24 -51| |Cb - 128| / 256
* |B| |74 128 0| |Cr - 128| / 256
*/
.align 2
.global lcd_write_yuv420_lines
.type lcd_write_yuv420_lines, @function
lcd_write_yuv420_lines:
lea.l (-36, %sp), %sp /* free up some registers */
movem.l %d2-%d6/%a2-%a5, (%sp)
lea.l 0xf0000002, %a0 /* LCD data port */
movem.l (36+4, %sp), %a1-%a5 /* Y data, Cb data, guv storage, Cr data, width */
lea.l (%a1, %a5), %a5 /* end address */
.yuv_line_loop1:
/* chroma for first & second pixel */
clr.l %d1 /* load bu component */
move.b (%a2), %d1
clr.l %d3 /* load rv component */
move.b (%a4), %d3
moveq.l #-128, %d0
add.l %d0, %d1
add.l %d0, %d3
move.l %d1, %d2 /* %d2 = cb component for guv */
asr.l #1, %d1 /* %d1 = 128 * (Cb - 128) / 256 */
move.b %d1, (%a2)+ /* save bu for next line */
moveq.l #-24, %d0
muls.w %d0, %d2 /* %d2 = -24 * (Cb - 128)*/
moveq.l #-51, %d0
muls.w %d3, %d0
add.l %d0, %d2 /* %d2 = -24 * (Cb - 128) - 51 * (Cr - 128) */
asr.l #8, %d2
move.b %d2, (%a3)+ /* save guv for next line */
moveq.l #101, %d0
muls.w %d0, %d3 /* %d3 = 101 * (Cr - 128) */
asr.l #8, %d3
move.b %d3, (%a4)+ /* save rv for next line */
/* luma for first pixel */
clr.l %d4 /* load y component */
move.b (%a1)+, %d4
moveq.l #74, %d0
muls.w %d0, %d4 /* %d4 = 36 * Y */
asr.l #8, %d4
subq.l #4, %d4 /* correction for (Y - 16) and rounding */
move.l %d4, %d5
move.l %d4, %d6
/* combine & write first pixel */
add.l %d1, %d4 /* %d4 = blue */
add.l %d2, %d5 /* %d5 = green */
add.l %d3, %d6 /* %d6 = red */
move.l %d4, %d0 /* clamping */
or.l %d5, %d0
or.l %d6, %d0
asr.l #6, %d0
beq.s .yuv_all_ok1
moveq.l #63, %d0
cmp.l %d0, %d4
bls.s .yuv_blue_ok1
spl.b %d4
and.l %d0, %d4
.yuv_blue_ok1:
cmp.l %d0, %d5
bls.s .yuv_green_ok1
spl.b %d5
and.l %d0, %d5
.yuv_green_ok1:
cmp.l %d0, %d6
bls.s .yuv_red_ok1
spl.b %d6
and.l %d0, %d6
.yuv_red_ok1:
.yuv_all_ok1:
lsr.l #1, %d6 /* pack, convert to RGB565 and output */
lsr.l #1, %d4
lsl.l #6, %d6
or.l %d6, %d5
lsl.l #5, %d5
or.l %d5, %d4
move.w %d4, (%a0)
/* luma for second pixel */
clr.l %d4 /* load y component */
move.b (%a1)+, %d4
moveq.l #74, %d0
muls.w %d0, %d4 /* %d4 = 36 * Y */
asr.l #8, %d4
subq.l #4, %d4 /* correction for (Y - 16) and rounding */
/* combine & write second pixel */
add.l %d4, %d1 /* %d1 = blue */
add.l %d4, %d2 /* %d2 = green */
add.l %d4, %d3 /* %d3 = red */
move.l %d1, %d0 /* clamping */
or.l %d2, %d0
or.l %d3, %d0
asr.l #6, %d0
beq.s .yuv_all_ok2
moveq.l #63, %d0
cmp.l %d0, %d1
bls.s .yuv_blue_ok2
spl.b %d1
and.l %d0, %d1
.yuv_blue_ok2:
cmp.l %d0, %d2
bls.s .yuv_green_ok2
spl.b %d2
and.l %d0, %d2
.yuv_green_ok2:
cmp.l %d0, %d3
bls.s .yuv_red_ok2
spl.b %d3
and.l %d0, %d3
.yuv_red_ok2:
.yuv_all_ok2:
lsr.l #1, %d3 /* pack, convert to RGB565 and output */
lsr.l #1, %d1
lsl.l #6, %d3
or.l %d3, %d2
lsl.l #5, %d2
or.l %d2, %d1
move.w %d1, (%a0)
cmp.l %a1,%a5 /* run %a1 up to end of line */
bhi.w .yuv_line_loop1
/* Rewind chroma pointers */
movem.l (36+8, %sp), %a2-%a5 /* bu data, guv data, rv data, width */
lea.l (%a1, %a5), %a5 /* next end address */
.yuv_line_loop2:
/* read saved chromas and sign extend */
move.b (%a2)+, %d1
extb.l %d1
move.b (%a3)+, %d2
extb.l %d2
move.b (%a4)+, %d3
extb.l %d3
/* luma for first pixel */
clr.l %d4 /* load y component */
move.b (%a1)+, %d4
moveq.l #74, %d0
muls.w %d0, %d4 /* %d4 = 36 * Y */
asr.l #8, %d4
subq.l #4, %d4 /* correction for (Y - 16) and rounding */
move.l %d4, %d5
move.l %d4, %d6
/* combine & write first pixel */
add.l %d1, %d4 /* %d4 = blue */
add.l %d2, %d5 /* %d5 = green */
add.l %d3, %d6 /* %d6 = red */
move.l %d4, %d0 /* clamping */
or.l %d5, %d0
or.l %d6, %d0
asr.l #6, %d0
beq.s .yuv_all_ok3
moveq.l #63, %d0
cmp.l %d0, %d4
bls.s .yuv_blue_ok3
spl.b %d4
and.l %d0, %d4
.yuv_blue_ok3:
cmp.l %d0, %d5
bls.s .yuv_green_ok3
spl.b %d5
and.l %d0, %d5
.yuv_green_ok3:
cmp.l %d0, %d6
bls.s .yuv_red_ok3
spl.b %d6
and.l %d0, %d6
.yuv_red_ok3:
.yuv_all_ok3:
lsr.l #1, %d6 /* pack, convert to RGB565 and output */
lsr.l #1, %d4
lsl.l #6, %d6
or.l %d6, %d5
lsl.l #5, %d5
or.l %d5, %d4
move.w %d4, (%a0)
/* luma for second pixel */
clr.l %d4 /* load y component */
move.b (%a1)+, %d4
moveq.l #74, %d0
muls.w %d0, %d4 /* %d4 = 36 * Y */
asr.l #8, %d4
subq.l #4, %d4 /* correction for (Y - 16) and rounding */
/* combine & write second pixel */
add.l %d4, %d1 /* %d1 = blue */
add.l %d4, %d2 /* %d2 = green */
add.l %d4, %d3 /* %d3 = red */
move.l %d1, %d0 /* clamping */
or.l %d2, %d0
or.l %d3, %d0
asr.l #6, %d0
beq.s .yuv_all_ok4
moveq.l #63, %d0
cmp.l %d0, %d1
bls.s .yuv_blue_ok4
spl.b %d1
and.l %d0, %d1
.yuv_blue_ok4:
cmp.l %d0, %d2
bls.s .yuv_green_ok4
spl.b %d2
and.l %d0, %d2
.yuv_green_ok4:
cmp.l %d0, %d3
bls.s .yuv_red_ok4
spl.b %d3
and.l %d0, %d3
.yuv_red_ok4:
.yuv_all_ok4:
lsr.l #1, %d3 /* pack, convert to RGB565 and output */
lsr.l #1, %d1
lsl.l #6, %d3
or.l %d3, %d2
lsl.l #5, %d2
or.l %d2, %d1
move.w %d1, (%a0)
cmp.l %a1, %a5 /* run %a1 up to end of line */
bhi.w .yuv_line_loop2
movem.l (%sp), %d2-%d6/%a2-%a5
lea.l (36, %sp), %sp /* restore registers */
rts
.lcd_write_yuv420_lines_end:
.size lcd_write_yuv420_lines, .lcd_write_yuv420_lines_end - lcd_write_yuv420_lines