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
This commit is contained in:
Frank Gevaerts 2010-01-18 19:05:20 +00:00
parent 39e51cc66e
commit 553626a958
29 changed files with 2572 additions and 6 deletions

View file

@ -31,6 +31,10 @@
#define ADC_DATA_2 (*(volatile unsigned long*)(0x7000ad24))
#define ADC_INIT (*(volatile unsigned long*)(0x7000ad2c))
#if defined(PBELL_VIBE500)
#define ADC_UNK (*(volatile unsigned long*)(0x7000002c))
#endif
static unsigned short adcdata[NUM_ADC_CHANNELS];
/* Scan ADC so that adcdata[channel] gets updated. */
@ -94,6 +98,10 @@ static void adc_tick(void)
/* Figured out from how the OF does things */
void adc_init(void)
{
#if defined(PBELL_VIBE500)
ADC_UNK |= 0x1000;
#endif
#if defined(PHILIPS_HDD1630) || defined(PHILIPS_HDD6330)
ADC_INIT = 0;
#else

View file

@ -270,7 +270,8 @@ void i2c_init(void)
#if CONFIG_I2C == I2C_PP5020
outl(0x0, 0x600060a4);
#if defined(PHILIPS_HDD1630) || defined(PHILIPS_HDD6330) || \
defined(SAMSUNG_YH820) || defined(SAMSUNG_YH920) || defined(SAMSUNG_YH925)
defined(SAMSUNG_YH820) || defined(SAMSUNG_YH920) || \
defined(SAMSUNG_YH925) || defined(PBELL_VIBE500)
outl(inl(0x600060a4) | 0x20, 0x600060a4);
outl(inl(0x7000c020) | 0x3, 0x7000c020);
outl(0x55, 0x7000c02c);

View file

@ -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 = .;
}
}

View file

@ -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
}

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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 <stdbool.h>
#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_ */

View file

@ -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_pos<scr_pos)&&(old_pos!=-1)) int_btn = BUTTON_DOWN;
if ((old_pos>scr_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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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 <stdbool.h>
#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);
}

View file

@ -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;
}

View file

@ -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

View file

@ -159,6 +159,16 @@ void __attribute__((interrupt("IRQ"))) irq_handler(void)
usb_insert_int();
}
/* end SAMSUNG_YHxxx */
#elif defined(PBELL_VIBE500)
else if (CPU_HI_INT_STAT & GPIO0_MASK) {
if (GPIOA_INT_STAT & 0x20)
button_int();
}
else if (CPU_HI_INT_STAT & GPIO2_MASK) {
if (GPIOL_INT_STAT & 0x04)
usb_insert_int();
}
/* end PBELL_VIBE500 */
#endif
#ifdef IPOD_ACCESSORY_PROTOCOL
else if (CPU_HI_INT_STAT & SER0_MASK) {
@ -461,6 +471,8 @@ void system_init(void)
/* to be done */
#elif defined (TATUNG_TPJ1022)
/* to be done */
#elif defined(PBELL_VIBE500)
/* to be done */
#endif
#if !defined(SANSA_E200) && !defined(SANSA_C200) && !defined(PHILIPS_SA9200)

View file

@ -88,6 +88,12 @@
#define USB_GPIO_MASK 0x10
#define USB_GPIO_VAL 0x10
#elif defined(PBELL_VIBE500)
/* GPIO L bit 3 is usb detect */
#define USB_GPIO GPIOL
#define USB_GPIO_MASK 0x04
#define USB_GPIO_VAL 0x04
#else
#error No USB GPIO config specified
#endif

View file

@ -33,7 +33,8 @@
#include "wmcodec.h"
#if defined(IRIVER_H10) || defined(IRIVER_H10_5GB) || \
defined(MROBE_100) || defined(PHILIPS_HDD1630)
defined(MROBE_100) || defined(PHILIPS_HDD1630) || \
defined(PBELL_VIBE500)
/* The H10's audio codec uses an I2C address of 0x1b */
#define I2C_AUDIO_ADDRESS 0x1b
#else