From 553626a9582a266f99134f735759e63da0a44714 Mon Sep 17 00:00:00 2001 From: Frank Gevaerts Date: Mon, 18 Jan 2010 19:05:20 +0000 Subject: Add initial Packard Bell Vibe 500 port, by Szymon Dziok Author: Szymon Dziok Flyspray: FS#10912 git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24276 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/pbell/app.lds | 198 ++++++++ firmware/target/arm/pbell/boot.lds | 64 +++ firmware/target/arm/pbell/vibe500/adc-target.h | 35 ++ .../target/arm/pbell/vibe500/backlight-target.h | 38 ++ .../target/arm/pbell/vibe500/backlight-vibe500.c | 87 ++++ firmware/target/arm/pbell/vibe500/button-target.h | 65 +++ firmware/target/arm/pbell/vibe500/button-vibe500.c | 114 +++++ firmware/target/arm/pbell/vibe500/lcd-as-vibe500.S | 556 +++++++++++++++++++++ firmware/target/arm/pbell/vibe500/lcd-vibe500.c | 503 +++++++++++++++++++ firmware/target/arm/pbell/vibe500/power-vibe500.c | 103 ++++ .../target/arm/pbell/vibe500/powermgmt-vibe500.c | 57 +++ firmware/target/arm/pbell/vibe500/usb-target.h | 29 ++ 12 files changed, 1849 insertions(+) create mode 100644 firmware/target/arm/pbell/app.lds create mode 100644 firmware/target/arm/pbell/boot.lds create mode 100644 firmware/target/arm/pbell/vibe500/adc-target.h create mode 100644 firmware/target/arm/pbell/vibe500/backlight-target.h create mode 100644 firmware/target/arm/pbell/vibe500/backlight-vibe500.c create mode 100644 firmware/target/arm/pbell/vibe500/button-target.h create mode 100644 firmware/target/arm/pbell/vibe500/button-vibe500.c create mode 100644 firmware/target/arm/pbell/vibe500/lcd-as-vibe500.S create mode 100644 firmware/target/arm/pbell/vibe500/lcd-vibe500.c create mode 100644 firmware/target/arm/pbell/vibe500/power-vibe500.c create mode 100644 firmware/target/arm/pbell/vibe500/powermgmt-vibe500.c create mode 100644 firmware/target/arm/pbell/vibe500/usb-target.h (limited to 'firmware/target/arm/pbell') diff --git a/firmware/target/arm/pbell/app.lds b/firmware/target/arm/pbell/app.lds new file mode 100644 index 0000000000..22468192eb --- /dev/null +++ b/firmware/target/arm/pbell/app.lds @@ -0,0 +1,198 @@ +#include "config.h" + +ENTRY(start) + +OUTPUT_FORMAT(elf32-littlearm) +OUTPUT_ARCH(arm) +STARTUP(target/arm/crt0-pp.o) + +#define PLUGINSIZE PLUGIN_BUFFER_SIZE +#define CODECSIZE CODEC_SIZE + +#ifdef DEBUG +#define STUBOFFSET 0x10000 +#else +#define STUBOFFSET 0 +#endif + +#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGINSIZE - STUBOFFSET - CODECSIZE + +#define DRAMORIG 0x00000000 + STUBOFFSET +#define IRAMORIG 0x40000000 +#define IRAMSIZE 0xc000 + +#ifdef CPU_PP502x +#define NOCACHE_BASE 0x10000000 +#else +#define NOCACHE_BASE 0x28000000 +#endif + +#define CACHEALIGN_SIZE 16 + +/* End of the audio buffer, where the codec buffer starts */ +#define ENDAUDIOADDR (DRAMORIG + DRAMSIZE) + +/* Where the codec buffer ends, and the plugin buffer starts */ +#define ENDADDR (ENDAUDIOADDR + CODECSIZE) + +MEMORY +{ + DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE + IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE +} + +SECTIONS +{ + .text : + { + loadaddress = .; + _loadaddress = .; + . = ALIGN(0x200); + *(.init.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + . = ALIGN(0x4); + } > DRAM + + .rodata : + { + *(.rodata) /* problems without this, dunno why */ + *(.rodata*) + *(.rodata.str1.1) + *(.rodata.str1.4) + . = ALIGN(0x4); + + /* Pseudo-allocate the copies of the data sections */ + _datacopy = .; + } > DRAM + + /* TRICK ALERT! For RAM execution, we put the .data section at the + same load address as the copy. Thus, we don't waste extra RAM + when we don't actually need the copy. */ + .data : AT ( _datacopy ) + { + _datastart = .; + *(.data*) + . = ALIGN(0x4); + _dataend = .; + } > DRAM + +#if NOCACHE_BASE != 0 + /* .ncdata section is placed at uncached physical alias address and is + * loaded at the proper cached virtual address - no copying is + * performed in the init code */ + .ncdata . + NOCACHE_BASE : + { + . = ALIGN(CACHEALIGN_SIZE); + *(.ncdata*) + . = ALIGN(CACHEALIGN_SIZE); + } AT> DRAM +#endif + + /DISCARD/ : + { + *(.eh_frame) + } + + .vectors 0x0 : + { + _vectorsstart = .; + *(.vectors); + _vectorsend = .; + } AT> DRAM + + _vectorscopy = LOADADDR(.vectors); + _noloaddram = LOADADDR(.vectors); + + .ibss IRAMORIG (NOLOAD) : + { + _iedata = .; + *(.qharray) + *(.ibss) + . = ALIGN(0x4); + _iend = .; + } > IRAM + + .iram _iend : + { + _iramstart = .; + *(.icode) + *(.irodata) + *(.idata) + . = ALIGN(0x4); + _iramend = .; + } > IRAM AT> DRAM + + _iramcopy = LOADADDR(.iram); + + .idle_stacks (NOLOAD) : + { + *(.idle_stacks) +#if NUM_CORES > 1 + cpu_idlestackbegin = .; + . += IDLE_STACK_SIZE; + cpu_idlestackend = .; +#endif + cop_idlestackbegin = .; + . += IDLE_STACK_SIZE; + cop_idlestackend = .; + } > IRAM + + .stack (NOLOAD) : + { + *(.stack) + stackbegin = .; + . += 0x2000; + stackend = .; + } > IRAM + + /* .bss and .ncbss are treated as a single section to use one init loop to + * zero it - note "_edata" and "_end" */ + .bss _noloaddram (NOLOAD) : + { + _edata = .; + *(.bss*) + *(COMMON) + . = ALIGN(0x4); + } > DRAM + +#if NOCACHE_BASE != 0 + .ncbss . + NOCACHE_BASE (NOLOAD): + { + . = ALIGN(CACHEALIGN_SIZE); + *(.ncbss*) + . = ALIGN(CACHEALIGN_SIZE); + } AT> DRAM +#endif + + /* This will be aligned by preceding alignments */ + .endaddr . - NOCACHE_BASE (NOLOAD) : + { + _end = .; + } > DRAM + + .audiobuf (NOLOAD) : + { + _audiobuffer = .; + audiobuffer = .; + } > DRAM + + .audiobufend ENDAUDIOADDR (NOLOAD) : + { + audiobufend = .; + _audiobufend = .; + } > DRAM + + .codec ENDAUDIOADDR (NOLOAD) : + { + codecbuf = .; + _codecbuf = .; + } + + .plugin ENDADDR (NOLOAD) : + { + _pluginbuf = .; + pluginbuf = .; + } +} diff --git a/firmware/target/arm/pbell/boot.lds b/firmware/target/arm/pbell/boot.lds new file mode 100644 index 0000000000..ccc68c0916 --- /dev/null +++ b/firmware/target/arm/pbell/boot.lds @@ -0,0 +1,64 @@ +#include "config.h" + +ENTRY(start) +OUTPUT_FORMAT(elf32-littlearm) +OUTPUT_ARCH(arm) +STARTUP(target/arm/crt0-pp-bl.o) + +#define DRAMSIZE (MEMORYSIZE * 0x100000) + +#define DRAMORIG 0x10000000 +#define IRAMORIG 0x40000000 +#define IRAMSIZE 0x18000 +#define FLASHORIG 0x001f0000 +#define FLASHSIZE 2M + +MEMORY +{ + DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE + IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE +} + +SECTIONS +{ + . = IRAMORIG; + + .text : { + *(.init.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + } > IRAM + + .data : { + *(.icode) + *(.irodata) + *(.idata) + *(.data*) + *(.ncdata*) + *(.rodata*) + _dataend = . ; + } > IRAM + + .stack : { + *(.stack) + _stackbegin = .; + stackbegin = .; + . += 0x2000; + _stackend = .; + stackend = .; + } > IRAM + + /* The bss section is too large for IRAM - we just move it 16MB into the + DRAM */ + + . = DRAMORIG; + .bss . + (16*1024*1024) : { + _edata = .; + *(.bss*); + *(.ibss); + *(COMMON) + *(.ncbss*); + _end = .; + } > DRAM +} diff --git a/firmware/target/arm/pbell/vibe500/adc-target.h b/firmware/target/arm/pbell/vibe500/adc-target.h new file mode 100644 index 0000000000..79a3f2d8ab --- /dev/null +++ b/firmware/target/arm/pbell/vibe500/adc-target.h @@ -0,0 +1,35 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id:$ + * + * Copyright (C) 2009 by Szymon Dziok + * + * 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. + * + ****************************************************************************/ +#ifndef _ADC_TARGET_H_ +#define _ADC_TARGET_H_ + +#define NUM_ADC_CHANNELS 1 + +#define ADC_BATTERY 0 +#define ADC_UNKNOWN_1 1 +#define ADC_UNKNOWN_2 2 +#define ADC_UNKNOWN_3 3 +#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */ + +/* Force a scan now */ +unsigned short adc_scan(int channel); + +#endif diff --git a/firmware/target/arm/pbell/vibe500/backlight-target.h b/firmware/target/arm/pbell/vibe500/backlight-target.h new file mode 100644 index 0000000000..7fd6d877fb --- /dev/null +++ b/firmware/target/arm/pbell/vibe500/backlight-target.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id:$ + * + * Copyright (C) 2009 by Szymon Dziok + * + * 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. + * + ****************************************************************************/ +#ifndef BACKLIGHT_TARGET_H +#define BACKLIGHT_TARGET_H + +#define _backlight_init() true +void _backlight_on(void); +void _backlight_off(void); + +#ifdef HAVE_BACKLIGHT_BRIGHTNESS +void _backlight_set_brightness(int brightness); +#endif + +#ifdef HAVE_BUTTON_LIGHT +void _buttonlight_on(void); +void _buttonlight_off(void); +void _buttonlight_set_brightness(int brightness); +#endif + +#endif /* BACKLIGHT_TARGET.H */ diff --git a/firmware/target/arm/pbell/vibe500/backlight-vibe500.c b/firmware/target/arm/pbell/vibe500/backlight-vibe500.c new file mode 100644 index 0000000000..727370633b --- /dev/null +++ b/firmware/target/arm/pbell/vibe500/backlight-vibe500.c @@ -0,0 +1,87 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id:$ + * + * Copyright (C) 2009 by Szymon Dziok + * Based on the Iriver H10 and the Philips HD1630 code. + * + * 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" +#include "system.h" +#include "backlight.h" +#include "backlight-target.h" +#include "lcd.h" +#include "synaptics-mep.h" + +void _backlight_on(void) +{ +#ifdef HAVE_LCD_ENABLE + lcd_enable(true); /* power on lcd + visible display */ +#endif + GPIO_SET_BITWISE(GPIOJ_OUTPUT_VAL, 0x01); +} + +void _backlight_off(void) +{ + GPIO_CLEAR_BITWISE(GPIOJ_OUTPUT_VAL, 0x01); +#ifdef HAVE_LCD_ENABLE + lcd_enable(false); /* power off visible display */ +#endif +} + +#ifdef HAVE_BACKLIGHT_BRIGHTNESS +static const int brightness_vals[16] = + {255,237,219,201,183,165,147,130,112,94,76,58,40,22,5,0}; + +void _backlight_set_brightness(int brightness) +{ + /* From PB Vibe Bootloader and OF */ + DEV_INIT1&=0xFFFF3F3F; + DEV_INIT1+=0x4000; + DEV_EN |= 0x20000; + outl(0x80000000 | (brightness_vals[brightness-1] << 16), 0x7000a010); +} +#endif + +#ifdef HAVE_BUTTON_LIGHT +static unsigned short buttonlight_status = 0; + +void _buttonlight_on(void) +{ + if (!buttonlight_status) + { + touchpad_set_buttonlights(0x0f, 0); + buttonlight_status = 1; + } +} + +void _buttonlight_off(void) +{ + if (buttonlight_status) + { + touchpad_set_buttonlights(0x00, 0); + buttonlight_status = 0; + } +} + +void _buttonlight_set_brightness(int brightness) +{ + /* no brightness control, but lights stays on - for compatibility */ + touchpad_set_buttonlights(0x0f, brightness); + buttonlight_status = 1; +} +#endif diff --git a/firmware/target/arm/pbell/vibe500/button-target.h b/firmware/target/arm/pbell/vibe500/button-target.h new file mode 100644 index 0000000000..8190b4313b --- /dev/null +++ b/firmware/target/arm/pbell/vibe500/button-target.h @@ -0,0 +1,65 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id:$ + * + * Copyright (C) 2009 by Szymon Dziok + * + * 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. + * + ****************************************************************************/ +#ifndef _BUTTON_TARGET_H_ +#define _BUTTON_TARGET_H_ + +#include +#include "config.h" + +#define MEP_BUTTON_HEADER 0x19 +#define MEP_BUTTON_ID 0x09 +#define MEP_ABSOLUTE_HEADER 0x0b + +#define HAS_BUTTON_HOLD + +bool button_hold(void); +void button_init_device(void); +int button_read_device(void); + +#ifndef BOOTLOADER +void button_int(void); +#endif + + +#define BUTTON_POWER 0x00000001 +#define BUTTON_MENU 0x00000002 +#define BUTTON_PLAY 0x00000004 +#define BUTTON_PREV 0x00000008 +#define BUTTON_NEXT 0x00000010 +#define BUTTON_REC 0x00000020 /* RECORD */ +#define BUTTON_UP 0x00000040 /* Scrollstrip up move */ +#define BUTTON_DOWN 0x00000080 /* Scrollstrip down move */ +#define BUTTON_OK 0x00000100 +#define BUTTON_CANCEL 0x00000200 + +/* there are no LEFT/RIGHT buttons, but other parts of the code expect them */ +#define BUTTON_LEFT 0x00000400 +#define BUTTON_RIGHT 0x00000800 + +#define BUTTON_MAIN 0x00000fff + +#define BUTTON_REMOTE 0 + +#define POWEROFF_BUTTON BUTTON_POWER +#define POWEROFF_COUNT 10 + +#endif /* _BUTTON_TARGET_H_ */ + diff --git a/firmware/target/arm/pbell/vibe500/button-vibe500.c b/firmware/target/arm/pbell/vibe500/button-vibe500.c new file mode 100644 index 0000000000..c95e996ef8 --- /dev/null +++ b/firmware/target/arm/pbell/vibe500/button-vibe500.c @@ -0,0 +1,114 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id:$ + * + * Copyright (C) 2009 Szymon Dziok + * Based on the Iriver H10 and the Philips HD1630 code + * + * 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 "system.h" +#include "button.h" +#include "backlight.h" +#include "synaptics-mep.h" + +static int int_btn = BUTTON_NONE; +static int old_pos = -1; + +void button_init_device(void) +{ +} + +/* + * Button interrupt handler + */ +void button_int(void) +{ + char data[4]; + int val; + + int_btn = BUTTON_NONE; + + val = touchpad_read_device(data, 4); + + if (val == MEP_BUTTON_HEADER) + { + /* Buttons packet */ + if (data[1] & 0x1) + int_btn |= BUTTON_MENU; + if (data[1] & 0x2) + int_btn |= BUTTON_PLAY; + if (data[1] & 0x4) + int_btn |= BUTTON_NEXT; + if (data[1] & 0x8) + int_btn |= BUTTON_PREV; + } + else if (val == MEP_ABSOLUTE_HEADER) + { + /* Absolute packet - the finger is on the vertical strip. + Position ranges from 1-4095, with 1 at the bottom. */ + val = ((data[1] >> 4) << 8) | data[2]; /* position */ + + if (val > 0) + { + int scr_pos = val >> 8; /* split the scrollstrip into 16 regions */ + if ((old_posscr_pos)&&(old_pos!=-1)) int_btn = BUTTON_UP; + old_pos = scr_pos; + } + else old_pos=-1; + } +} + +int button_read_device(void) +{ + int buttons = int_btn; + unsigned char state; + static bool hold_button = false; + bool hold_button_old; + + hold_button_old = hold_button; + hold_button = button_hold(); + +#ifndef BOOTLOADER + if (hold_button != hold_button_old) + { + backlight_hold_changed(hold_button); + } +#endif + + /* device buttons */ + if (!hold_button) + { + /* Read Record, OK, C */ + state = GPIOA_INPUT_VAL; + if ((state & 0x01)==0) buttons|=BUTTON_REC; + if ((state & 0x40)==0) buttons|=BUTTON_OK; + if ((state & 0x08)==0) buttons|=BUTTON_CANCEL; + + /* Read POWER button */ + if ((GPIOD_INPUT_VAL & 0x40)==0) buttons|=BUTTON_POWER; + } + else return BUTTON_NONE; + return buttons; +} + +bool button_hold(void) +{ + /* GPIOK 01000000B - HOLD when bit not set */ + return (GPIOK_INPUT_VAL & 0x40)?false:true; +} + diff --git a/firmware/target/arm/pbell/vibe500/lcd-as-vibe500.S b/firmware/target/arm/pbell/vibe500/lcd-as-vibe500.S new file mode 100644 index 0000000000..06e78d2aa1 --- /dev/null +++ b/firmware/target/arm/pbell/vibe500/lcd-as-vibe500.S @@ -0,0 +1,556 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id:$ + * + * Copyright (C) 2007-2008 by Michael Sevakis + * Adapted for the Packard Bell Vibe 500 by Szymon Dziok + * + * Packard Bell Vibe 500 LCD assembly routines + * + * 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" + +/**************************************************************************** + * void lcd_write_yuv_420_lines(unsigned char const * const src[3], + * int width, + * int stride); + * + * |R| |1.000000 -0.000001 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 RGB 565: + * |R| |74 0 101| |Y' - 16| >> 9 + * |G| = |74 -24 -51| |Cb - 128| >> 8 + * |B| |74 128 0| |Cr - 128| >> 9 + * + * Write four RGB565 pixels in the following order on each loop: + * 1 3 + > down + * 2 4 \/ left + */ + .section .icode, "ax", %progbits + .align 2 + .global lcd_write_yuv420_lines + .type lcd_write_yuv420_lines, %function +lcd_write_yuv420_lines: + @ r0 = yuv_src + @ r1 = width + @ r2 = stride + stmfd sp!, { r4-r11, lr } @ save non-scratch + ldmia r0, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p + @ r5 = yuv_src[1] = Cb_p + @ r6 = yuv_src[2] = Cr_p + @ + ldr r0, =LCD1_BASE @ + @ + sub r2, r2, #1 @ Adjust stride because of increment +10: @ loop line @ + ldrb r7, [r4], #1 @ r7 = *Y'_p++; + ldrb r8, [r5], #1 @ r8 = *Cb_p++; + ldrb r9, [r6], #1 @ r9 = *Cr_p++; + @ + sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74 + add r12, r7, r7, asl #2 @ actually (Y' - 16)*37 and shift right + add r7, r12, r7, asl #5 @ by one less when adding - same for all + @ + sub r8, r8, #128 @ Cb -= 128 + sub r9, r9, #128 @ Cr -= 128 + @ + add r10, r9, r9, asl #1 @ r10 = Cr*51 + Cb*24 + add r10, r10, r10, asl #4 @ + add r10, r10, r8, asl #3 @ + add r10, r10, r8, asl #4 @ + @ + add r11, r9, r9, asl #2 @ r9 = Cr*101 + add r11, r11, r9, asl #5 @ + add r9, r11, r9, asl #6 @ + @ + add r8, r8, #2 @ r8 = bu = (Cb*128 + 128) >> 8 + mov r8, r8, asr #2 @ + add r9, r9, #256 @ r9 = rv = (r8 + 256) >> 9 + mov r9, r9, asr #9 @ + rsb r10, r10, #128 @ r10 = guv = (-r9 + 128) >> 8 + mov r10, r10, asr #8 @ + @ compute R, G, and B + add r3, r8, r7, asr #8 @ r3 = b = (Y >> 9) + bu + add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv + add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv + @ + orr r12, r3, r11 @ check if clamping is needed... + orr r12, r12, r7, asr #1 @ ...at all + cmp r12, #31 @ + bls 15f @ no clamp @ + cmp r3, #31 @ clamp b + mvnhi r3, r3, asr #31 @ + andhi r3, r3, #31 @ + cmp r11, #31 @ clamp r + mvnhi r11, r11, asr #31 @ + andhi r11, r11, #31 @ + cmp r7, #63 @ clamp g + mvnhi r7, r7, asr #31 @ + andhi r7, r7, #63 @ +15: @ no clamp @ + @ + ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) + @ + orr r3, r3, r11, lsl #11 @ r3 = b | (r << 11) + orr r3, r3, r7, lsl #5 @ r3 |= (g << 5) + @ + movs r7, r3, lsr #8 @ store pixel +20: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 20b @ + str r7, [r0, #0x10] @ +25: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 25b @ + str r3, [r0, #0x10] @ + @ + sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74 + add r12, r7, r7, asl #2 @ + add r7, r12, r7, asl #5 @ + @ compute R, G, and B + add r3, r8, r7, asr #8 @ r3 = b = (Y >> 9) + bu + add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv + add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv + @ + orr r12, r3, r11 @ check if clamping is needed... + orr r12, r12, r7, asr #1 @ ...at all + cmp r12, #31 @ + bls 15f @ no clamp @ + cmp r3, #31 @ clamp b + mvnhi r3, r3, asr #31 @ + andhi r3, r3, #31 @ + cmp r11, #31 @ clamp r + mvnhi r11, r11, asr #31 @ + andhi r11, r11, #31 @ + cmp r7, #63 @ clamp g + mvnhi r7, r7, asr #31 @ + andhi r7, r7, #63 @ +15: @ no clamp @ + @ + ldrb r12, [r4], #1 @ r12 = Y' = *(Y'_p++) + @ + orr r3, r3, r11, lsl #11 @ r3 = b | (r << 11) + orr r3, r3, r7, lsl #5 @ r3 |= (g << 5) + @ + movs r7, r3, lsr #8 @ store pixel +20: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 20b @ + str r7, [r0, #0x10] @ +25: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 25b @ + str r3, [r0, #0x10] @ + @ + sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74 + add r12, r7, r7, asl #2 @ + add r7, r12, r7, asl #5 @ + @ compute R, G, and B + add r3, r8, r7, asr #8 @ r3 = b = (Y >> 9) + bu + add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv + add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv + @ + orr r12, r3, r11 @ check if clamping is needed... + orr r12, r12, r7, asr #1 @ ...at all + cmp r12, #31 @ + bls 15f @ no clamp @ + cmp r3, #31 @ clamp b + mvnhi r3, r3, asr #31 @ + andhi r3, r3, #31 @ + cmp r11, #31 @ clamp r + mvnhi r11, r11, asr #31 @ + andhi r11, r11, #31 @ + cmp r7, #63 @ clamp g + mvnhi r7, r7, asr #31 @ + andhi r7, r7, #63 @ +15: @ no clamp @ + @ + ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) + @ + orr r3, r3, r7, lsl #5 @ r3 = b | (g << 5) + orr r3, r3, r11, lsl #11 @ r3 |= (r << 11) + @ + movs r7, r3, lsr #8 @ store pixel +20: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 20b @ + str r7, [r0, #0x10] @ +25: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 25b @ + str r3, [r0, #0x10] @ + @ + sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74 + add r12, r7, r7, asl #2 @ + add r7, r12, r7, asl #5 @ + @ compute R, G, and B + add r3, r8, r7, asr #8 @ r3 = b = (Y >> 9) + bu + add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv + add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv + @ + orr r12, r3, r11 @ check if clamping is needed... + orr r12, r12, r7, asr #1 @ ...at all + cmp r12, #31 @ + bls 15f @ no clamp @ + cmp r3, #31 @ clamp b + mvnhi r3, r3, asr #31 @ + andhi r3, r3, #31 @ + cmp r11, #31 @ clamp r + mvnhi r11, r11, asr #31 @ + andhi r11, r11, #31 @ + cmp r7, #63 @ clamp g + mvnhi r7, r7, asr #31 @ + andhi r7, r7, #63 @ +15: @ no clamp @ + @ + orr r3, r3, r11, lsl #11 @ r3 = b | (r << 11) + orr r3, r3, r7, lsl #5 @ r3 |= (g << 5) + @ + movs r7, r3, lsr #8 @ store pixel +20: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 20b @ + str r7, [r0, #0x10] @ +25: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 25b @ + str r3, [r0, #0x10] @ + @ + subs r1, r1, #2 @ subtract block from width + bgt 10b @ loop line @ + @ + ldmfd sp!, { r4-r11, pc } @ restore registers and return + .ltorg @ dump constant pool + .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines + + +/**************************************************************************** + * void lcd_write_yuv_420_lines_odither(unsigned char const * const src[3], + * int width, + * int stride, + * int x_screen, + * int y_screen); + * + * |R| |1.000000 -0.000001 1.402000| |Y'| + * |G| = |1.000000 -0.334136 -0.714136| |Pb| + * |B| |1.000000 1.772000 0.000000| |Pr| + * Red scaled at twice g & b but at same precision to place it in correct + * bit position after multiply and leave instruction count lower. + * |R| |258 0 408| |Y' - 16| + * |G| = |149 -49 -104| |Cb - 128| + * |B| |149 258 0| |Cr - 128| + * + * Write four RGB565 pixels in the following order on each loop: + * 1 3 + > down + * 2 4 \/ left + * + * Kernel pattern (raw|use order): + * 5 3 4 2 row0 row2 > down + * 1 7 0 6 | 5 1 3 7 4 0 2 6 col0 left + * 4 2 5 3 | 4 0 2 6 5 1 3 7 col2 \/ + * 0 6 1 7 + */ + .section .icode, "ax", %progbits + .align 2 + .global lcd_write_yuv420_lines_odither + .type lcd_write_yuv420_lines_odither, %function +lcd_write_yuv420_lines_odither: + @ r0 = yuv_src + @ r1 = width + @ r2 = stride + @ r3 = x_screen + @ [sp] = y_screen + stmfd sp!, { r4-r11, lr } @ save non-scratch + ldmia r0, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p + @ r5 = yuv_src[1] = Cb_p + @ r6 = yuv_src[2] = Cr_p + @ + ldr r0, [sp, #40] @ Line up pattern and kernel quadrant + eor r14, r3, r0 @ + and r14, r14, #0x2 @ + mov r14, r14, lsl #6 @ 0x00 or 0x80 + @ + ldr r0, =LCD1_BASE @ + @ + sub r2, r2, #1 @ Adjust stride because of increment +10: @ loop line @ + @ + ldrb r7, [r4], #1 @ r7 = *Y'_p++; + ldrb r8, [r5], #1 @ r8 = *Cb_p++; + ldrb r9, [r6], #1 @ r9 = *Cr_p++; + @ + eor r14, r14, #0x80 @ flip pattern quadrant + @ + sub r7, r7, #16 @ r7 = Y = (Y' - 16)*149 + add r12, r7, r7, asl #2 @ + add r12, r12, r12, asl #4 @ + add r7, r12, r7, asl #6 @ + @ + sub r8, r8, #128 @ Cb -= 128 + sub r9, r9, #128 @ Cr -= 128 + @ + add r10, r8, r8, asl #4 @ r10 = guv = Cr*104 + Cb*49 + add r10, r10, r8, asl #5 @ + add r10, r10, r9, asl #3 @ + add r10, r10, r9, asl #5 @ + add r10, r10, r9, asl #6 @ + @ + mov r8, r8, asl #1 @ r8 = bu = Cb*258 + add r8, r8, r8, asl #7 @ + @ + add r9, r9, r9, asl #1 @ r9 = rv = Cr*408 + add r9, r9, r9, asl #4 @ + mov r9, r9, asl #3 @ + @ + @ compute R, G, and B + add r3, r8, r7 @ r3 = b' = Y + bu + add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv + rsb r7, r10, r7 @ r7 = g' = Y + guv + @ + @ r8 = bu, r9 = rv, r10 = guv + @ + sub r12, r3, r3, lsr #5 @ r3 = 31/32*b + b/256 + add r3, r12, r3, lsr #8 @ + @ + sub r12, r11, r11, lsr #5 @ r11 = 31/32*r + r/256 + add r11, r12, r11, lsr #8 @ + @ + sub r12, r7, r7, lsr #6 @ r7 = 63/64*g + g/256 + add r7, r12, r7, lsr #8 @ + @ + add r12, r14, #0x200 @ + @ + add r3, r3, r12 @ b = r3 + delta + add r11, r11, r12, lsl #1 @ r = r11 + delta*2 + add r7, r7, r12, lsr #1 @ g = r7 + delta/2 + @ + orr r12, r3, r11, asr #1 @ check if clamping is needed... + orr r12, r12, r7 @ ...at all + movs r12, r12, asr #15 @ + beq 15f @ no clamp @ + movs r12, r3, asr #15 @ clamp b + mvnne r3, r12, lsr #15 @ + andne r3, r3, #0x7c00 @ mask b only if clamped + movs r12, r11, asr #16 @ clamp r + mvnne r11, r12, lsr #16 @ + movs r12, r7, asr #15 @ clamp g + mvnne r7, r12, lsr #15 @ +15: @ no clamp @ + @ + ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) + @ + and r11, r11, #0xf800 @ pack pixel + and r7, r7, #0x7e00 @ r3 = pixel = (r & 0xf800) | + orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | + orr r3, r11, r3, lsr #10 @ (b >> 10) + @ + movs r7, r3, lsr #8 @ store pixel +20: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 20b @ + str r7, [r0, #0x10] @ +25: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 25b @ + str r3, [r0, #0x10] @ + @ + sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149 + add r12, r7, r7, asl #2 @ + add r12, r12, r12, asl #4 @ + add r7, r12, r7, asl #6 @ + @ compute R, G, and B + add r3, r8, r7 @ r3 = b' = Y + bu + add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv + rsb r7, r10, r7 @ r7 = g' = Y + guv + @ + sub r12, r3, r3, lsr #5 @ r3 = 31/32*b' + b'/256 + add r3, r12, r3, lsr #8 @ + @ + sub r12, r11, r11, lsr #5 @ r11 = 31/32*r' + r'/256 + add r11, r12, r11, lsr #8 @ + @ + sub r12, r7, r7, lsr #6 @ r7 = 63/64*g' + g'/256 + add r7, r12, r7, lsr #8 @ + @ + @ This element is zero - use r14 @ + @ + add r3, r3, r14 @ b = r3 + delta + add r11, r11, r14, lsl #1 @ r = r11 + delta*2 + add r7, r7, r14, lsr #1 @ g = r7 + delta/2 + @ + orr r12, r3, r11, asr #1 @ check if clamping is needed... + orr r12, r12, r7 @ ...at all + movs r12, r12, asr #15 @ + beq 15f @ no clamp @ + movs r12, r3, asr #15 @ clamp b + mvnne r3, r12, lsr #15 @ + andne r3, r3, #0x7c00 @ mask b only if clamped + movs r12, r11, asr #16 @ clamp r + mvnne r11, r12, lsr #16 @ + movs r12, r7, asr #15 @ clamp g + mvnne r7, r12, lsr #15 @ +15: @ no clamp @ + @ + ldrb r12, [r4], #1 @ r12 = Y' = *(Y'_p++) + @ + and r11, r11, #0xf800 @ pack pixel + and r7, r7, #0x7e00 @ r3 = pixel = (r & 0xf800) | + orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | + orr r3, r11, r3, lsr #10 @ (b >> 10) + @ + movs r7, r3, lsr #8 @ store pixel +20: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 20b @ + str r7, [r0, #0x10] @ +25: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 25b @ + str r3, [r0, #0x10] @ + @ + sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149 + add r12, r7, r7, asl #2 @ + add r12, r12, r12, asl #4 @ + add r7, r12, r7, asl #6 @ + @ compute R, G, and B + add r3, r8, r7 @ r3 = b' = Y + bu + add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv + rsb r7, r10, r7 @ r7 = g' = Y + guv + @ + @ r8 = bu, r9 = rv, r10 = guv + @ + sub r12, r3, r3, lsr #5 @ r3 = 31/32*b' + b'/256 + add r3, r12, r3, lsr #8 @ + @ + sub r12, r11, r11, lsr #5 @ r11 = 31/32*r' + r'/256 + add r11, r12, r11, lsr #8 @ + @ + sub r12, r7, r7, lsr #6 @ r7 = 63/64*g' + g'/256 + add r7, r12, r7, lsr #8 @ + @ + add r12, r14, #0x100 @ + @ + add r3, r3, r12 @ b = r3 + delta + add r11, r11, r12, lsl #1 @ r = r11 + delta*2 + add r7, r7, r12, lsr #1 @ g = r7 + delta/2 + @ + orr r12, r3, r11, asr #1 @ check if clamping is needed... + orr r12, r12, r7 @ ...at all + movs r12, r12, asr #15 @ + beq 15f @ no clamp @ + movs r12, r3, asr #15 @ clamp b + mvnne r3, r12, lsr #15 @ + andne r3, r3, #0x7c00 @ mask b only if clamped + movs r12, r11, asr #16 @ clamp r + mvnne r11, r12, lsr #16 @ + movs r12, r7, asr #15 @ clamp g + mvnne r7, r12, lsr #15 @ +15: @ no clamp @ + @ + ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) + @ + and r11, r11, #0xf800 @ pack pixel + and r7, r7, #0x7e00 @ r3 = pixel = (r & 0xf800) | + orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | + orr r3, r11, r3, lsr #10 @ (b >> 10) + @ + movs r7, r3, lsr #8 @ store pixel +20: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 20b @ + str r7, [r0, #0x10] @ +25: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 25b @ + str r3, [r0, #0x10] @ + @ + sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149 + add r12, r7, r7, asl #2 @ + add r12, r12, r12, asl #4 @ + add r7, r12, r7, asl #6 @ + @ compute R, G, and B + add r3, r8, r7 @ r3 = b' = Y + bu + add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv + rsb r7, r10, r7 @ r7 = g' = Y + guv + @ + sub r12, r3, r3, lsr #5 @ r3 = 31/32*b + b/256 + add r3, r12, r3, lsr #8 @ + @ + sub r12, r11, r11, lsr #5 @ r11 = 31/32*r + r/256 + add r11, r12, r11, lsr #8 @ + @ + sub r12, r7, r7, lsr #6 @ r7 = 63/64*g + g/256 + add r7, r12, r7, lsr #8 @ + @ + add r12, r14, #0x300 @ + @ + add r3, r3, r12 @ b = r3 + delta + add r11, r11, r12, lsl #1 @ r = r11 + delta*2 + add r7, r7, r12, lsr #1 @ g = r7 + delta/2 + @ + orr r12, r3, r11, asr #1 @ check if clamping is needed... + orr r12, r12, r7 @ ...at all + movs r12, r12, asr #15 @ + beq 15f @ no clamp @ + movs r12, r3, asr #15 @ clamp b + mvnne r3, r12, lsr #15 @ + andne r3, r3, #0x7c00 @ mask b only if clamped + movs r12, r11, asr #16 @ clamp r + mvnne r11, r12, lsr #16 @ + movs r12, r7, asr #15 @ clamp g + mvnne r7, r12, lsr #15 @ +15: @ no clamp @ + @ + and r11, r11, #0xf800 @ pack pixel + and r7, r7, #0x7e00 @ r3 = pixel = (r & 0xf800) | + orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | + orr r3, r11, r3, lsr #10 @ (b >> 10) + @ + movs r7, r3, lsr #8 @ store pixel +20: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 20b @ + str r7, [r0, #0x10] @ +25: @ + ldr r11, [r0] @ + tst r11, #LCD1_BUSY_MASK @ + bne 25b @ + str r3, [r0, #0x10] @ + @ + subs r1, r1, #2 @ subtract block from width + bgt 10b @ loop line @ + @ + ldmfd sp!, { r4-r11, pc } @ restore registers and return + .ltorg @ dump constant pool + .size lcd_write_yuv420_lines_odither, .-lcd_write_yuv420_lines_odither diff --git a/firmware/target/arm/pbell/vibe500/lcd-vibe500.c b/firmware/target/arm/pbell/vibe500/lcd-vibe500.c new file mode 100644 index 0000000000..ca483f74ea --- /dev/null +++ b/firmware/target/arm/pbell/vibe500/lcd-vibe500.c @@ -0,0 +1,503 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id:$ + * + * Copyright (C) 2009 by Szymon Dziok + * Based on the Iriver H10 code by Barry Wardell + * + * 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" +#include "lcd.h" +#include "kernel.h" +#include "system.h" + +/** Initialized in lcd_init_device() **/ +/* Is the power turned on? */ +static bool power_on; +/* Is the display turned on? */ +static bool display_on; +/* Reverse flag. Must be remembered when display is turned off. */ +static unsigned short disp_control_rev; +/* Contrast setting << 8 */ +static int lcd_contrast; + +static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0; + +/* Forward declarations */ +#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) +static void lcd_display_off(void); +#endif + +/* register defines for the Renesas HD66773R */ +/* + In Packard Bell from the OF - it seems to be + HD66774(gate) with HD66772(source) - registers + are very similar but not all the same +*/ +#define R_START_OSC 0x00 +#define R_DEVICE_CODE_READ 0x00 +#define R_DRV_OUTPUT_CONTROL 0x01 +#define R_DRV_AC_CONTROL 0x02 +#define R_POWER_CONTROL1 0x03 +#define R_POWER_CONTROL2 0x04 +#define R_ENTRY_MODE 0x05 +#define R_COMPARE_REG 0x06 +#define R_DISP_CONTROL 0x07 +#define R_FRAME_CYCLE_CONTROL 0x0b +#define R_POWER_CONTROL3 0x0c +#define R_POWER_CONTROL4 0x0d +#define R_POWER_CONTROL5 0x0e +#define R_GATE_SCAN_START_POS 0x0f +#define R_VERT_SCROLL_CONTROL 0x11 +#define R_1ST_SCR_DRV_POS 0x14 +#define R_2ND_SCR_DRV_POS 0x15 +#define R_HORIZ_RAM_ADDR_POS 0x16 +#define R_VERT_RAM_ADDR_POS 0x17 +#define R_RAM_WRITE_DATA_MASK 0x20 +#define R_RAM_ADDR_SET 0x21 +#define R_WRITE_DATA_2_GRAM 0x22 +#define R_RAM_READ_DATA 0x22 +#define R_GAMMA_FINE_ADJ_POS1 0x30 +#define R_GAMMA_FINE_ADJ_POS2 0x31 +#define R_GAMMA_FINE_ADJ_POS3 0x32 +#define R_GAMMA_GRAD_ADJ_POS 0x33 +#define R_GAMMA_FINE_ADJ_NEG1 0x34 +#define R_GAMMA_FINE_ADJ_NEG2 0x35 +#define R_GAMMA_FINE_ADJ_NEG3 0x36 +#define R_GAMMA_GRAD_ADJ_NEG 0x37 +#define R_GAMMA_AMP_ADJ_POS 0x3a +#define R_GAMMA_AMP_ADJ_NEG 0x3b + +static inline void lcd_wait_write(void) +{ + while (LCD1_CONTROL & LCD1_BUSY_MASK); +} + +/* Send command */ +static inline void lcd_send_cmd(unsigned v) +{ + lcd_wait_write(); + LCD1_CMD = (v >> 8); + lcd_wait_write(); + LCD1_CMD = (v & 0xff); +} + +/* Send 16-bit data */ +static inline void lcd_send_data(unsigned v) +{ + lcd_wait_write(); + LCD1_DATA = (v >> 8); + lcd_wait_write(); + LCD1_DATA = (v & 0xff); +} + +/* Send 16-bit data byte-swapped. */ +static inline void lcd_send_data_swapped(unsigned v) +{ + lcd_wait_write(); + LCD1_DATA = (v & 0xff); + lcd_wait_write(); + LCD1_DATA = (v >> 8); +} + +/* Write value to register */ +static void lcd_write_reg(int reg, int val) +{ + lcd_send_cmd(reg); + lcd_send_data(val); +} + +/*** hardware configuration ***/ + +int lcd_default_contrast(void) +{ + return DEFAULT_CONTRAST_SETTING; +} + +void lcd_set_contrast(int val) +{ + lcd_contrast = (val&0x1f) << 8; + if (!power_on) return; + + /* VCOMG=1, VDV4-0=xxxxx, VCM4-0=11000 */ + lcd_write_reg(R_POWER_CONTROL5, 0x2018 | lcd_contrast); +} + +void lcd_set_invert_display(bool yesno) +{ + if (yesno == (disp_control_rev == 0x0000)) + return; + + disp_control_rev = yesno ? 0x0000 : 0x0004; + + if (!display_on) + return; + + /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=1, REV=x, D1-0=11 */ + lcd_write_reg(R_DISP_CONTROL, 0x0033 | disp_control_rev); +} + +/* turn the display upside down (call lcd_update() afterwards) */ +void lcd_set_flip(bool yesno) +{ + if (!power_on) + return; + + /* SM=0, GS=x, SS=x, NL4-0=10011 (G1-G160) */ + lcd_write_reg(R_DRV_OUTPUT_CONTROL, yesno ? 0x0313 : 0x0013); +} + +/* LCD init */ +void lcd_init_device(void) +{ + power_on = true; + display_on = true; + disp_control_rev = 0x0004; + lcd_contrast = DEFAULT_CONTRAST_SETTING << 8; +} + +#ifdef HAVE_LCD_SLEEP +static void lcd_power_on(void) +{ + /* from the OF */ + lcd_write_reg(R_START_OSC,0x01); /* START_OSC */ + sleep(HZ/40); /* 25ms */ + /* set 396x160 dots, SM=0, GS=x, SS=0, NL4-0=10011 G1-G160)*/ + lcd_write_reg(R_DRV_OUTPUT_CONTROL,0x13); + /* FLD1-0=01 (1 field), B/C=1, EOR=1 (C-pat), NW5-0=000000 (1 row) */ + lcd_write_reg(R_DRV_AC_CONTROL,7 << 8); + /* DIT=0, BGR=1, HWM=0, I/D1-0=0 - decrement AC, AM=1, LG2-0=000 */ + lcd_write_reg(R_ENTRY_MODE,0x1008); + lcd_write_reg(0x25,0x0000); /* - ?? */ + lcd_write_reg(0x26,0x0202); /* - ?? */ + lcd_write_reg(0x0A,0x0000); /* - ?? */ + lcd_write_reg(R_FRAME_CYCLE_CONTROL,0x0000); + lcd_write_reg(R_POWER_CONTROL4,0x0000); + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL5,0x0000); + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL3,0x0000); + lcd_write_reg(0x09,0x0008); /* - ?? */ + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL4,0x0003); + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL5,0x1019); + sleep(HZ/20); /* 50ms */ + lcd_write_reg(R_POWER_CONTROL4,0x0013); + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL1,0x0010); + sleep(HZ/67); /* 15ms */ + lcd_write_reg(0x09,0x0000); /* - ?? */ + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL1,0x0010); + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL5,0x3019); + sleep(HZ/6.6);/* 150ms */ + lcd_write_reg(0x09,0x0002); /* - ?? */ + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL4,0x0018); + sleep(HZ/20); /* 50ms */ + /* RAM Address set (0x0000) */ + lcd_write_reg(R_RAM_ADDR_SET,0x0000); + /* Gamma settings */ + lcd_write_reg(R_GAMMA_FINE_ADJ_POS1,0x0004); + lcd_write_reg(R_GAMMA_FINE_ADJ_POS2,0x0606); + lcd_write_reg(R_GAMMA_FINE_ADJ_POS3,0x0505); + lcd_write_reg(R_GAMMA_GRAD_ADJ_POS,0x0206); + lcd_write_reg(R_GAMMA_FINE_ADJ_NEG1,0x0505); + lcd_write_reg(R_GAMMA_FINE_ADJ_NEG2,0x0707); + lcd_write_reg(R_GAMMA_FINE_ADJ_NEG3,0x0105); + lcd_write_reg(R_GAMMA_GRAD_ADJ_NEG,0x0301); + lcd_write_reg(R_GAMMA_AMP_ADJ_POS,0x1A00); + lcd_write_reg(R_GAMMA_AMP_ADJ_NEG,0x010E); + + lcd_write_reg(R_GATE_SCAN_START_POS,0x0000); + /* Horizontal ram address start/end position (0,127); */ + lcd_write_reg(R_HORIZ_RAM_ADDR_POS,0x7F00); + /* Vertical ram address start/end position (0,159); */ + lcd_write_reg(R_VERT_RAM_ADDR_POS,0x9F00); + + lcd_write_reg(R_DISP_CONTROL,0x0005); + sleep(HZ/25); /* 40ms */ + lcd_write_reg(R_DISP_CONTROL,0x0025); + lcd_write_reg(R_DISP_CONTROL,0x0027); + sleep(HZ/25); /* 40ms */ + lcd_write_reg(R_DISP_CONTROL,0x0033 | disp_control_rev); + sleep(HZ/100); /* 10ms */ + lcd_write_reg(R_POWER_CONTROL1,0x0110); + lcd_write_reg(R_FRAME_CYCLE_CONTROL,0x0000); + lcd_write_reg(R_POWER_CONTROL4,0x0013); + lcd_write_reg(R_POWER_CONTROL5,0x2018 | lcd_contrast); + sleep(HZ/20); /* 50ms */ + + power_on = true; +} + +static void lcd_power_off(void) +{ + /* Display must be off first */ + if (display_on) + lcd_display_off(); + + /* power_on = false; */ + + /** Power OFF sequence **/ + /* The method is unknown */ +} + +void lcd_sleep(void) +{ + if (power_on) + lcd_power_off(); + + /* Set standby mode */ + /* Because we dont know how to power off display + we cannot set standby */ + /* BT2-0=000, DC2-0=000, AP2-0=000, SLP=0, STB=1 */ + /* lcd_write_reg(R_POWER_CONTROL1, 0x0001); */ +} +#endif + +#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) +static void lcd_display_off(void) +{ + display_on = false; + + /** Display OFF sequence **/ + /* In the OF it is called "EnterStandby" */ + + /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=1, REV=x, D1-0=10 */ + lcd_write_reg(R_DISP_CONTROL, 0x0032 | disp_control_rev); + sleep(HZ/22); /* 45ms */ + /* PT1-0=00, VLE2-1=00, SPT=0, GON=1, DTE=0, REV=x, D1-0=10 */ + lcd_write_reg(R_DISP_CONTROL, 0x0022 | disp_control_rev); + sleep(HZ/22); /* 45ms */ + /* PT1-0=00, VLE2-1=00, SPT=0, GON=0, DTE=0, REV=0, D1-0=00 */ + lcd_write_reg(R_DISP_CONTROL, 0x0000); + + lcd_write_reg(R_POWER_CONTROL1, 0x0000); + lcd_write_reg(0x09, 0x0000); /* -?? */ + lcd_write_reg(R_POWER_CONTROL4, 0x0000); + + sleep(HZ/22); /* 45ms */ +} +#endif + +#if defined(HAVE_LCD_ENABLE) +static void lcd_display_on(void) +{ + /* Be sure power is on first */ + if (!power_on) + lcd_power_on(); + + /** Display ON Sequence **/ + /* In the OF it is called "ExitStandby" */ + + lcd_write_reg(R_START_OSC,1); + sleep(HZ/40); /* 25ms */ + lcd_write_reg(R_POWER_CONTROL4,0); + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL5,0); + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_DISP_CONTROL,0); + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL3,0); + lcd_write_reg(0x09,8); /* -?? */ + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL4,3); + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL5,0x1019); + sleep(HZ/20); /* 50ms */ + lcd_write_reg(R_POWER_CONTROL4,0x13); + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL1,0x10); + sleep(HZ/20); /* 50ms */ + lcd_write_reg(0x09,0); /* -?? */ + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL1,0x10); + sleep(HZ/67); /* 15ms */ + lcd_write_reg(R_POWER_CONTROL5,0x3019); + sleep(HZ/6.6);/* 150ms */ + lcd_write_reg(0x09,2); /* -?? */ + sleep(HZ/20); /* 50ms */ + lcd_write_reg(R_DISP_CONTROL,5); + sleep(HZ/22); /* 45ms */ + lcd_write_reg(R_DISP_CONTROL,0x25); + sleep(HZ/22); /* 45ms */ + lcd_write_reg(R_DISP_CONTROL,0x27); + sleep(HZ/25); /* 40ms */ + lcd_write_reg(R_DISP_CONTROL,0x33 | disp_control_rev); + sleep(HZ/22); /* 45ms */ + /* fix contrast */ + lcd_write_reg(R_POWER_CONTROL5, 0x2018 | lcd_contrast); + + display_on = true; +} + +void lcd_enable(bool on) +{ + if (on == display_on) + return; + + if (on) + { + lcd_display_on(); + /* Probably out of sync and we don't wanna pepper the code with + lcd_update() calls for this. */ + lcd_update(); + send_event(LCD_EVENT_ACTIVATION, NULL); + } + else + { + lcd_display_off(); + } +} +#endif + +#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) +bool lcd_active(void) +{ + return display_on; +} +#endif + +/*** update functions ***/ + +void lcd_yuv_set_options(unsigned options) +{ + lcd_yuv_options = options; +} + +/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ + +extern void lcd_write_yuv420_lines(unsigned char const * const src[3], + int width, + int stride); +extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3], + int width, + int stride, + int x_screen, /* To align dither pattern */ + int y_screen); + +/* Performance function to blit a YUV bitmap directly to the LCD */ +void lcd_blit_yuv(unsigned char * const src[3], + int src_x, int src_y, int stride, + int x, int y, int width, int height) +{ + const unsigned char *yuv_src[3]; + const unsigned char *ysrc_max; + int y0; + int options; + + if (!display_on) + return; + + width &= ~1; + height &= ~1; + + lcd_write_reg(R_VERT_RAM_ADDR_POS, ((LCD_WIDTH - 1 - x) << 8) | + ((LCD_WIDTH-1) - (x + width - 1))); + + y0 = LCD_HEIGHT - 1 - y; + + lcd_write_reg(R_ENTRY_MODE,0x1000); + + yuv_src[0] = src[0] + src_y * stride + src_x; + yuv_src[1] = src[1] + (src_y * stride >> 2) + (src_x >> 1); + yuv_src[2] = src[2] + (yuv_src[1] - src[1]); + ysrc_max = yuv_src[0] + height * stride; + + options = lcd_yuv_options; + + do + { + lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (y0 << 8) | (y0 - 1)); + lcd_write_reg(R_RAM_ADDR_SET, ((LCD_WIDTH - 1 - x) << 8) | y0); + + /* start drawing */ + lcd_send_cmd(R_WRITE_DATA_2_GRAM); + + if (options & LCD_YUV_DITHER) + { + lcd_write_yuv420_lines_odither(yuv_src, width, stride,x, y); + y -= 2; + } + else + { + lcd_write_yuv420_lines(yuv_src, width, stride); + } + + y0 -= 2; + yuv_src[0] += stride << 1; + yuv_src[1] += stride >> 1; + yuv_src[2] += stride >> 1; + } + while (yuv_src[0] < ysrc_max); + lcd_write_reg(R_ENTRY_MODE,0x1008); +} + +/* Update a fraction of the display. */ +void lcd_update_rect(int x0, int y0, int width, int height) +{ + const fb_data *addr; + int x1, y1; + + if (!display_on) + return; + + if ((width<=0)||(height<=0)) + return; + + if ((x0 + width)>=LCD_WIDTH) + width = LCD_WIDTH - x0; + if ((y0 + height)>=LCD_HEIGHT) + height = LCD_HEIGHT - y0; + + y1 = (y0 + height) - 1; + x1 = (x0 + width) - 1; + + /* In the PB Vibe LCD is flipped and the RAM addresses are decremented */ + lcd_send_cmd(R_HORIZ_RAM_ADDR_POS); + lcd_send_data( (((LCD_HEIGHT-1)-y0) << 8) | ((LCD_HEIGHT-1)-y1)); + + lcd_send_cmd(R_VERT_RAM_ADDR_POS); + lcd_send_data( (((LCD_WIDTH -1)-x0) << 8) | ((LCD_WIDTH -1)-x1)); + + lcd_send_cmd(R_RAM_ADDR_SET); + lcd_send_data( (((LCD_WIDTH -1)-x0) << 8) | ((LCD_HEIGHT-1)-y0)); + + /* start drawing */ + lcd_send_cmd(R_WRITE_DATA_2_GRAM); + + addr = &lcd_framebuffer[y0][x0]; + + int c, r; + for (r = 0; r < height; r++) + { + for (c = 0; c < width; c++) + lcd_send_data_swapped(*addr++); + addr += LCD_WIDTH - width; + } +} + +/* Update the display. + This must be called after all other LCD + functions that change the display. */ +void lcd_update(void) +{ + lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); +} diff --git a/firmware/target/arm/pbell/vibe500/power-vibe500.c b/firmware/target/arm/pbell/vibe500/power-vibe500.c new file mode 100644 index 0000000000..e55c69e033 --- /dev/null +++ b/firmware/target/arm/pbell/vibe500/power-vibe500.c @@ -0,0 +1,103 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id:$ + * + * Copyright (C) 2009 by Szymon Dziok + * + * 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" +#include +#include "kernel.h" +#include "system.h" +#include "power.h" +#include "logf.h" +#include "usb.h" +#include "synaptics-mep.h" + +void power_init(void) +{ + GPIOD_ENABLE |= 0x80; /* enable ACK */ + GPIOA_ENABLE |= (0x10 | 0x20); /* enable DATA, CLK */ + + GPIOD_OUTPUT_EN |= 0x80; /* set ACK */ + GPIOD_OUTPUT_VAL |= 0x80; /* high */ + + GPIOA_OUTPUT_EN &= ~0x20; /* CLK */ + + GPIOA_OUTPUT_EN |= 0x10; /* set DATA */ + GPIOA_OUTPUT_VAL |= 0x10; /* high */ + + if (!touchpad_init()) + { + logf("touchpad not ready"); + } + /* Sound unmute (on) */ + GPIO_CLEAR_BITWISE(GPIOL_OUTPUT_VAL, 0x10); +} + +unsigned int power_input_status(void) +{ + unsigned int status = POWER_INPUT_NONE; + /* GPIOL - external charger connected */ + if (GPIOL_INPUT_VAL & 0x20) + status = POWER_INPUT_MAIN_CHARGER; + /* GPIOL - usb connected */ + if (GPIOL_INPUT_VAL & 0x04) + status |= POWER_INPUT_USB_CHARGER; + + return status; +} + +void ide_power_enable(bool on) +{ + if(on){ + GPIO_SET_BITWISE(GPIOC_OUTPUT_VAL, 0x08); + DEV_EN |= DEV_IDE0; + } else + { + DEV_EN &= ~DEV_IDE0; + GPIO_CLEAR_BITWISE(GPIOC_OUTPUT_VAL, 0x08); + } +} + +bool ide_powered(void) +{ + return ((GPIOC_INPUT_VAL & 0x08) == 1); +} + +void power_off(void) +{ + /* from the OF */ +/* + DEV_INIT2 |= DEV_I2S; + GPIO_SET_BITWISE(GPIOL_OUTPUT_VAL, 0x10); + sleep(HZ/100); + GPIO_SET_BITWISE(GPIOL_OUTPUT_VAL, 0x10); + sleep(HZ); + GPIO_CLEAR_BITWISE(GPIOB_OUTPUT_VAL, 0x80); + sleep(HZ); + GPIO_CLEAR_BITWISE(GPIOC_OUTPUT_VAL, 0x08); + GPO32_VAL |= 0x40000000; + GPO32_ENABLE |= 0x40000000; +*/ + /* Sound mute (off) */ + DEV_INIT2 |= DEV_I2S; + GPIO_SET_BITWISE(GPIOL_OUTPUT_VAL, 0x10); + /* shutdown bit */ + GPIO_CLEAR_BITWISE(GPIOB_OUTPUT_VAL, 0x80); +} diff --git a/firmware/target/arm/pbell/vibe500/powermgmt-vibe500.c b/firmware/target/arm/pbell/vibe500/powermgmt-vibe500.c new file mode 100644 index 0000000000..d84881cea1 --- /dev/null +++ b/firmware/target/arm/pbell/vibe500/powermgmt-vibe500.c @@ -0,0 +1,57 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id:$ + * + * Copyright (C) 2002 by Heikki Hannikainen, Uwe Freese + * Revisions copyright (C) 2005 by Gerald Van Baren + * Copyright (C) 2009 by Szymon Dziok + * + * 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 "adc.h" +#include "powermgmt.h" + +const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = +{ + 3515 +}; + +const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = +{ + 3486 +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ +const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +{ + { 3474, 3515, 3556, 3597, 3638, 3679, 3720, 3761, 3802, 3843, 3884 } +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ +const unsigned short percent_to_volt_charge[11] = +{ + 3474, 3515, 3556, 3597, 3638, 3679, 3720, 3761, 3802, 3843, 3884 +}; + +#define BATTERY_SCALE_FACTOR 4200 +/* full-scale ADC readout (2^10) in millivolt */ + +/* Returns battery voltage from ADC [millivolts] */ +unsigned int battery_adc_voltage(void) +{ + return (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) >> 10; +} diff --git a/firmware/target/arm/pbell/vibe500/usb-target.h b/firmware/target/arm/pbell/vibe500/usb-target.h new file mode 100644 index 0000000000..a453a7cbfa --- /dev/null +++ b/firmware/target/arm/pbell/vibe500/usb-target.h @@ -0,0 +1,29 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id:$ + * + * Copyright (C) 2006 by Barry Wardell + * + * 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. + * + ****************************************************************************/ + +/* Based off x5 version */ + +#ifndef USB_TARGET_H +#define USB_TARGET_H + +bool usb_init_device(void); + +#endif -- cgit v1.2.3