mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-09 13:15:18 -05:00
move the Gigabeat from gigabeat/meg-fx to s3c2440/gigabeat-fx to avoid problems with possible ports in the future: Gigabeat S/V (i.mx31 based) and Kenwood HD20GA7/HD20GA9 (s3c2440 based)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13200 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
c3dcc87aa4
commit
f44f961812
29 changed files with 18 additions and 18 deletions
144
firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c
Normal file
144
firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Wade Brown
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cpu.h"
|
||||
#include "adc-target.h"
|
||||
#include "kernel.h"
|
||||
|
||||
|
||||
|
||||
static unsigned short adc_readings[NUM_ADC_CHANNELS];
|
||||
|
||||
/* prototypes */
|
||||
static unsigned short __adc_read(int channel);
|
||||
static void adc_tick(void);
|
||||
|
||||
|
||||
|
||||
void adc_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Turn on the ADC PCLK */
|
||||
CLKCON |= (1<<15);
|
||||
|
||||
/* Set channel 0, normal mode, disable "start by read" */
|
||||
ADCCON &= ~(0x3F);
|
||||
|
||||
/* No start delay. Use normal conversion mode. */
|
||||
ADCDLY = 0x1;
|
||||
|
||||
/* Set and enable the prescaler */
|
||||
ADCCON = (ADCCON & ~(0xff<<6)) | (0x19<<6);
|
||||
ADCCON |= (1<<14);
|
||||
|
||||
/* prefill the adc channels */
|
||||
for (i = 0; i < NUM_ADC_CHANNELS; i++)
|
||||
{
|
||||
adc_readings[i] = __adc_read(i);
|
||||
}
|
||||
|
||||
/* start at zero so when the tick starts it is at zero */
|
||||
adc_readings[0] = __adc_read(0);
|
||||
|
||||
/* attach the adc reading to the tick */
|
||||
tick_add_task(adc_tick);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Called to get the recent ADC reading */
|
||||
inline unsigned short adc_read(int channel)
|
||||
{
|
||||
return adc_readings[channel];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Read the ADC by polling
|
||||
* @param channel The ADC channel to read
|
||||
* @return 10bit reading from ADC channel or ADC_READ_ERROR if timeout
|
||||
*/
|
||||
static unsigned short __adc_read(int channel)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Set the channel */
|
||||
ADCCON = (ADCCON & ~(0x7<<3)) | (channel<<3);
|
||||
|
||||
/* Start the conversion process */
|
||||
ADCCON |= 0x1;
|
||||
|
||||
/* Wait for a low Enable_start */
|
||||
for (i = 20000;;) {
|
||||
if(0 == (ADCCON & 0x1)) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
i--;
|
||||
if (0 == i) {
|
||||
/* Ran out of time */
|
||||
return ADC_READ_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for high End_of_Conversion */
|
||||
for(i = 20000;;) {
|
||||
if(ADCCON & (1<<15)) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
i--;
|
||||
if(0 == i) {
|
||||
/* Ran out of time */
|
||||
return ADC_READ_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (ADCDAT0 & 0x3ff);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* add this to the tick so that the ADC converts are done in the background */
|
||||
static void adc_tick(void)
|
||||
{
|
||||
static unsigned channel;
|
||||
|
||||
/* Check if the End Of Conversion is set */
|
||||
if (ADCCON & (1<<15))
|
||||
{
|
||||
adc_readings[channel] = (ADCDAT0 & 0x3FF);
|
||||
if (++channel >= NUM_ADC_CHANNELS)
|
||||
{
|
||||
channel = 0;
|
||||
}
|
||||
|
||||
/* setup the next conversion and start it*/
|
||||
ADCCON = (ADCCON & ~(0x7<<3)) | (channel<<3) | 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
37
firmware/target/arm/s3c2440/gigabeat-fx/adc-target.h
Normal file
37
firmware/target/arm/s3c2440/gigabeat-fx/adc-target.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Barry Wardell
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef _ADC_TARGET_H_
|
||||
#define _ADC_TARGET_H_
|
||||
|
||||
/* only two channels used by the Gigabeat */
|
||||
#define NUM_ADC_CHANNELS 2
|
||||
|
||||
#define ADC_BATTERY 0
|
||||
#define ADC_HPREMOTE 1
|
||||
#define ADC_UNKNOWN_3 2
|
||||
#define ADC_UNKNOWN_4 3
|
||||
#define ADC_UNKNOWN_5 4
|
||||
#define ADC_UNKNOWN_6 5
|
||||
#define ADC_UNKNOWN_7 6
|
||||
#define ADC_UNKNOWN_8 7
|
||||
|
||||
#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
|
||||
#define ADC_READ_ERROR 0xFFFF
|
||||
|
||||
#endif
|
||||
143
firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c
Normal file
143
firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id $
|
||||
*
|
||||
* Copyright (C) 2006,2007 by Marcoen Hirschberg
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include <stdbool.h>
|
||||
#include "kernel.h"
|
||||
#include "system.h"
|
||||
#include "power.h"
|
||||
#include "panic.h"
|
||||
#include "pcf50606.h"
|
||||
#include "ata-target.h"
|
||||
#include "mmu-meg-fx.h"
|
||||
#include "backlight-target.h"
|
||||
|
||||
/* ARESET on C7C68300 and RESET on ATA interface (Active Low) */
|
||||
#define ATA_RESET_ENABLE GPGDAT &= ~(1 << 10)
|
||||
#define ATA_RESET_DISABLE GPGDAT |= (1 << 10)
|
||||
|
||||
/* ATA_EN on C7C68300 */
|
||||
#define USB_ATA_ENABLE GPBDAT |= (1 << 5)
|
||||
#define USB_ATA_DISABLE GPBDAT &= ~(1 << 5)
|
||||
|
||||
void ata_reset(void)
|
||||
{
|
||||
ATA_RESET_ENABLE;
|
||||
sleep(1); /* > 25us */
|
||||
ATA_RESET_DISABLE;
|
||||
sleep(1); /* > 2ms */
|
||||
}
|
||||
|
||||
/* This function is called before enabling the USB bus */
|
||||
void ata_enable(bool on)
|
||||
{
|
||||
if(on)
|
||||
USB_ATA_DISABLE;
|
||||
else
|
||||
USB_ATA_ENABLE;
|
||||
|
||||
GPBCON=( GPGCON&~(1<<11) ) | (1<<10); /* Make the pin an output */
|
||||
// GPBUP|=1<<5; /* Disable pullup in SOC as we are now driving */
|
||||
}
|
||||
|
||||
bool ata_is_coldstart(void)
|
||||
{
|
||||
/* Check the pin configuration - return true when pin is unconfigured */
|
||||
return (GPGCON & 0x00300000) == 0;
|
||||
}
|
||||
|
||||
void ata_device_init(void)
|
||||
{
|
||||
/* ATA reset */
|
||||
ATA_RESET_DISABLE; /* Set the pin to disable an active low reset */
|
||||
GPGCON=( GPGCON&~(1<<21) ) | (1<<20); /* Make the pin an output */
|
||||
GPGUP |= 1<<10; /* Disable pullup in SOC as we are now driving */
|
||||
}
|
||||
|
||||
#if !defined(BOOTLOADER)
|
||||
void copy_read_sectors(unsigned char* buf, int wordcount)
|
||||
{
|
||||
__buttonlight_trigger();
|
||||
|
||||
/* Unaligned transfer - slow copy */
|
||||
if ( (unsigned long)buf & 1)
|
||||
{ /* not 16-bit aligned, copy byte by byte */
|
||||
unsigned short tmp = 0;
|
||||
unsigned char* bufend = buf + wordcount*2;
|
||||
do
|
||||
{
|
||||
tmp = ATA_DATA;
|
||||
*buf++ = tmp & 0xff; /* I assume big endian */
|
||||
*buf++ = tmp >> 8; /* and don't use the SWAB16 macro */
|
||||
} while (buf < bufend); /* tail loop is faster */
|
||||
return;
|
||||
}
|
||||
/* This should never happen, but worth watching for */
|
||||
if(wordcount > (1 << 18))
|
||||
panicf("atd-meg-fx.c: copy_read_sectors: too many sectors per read!");
|
||||
|
||||
//#define GIGABEAT_DEBUG_ATA
|
||||
#ifdef GIGABEAT_DEBUG_ATA
|
||||
static int line = 0;
|
||||
static char str[256];
|
||||
snprintf(str, sizeof(str), "ODD DMA to %08x, %d", buf, wordcount);
|
||||
lcd_puts(10, line, str);
|
||||
line = (line+1) % 32;
|
||||
lcd_update();
|
||||
#endif
|
||||
/* Reset the channel */
|
||||
DMASKTRIG0 |= 4;
|
||||
/* Wait for DMA controller to be ready */
|
||||
while(DMASKTRIG0 & 0x2)
|
||||
;
|
||||
while(DSTAT0 & (1 << 20))
|
||||
;
|
||||
/* Source is ATA_DATA, on AHB Bus, Fixed */
|
||||
DISRC0 = (int) 0x18000000;
|
||||
DISRCC0 = 0x1;
|
||||
/* Dest mapped to physical address, on AHB bus, increment */
|
||||
DIDST0 = (int) buf;
|
||||
if(DIDST0 < 0x30000000)
|
||||
DIDST0 += 0x30000000;
|
||||
DIDSTC0 = 0;
|
||||
|
||||
/* DACK/DREQ Sync to AHB, Int on Transfer complete, Whole service, No reload, 16-bit transfers */
|
||||
DCON0 = ((1 << 30) | (1<< 29) | (1<<27) | (1<<22) | (1<<20)) | wordcount;
|
||||
|
||||
/* Activate the channel */
|
||||
DMASKTRIG0 = 0x2;
|
||||
|
||||
invalidate_dcache_range((void *)buf, wordcount*2);
|
||||
|
||||
INTMSK &= ~(1<<17); /* unmask the interrupt */
|
||||
SRCPND = (1<<17); /* clear any pending interrupts */
|
||||
/* Start DMA */
|
||||
DMASKTRIG0 |= 0x1;
|
||||
|
||||
/* Wait for transfer to complete */
|
||||
while((DSTAT0 & 0x000fffff))
|
||||
yield();
|
||||
/* Dump cache for the buffer */
|
||||
}
|
||||
#endif
|
||||
void dma0(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
70
firmware/target/arm/s3c2440/gigabeat-fx/ata-target.h
Normal file
70
firmware/target/arm/s3c2440/gigabeat-fx/ata-target.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Linus Nielsen Feltzing
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef ATA_TARGET_H
|
||||
#define ATA_TARGET_H
|
||||
|
||||
/* Plain C read & write loops */
|
||||
#define PREFER_C_READING
|
||||
#define PREFER_C_WRITING
|
||||
#if !defined(BOOTLOADER)
|
||||
#define ATA_OPTIMIZED_READING
|
||||
void copy_read_sectors(unsigned char* buf, int wordcount);
|
||||
#endif
|
||||
|
||||
#define ATA_IOBASE 0x18000000
|
||||
#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE)))
|
||||
#define ATA_ERROR (*((volatile unsigned char*)(ATA_IOBASE + 0x02)))
|
||||
#define ATA_NSECTOR (*((volatile unsigned char*)(ATA_IOBASE + 0x04)))
|
||||
#define ATA_SECTOR (*((volatile unsigned char*)(ATA_IOBASE + 0x06)))
|
||||
#define ATA_LCYL (*((volatile unsigned char*)(ATA_IOBASE + 0x08)))
|
||||
#define ATA_HCYL (*((volatile unsigned char*)(ATA_IOBASE + 0x0A)))
|
||||
#define ATA_SELECT (*((volatile unsigned char*)(ATA_IOBASE + 0x0C)))
|
||||
#define ATA_COMMAND (*((volatile unsigned char*)(ATA_IOBASE + 0x0E)))
|
||||
#define ATA_CONTROL (*((volatile unsigned char*)(0x20000000 + 0x1C)))
|
||||
|
||||
#define STATUS_BSY 0x80
|
||||
#define STATUS_RDY 0x40
|
||||
#define STATUS_DF 0x20
|
||||
#define STATUS_DRQ 0x08
|
||||
#define STATUS_ERR 0x01
|
||||
#define ERROR_ABRT 0x04
|
||||
|
||||
#define WRITE_PATTERN1 0xa5
|
||||
#define WRITE_PATTERN2 0x5a
|
||||
#define WRITE_PATTERN3 0xaa
|
||||
#define WRITE_PATTERN4 0x55
|
||||
|
||||
#define READ_PATTERN1 0xa5
|
||||
#define READ_PATTERN2 0x5a
|
||||
#define READ_PATTERN3 0xaa
|
||||
#define READ_PATTERN4 0x55
|
||||
|
||||
#define READ_PATTERN1_MASK 0xff
|
||||
#define READ_PATTERN2_MASK 0xff
|
||||
#define READ_PATTERN3_MASK 0xff
|
||||
#define READ_PATTERN4_MASK 0xff
|
||||
|
||||
#define SET_REG(reg,val) reg = (val)
|
||||
#define SET_16BITREG(reg,val) reg = (val)
|
||||
|
||||
void ata_reset(void);
|
||||
void ata_device_init(void);
|
||||
bool ata_is_coldstart(void);
|
||||
|
||||
#endif
|
||||
692
firmware/target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c
Normal file
692
firmware/target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c
Normal file
|
|
@ -0,0 +1,692 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Linus Nielsen Feltzing
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include "system.h"
|
||||
#include "backlight-target.h"
|
||||
#include "backlight.h"
|
||||
#include "lcd.h"
|
||||
#include "sc606-meg-fx.h"
|
||||
#include "power.h"
|
||||
|
||||
|
||||
#define FLICKER_PERIOD 15
|
||||
#define BUTTONLIGHT_MENU (SC606_LED_B1)
|
||||
#define BUTTONLIGHT_ALL (SC606_LED_B1 | SC606_LED_B2 | SC606_LED_C1 | SC606_LED_C2)
|
||||
|
||||
static void led_control_service(void);
|
||||
static unsigned short backlight_brightness;
|
||||
static unsigned short backlight_current;
|
||||
static unsigned short backlight_target;
|
||||
static unsigned short time_til_fade;
|
||||
static unsigned short fade_interval;
|
||||
static unsigned short initial_tick_delay;
|
||||
static unsigned char backlight_leds;
|
||||
|
||||
static enum backlight_states
|
||||
{
|
||||
BACKLIGHT_CONTROL_IDLE,
|
||||
BACKLIGHT_CONTROL_OFF,
|
||||
BACKLIGHT_CONTROL_ON,
|
||||
BACKLIGHT_CONTROL_SET,
|
||||
BACKLIGHT_CONTROL_FADE_OFF,
|
||||
BACKLIGHT_CONTROL_FADE_ON,
|
||||
BACKLIGHT_CONTROL_FADE_ON_FROM_OFF
|
||||
} backlight_control;
|
||||
|
||||
|
||||
|
||||
enum buttonlight_states
|
||||
{
|
||||
/* turn button lights off */
|
||||
BUTTONLIGHT_MODE_OFF_ENTRY,
|
||||
BUTTONLIGHT_MODE_OFF,
|
||||
|
||||
/* turns button lights on to setting */
|
||||
BUTTONLIGHT_MODE_ON_ENTRY,
|
||||
BUTTONLIGHT_MODE_ON,
|
||||
|
||||
/* turns button lights on to minimum */
|
||||
BUTTONLIGHT_MODE_FAINT_ENTRY,
|
||||
BUTTONLIGHT_MODE_FAINT,
|
||||
|
||||
/* allows button lights to flicker when triggered */
|
||||
BUTTONLIGHT_MODE_FLICKER_ENTRY,
|
||||
BUTTONLIGHT_MODE_FLICKER,
|
||||
BUTTONLIGHT_MODE_FLICKERING,
|
||||
|
||||
/* button lights solid */
|
||||
BUTTONLIGHT_MODE_SOLID_ENTRY,
|
||||
BUTTONLIGHT_MODE_SOLID,
|
||||
|
||||
/* button light charing */
|
||||
BUTTONLIGHT_MODE_CHARGING_ENTRY,
|
||||
BUTTONLIGHT_MODE_CHARGING,
|
||||
BUTTONLIGHT_MODE_CHARGING_WAIT,
|
||||
|
||||
/* internal use only */
|
||||
BUTTONLIGHT_HELPER_SET,
|
||||
BUTTONLIGHT_HELPER_SET_FINAL,
|
||||
BUTTONLIGHT_MODE_STOP,
|
||||
|
||||
/* buttonlights follow the backlight settings */
|
||||
BUTTONLIGHT_MODE_FOLLOW_ENTRY,
|
||||
BUTTONLIGHT_MODE_FOLLOW,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static char buttonlight_leds;
|
||||
static unsigned short buttonlight_setting;
|
||||
static unsigned short buttonlight_current;
|
||||
static unsigned char buttonlight_selected;
|
||||
static enum buttonlight_states buttonlight_state;
|
||||
static enum buttonlight_states buttonlight_saved_state;
|
||||
static unsigned short buttonlight_flickering;
|
||||
|
||||
static unsigned short buttonlight_trigger_now;
|
||||
static unsigned short buttonlight_trigger_brightness;
|
||||
|
||||
|
||||
|
||||
static unsigned short charging_led_index;
|
||||
static unsigned short buttonlight_charging_counter;
|
||||
|
||||
#define CHARGING_LED_COUNT 60
|
||||
unsigned char charging_leds[] = { 0x00, 0x20, 0x38, 0x3C };
|
||||
|
||||
|
||||
|
||||
bool __backlight_init(void)
|
||||
{
|
||||
backlight_control = BACKLIGHT_CONTROL_IDLE;
|
||||
|
||||
backlight_current = DEFAULT_BRIGHTNESS_SETTING;
|
||||
|
||||
buttonlight_state = BUTTONLIGHT_MODE_OFF;
|
||||
|
||||
buttonlight_selected = 0x04;
|
||||
|
||||
/* delay 4 seconds before any fading */
|
||||
initial_tick_delay = 400;
|
||||
/* put the led control on the tick list */
|
||||
tick_add_task(led_control_service);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void __backlight_on(void)
|
||||
{
|
||||
/* now go turn the backlight on */
|
||||
backlight_control = BACKLIGHT_CONTROL_ON;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void __backlight_off(void)
|
||||
{
|
||||
backlight_control = BACKLIGHT_CONTROL_OFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Assumes that the backlight has been initialized */
|
||||
void __backlight_set_brightness(int brightness)
|
||||
{
|
||||
/* stop the interrupt from messing us up */
|
||||
backlight_control = BACKLIGHT_CONTROL_IDLE;
|
||||
|
||||
backlight_brightness = brightness + 1;
|
||||
|
||||
/* only set the brightness if it is different from the current */
|
||||
if (backlight_brightness != backlight_current)
|
||||
{
|
||||
backlight_control = BACKLIGHT_CONTROL_SET;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* only works if the buttonlight mode is set to triggered mode */
|
||||
void __buttonlight_trigger(void)
|
||||
{
|
||||
buttonlight_trigger_now = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* map the mode from the command into the state machine entries */
|
||||
void __buttonlight_mode(enum buttonlight_mode mode,
|
||||
enum buttonlight_selection selection,
|
||||
unsigned short brightness)
|
||||
{
|
||||
/* choose stop to setup mode */
|
||||
buttonlight_state = BUTTONLIGHT_MODE_STOP;
|
||||
|
||||
|
||||
/* clip brightness */
|
||||
if (brightness > MAX_BRIGHTNESS_SETTING)
|
||||
{
|
||||
brightness = MAX_BRIGHTNESS_SETTING;
|
||||
}
|
||||
|
||||
brightness++;
|
||||
|
||||
/* Select which LEDs to use */
|
||||
switch (selection)
|
||||
{
|
||||
case BUTTONLIGHT_LED_ALL:
|
||||
buttonlight_selected = BUTTONLIGHT_ALL;
|
||||
break;
|
||||
|
||||
case BUTTONLIGHT_LED_MENU:
|
||||
buttonlight_selected = BUTTONLIGHT_MENU;
|
||||
break;
|
||||
}
|
||||
|
||||
/* which mode to use */
|
||||
switch (mode)
|
||||
{
|
||||
case BUTTONLIGHT_OFF:
|
||||
buttonlight_state = BUTTONLIGHT_MODE_OFF_ENTRY;
|
||||
break;
|
||||
|
||||
case BUTTONLIGHT_ON:
|
||||
buttonlight_trigger_brightness = brightness;
|
||||
buttonlight_state = BUTTONLIGHT_MODE_ON_ENTRY;
|
||||
break;
|
||||
|
||||
/* faint is just a quick way to set ON to 1 */
|
||||
case BUTTONLIGHT_FAINT:
|
||||
buttonlight_trigger_brightness = 1;
|
||||
buttonlight_state = BUTTONLIGHT_MODE_ON_ENTRY;
|
||||
break;
|
||||
|
||||
case BUTTONLIGHT_FLICKER:
|
||||
buttonlight_trigger_brightness = brightness;
|
||||
buttonlight_state = BUTTONLIGHT_MODE_FLICKER_ENTRY;
|
||||
break;
|
||||
|
||||
case BUTTONLIGHT_SIGNAL:
|
||||
buttonlight_trigger_brightness = brightness;
|
||||
buttonlight_state = BUTTONLIGHT_MODE_SOLID_ENTRY;
|
||||
break;
|
||||
|
||||
case BUTTONLIGHT_FOLLOW:
|
||||
buttonlight_state = BUTTONLIGHT_MODE_FOLLOW_ENTRY;
|
||||
break;
|
||||
|
||||
case BUTTONLIGHT_CHARGING:
|
||||
buttonlight_state = BUTTONLIGHT_MODE_CHARGING_ENTRY;
|
||||
break;
|
||||
|
||||
default:
|
||||
return; /* unknown mode */
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The button lights have 'modes' of operation. Each mode must setup and
|
||||
* execute its own operation - taking care that this is all done in an ISR.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* led_control_service runs in interrupt context - be brief!
|
||||
* This service is called once per interrupt timer tick - 100 times a second.
|
||||
*
|
||||
* There should be at most only one i2c operation per call - if more are need
|
||||
* the calls should be spread across calls.
|
||||
*
|
||||
* Putting all led servicing in one thread means that we wont step on any
|
||||
* i2c operations - they are all serialized here in the ISR tick. It also
|
||||
* insures that we get called at equal timing for good visual effect.
|
||||
*
|
||||
* The buttonlight service runs only after all backlight services have finished.
|
||||
* Fading the buttonlights is possible, but not recommended because of the
|
||||
* additional calls needed during the ISR
|
||||
*/
|
||||
static void led_control_service(void)
|
||||
{
|
||||
if(initial_tick_delay) {
|
||||
initial_tick_delay--;
|
||||
return;
|
||||
}
|
||||
switch (backlight_control)
|
||||
{
|
||||
case BACKLIGHT_CONTROL_IDLE:
|
||||
switch (buttonlight_state)
|
||||
{
|
||||
case BUTTONLIGHT_MODE_STOP: break;
|
||||
|
||||
/* Buttonlight mode: OFF */
|
||||
case BUTTONLIGHT_MODE_OFF_ENTRY:
|
||||
if (buttonlight_current)
|
||||
{
|
||||
buttonlight_leds = 0x00;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds);
|
||||
buttonlight_current = 0;
|
||||
}
|
||||
buttonlight_state = BUTTONLIGHT_MODE_OFF;
|
||||
break;
|
||||
|
||||
case BUTTONLIGHT_MODE_OFF:
|
||||
break;
|
||||
|
||||
|
||||
/* button mode: CHARGING - show charging sequence */
|
||||
case BUTTONLIGHT_MODE_CHARGING_ENTRY:
|
||||
/* start turned off */
|
||||
buttonlight_leds = 0x00;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds);
|
||||
buttonlight_current = 0;
|
||||
|
||||
/* temporary save for the next mode - then to do settings */
|
||||
buttonlight_setting = DEFAULT_BRIGHTNESS_SETTING;
|
||||
buttonlight_saved_state = BUTTONLIGHT_MODE_CHARGING_WAIT;
|
||||
buttonlight_state = BUTTONLIGHT_HELPER_SET;
|
||||
break;
|
||||
|
||||
|
||||
case BUTTONLIGHT_MODE_CHARGING:
|
||||
if (--buttonlight_charging_counter == 0)
|
||||
{
|
||||
/* change led */
|
||||
if (charging_state())
|
||||
{
|
||||
buttonlight_leds = charging_leds[charging_led_index];
|
||||
if (++charging_led_index >= sizeof(charging_leds))
|
||||
{
|
||||
charging_led_index = 0;
|
||||
}
|
||||
sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
|
||||
buttonlight_charging_counter = CHARGING_LED_COUNT;
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonlight_state = BUTTONLIGHT_MODE_CHARGING_ENTRY;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* wait for the charget to be plugged in */
|
||||
case BUTTONLIGHT_MODE_CHARGING_WAIT:
|
||||
if (charging_state())
|
||||
{
|
||||
charging_led_index = 0;
|
||||
buttonlight_charging_counter = CHARGING_LED_COUNT;
|
||||
buttonlight_state = BUTTONLIGHT_MODE_CHARGING;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/* Buttonlight mode: FOLLOW - try to stay current with backlight
|
||||
* since this runs in the idle of the backlight it will not really
|
||||
* follow in real time
|
||||
*/
|
||||
case BUTTONLIGHT_MODE_FOLLOW_ENTRY:
|
||||
/* case 1 - backlight on, but buttonlight is off */
|
||||
if (backlight_current)
|
||||
{
|
||||
/* Turn the buttonlights on */
|
||||
buttonlight_leds = buttonlight_selected;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
|
||||
|
||||
/* temporary save for the next mode - then to do settings */
|
||||
buttonlight_setting = backlight_current;
|
||||
buttonlight_saved_state = BUTTONLIGHT_MODE_FOLLOW;
|
||||
buttonlight_state = BUTTONLIGHT_HELPER_SET;
|
||||
}
|
||||
/* case 2 - backlight off, but buttonlight is on */
|
||||
else
|
||||
{
|
||||
buttonlight_current = 0;
|
||||
buttonlight_leds = 0x00;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds);
|
||||
buttonlight_state = BUTTONLIGHT_MODE_FOLLOW;
|
||||
}
|
||||
break;
|
||||
|
||||
case BUTTONLIGHT_MODE_FOLLOW:
|
||||
if (buttonlight_current != backlight_current)
|
||||
{
|
||||
/* case 1 - backlight on, but buttonlight is off */
|
||||
if (backlight_current)
|
||||
{
|
||||
if (0 == buttonlight_current)
|
||||
{
|
||||
/* Turn the buttonlights on */
|
||||
buttonlight_leds = buttonlight_selected;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
|
||||
}
|
||||
|
||||
/* temporary save for the next mode - then to do settings */
|
||||
buttonlight_setting = backlight_current;
|
||||
buttonlight_saved_state = BUTTONLIGHT_MODE_FOLLOW;
|
||||
buttonlight_state = BUTTONLIGHT_HELPER_SET;
|
||||
}
|
||||
|
||||
/* case 2 - backlight off, but buttonlight is on */
|
||||
else
|
||||
{
|
||||
buttonlight_current = 0;
|
||||
buttonlight_leds = 0x00;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
/* Buttonlight mode: ON - stays at the set brightness */
|
||||
case BUTTONLIGHT_MODE_ON_ENTRY:
|
||||
buttonlight_leds = buttonlight_selected;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
|
||||
|
||||
/* temporary save for the next mode - then to do settings */
|
||||
buttonlight_setting = buttonlight_trigger_brightness;
|
||||
buttonlight_saved_state = BUTTONLIGHT_MODE_ON;
|
||||
buttonlight_state = BUTTONLIGHT_HELPER_SET;
|
||||
break;
|
||||
|
||||
case BUTTONLIGHT_MODE_ON:
|
||||
break;
|
||||
|
||||
|
||||
|
||||
/* Buttonlight mode: FLICKER */
|
||||
case BUTTONLIGHT_MODE_FLICKER_ENTRY:
|
||||
/* already on? turn it off */
|
||||
if (buttonlight_current)
|
||||
{
|
||||
buttonlight_leds = 0x00;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds);
|
||||
buttonlight_current = 0;
|
||||
}
|
||||
|
||||
/* set the brightness if not already set */
|
||||
if (buttonlight_current != buttonlight_trigger_brightness)
|
||||
{
|
||||
/* temporary save for the next mode - then to do settings */
|
||||
buttonlight_setting = buttonlight_trigger_brightness;
|
||||
buttonlight_saved_state = BUTTONLIGHT_MODE_FLICKER;
|
||||
buttonlight_state = BUTTONLIGHT_HELPER_SET;
|
||||
}
|
||||
else buttonlight_state = BUTTONLIGHT_MODE_FLICKER;
|
||||
break;
|
||||
|
||||
|
||||
case BUTTONLIGHT_MODE_FLICKER:
|
||||
/* wait for the foreground to trigger flickering */
|
||||
if (buttonlight_trigger_now)
|
||||
{
|
||||
/* turn them on */
|
||||
buttonlight_leds = buttonlight_selected;
|
||||
buttonlight_current = buttonlight_setting;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
|
||||
|
||||
/* reset the trigger and go flicker the LEDs */
|
||||
buttonlight_trigger_now = 0;
|
||||
buttonlight_flickering = FLICKER_PERIOD;
|
||||
buttonlight_state = BUTTONLIGHT_MODE_FLICKERING;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case BUTTONLIGHT_MODE_FLICKERING:
|
||||
/* flicker the LEDs for as long as we get triggered */
|
||||
if (buttonlight_flickering)
|
||||
{
|
||||
/* turn the leds off if they are on */
|
||||
if (buttonlight_current)
|
||||
{
|
||||
buttonlight_leds = 0x00;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds);
|
||||
buttonlight_current = 0;
|
||||
}
|
||||
|
||||
buttonlight_flickering--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* is flickering triggered again? */
|
||||
if (!buttonlight_trigger_now)
|
||||
{
|
||||
/* completed a cycle - no new triggers - go back and wait */
|
||||
buttonlight_state = BUTTONLIGHT_MODE_FLICKER;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* reset flickering */
|
||||
buttonlight_trigger_now = 0;
|
||||
buttonlight_flickering = FLICKER_PERIOD;
|
||||
|
||||
/* turn buttonlights on */
|
||||
buttonlight_leds = buttonlight_selected;
|
||||
buttonlight_current = buttonlight_setting;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/* Buttonlight mode: SIGNAL / SOLID */
|
||||
case BUTTONLIGHT_MODE_SOLID_ENTRY:
|
||||
/* already on? turn it off */
|
||||
if (buttonlight_current)
|
||||
{
|
||||
buttonlight_leds = 0x00;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds);
|
||||
buttonlight_current = 0;
|
||||
}
|
||||
|
||||
/* set the brightness if not already set */
|
||||
/* temporary save for the next mode - then to do settings */
|
||||
buttonlight_setting = buttonlight_trigger_brightness;
|
||||
buttonlight_saved_state = BUTTONLIGHT_MODE_SOLID;
|
||||
buttonlight_state = BUTTONLIGHT_HELPER_SET;
|
||||
break;
|
||||
|
||||
|
||||
case BUTTONLIGHT_MODE_SOLID:
|
||||
/* wait for the foreground to trigger */
|
||||
if (buttonlight_trigger_now)
|
||||
{
|
||||
/* turn them on if not already on */
|
||||
if (0 == buttonlight_current)
|
||||
{
|
||||
buttonlight_leds = buttonlight_selected;
|
||||
buttonlight_current = buttonlight_setting;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
|
||||
}
|
||||
|
||||
/* reset the trigger */
|
||||
buttonlight_trigger_now = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buttonlight_current)
|
||||
{
|
||||
buttonlight_leds = 0x00;
|
||||
sc606_write(SC606_REG_CONF, backlight_leds);
|
||||
buttonlight_current = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/* set the brightness for the buttonlights - takes 2 passes */
|
||||
case BUTTONLIGHT_HELPER_SET:
|
||||
sc606_write(SC606_REG_B, buttonlight_setting-1);
|
||||
buttonlight_state = BUTTONLIGHT_HELPER_SET_FINAL;
|
||||
break;
|
||||
|
||||
case BUTTONLIGHT_HELPER_SET_FINAL:
|
||||
sc606_write(SC606_REG_C, buttonlight_setting-1);
|
||||
buttonlight_current = buttonlight_setting;
|
||||
buttonlight_state = buttonlight_saved_state;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case BACKLIGHT_CONTROL_FADE_ON_FROM_OFF:
|
||||
backlight_leds = 0x03;
|
||||
sc606_write(SC606_REG_CONF, 0x03 | buttonlight_leds);
|
||||
backlight_control = BACKLIGHT_CONTROL_FADE_ON;
|
||||
break;
|
||||
|
||||
|
||||
case BACKLIGHT_CONTROL_OFF:
|
||||
backlight_current = 0;
|
||||
backlight_leds = 0x00;
|
||||
sc606_write(SC606_REG_CONF, buttonlight_leds);
|
||||
backlight_control = BACKLIGHT_CONTROL_IDLE;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case BACKLIGHT_CONTROL_ON:
|
||||
backlight_leds = 0x03;
|
||||
sc606_write(SC606_REG_CONF, 0x03 | buttonlight_leds);
|
||||
backlight_current = backlight_brightness;
|
||||
backlight_control = BACKLIGHT_CONTROL_IDLE;
|
||||
break;
|
||||
|
||||
|
||||
case BACKLIGHT_CONTROL_SET:
|
||||
/* The SC606 LED driver can set the brightness in 64 steps */
|
||||
sc606_write(SC606_REG_A, backlight_brightness-1);
|
||||
|
||||
/* if we were turned off - turn the backlight on */
|
||||
if (backlight_current)
|
||||
{
|
||||
backlight_current = backlight_brightness;
|
||||
backlight_control = BACKLIGHT_CONTROL_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
backlight_control = BACKLIGHT_CONTROL_ON;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case BACKLIGHT_CONTROL_FADE_ON:
|
||||
if (--time_til_fade) return;
|
||||
|
||||
/* The SC606 LED driver can set the brightness in 64 steps */
|
||||
sc606_write(SC606_REG_A, backlight_current++);
|
||||
|
||||
/* have we hit the target? */
|
||||
if (backlight_current == backlight_target)
|
||||
{
|
||||
backlight_control = BACKLIGHT_CONTROL_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
time_til_fade = fade_interval;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case BACKLIGHT_CONTROL_FADE_OFF:
|
||||
if (--time_til_fade) return;
|
||||
|
||||
/* The SC606 LED driver can set the brightness in 64 steps */
|
||||
sc606_write(SC606_REG_A, --backlight_current);
|
||||
|
||||
/* have we hit the target? */
|
||||
if (backlight_current == backlight_target)
|
||||
{
|
||||
if (backlight_current)
|
||||
{
|
||||
backlight_control = BACKLIGHT_CONTROL_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
backlight_control = BACKLIGHT_CONTROL_OFF;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
time_til_fade = fade_interval;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(backlight_current)
|
||||
lcd_enable(true);
|
||||
else
|
||||
lcd_enable(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void __backlight_dim(bool dim_now)
|
||||
{
|
||||
unsigned short target;
|
||||
|
||||
/* dont let the interrupt tick happen */
|
||||
backlight_control = BACKLIGHT_CONTROL_IDLE;
|
||||
|
||||
target = (dim_now == true) ? 0 : backlight_brightness;
|
||||
|
||||
/* only try and fade if the target is different */
|
||||
if (backlight_current != target)
|
||||
{
|
||||
backlight_target = target;
|
||||
|
||||
if (backlight_current > backlight_target)
|
||||
{
|
||||
time_til_fade = fade_interval = 4;
|
||||
backlight_control = BACKLIGHT_CONTROL_FADE_OFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
time_til_fade = fade_interval = 1;
|
||||
if (backlight_current)
|
||||
{
|
||||
backlight_control = BACKLIGHT_CONTROL_FADE_ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
backlight_control = BACKLIGHT_CONTROL_FADE_ON_FROM_OFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
87
firmware/target/arm/s3c2440/gigabeat-fx/backlight-target.h
Normal file
87
firmware/target/arm/s3c2440/gigabeat-fx/backlight-target.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Linus Nielsen Feltzing
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef BACKLIGHT_TARGET_H
|
||||
#define BACKLIGHT_TARGET_H
|
||||
|
||||
|
||||
/* select the led */
|
||||
enum buttonlight_selection
|
||||
{
|
||||
/* all leds */
|
||||
BUTTONLIGHT_LED_ALL,
|
||||
|
||||
/* only the menu/power led (two buttons for one LED) */
|
||||
BUTTONLIGHT_LED_MENU
|
||||
};
|
||||
|
||||
|
||||
/* Use these to set the buttonlight mode */
|
||||
enum buttonlight_mode
|
||||
{
|
||||
/* ON follows the setting */
|
||||
BUTTONLIGHT_ON,
|
||||
|
||||
/* buttonlights always off */
|
||||
BUTTONLIGHT_OFF,
|
||||
|
||||
/* buttonlights always on but set at lowest brightness */
|
||||
BUTTONLIGHT_FAINT,
|
||||
|
||||
/* buttonlights flicker when triggered - continues to flicker
|
||||
* even if the flicker is still asserted.
|
||||
*/
|
||||
BUTTONLIGHT_FLICKER,
|
||||
|
||||
/* buttonlights solid for as long as triggered */
|
||||
BUTTONLIGHT_SIGNAL,
|
||||
|
||||
/* buttonlights follow backlight */
|
||||
BUTTONLIGHT_FOLLOW,
|
||||
|
||||
/* buttonlights show battery charging */
|
||||
BUTTONLIGHT_CHARGING,
|
||||
};
|
||||
|
||||
|
||||
/* Call this to flicker or signal the button lights. Only is effective for
|
||||
* modes that take a trigger input.
|
||||
*/
|
||||
void __buttonlight_trigger(void);
|
||||
|
||||
|
||||
/* select which led to use on the button lights. Other combinations are
|
||||
* possible, but don't look very good.
|
||||
*/
|
||||
|
||||
/* map the mode from the command into the state machine entries */
|
||||
/* See enum buttonlight_mode for available functions */
|
||||
void __buttonlight_mode(enum buttonlight_mode mode,
|
||||
enum buttonlight_selection selection,
|
||||
unsigned short brightness);
|
||||
|
||||
|
||||
bool __backlight_init(void);
|
||||
void __backlight_on(void);
|
||||
void __backlight_off(void);
|
||||
void __backlight_set_brightness(int val);
|
||||
|
||||
/* true: backlight fades off - false: backlight fades on */
|
||||
void __backlight_dim(bool dim);
|
||||
|
||||
#endif
|
||||
157
firmware/target/arm/s3c2440/gigabeat-fx/button-meg-fx.c
Normal file
157
firmware/target/arm/s3c2440/gigabeat-fx/button-meg-fx.c
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Linus Nielsen Feltzing
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include "system.h"
|
||||
#include "button.h"
|
||||
#include "kernel.h"
|
||||
#include "backlight.h"
|
||||
#include "adc.h"
|
||||
#include "system.h"
|
||||
#include "backlight-target.h"
|
||||
|
||||
static bool headphones_detect;
|
||||
static bool hold_button = false;
|
||||
|
||||
static int const remote_buttons[] =
|
||||
{
|
||||
BUTTON_NONE, /* Headphones connected - remote disconnected */
|
||||
BUTTON_SELECT,
|
||||
BUTTON_MENU, /* could be changed to BUTTON_A */
|
||||
BUTTON_LEFT,
|
||||
BUTTON_RIGHT,
|
||||
BUTTON_UP, /* could be changed to BUTTON_VOL_UP */
|
||||
BUTTON_DOWN, /* could be changed to BUTTON_VOL_DOWN */
|
||||
BUTTON_NONE, /* Remote control attached - no buttons pressed */
|
||||
BUTTON_NONE, /* Nothing in the headphone socket */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void button_init_device(void)
|
||||
{
|
||||
/* Power, Remote Play & Hold switch */
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool button_hold(void)
|
||||
{
|
||||
return (GPGDAT & (1 << 15));
|
||||
}
|
||||
|
||||
|
||||
|
||||
int button_read_device(void)
|
||||
{
|
||||
int touchpad;
|
||||
int buttons;
|
||||
static int lastbutton;
|
||||
unsigned short remote_adc;
|
||||
int btn = BUTTON_NONE;
|
||||
bool hold_button_old;
|
||||
|
||||
/* normal buttons */
|
||||
hold_button_old = hold_button;
|
||||
hold_button = button_hold();
|
||||
|
||||
#ifndef BOOTLOADER
|
||||
/* give BL notice if HB state chaged */
|
||||
if (hold_button != hold_button_old)
|
||||
backlight_hold_changed(hold_button);
|
||||
#endif
|
||||
|
||||
/* See header for ADC values when remote control buttons are pressed */
|
||||
/* Only one button can be sensed at a time on the remote. */
|
||||
/* Need to filter the remote button because the ADC is so fast */
|
||||
remote_adc = adc_read(ADC_HPREMOTE);
|
||||
btn = remote_buttons[(remote_adc + 64) / 128];
|
||||
if (btn != lastbutton)
|
||||
{
|
||||
/* if the buttons dont agree twice in a row, then its none */
|
||||
lastbutton = btn;
|
||||
btn = BUTTON_NONE;
|
||||
}
|
||||
|
||||
/* Check for hold first - exit if asserted with no button pressed */
|
||||
if (hold_button)
|
||||
return btn;
|
||||
|
||||
/* the side buttons - Check before doing all of the work on each bit */
|
||||
buttons = GPGDAT & 0x1F;
|
||||
if (buttons)
|
||||
{
|
||||
if (buttons & (1 << 0))
|
||||
btn |= BUTTON_POWER;
|
||||
|
||||
if (buttons & (1 << 1))
|
||||
btn |= BUTTON_MENU;
|
||||
|
||||
if (buttons & (1 << 2))
|
||||
btn |= BUTTON_VOL_UP;
|
||||
|
||||
if (buttons & (1 << 3))
|
||||
btn |= BUTTON_VOL_DOWN;
|
||||
|
||||
if (buttons & (1 << 4))
|
||||
btn |= BUTTON_A;
|
||||
}
|
||||
|
||||
/* the touchpad */
|
||||
touchpad = GPJDAT & 0x10C9;
|
||||
if (touchpad)
|
||||
{
|
||||
if (touchpad & (1 << 0))
|
||||
btn |= BUTTON_UP;
|
||||
|
||||
if (touchpad & (1 << 12))
|
||||
btn |= BUTTON_RIGHT;
|
||||
|
||||
if (touchpad & (1 << 6))
|
||||
btn |= BUTTON_DOWN;
|
||||
|
||||
if (touchpad & (1 << 7))
|
||||
btn |= BUTTON_LEFT;
|
||||
|
||||
if (touchpad & (1 << 3))
|
||||
btn |= BUTTON_SELECT;
|
||||
}
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool headphones_inserted(void)
|
||||
{
|
||||
unsigned short remote_adc = adc_read(ADC_HPREMOTE);
|
||||
if (remote_adc != ADC_READ_ERROR)
|
||||
{
|
||||
/* If there is nothing in the headphone socket, the ADC reads high */
|
||||
if (remote_adc < 940)
|
||||
headphones_detect = true;
|
||||
else
|
||||
headphones_detect = false;
|
||||
}
|
||||
return headphones_detect;
|
||||
}
|
||||
89
firmware/target/arm/s3c2440/gigabeat-fx/button-target.h
Normal file
89
firmware/target/arm/s3c2440/gigabeat-fx/button-target.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Linus Nielsen Feltzing
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef _BUTTON_TARGET_H_
|
||||
#define _BUTTON_TARGET_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "config.h"
|
||||
|
||||
#define HAS_BUTTON_HOLD
|
||||
|
||||
bool button_hold(void);
|
||||
void button_init_device(void);
|
||||
int button_read_device(void);
|
||||
|
||||
/* Toshiba Gigabeat specific button codes */
|
||||
|
||||
#define BUTTON_POWER 0x00000001
|
||||
#define BUTTON_MENU 0x00000002
|
||||
|
||||
#define BUTTON_LEFT 0x00000004
|
||||
#define BUTTON_RIGHT 0x00000008
|
||||
#define BUTTON_UP 0x00000010
|
||||
#define BUTTON_DOWN 0x00000020
|
||||
|
||||
#define BUTTON_VOL_UP 0x00000040
|
||||
#define BUTTON_VOL_DOWN 0x00000080
|
||||
|
||||
#define BUTTON_SELECT 0x00000100
|
||||
#define BUTTON_A 0x00000200
|
||||
|
||||
|
||||
/* Toshiba Gigabeat specific remote button ADC values */
|
||||
/* The remote control uses ADC 1 to emulate button pushes
|
||||
Reading (approx) Button HP plugged in? Remote plugged in?
|
||||
0 N/A Yes No
|
||||
125 Play/Pause Cant tell Yes
|
||||
241 Speaker+ Cant tell Yes
|
||||
369 Rewind Cant tell Yes
|
||||
492 Fast Fwd Cant tell Yes
|
||||
616 Vol + Cant tell Yes
|
||||
742 Vol - Cant tell Yes
|
||||
864 None Cant tell Yes
|
||||
1023 N/A No No
|
||||
*/
|
||||
|
||||
/*
|
||||
Notes:
|
||||
|
||||
Buttons on the remote are translated into equivalent button presses just
|
||||
as if you were pressing them on the Gigabeat itself.
|
||||
|
||||
We cannot tell if the hold is asserted on the remote. The Hold function on
|
||||
the remote is to block the output of the buttons changing.
|
||||
|
||||
Only one button can be sensed at a time. If another is pressed, the button
|
||||
with the lowest reading is dominant. So, if Rewind and Vol + are pressed
|
||||
at the same time, Rewind value is the one that is read.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#define BUTTON_MAIN (BUTTON_POWER|BUTTON_MENU|BUTTON_LEFT|BUTTON_RIGHT\
|
||||
|BUTTON_UP|BUTTON_DOWN|BUTTON_VOL_UP|BUTTON_VOL_DOWN\
|
||||
|BUTTON_SELECT|BUTTON_A)
|
||||
|
||||
|
||||
#define BUTTON_REMOTE 0
|
||||
|
||||
#define POWEROFF_BUTTON BUTTON_POWER
|
||||
#define POWEROFF_COUNT 10
|
||||
|
||||
#endif /* _BUTTON_TARGET_H_ */
|
||||
8
firmware/target/arm/s3c2440/gigabeat-fx/dma_start.c
Normal file
8
firmware/target/arm/s3c2440/gigabeat-fx/dma_start.c
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#include <sys/types.h>
|
||||
|
||||
void dma_start(const void* addr, size_t size) {
|
||||
(void) addr;
|
||||
(void) size;
|
||||
//TODO:
|
||||
}
|
||||
|
||||
134
firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c
Normal file
134
firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Linus Nielsen Feltzing
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include <stdbool.h>
|
||||
#include "kernel.h"
|
||||
#include "system.h"
|
||||
#include "logf.h"
|
||||
#include "debug.h"
|
||||
#include "string.h"
|
||||
#include "generic_i2c.h"
|
||||
|
||||
static void i2c_sda_output(void)
|
||||
{
|
||||
GPECON |= (1 << 30);
|
||||
}
|
||||
|
||||
static void i2c_sda_input(void)
|
||||
{
|
||||
GPECON &= ~(3 << 30);
|
||||
}
|
||||
|
||||
static void i2c_sda_lo(void)
|
||||
{
|
||||
GPEDAT &= ~(1 << 15);
|
||||
}
|
||||
|
||||
static void i2c_sda_hi(void)
|
||||
{
|
||||
GPEDAT |= (1 << 15);
|
||||
}
|
||||
|
||||
static int i2c_sda(void)
|
||||
{
|
||||
return GPEDAT & (1 << 15);
|
||||
}
|
||||
|
||||
static void i2c_scl_output(void)
|
||||
{
|
||||
GPECON |= (1 << 28);
|
||||
}
|
||||
|
||||
static void i2c_scl_input(void)
|
||||
{
|
||||
GPECON &= ~(3 << 28);
|
||||
}
|
||||
|
||||
static void i2c_scl_lo(void)
|
||||
{
|
||||
GPEDAT &= ~(1 << 14);
|
||||
}
|
||||
|
||||
static int i2c_scl(void)
|
||||
{
|
||||
return GPEDAT & (1 << 14);
|
||||
}
|
||||
|
||||
static void i2c_scl_hi(void)
|
||||
{
|
||||
i2c_scl_input();
|
||||
while(!i2c_scl());
|
||||
GPEDAT |= (1 << 14);
|
||||
i2c_scl_output();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void i2c_delay(void)
|
||||
{
|
||||
unsigned _x;
|
||||
|
||||
/* The i2c can clock at 500KHz: 2uS period -> 1uS half period */
|
||||
/* about 30 cycles overhead + X * 7 */
|
||||
/* 300MHz: 1000nS @3.36nS/cyc = 297cyc: X = 38*/
|
||||
/* 100MHz: 1000nS @10nS/cyc = 100cyc : X = 10 */
|
||||
for (_x = 38; _x; _x--)
|
||||
{
|
||||
/* burn CPU cycles */
|
||||
/* gcc makes it an inc loop - check with objdump for asm timing */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct i2c_interface s3c2440_i2c = {
|
||||
0x34, /* Address */
|
||||
|
||||
/* Bit-banged interface definitions */
|
||||
i2c_scl_hi, /* Drive SCL high, might sleep on clk stretch */
|
||||
i2c_scl_lo, /* Drive SCL low */
|
||||
i2c_sda_hi, /* Drive SDA high */
|
||||
i2c_sda_lo, /* Drive SDA low */
|
||||
i2c_sda_input, /* Set SDA as input */
|
||||
i2c_sda_output, /* Set SDA as output */
|
||||
i2c_scl_input, /* Set SCL as input */
|
||||
i2c_scl_output, /* Set SCL as output */
|
||||
i2c_scl, /* Read SCL, returns 0 or nonzero */
|
||||
i2c_sda, /* Read SDA, returns 0 or nonzero */
|
||||
|
||||
i2c_delay, /* START SDA hold time (tHD:SDA) */
|
||||
i2c_delay, /* SDA hold time (tHD:DAT) */
|
||||
i2c_delay, /* SDA setup time (tSU:DAT) */
|
||||
i2c_delay, /* STOP setup time (tSU:STO) */
|
||||
i2c_delay, /* Rep. START setup time (tSU:STA) */
|
||||
i2c_delay, /* SCL high period (tHIGH) */
|
||||
};
|
||||
|
||||
void i2c_init(void)
|
||||
{
|
||||
/* Set GPE15 (SDA) and GPE14 (SCL) to 1 */
|
||||
GPECON = (GPECON & ~(0xF<<28)) | 5<<28;
|
||||
i2c_add_node(&s3c2440_i2c);
|
||||
}
|
||||
|
||||
void i2c_send(int bus_address, int reg_address, const unsigned char buf)
|
||||
{
|
||||
i2c_write_data(bus_address, reg_address, &buf, 1);
|
||||
}
|
||||
22
firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.h
Normal file
22
firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Linus Nielsen Feltzing
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* chip-specific i2c functions */
|
||||
|
||||
void i2c_send(int bus_address, int reg_address, const unsigned char buf);
|
||||
25
firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
Normal file
25
firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#include "kernel.h"
|
||||
#include "thread.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "lcd.h"
|
||||
|
||||
extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
|
||||
|
||||
void timer4(void) {
|
||||
int i;
|
||||
/* Run through the list of tick tasks */
|
||||
for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
|
||||
{
|
||||
if(tick_funcs[i])
|
||||
{
|
||||
tick_funcs[i]();
|
||||
}
|
||||
}
|
||||
|
||||
current_tick++;
|
||||
|
||||
/* following needs to be fixed. */
|
||||
/*wake_up_thread();*/
|
||||
}
|
||||
|
||||
222
firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S
Normal file
222
firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2007 by Michael Sevakis
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
|
||||
/****************************************************************************
|
||||
* void lcd_write_yuv_420_lines(fb_data *dst,
|
||||
* unsigned char chroma_buf[LCD_HEIGHT/2*3],
|
||||
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
|
||||
*/
|
||||
.section .icode, "ax", %progbits
|
||||
.align 2
|
||||
.global lcd_write_yuv420_lines
|
||||
.type lcd_write_yuv420_lines, %function
|
||||
lcd_write_yuv420_lines:
|
||||
@ r0 = dst
|
||||
@ r1 = chroma_buf
|
||||
@ r2 = yuv_src
|
||||
@ r3 = width
|
||||
@ [sp] = stride
|
||||
stmdb sp!, { r4-r12, lr } @ save non-scratch
|
||||
stmdb sp!, { r0, r3 } @ save dst and width
|
||||
mov r14, #74 @ r14 = Y factor
|
||||
ldmia r2, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p
|
||||
@ r5 = yuv_src[1] = Cb_p
|
||||
@ r6 = yuv_src[2] = Cr_p
|
||||
10: @ loop line 1 @
|
||||
ldrb r2, [r4], #1 @ r2 = *Y'_p++;
|
||||
ldrb r8, [r5], #1 @ r8 = *Cb_p++;
|
||||
ldrb r11, [r6], #1 @ r11 = *Cr_p++;
|
||||
@
|
||||
@ compute Y
|
||||
sub r2, r2, #16 @ r7 = Y = (Y' - 16)*74
|
||||
mul r7, r2, r14 @
|
||||
@
|
||||
sub r8, r8, #128 @ Cb -= 128
|
||||
sub r11, r11, #128 @ Cr -= 128
|
||||
@
|
||||
mvn r2, #24 @ compute guv
|
||||
mul r10, r2, r8 @ r10 = Cb*-24
|
||||
mvn r2, #51 @
|
||||
mla r10, r2, r11, r10 @ r10 = r10 + Cr*-51
|
||||
@
|
||||
mov r2, #101 @ compute rv
|
||||
mul r9, r11, r2 @ r9 = rv = Cr*101
|
||||
@
|
||||
@ store chromas in line buffer
|
||||
add r8, r8, #2 @ bu = (Cb + 2) >> 2
|
||||
mov r8, r8, asr #2 @
|
||||
strb r8, [r1], #1 @
|
||||
add r9, r9, #256 @ rv = (Cr + 256) >> 9
|
||||
mov r9, r9, asr #9 @
|
||||
strb r9, [r1], #1 @
|
||||
mov r10, r10, asr #8 @ guv >>= 8
|
||||
strb r10, [r1], #1 @
|
||||
@ compute R, G, and B
|
||||
add r2, r8, r7, asr #9 @ r2 = b = (Y >> 9) + bu
|
||||
add r11, r9, r7, asr #9 @ r11 = r = (Y >> 9) + rv
|
||||
add r7, r10, r7, asr #8 @ r7 = g = (Y >> 8) + guv
|
||||
@
|
||||
orr r12, r2, r11 @ check if clamping is needed...
|
||||
orr r12, r12, r7, asr #1 @ ...at all
|
||||
cmp r12, #31 @
|
||||
bls 15f @ no clamp @
|
||||
mov r12, #31 @
|
||||
cmp r12, r2 @ clamp b
|
||||
andlo r2, r12, r2, asr #31 @
|
||||
eorlo r2, r2, r12 @
|
||||
cmp r12, r11 @ clamp r
|
||||
andlo r11, r12, r11, asr #31 @
|
||||
eorlo r11, r11, r12 @
|
||||
cmp r12, r7, asr #1 @ clamp g
|
||||
andlo r7, r12, r7, asr #31 @
|
||||
eorlo r7, r7, r12 @
|
||||
orrlo r7, r7, r7, asl #1 @
|
||||
15: @ no clamp @
|
||||
@
|
||||
orr r12, r2, r7, lsl #5 @ r4 |= (g << 5)
|
||||
ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++
|
||||
orr r12, r12, r11, lsl #11 @ r4 = b | (r << 11)
|
||||
strh r12, [r0], #240 @ store pixel
|
||||
@
|
||||
sub r2, r2, #16 @ r7 = Y = (Y' - 16)*74
|
||||
mul r7, r2, r14 @ next Y
|
||||
@ compute R, G, and B
|
||||
add r2, r8, r7, asr #9 @ r2 = b = (Y >> 9) + bu
|
||||
add r11, r9, r7, asr #9 @ r11 = r = (Y >> 9) + rv
|
||||
add r7, r10, r7, asr #8 @ r7 = g = (Y >> 8) + guv
|
||||
@
|
||||
orr r12, r2, r11 @ check if clamping is needed...
|
||||
orr r12, r12, r7, asr #1 @ ...at all
|
||||
cmp r12, #31 @
|
||||
bls 15f @ no clamp @
|
||||
mov r12, #31 @
|
||||
cmp r12, r2 @ clamp b
|
||||
andlo r2, r12, r2, asr #31 @
|
||||
eorlo r2, r2, r12 @
|
||||
cmp r12, r11 @ clamp r
|
||||
andlo r11, r12, r11, asr #31 @
|
||||
eorlo r11, r11, r12 @
|
||||
cmp r12, r7, asr #1 @ clamp g
|
||||
andlo r7, r12, r7, asr #31 @
|
||||
eorlo r7, r7, r12 @
|
||||
orrlo r7, r7, r7, asl #1 @
|
||||
15: @ no clamp @
|
||||
@
|
||||
orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11)
|
||||
orr r12, r12, r7, lsl #5 @ r4 |= (g << 5)
|
||||
strh r12, [r0, #240]! @ store pixel
|
||||
add r0, r0, #2*240 @
|
||||
@
|
||||
subs r3, r3, #2 @
|
||||
bgt 10b @ loop line 1 @
|
||||
@ do second line
|
||||
@
|
||||
ldmia sp!, { r0, r3 } @ pop dst and width
|
||||
sub r0, r0, #2 @ set dst to start of next line
|
||||
sub r1, r1, r3, asl #1 @ rewind chroma pointer...
|
||||
ldr r2, [sp, #40] @ r2 = stride
|
||||
add r1, r1, r3, asr #1 @ ... (r1 -= width/2*3)
|
||||
@ move sources to start of next line
|
||||
sub r2, r2, r3 @ r2 = skip = stride - width
|
||||
add r4, r4, r2 @ r4 = Y'_p + skip
|
||||
@
|
||||
20: @ loop line 2 @
|
||||
ldrb r2, [r4], #1 @ r7 = Y' = *Y'_p++
|
||||
ldrsb r8, [r1], #1 @ reload saved chromas
|
||||
ldrsb r9, [r1], #1 @
|
||||
ldrsb r10, [r1], #1 @
|
||||
@
|
||||
sub r2, r2, #16 @ r2 = Y = (Y' - 16)*74
|
||||
mul r7, r2, r14 @
|
||||
@ compute R, G, and B
|
||||
add r2, r8, r7, asr #9 @ r2 = b = (Y >> 9) + bu
|
||||
add r11, r9, r7, asr #9 @ r11 = r = (Y >> 9) + rv
|
||||
add r7, r10, r7, asr #8 @ r7 = g = (Y >> 8) + guv
|
||||
@
|
||||
orr r12, r2, r11 @ check if clamping is needed...
|
||||
orr r12, r12, r7, asr #1 @ ...at all
|
||||
cmp r12, #31 @
|
||||
bls 25f @ no clamp @
|
||||
mov r12, #31 @
|
||||
cmp r12, r2 @ clamp b
|
||||
andlo r2, r12, r2, asr #31 @
|
||||
eorlo r2, r2, r12 @
|
||||
cmp r12, r11 @ clamp r
|
||||
andlo r11, r12, r11, asr #31 @
|
||||
eorlo r11, r11, r12 @
|
||||
cmp r12, r7, asr #1 @ clamp g
|
||||
andlo r7, r12, r7, asr #31 @
|
||||
eorlo r7, r7, r12 @
|
||||
orrlo r7, r7, r7, asl #1 @
|
||||
25: @ no clamp @
|
||||
@
|
||||
orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11)
|
||||
ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++
|
||||
orr r12, r12, r7, lsl #5 @ r4 |= (g << 5)
|
||||
strh r12, [r0], #240 @ store pixel
|
||||
@
|
||||
@ do second pixel
|
||||
@
|
||||
sub r2, r2, #16 @ r2 = Y = (Y' - 16)*74
|
||||
mul r7, r2, r14 @
|
||||
@ compute R, G, and B
|
||||
add r2, r8, r7, asr #9 @ r2 = b = (Y >> 9) + bu
|
||||
add r11, r9, r7, asr #9 @ r11 = r = (Y >> 9) + rv
|
||||
add r7, r10, r7, asr #8 @ r7 = g = (Y >> 8) + guv
|
||||
@
|
||||
orr r12, r2, r11 @ check if clamping is needed...
|
||||
orr r12, r12, r7, asr #1 @ ...at all
|
||||
cmp r12, #31 @
|
||||
bls 25f @ no clamp @
|
||||
mov r12, #31 @
|
||||
cmp r12, r2 @ clamp b
|
||||
andlo r2, r12, r2, asr #31 @
|
||||
eorlo r2, r2, r12 @
|
||||
cmp r12, r11 @ clamp r
|
||||
andlo r11, r12, r11, asr #31 @
|
||||
eorlo r11, r11, r12 @
|
||||
cmp r12, r7, asr #1 @ clamp g
|
||||
andlo r7, r12, r7, asr #31 @
|
||||
eorlo r7, r7, r12 @
|
||||
orrlo r7, r7, r7, asl #1 @
|
||||
25: @ no clamp @
|
||||
@
|
||||
orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11)
|
||||
orr r12, r12, r7, lsl #5 @ r4 |= (g << 5)
|
||||
strh r12, [r0, #240]! @ store pixel
|
||||
add r0, r0, #2*240 @
|
||||
@
|
||||
subs r3, r3, #2 @
|
||||
bgt 20b @ loop line 2 @
|
||||
@
|
||||
ldmia sp!, { r4-r12, pc } @ restore registers and return
|
||||
.size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines
|
||||
367
firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
Normal file
367
firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include "cpu.h"
|
||||
#include "lcd.h"
|
||||
#include "kernel.h"
|
||||
#include "system.h"
|
||||
#include "mmu-meg-fx.h"
|
||||
#include <stdlib.h>
|
||||
#include "memory.h"
|
||||
#include "lcd-target.h"
|
||||
#include "font.h"
|
||||
#include "rbunicode.h"
|
||||
#include "bidi.h"
|
||||
|
||||
#define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)])
|
||||
/*
|
||||
** We prepare foreground and background fills ahead of time - DMA fills in 16 byte groups
|
||||
*/
|
||||
unsigned long fg_pattern_blit[4];
|
||||
unsigned long bg_pattern_blit[4];
|
||||
|
||||
volatile bool use_dma_blit = false;
|
||||
static volatile bool lcd_on = true;
|
||||
volatile bool lcd_poweroff = false;
|
||||
/*
|
||||
** These are imported from lcd-16bit.c
|
||||
*/
|
||||
extern unsigned fg_pattern;
|
||||
extern unsigned bg_pattern;
|
||||
|
||||
bool lcd_enabled()
|
||||
{
|
||||
return lcd_on;
|
||||
}
|
||||
|
||||
unsigned int LCDBANK(unsigned int address)
|
||||
{
|
||||
return ((address >> 22) & 0xff);
|
||||
}
|
||||
|
||||
unsigned int LCDBASEU(unsigned int address)
|
||||
{
|
||||
return (address & ((1 << 22)-1)) >> 1;
|
||||
}
|
||||
|
||||
unsigned int LCDBASEL(unsigned int address)
|
||||
{
|
||||
address += 320*240*2;
|
||||
return (address & ((1 << 22)-1)) >> 1;
|
||||
}
|
||||
|
||||
|
||||
/* LCD init */
|
||||
void lcd_init_device(void)
|
||||
{
|
||||
LCDSADDR1 = (LCDBANK((unsigned)FRAME) << 21) | (LCDBASEU((unsigned)FRAME));
|
||||
LCDSADDR2 = LCDBASEL((unsigned)FRAME);
|
||||
LCDSADDR3 = 0x000000F0;
|
||||
|
||||
LCDCON5 |= 1 << 11; /* Switch from 555I mode to 565 mode */
|
||||
|
||||
#if !defined(BOOTLOADER)
|
||||
memset16(fg_pattern_blit, fg_pattern, sizeof(fg_pattern_blit)/2);
|
||||
memset16(bg_pattern_blit, bg_pattern, sizeof(bg_pattern_blit)/2);
|
||||
clean_dcache_range((void *)fg_pattern_blit, sizeof(fg_pattern_blit));
|
||||
clean_dcache_range((void *)bg_pattern_blit, sizeof(bg_pattern_blit));
|
||||
use_dma_blit = true;
|
||||
lcd_poweroff = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Update a fraction of the display. */
|
||||
void lcd_update_rect(int x, int y, int width, int height)
|
||||
{
|
||||
(void)x;
|
||||
(void)width;
|
||||
(void)y;
|
||||
(void)height;
|
||||
|
||||
if(!lcd_on)
|
||||
{
|
||||
sleep(200);
|
||||
return;
|
||||
}
|
||||
if (use_dma_blit)
|
||||
{
|
||||
/* Wait for this controller to stop pending transfer */
|
||||
while((DSTAT1 & 0x000fffff))
|
||||
CLKCON |= (1 << 2); /* set IDLE bit */
|
||||
|
||||
/* Flush DCache */
|
||||
invalidate_dcache_range((void *)(((int) &lcd_framebuffer[0][0])+(y * sizeof(fb_data) * LCD_WIDTH)), (height * sizeof(fb_data) * LCD_WIDTH));
|
||||
|
||||
/* set DMA dest */
|
||||
DIDST1 = ((int) FRAME) + (y * sizeof(fb_data) * LCD_WIDTH);
|
||||
|
||||
/* FRAME on AHB buf, increment */
|
||||
DIDSTC1 = 0;
|
||||
/* Handshake on AHB, Burst transfer, Whole service, Don't reload, transfer 32-bits */
|
||||
DCON1 = ((1<<30) | (1<<28) | (1<<27) | (1<<22) | (2<<20)) | ((height * sizeof(fb_data) * LCD_WIDTH) >> 4);
|
||||
|
||||
/* set DMA source */
|
||||
DISRC1 = ((int) &lcd_framebuffer[0][0]) + (y * sizeof(fb_data) * LCD_WIDTH) + 0x30000000;
|
||||
/* memory is on AHB bus, increment addresses */
|
||||
DISRCC1 = 0x00;
|
||||
|
||||
/* Activate the channel */
|
||||
DMASKTRIG1 = 0x2;
|
||||
|
||||
/* Start DMA */
|
||||
DMASKTRIG1 |= 0x1;
|
||||
|
||||
/* Wait for transfer to complete */
|
||||
while((DSTAT1 & 0x000fffff))
|
||||
CLKCON |= (1 << 2); /* set IDLE bit */
|
||||
}
|
||||
else
|
||||
memcpy(((char*)FRAME) + (y * sizeof(fb_data) * LCD_WIDTH), ((char *)&lcd_framebuffer) + (y * sizeof(fb_data) * LCD_WIDTH), ((height * sizeof(fb_data) * LCD_WIDTH)));
|
||||
}
|
||||
|
||||
|
||||
void lcd_enable(bool state)
|
||||
{
|
||||
if(!lcd_poweroff)
|
||||
return;
|
||||
if(state) {
|
||||
if(!lcd_on) {
|
||||
lcd_on = true;
|
||||
memcpy(FRAME, lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT*2);
|
||||
LCDCON1 |= 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(lcd_on) {
|
||||
lcd_on = false;
|
||||
LCDCON1 &= ~1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_set_foreground(unsigned color)
|
||||
{
|
||||
fg_pattern = color;
|
||||
|
||||
memset16(fg_pattern_blit, fg_pattern, sizeof(fg_pattern_blit)/2);
|
||||
invalidate_dcache_range((void *)fg_pattern_blit, sizeof(fg_pattern_blit));
|
||||
}
|
||||
|
||||
void lcd_set_background(unsigned color)
|
||||
{
|
||||
bg_pattern = color;
|
||||
memset16(bg_pattern_blit, bg_pattern, sizeof(bg_pattern_blit)/2);
|
||||
invalidate_dcache_range((void *)bg_pattern_blit, sizeof(bg_pattern_blit));
|
||||
}
|
||||
|
||||
void lcd_device_prepare_backdrop(fb_data* backdrop)
|
||||
{
|
||||
if(backdrop)
|
||||
invalidate_dcache_range((void *)backdrop, (LCD_HEIGHT * sizeof(fb_data) * LCD_WIDTH));
|
||||
}
|
||||
|
||||
void lcd_clear_display_dma(void)
|
||||
{
|
||||
void *src;
|
||||
bool inc = false;
|
||||
|
||||
if(!lcd_on) {
|
||||
sleep(200);
|
||||
}
|
||||
if (lcd_get_drawmode() & DRMODE_INVERSEVID)
|
||||
src = fg_pattern_blit;
|
||||
else
|
||||
{
|
||||
fb_data* lcd_backdrop = lcd_get_backdrop();
|
||||
|
||||
if (!lcd_backdrop)
|
||||
src = bg_pattern_blit;
|
||||
else
|
||||
{
|
||||
src = lcd_backdrop;
|
||||
inc = true;
|
||||
}
|
||||
}
|
||||
/* Wait for any pending transfer to complete */
|
||||
while((DSTAT3 & 0x000fffff))
|
||||
CLKCON |= (1 << 2); /* set IDLE bit */
|
||||
DMASKTRIG3 |= 0x4; /* Stop controller */
|
||||
DIDST3 = ((int) &lcd_framebuffer[0][0]) + 0x30000000; /* set DMA dest, physical address */
|
||||
DIDSTC3 = 0; /* Dest on AHB, increment */
|
||||
|
||||
DISRC3 = ((int) src) + 0x30000000; /* Set source, in physical space */
|
||||
DISRCC3 = inc ? 0x00 : 0x01; /* memory is on AHB bus, increment addresses based on backdrop */
|
||||
|
||||
/* Handshake on AHB, Burst mode, whole service mode, no reload, move 32-bits */
|
||||
DCON3 = ((1<<30) | (1<<28) | (1<<27) | (1<<22) | (2<<20)) | ((LCD_WIDTH*LCD_HEIGHT*sizeof(fb_data)) >> 4);
|
||||
|
||||
/* Dump DCache for dest, we are about to overwrite it with DMA */
|
||||
invalidate_dcache_range((void *)lcd_framebuffer, sizeof(lcd_framebuffer));
|
||||
/* Activate the channel */
|
||||
DMASKTRIG3 = 2;
|
||||
/* Start DMA */
|
||||
DMASKTRIG3 |= 1;
|
||||
|
||||
/* Wait for transfer to complete */
|
||||
while((DSTAT3 & 0x000fffff))
|
||||
CLKCON |= (1 << 2); /* set IDLE bit */
|
||||
}
|
||||
|
||||
void lcd_clear_display(void)
|
||||
{
|
||||
lcd_stop_scroll();
|
||||
|
||||
if(use_dma_blit)
|
||||
{
|
||||
lcd_clear_display_dma();
|
||||
return;
|
||||
}
|
||||
|
||||
fb_data *dst = &lcd_framebuffer[0][0];
|
||||
|
||||
if (lcd_get_drawmode() & DRMODE_INVERSEVID)
|
||||
{
|
||||
memset16(dst, fg_pattern, LCD_WIDTH*LCD_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
fb_data* lcd_backdrop = lcd_get_backdrop();
|
||||
if (!lcd_backdrop)
|
||||
memset16(dst, bg_pattern, LCD_WIDTH*LCD_HEIGHT);
|
||||
else
|
||||
memcpy(dst, lcd_backdrop, sizeof(lcd_framebuffer));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y,
|
||||
int stride, int x, int y, int width,
|
||||
int height)
|
||||
{
|
||||
fb_data *dst, *dst_end;
|
||||
unsigned int transcolor;
|
||||
|
||||
/* nothing to draw? */
|
||||
if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
|
||||
|| (x + width <= 0) || (y + height <= 0))
|
||||
return;
|
||||
|
||||
/* clipping */
|
||||
if (x < 0)
|
||||
{
|
||||
width += x;
|
||||
src_x -= x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
height += y;
|
||||
src_y -= y;
|
||||
y = 0;
|
||||
}
|
||||
if (x + width > LCD_WIDTH)
|
||||
width = LCD_WIDTH - x;
|
||||
if (y + height > LCD_HEIGHT)
|
||||
height = LCD_HEIGHT - y;
|
||||
|
||||
src += stride * src_y + src_x; /* move starting point */
|
||||
dst = &lcd_framebuffer[(y)][(x)];
|
||||
dst_end = dst + height * LCD_WIDTH;
|
||||
width *= 2;
|
||||
stride *= 2;
|
||||
transcolor = TRANSPARENT_COLOR;
|
||||
asm volatile(
|
||||
"rowstart: \n"
|
||||
"mov r0, #0 \n"
|
||||
"nextpixel: \n"
|
||||
"ldrh r1, [%0, r0] \n" /* Load word src+r0 */
|
||||
"cmp r1, %5 \n" /* Compare to transparent color */
|
||||
"strneh r1, [%1, r0] \n" /* Store dst+r0 if not transparent */
|
||||
"add r0, r0, #2 \n"
|
||||
"cmp r0, %2 \n" /* r0 == width? */
|
||||
"bne nextpixel \n" /* More in this row? */
|
||||
"add %0, %0, %4 \n" /* src += stride */
|
||||
"add %1, %1, #480 \n" /* dst += LCD_WIDTH (x2) */
|
||||
"cmp %1, %3 \n"
|
||||
"bne rowstart \n" /* if(dst != dst_end), keep going */
|
||||
: : "r" (src), "r" (dst), "r" (width), "r" (dst_end), "r" (stride), "r" (transcolor) : "r0", "r1" );
|
||||
}
|
||||
|
||||
/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
|
||||
extern void lcd_write_yuv420_lines(fb_data *dst,
|
||||
unsigned char chroma_buf[LCD_HEIGHT/2*3],
|
||||
unsigned char const * const src[3],
|
||||
int width,
|
||||
int stride);
|
||||
/* Performance function to blit a YUV bitmap directly to the LCD */
|
||||
/* For the Gigabeat - show it rotated */
|
||||
/* So the LCD_WIDTH is now the height */
|
||||
void lcd_yuv_blit(unsigned char * const src[3],
|
||||
int src_x, int src_y, int stride,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
/* Caches for chroma data so it only need be recaculated every other
|
||||
line */
|
||||
unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */
|
||||
unsigned char const * yuv_src[3];
|
||||
off_t z;
|
||||
|
||||
if (!lcd_on)
|
||||
return;
|
||||
|
||||
/* Sorry, but width and height must be >= 2 or else */
|
||||
width &= ~1;
|
||||
height >>= 1;
|
||||
|
||||
fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1;
|
||||
|
||||
z = stride*src_y;
|
||||
yuv_src[0] = src[0] + z + src_x;
|
||||
yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
|
||||
yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
|
||||
|
||||
do
|
||||
{
|
||||
lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width,
|
||||
stride);
|
||||
yuv_src[0] += stride << 1; /* Skip down two luma lines */
|
||||
yuv_src[1] += stride >> 1; /* Skip down one chroma line */
|
||||
yuv_src[2] += stride >> 1;
|
||||
dst -= 2;
|
||||
}
|
||||
while (--height > 0);
|
||||
}
|
||||
|
||||
void lcd_set_contrast(int val) {
|
||||
(void) val;
|
||||
// TODO:
|
||||
}
|
||||
|
||||
void lcd_set_invert_display(bool yesno) {
|
||||
(void) yesno;
|
||||
// TODO:
|
||||
}
|
||||
|
||||
void lcd_blit(const fb_data* data, int bx, int y, int bwidth,
|
||||
int height, int stride)
|
||||
{
|
||||
(void) data;
|
||||
(void) bx;
|
||||
(void) y;
|
||||
(void) bwidth;
|
||||
(void) height;
|
||||
(void) stride;
|
||||
//TODO:
|
||||
}
|
||||
|
||||
void lcd_set_flip(bool yesno) {
|
||||
(void) yesno;
|
||||
// TODO:
|
||||
}
|
||||
|
||||
21
firmware/target/arm/s3c2440/gigabeat-fx/lcd-target.h
Normal file
21
firmware/target/arm/s3c2440/gigabeat-fx/lcd-target.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id $
|
||||
*
|
||||
* Copyright (C) 2007 by Greg White
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
extern void lcd_enable(bool state);
|
||||
|
||||
222
firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.c
Normal file
222
firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.c
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
#include <string.h>
|
||||
#include "s3c2440.h"
|
||||
#include "mmu-meg-fx.h"
|
||||
#include "panic.h"
|
||||
|
||||
void map_memory(void);
|
||||
static void enable_mmu(void);
|
||||
static void set_ttb(void);
|
||||
static void set_page_tables(void);
|
||||
static void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags);
|
||||
|
||||
#define SECTION_ADDRESS_MASK (-1 << 20)
|
||||
#define CACHE_ALL (1 << 3 | 1 << 2 )
|
||||
#define CACHE_NONE 0
|
||||
#define BUFFERED (1 << 2)
|
||||
#define MB (1 << 20)
|
||||
|
||||
void map_memory(void) {
|
||||
set_ttb();
|
||||
set_page_tables();
|
||||
enable_mmu();
|
||||
}
|
||||
|
||||
unsigned int* ttb_base = (unsigned int *) TTB_BASE;
|
||||
const int ttb_size = 4096;
|
||||
|
||||
void set_ttb() {
|
||||
int i;
|
||||
int* ttbPtr;
|
||||
int domain_access;
|
||||
|
||||
/* must be 16Kb (0x4000) aligned */
|
||||
ttb_base = (int*) TTB_BASE;
|
||||
for (i=0; i<ttb_size; i++,ttbPtr++)
|
||||
ttbPtr = 0;
|
||||
asm volatile("mcr p15, 0, %0, c2, c0, 0" : : "r" (ttb_base));
|
||||
|
||||
/* set domain D0 to "client" permission access */
|
||||
|
||||
domain_access = 3;
|
||||
asm volatile("mcr p15, 0, %0, c3, c0, 0" : : "r" (domain_access));
|
||||
|
||||
}
|
||||
|
||||
void set_page_tables() {
|
||||
|
||||
map_section(0, 0, 0x1000, CACHE_NONE); /* map every memory region to itself */
|
||||
map_section(0x30000000, 0, 32, CACHE_ALL); /* map RAM to 0 and enable caching for it */
|
||||
map_section((int)FRAME, (int)FRAME, 1, BUFFERED); /* enable buffered writing for the framebuffer */
|
||||
}
|
||||
|
||||
void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags) {
|
||||
unsigned int* ttbPtr;
|
||||
int i;
|
||||
int section_no;
|
||||
|
||||
section_no = va >> 20; /* sections are 1Mb size */
|
||||
ttbPtr = ttb_base + section_no;
|
||||
pa &= SECTION_ADDRESS_MASK; /* align to 1Mb */
|
||||
for(i=0; i<mb; i++, pa += MB) {
|
||||
*(ttbPtr + i) =
|
||||
pa |
|
||||
1 << 10 | /* superuser - r/w, user - no access */
|
||||
0 << 5 | /* domain 0th */
|
||||
1 << 4 | /* should be "1" */
|
||||
cache_flags |
|
||||
1 << 1; /* Section signature */
|
||||
}
|
||||
}
|
||||
|
||||
static void enable_mmu(void) {
|
||||
asm volatile("mov r0, #0\n"
|
||||
"mcr p15, 0, r0, c8, c7, 0\n" /* invalidate TLB */
|
||||
|
||||
"mcr p15, 0, r0, c7, c7,0\n" /* invalidate both icache and dcache */
|
||||
|
||||
"mrc p15, 0, r0, c1, c0, 0\n"
|
||||
"orr r0, r0, #1<<0\n" /* enable mmu bit, icache and dcache */
|
||||
"orr r0, r0, #1<<2\n" /* enable dcache */
|
||||
"orr r0, r0, #1<<12\n" /* enable icache */
|
||||
"mcr p15, 0, r0, c1, c0, 0" : : : "r0");
|
||||
asm volatile("nop \n nop \n nop \n nop");
|
||||
}
|
||||
|
||||
/* Invalidate DCache for this range */
|
||||
/* Will do write back */
|
||||
void invalidate_dcache_range(const void *base, unsigned int size) {
|
||||
unsigned int addr = (((int) base) & ~31); /* Align start to cache line*/
|
||||
unsigned int end = ((addr+size) & ~31)+64; /* Align end to cache line, pad */
|
||||
asm volatile(
|
||||
"inv_start: \n"
|
||||
"mcr p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
|
||||
"add %0, %0, #32 \n"
|
||||
"cmp %0, %1 \n"
|
||||
"mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
|
||||
"addne %0, %0, #32 \n"
|
||||
"cmpne %0, %1 \n"
|
||||
"mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
|
||||
"addne %0, %0, #32 \n"
|
||||
"cmpne %0, %1 \n"
|
||||
"mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
|
||||
"addne %0, %0, #32 \n"
|
||||
"cmpne %0, %1 \n"
|
||||
"mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
|
||||
"addne %0, %0, #32 \n"
|
||||
"cmpne %0, %1 \n"
|
||||
"mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
|
||||
"addne %0, %0, #32 \n"
|
||||
"cmpne %0, %1 \n"
|
||||
"mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
|
||||
"addne %0, %0, #32 \n"
|
||||
"cmpne %0, %1 \n"
|
||||
"mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
|
||||
"addne %0, %0, #32 \n"
|
||||
"cmpne %0, %1 \n"
|
||||
"bne inv_start \n"
|
||||
"mov %0, #0\n"
|
||||
"mcr p15,0,%0,c7,c10,4\n" /* Drain write buffer */
|
||||
: : "r" (addr), "r" (end));
|
||||
}
|
||||
|
||||
/* clean DCache for this range */
|
||||
/* forces DCache writeback for the specified range */
|
||||
void clean_dcache_range(const void *base, unsigned int size) {
|
||||
unsigned int addr = (int) base;
|
||||
unsigned int end = addr+size+32;
|
||||
asm volatile(
|
||||
"bic %0, %0, #31 \n"
|
||||
"clean_start: \n"
|
||||
"mcr p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
|
||||
"add %0, %0, #32 \n"
|
||||
"cmp %0, %1 \n"
|
||||
"mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
|
||||
"addlo %0, %0, #32 \n"
|
||||
"cmplo %0, %1 \n"
|
||||
"mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
|
||||
"addlo %0, %0, #32 \n"
|
||||
"cmplo %0, %1 \n"
|
||||
"mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
|
||||
"addlo %0, %0, #32 \n"
|
||||
"cmplo %0, %1 \n"
|
||||
"mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
|
||||
"addlo %0, %0, #32 \n"
|
||||
"cmplo %0, %1 \n"
|
||||
"mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
|
||||
"addlo %0, %0, #32 \n"
|
||||
"cmplo %0, %1 \n"
|
||||
"mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
|
||||
"addlo %0, %0, #32 \n"
|
||||
"cmplo %0, %1 \n"
|
||||
"mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
|
||||
"addlo %0, %0, #32 \n"
|
||||
"cmplo %0, %1 \n"
|
||||
"blo clean_start \n"
|
||||
"mov %0, #0\n"
|
||||
"mcr p15,0,%0,c7,c10,4 \n" /* Drain write buffer */
|
||||
: : "r" (addr), "r" (end));
|
||||
}
|
||||
|
||||
/* Dump DCache for this range */
|
||||
/* Will *NOT* do write back */
|
||||
void dump_dcache_range(const void *base, unsigned int size) {
|
||||
unsigned int addr = (int) base;
|
||||
unsigned int end = addr+size;
|
||||
asm volatile(
|
||||
"tst %0, #31 \n" /* Check to see if low five bits are set */
|
||||
"bic %0, %0, #31 \n" /* Clear them */
|
||||
"mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line, if those bits were set */
|
||||
"add %0, %0, #32 \n" /* Move to the next cache line */
|
||||
"tst %1, #31 \n" /* Check last line for bits set */
|
||||
"bic %1, %1, #31 \n" /* Clear those bits */
|
||||
"mcrne p15, 0, %1, c7, c14, 1 \n" /* Clean and invalidate this line, if not cache aligned */
|
||||
"dump_start: \n"
|
||||
"mcr p15, 0, %0, c7, c6, 1 \n" /* Invalidate this line */
|
||||
"add %0, %0, #32 \n" /* Next cache line */
|
||||
"cmp %0, %1 \n"
|
||||
"bne dump_start \n"
|
||||
"dump_end: \n"
|
||||
"mcr p15,0,%0,c7,c10,4 \n" /* Drain write buffer */
|
||||
: : "r" (addr), "r" (end));
|
||||
}
|
||||
/* Cleans entire DCache */
|
||||
void clean_dcache(void)
|
||||
{
|
||||
unsigned int index, addr;
|
||||
|
||||
for(index = 0; index <= 63; index++) {
|
||||
addr = (0 << 5) | (index << 26);
|
||||
asm volatile(
|
||||
"mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
|
||||
: : "r" (addr));
|
||||
addr = (1 << 5) | (index << 26);
|
||||
asm volatile(
|
||||
"mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
|
||||
: : "r" (addr));
|
||||
addr = (2 << 5) | (index << 26);
|
||||
asm volatile(
|
||||
"mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
|
||||
: : "r" (addr));
|
||||
addr = (3 << 5) | (index << 26);
|
||||
asm volatile(
|
||||
"mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
|
||||
: : "r" (addr));
|
||||
addr = (4 << 5) | (index << 26);
|
||||
asm volatile(
|
||||
"mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
|
||||
: : "r" (addr));
|
||||
addr = (5 << 5) | (index << 26);
|
||||
asm volatile(
|
||||
"mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
|
||||
: : "r" (addr));
|
||||
addr = (6 << 5) | (index << 26);
|
||||
asm volatile(
|
||||
"mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
|
||||
: : "r" (addr));
|
||||
addr = (7 << 5) | (index << 26);
|
||||
asm volatile(
|
||||
"mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
|
||||
: : "r" (addr));
|
||||
}
|
||||
}
|
||||
|
||||
35
firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.h
Normal file
35
firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006,2007 by Greg White
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Invalidate DCache for this range */
|
||||
/* Will do write back */
|
||||
void invalidate_dcache_range(const void *base, unsigned int size);
|
||||
|
||||
/* clean DCache for this range */
|
||||
/* forces DCache writeback for the specified range */
|
||||
void clean_dcache_range(const void *base, unsigned int size);
|
||||
|
||||
/* Dump DCache for this range */
|
||||
/* Will *NOT* do write back */
|
||||
void dump_dcache_range(const void *base, unsigned int size);
|
||||
|
||||
/* Cleans entire DCache */
|
||||
void clean_dcache(void);
|
||||
|
||||
|
||||
376
firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
Normal file
376
firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Michael Sevakis
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "system.h"
|
||||
#include "kernel.h"
|
||||
#include "logf.h"
|
||||
#include "audio.h"
|
||||
#include "sound.h"
|
||||
#include "file.h"
|
||||
#include "mmu-meg-fx.h"
|
||||
|
||||
static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
|
||||
|
||||
#define GIGABEAT_8000HZ 0x4d
|
||||
#define GIGABEAT_11025HZ 0x32
|
||||
#define GIGABEAT_12000HZ 0x61
|
||||
#define GIGABEAT_16000HZ 0x55
|
||||
#define GIGABEAT_22050HZ 0x36
|
||||
#define GIGABEAT_24000HZ 0x79
|
||||
#define GIGABEAT_32000HZ 0x59
|
||||
#define GIGABEAT_44100HZ 0x22
|
||||
#define GIGABEAT_48000HZ 0x41
|
||||
#define GIGABEAT_88200HZ 0x3e
|
||||
#define GIGABEAT_96000HZ 0x5d
|
||||
|
||||
#define FIFO_COUNT ((IISFCON >> 6) & 0x01F)
|
||||
|
||||
/* number of bytes in FIFO */
|
||||
#define IIS_FIFO_SIZE 64
|
||||
|
||||
/* Setup for the DMA controller */
|
||||
#define DMA_CONTROL_SETUP ((1<<31) | (1<<29) | (1<<23) | (1<<22) | (1<<20))
|
||||
|
||||
unsigned short * p;
|
||||
size_t p_size;
|
||||
|
||||
|
||||
|
||||
/* DMA count has hit zero - no more data */
|
||||
/* Get more data from the callback and top off the FIFO */
|
||||
//void fiq(void) __attribute__ ((interrupt ("naked")));
|
||||
void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ")));
|
||||
void fiq(void)
|
||||
{
|
||||
/* clear any pending interrupt */
|
||||
SRCPND = (1<<19);
|
||||
|
||||
/* Buffer empty. Try to get more. */
|
||||
if (pcm_callback_for_more)
|
||||
{
|
||||
pcm_callback_for_more((unsigned char**)&p, &p_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* callback func is missing? */
|
||||
pcm_play_dma_stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_size)
|
||||
{
|
||||
/* Flush any pending cache writes */
|
||||
clean_dcache_range(p, p_size);
|
||||
|
||||
/* set the new DMA values */
|
||||
DCON2 = DMA_CONTROL_SETUP | (p_size >> 1);
|
||||
DISRC2 = (int)p + 0x30000000;
|
||||
|
||||
/* Re-Activate the channel */
|
||||
DMASKTRIG2 = 0x2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No more DMA to do */
|
||||
pcm_play_dma_stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pcm_init(void)
|
||||
{
|
||||
pcm_playing = false;
|
||||
pcm_paused = false;
|
||||
pcm_callback_for_more = NULL;
|
||||
|
||||
audiohw_init();
|
||||
audiohw_enable_output(true);
|
||||
|
||||
/* cannot use the WM8975 defaults since our clock is not the same */
|
||||
/* the input master clock is 16.9344MHz - we can divide exact for that */
|
||||
pcm_set_frequency(SAMPR_44);
|
||||
|
||||
/* init GPIO */
|
||||
GPCCON = (GPCCON & ~(3<<14)) | (1<<14);
|
||||
GPCDAT |= 1<<7;
|
||||
GPECON |= 0x2aa;
|
||||
|
||||
/* Do not service DMA requests, yet */
|
||||
/* clear any pending int and mask it */
|
||||
INTMSK |= (1<<19); /* mask the interrupt */
|
||||
SRCPND = (1<<19); /* clear any pending interrupts */
|
||||
INTMOD |= (1<<19); /* connect to FIQ */
|
||||
|
||||
}
|
||||
|
||||
void pcm_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
/* sanity check: bad pointer or too small file */
|
||||
if (NULL == addr || size <= IIS_FIFO_SIZE) return;
|
||||
|
||||
p = (unsigned short *)addr;
|
||||
p_size = size;
|
||||
|
||||
/* Enable the IIS clock */
|
||||
CLKCON |= (1<<17);
|
||||
|
||||
/* IIS interface setup and set to idle */
|
||||
IISCON = (1<<5) | (1<<3);
|
||||
|
||||
/* slave, transmit mode, 16 bit samples - 384fs - use 16.9344Mhz */
|
||||
IISMOD = (1<<9) | (1<<8) | (2<<6) | (1<<3) | (1<<2);
|
||||
|
||||
/* connect DMA to the FIFO and enable the FIFO */
|
||||
IISFCON = (1<<15) | (1<<13);
|
||||
|
||||
/* set DMA dest */
|
||||
DIDST2 = (int)&IISFIFO;
|
||||
|
||||
/* IIS is on the APB bus, INT when TC reaches 0, fixed dest addr */
|
||||
DIDSTC2 = 0x03;
|
||||
|
||||
/* How many transfers to make - we transfer half-word at a time = 2 bytes */
|
||||
/* DMA control: CURR_TC int, single service mode, I2SSDO int, HW trig */
|
||||
/* no auto-reload, half-word (16bit) */
|
||||
DCON2 = DMA_CONTROL_SETUP | (p_size / 2);
|
||||
|
||||
/* set DMA source and options */
|
||||
DISRC2 = (int)p + 0x30000000;
|
||||
DISRCC2 = 0x00; /* memory is on AHB bus, increment addresses */
|
||||
|
||||
/* clear pending DMA interrupt */
|
||||
SRCPND = 1<<19;
|
||||
|
||||
set_fiq_handler(fiq);
|
||||
enable_fiq();
|
||||
|
||||
/* unmask the DMA interrupt */
|
||||
INTMSK &= ~(1<<19);
|
||||
|
||||
/* Flush any pending writes */
|
||||
clean_dcache_range(addr, size);
|
||||
|
||||
/* Activate the channel */
|
||||
DMASKTRIG2 = 0x2;
|
||||
|
||||
/* turn off the idle */
|
||||
IISCON &= ~(1<<3);
|
||||
|
||||
pcm_playing = true;
|
||||
|
||||
/* start the IIS */
|
||||
IISCON |= (1<<0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Disconnect the DMA and wait for the FIFO to clear */
|
||||
void pcm_play_dma_stop(void)
|
||||
{
|
||||
/* mask the DMA interrupt */
|
||||
INTMSK |= (1<<19);
|
||||
|
||||
/* are we playing? wait for the chunk to finish */
|
||||
if (pcm_playing)
|
||||
{
|
||||
/* wait for the FIFO to empty before turning things off */
|
||||
while (IISCON & (1<<7)) ;
|
||||
|
||||
pcm_playing = false;
|
||||
}
|
||||
|
||||
/* De-Activate the DMA channel */
|
||||
DMASKTRIG2 = 0x4;
|
||||
|
||||
/* Disconnect the IIS clock */
|
||||
CLKCON &= ~(1<<17);
|
||||
|
||||
disable_fiq();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pcm_play_pause_pause(void)
|
||||
{
|
||||
/* stop servicing refills */
|
||||
INTMSK |= (1<<19);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pcm_play_pause_unpause(void)
|
||||
{
|
||||
/* refill buffer and keep going */
|
||||
INTMSK &= ~(1<<19);
|
||||
}
|
||||
|
||||
void pcm_set_frequency(unsigned int frequency)
|
||||
{
|
||||
int sr_ctrl;
|
||||
|
||||
switch(frequency)
|
||||
{
|
||||
case SAMPR_8:
|
||||
sr_ctrl = GIGABEAT_8000HZ;
|
||||
break;
|
||||
case SAMPR_11:
|
||||
sr_ctrl = GIGABEAT_11025HZ;
|
||||
break;
|
||||
case SAMPR_12:
|
||||
sr_ctrl = GIGABEAT_12000HZ;
|
||||
break;
|
||||
case SAMPR_16:
|
||||
sr_ctrl = GIGABEAT_16000HZ;
|
||||
break;
|
||||
case SAMPR_22:
|
||||
sr_ctrl = GIGABEAT_22050HZ;
|
||||
break;
|
||||
case SAMPR_24:
|
||||
sr_ctrl = GIGABEAT_24000HZ;
|
||||
break;
|
||||
case SAMPR_32:
|
||||
sr_ctrl = GIGABEAT_32000HZ;
|
||||
break;
|
||||
default:
|
||||
frequency = SAMPR_44;
|
||||
case SAMPR_44:
|
||||
sr_ctrl = GIGABEAT_44100HZ;
|
||||
break;
|
||||
case SAMPR_48:
|
||||
sr_ctrl = GIGABEAT_48000HZ;
|
||||
break;
|
||||
case SAMPR_88:
|
||||
sr_ctrl = GIGABEAT_88200HZ;
|
||||
break;
|
||||
case SAMPR_96:
|
||||
sr_ctrl = GIGABEAT_96000HZ;
|
||||
break;
|
||||
}
|
||||
|
||||
audiohw_set_sample_rate(sr_ctrl);
|
||||
pcm_freq = frequency;
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t pcm_get_bytes_waiting(void)
|
||||
{
|
||||
return (DSTAT2 & 0xFFFFF) * 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* dummy functions for those not actually supporting all this yet */
|
||||
void pcm_apply_settings(void)
|
||||
{
|
||||
}
|
||||
|
||||
void pcm_set_monitor(int monitor)
|
||||
{
|
||||
(void)monitor;
|
||||
}
|
||||
/** **/
|
||||
|
||||
void pcm_mute(bool mute)
|
||||
{
|
||||
audiohw_mute(mute);
|
||||
if (mute)
|
||||
sleep(HZ/16);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function goes directly into the DMA buffer to calculate the left and
|
||||
* right peak values. To avoid missing peaks it tries to look forward two full
|
||||
* peek periods (2/HZ sec, 100% overlap), although it's always possible that
|
||||
* the entire period will not be visible. To reduce CPU load it only looks at
|
||||
* every third sample, and this can be reduced even further if needed (even
|
||||
* every tenth sample would still be pretty accurate).
|
||||
*/
|
||||
|
||||
/* Check for a peak every PEAK_STRIDE samples */
|
||||
#define PEAK_STRIDE 3
|
||||
/* Up to 1/50th of a second of audio for peak calculation */
|
||||
/* This should use NATIVE_FREQUENCY, or eventually an adjustable freq. value */
|
||||
#define PEAK_SAMPLES (44100/50)
|
||||
void pcm_calculate_peaks(int *left, int *right)
|
||||
{
|
||||
short *addr;
|
||||
short *end;
|
||||
{
|
||||
size_t samples = p_size / 4;
|
||||
addr = p;
|
||||
|
||||
if (samples > PEAK_SAMPLES)
|
||||
samples = PEAK_SAMPLES - (PEAK_STRIDE - 1);
|
||||
else
|
||||
samples -= MIN(PEAK_STRIDE - 1, samples);
|
||||
|
||||
end = &addr[samples * 2];
|
||||
}
|
||||
|
||||
if (left && right) {
|
||||
int left_peak = 0, right_peak = 0;
|
||||
|
||||
while (addr < end) {
|
||||
int value;
|
||||
if ((value = addr [0]) > left_peak)
|
||||
left_peak = value;
|
||||
else if (-value > left_peak)
|
||||
left_peak = -value;
|
||||
|
||||
if ((value = addr [PEAK_STRIDE | 1]) > right_peak)
|
||||
right_peak = value;
|
||||
else if (-value > right_peak)
|
||||
right_peak = -value;
|
||||
|
||||
addr = &addr[PEAK_STRIDE * 2];
|
||||
}
|
||||
|
||||
*left = left_peak;
|
||||
*right = right_peak;
|
||||
}
|
||||
else if (left || right) {
|
||||
int peak_value = 0, value;
|
||||
|
||||
if (right)
|
||||
addr += (PEAK_STRIDE | 1);
|
||||
|
||||
while (addr < end) {
|
||||
if ((value = addr [0]) > peak_value)
|
||||
peak_value = value;
|
||||
else if (-value > peak_value)
|
||||
peak_value = -value;
|
||||
|
||||
addr += PEAK_STRIDE * 2;
|
||||
}
|
||||
|
||||
if (left)
|
||||
*left = peak_value;
|
||||
else
|
||||
*right = peak_value;
|
||||
}
|
||||
}
|
||||
90
firmware/target/arm/s3c2440/gigabeat-fx/power-meg-fx.c
Normal file
90
firmware/target/arm/s3c2440/gigabeat-fx/power-meg-fx.c
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Linus Nielsen Feltzing
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include <stdbool.h>
|
||||
#include "kernel.h"
|
||||
#include "system.h"
|
||||
#include "power.h"
|
||||
#include "pcf50606.h"
|
||||
#include "backlight.h"
|
||||
#include "backlight-target.h"
|
||||
|
||||
#ifndef SIMULATOR
|
||||
|
||||
void power_init(void)
|
||||
{
|
||||
/* Charger detect */
|
||||
}
|
||||
|
||||
bool charger_inserted(void)
|
||||
{
|
||||
return (GPFDAT & (1 << 4)) ? false : true;
|
||||
}
|
||||
|
||||
/* Returns true if the unit is charging the batteries. */
|
||||
bool charging_state(void) {
|
||||
return (GPGDAT & (1 << 8)) ? false : true;
|
||||
}
|
||||
|
||||
void ide_power_enable(bool on)
|
||||
{
|
||||
if (on)
|
||||
GPGDAT |= (1 << 11);
|
||||
else
|
||||
GPGDAT &= ~(1 << 11);
|
||||
}
|
||||
|
||||
bool ide_powered(void)
|
||||
{
|
||||
return (GPGDAT & (1 << 11)) != 0;
|
||||
}
|
||||
|
||||
void power_off(void)
|
||||
{
|
||||
/* turn off backlight and wait for 1 second */
|
||||
__backlight_off();
|
||||
sleep(HZ/2);
|
||||
/* set SLEEP bit to on in CLKCON to turn off */
|
||||
CLKCON |=(1<<3);
|
||||
}
|
||||
|
||||
#else /* SIMULATOR */
|
||||
|
||||
bool charger_inserted(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void charger_enable(bool on)
|
||||
{
|
||||
(void)on;
|
||||
}
|
||||
|
||||
void power_off(void)
|
||||
{
|
||||
}
|
||||
|
||||
void ide_power_enable(bool on)
|
||||
{
|
||||
(void)on;
|
||||
}
|
||||
|
||||
#endif /* SIMULATOR */
|
||||
|
||||
225
firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c
Normal file
225
firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include <stdbool.h>
|
||||
#include "kernel.h"
|
||||
#include "system.h"
|
||||
#include "logf.h"
|
||||
#include "debug.h"
|
||||
#include "string.h"
|
||||
|
||||
#define SLAVE_ADDRESS 0xCC
|
||||
|
||||
#define SDA_LO (GPHDAT &= ~(1 << 9))
|
||||
#define SDA_HI (GPHDAT |= (1 << 9))
|
||||
#define SDA_INPUT (GPHCON &= ~(3 << 18))
|
||||
#define SDA_OUTPUT (GPHCON |= (1 << 18))
|
||||
#define SDA (GPHDAT & (1 << 9))
|
||||
|
||||
#define SCL_LO (GPHDAT &= ~(1 << 10))
|
||||
#define SCL_HI (GPHDAT |= (1 << 10))
|
||||
#define SCL_INPUT (GPHCON &= ~(3 << 20))
|
||||
#define SCL_OUTPUT (GPHCON |= (1 << 20))
|
||||
#define SCL (GPHDAT & (1 << 10))
|
||||
|
||||
#define SCL_SDA_HI (GPHDAT |= (3 << 9))
|
||||
|
||||
/* The SC606 can clock at 400KHz: */
|
||||
/* Clock period high is 600nS and low is 1300nS */
|
||||
/* The high and low times are different enough to need different timings */
|
||||
/* cycles delayed = 30 + 7 * loops */
|
||||
/* 100MHz = 10nS per cycle: LO:1300nS=130:14 HI:600nS=60:9 */
|
||||
/* 300MHz = 3.36nS per cycle: LO:1300nS=387:51 HI:600nS=179:21 */
|
||||
#define DELAY_LO do{int x;for(x=51;x;x--);} while (0)
|
||||
#define DELAY do{int x;for(x=35;x;x--);} while (0)
|
||||
#define DELAY_HI do{int x;for(x=21;x;x--);} while (0)
|
||||
|
||||
|
||||
|
||||
static void sc606_i2c_start(void)
|
||||
{
|
||||
SCL_SDA_HI;
|
||||
DELAY;
|
||||
SDA_LO;
|
||||
DELAY;
|
||||
SCL_LO;
|
||||
}
|
||||
|
||||
static void sc606_i2c_restart(void)
|
||||
{
|
||||
SCL_SDA_HI;
|
||||
DELAY;
|
||||
SDA_LO;
|
||||
DELAY;
|
||||
SCL_LO;
|
||||
}
|
||||
|
||||
static void sc606_i2c_stop(void)
|
||||
{
|
||||
SDA_LO;
|
||||
SCL_HI;
|
||||
DELAY_HI;
|
||||
SDA_HI;
|
||||
}
|
||||
|
||||
static void sc606_i2c_ack(void)
|
||||
{
|
||||
|
||||
SDA_LO;
|
||||
SCL_HI;
|
||||
DELAY_HI;
|
||||
SCL_LO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int sc606_i2c_getack(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Don't need a delay since follows a data bit with a delay on the end */
|
||||
SDA_INPUT; /* And set to input */
|
||||
DELAY;
|
||||
SCL_HI;
|
||||
|
||||
ret = (SDA != 0); /* ack failed if SDA is not low */
|
||||
DELAY_HI;
|
||||
|
||||
SCL_LO;
|
||||
DELAY_LO;
|
||||
|
||||
SDA_HI;
|
||||
SDA_OUTPUT;
|
||||
DELAY_LO;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void sc606_i2c_outb(unsigned char byte)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* clock out each bit, MSB first */
|
||||
for (i = 0x80; i; i >>= 1)
|
||||
{
|
||||
if (i & byte)
|
||||
{
|
||||
SDA_HI;
|
||||
}
|
||||
else
|
||||
{
|
||||
SDA_LO;
|
||||
}
|
||||
DELAY;
|
||||
|
||||
SCL_HI;
|
||||
DELAY_HI;
|
||||
|
||||
SCL_LO;
|
||||
DELAY_LO;
|
||||
}
|
||||
|
||||
SDA_HI;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned char sc606_i2c_inb(void)
|
||||
{
|
||||
int i;
|
||||
unsigned char byte = 0;
|
||||
|
||||
SDA_INPUT; /* And set to input */
|
||||
/* clock in each bit, MSB first */
|
||||
for (i = 0x80; i; i >>= 1) {
|
||||
SCL_HI;
|
||||
|
||||
if (SDA)
|
||||
byte |= i;
|
||||
|
||||
SCL_LO;
|
||||
}
|
||||
SDA_OUTPUT;
|
||||
|
||||
sc606_i2c_ack();
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* returns number of acks that were bad */
|
||||
int sc606_write(unsigned char reg, unsigned char data)
|
||||
{
|
||||
int x;
|
||||
|
||||
sc606_i2c_start();
|
||||
|
||||
sc606_i2c_outb(SLAVE_ADDRESS);
|
||||
x = sc606_i2c_getack();
|
||||
|
||||
sc606_i2c_outb(reg);
|
||||
x += sc606_i2c_getack();
|
||||
|
||||
sc606_i2c_restart();
|
||||
|
||||
sc606_i2c_outb(SLAVE_ADDRESS);
|
||||
x += sc606_i2c_getack();
|
||||
|
||||
sc606_i2c_outb(data);
|
||||
x += sc606_i2c_getack();
|
||||
|
||||
sc606_i2c_stop();
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int sc606_read(unsigned char reg, unsigned char* data)
|
||||
{
|
||||
int x;
|
||||
|
||||
sc606_i2c_start();
|
||||
sc606_i2c_outb(SLAVE_ADDRESS);
|
||||
x = sc606_i2c_getack();
|
||||
|
||||
sc606_i2c_outb(reg);
|
||||
x += sc606_i2c_getack();
|
||||
|
||||
sc606_i2c_restart();
|
||||
sc606_i2c_outb(SLAVE_ADDRESS | 1);
|
||||
x += sc606_i2c_getack();
|
||||
|
||||
*data = sc606_i2c_inb();
|
||||
sc606_i2c_stop();
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sc606_init(void)
|
||||
{
|
||||
volatile int i;
|
||||
|
||||
/* Set GPB2 (EN) to 1 */
|
||||
GPBCON = (GPBCON & ~(3<<4)) | 1<<4;
|
||||
|
||||
/* Turn enable line on */
|
||||
GPBDAT |= 1<<2;
|
||||
/* OFF GPBDAT &= ~(1 << 2); */
|
||||
|
||||
/* About 400us - needs 350us */
|
||||
for (i = 200; i; i--)
|
||||
{
|
||||
DELAY_LO;
|
||||
}
|
||||
|
||||
/* Set GPH9 (SDA) and GPH10 (SCL) to 1 */
|
||||
GPHUP &= ~(3<<9);
|
||||
GPHCON = (GPHCON & ~(0xF<<18)) | 5<<18;
|
||||
}
|
||||
|
||||
28
firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.h
Normal file
28
firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#include "config.h"
|
||||
#include "cpu.h"
|
||||
#include <stdbool.h>
|
||||
#include "kernel.h"
|
||||
#include "system.h"
|
||||
#include "logf.h"
|
||||
#include "debug.h"
|
||||
#include "string.h"
|
||||
|
||||
#define SC606_REG_A 0
|
||||
#define SC606_REG_B 1
|
||||
#define SC606_REG_C 2
|
||||
#define SC606_REG_CONF 3
|
||||
|
||||
#define SC606_LED_A1 (1 << 0)
|
||||
#define SC606_LED_A2 (1 << 1)
|
||||
#define SC606_LED_B1 (1 << 2)
|
||||
#define SC606_LED_B2 (1 << 3)
|
||||
#define SC606_LED_C1 (1 << 4)
|
||||
#define SC606_LED_C2 (1 << 5)
|
||||
|
||||
#define SC606_LOW_FREQ (1 << 6)
|
||||
|
||||
int sc606_write(unsigned char reg, unsigned char data);
|
||||
|
||||
int sc606_read(unsigned char reg, unsigned char* data);
|
||||
|
||||
void sc606_init(void);
|
||||
96
firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c
Normal file
96
firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#include "kernel.h"
|
||||
#include "system.h"
|
||||
#include "panic.h"
|
||||
|
||||
#include "lcd.h"
|
||||
#include <stdio.h>
|
||||
|
||||
const int TIMER4_MASK = (1 << 14);
|
||||
const int LCD_MASK = (1 << 16);
|
||||
const int DMA0_MASK = (1 << 17);
|
||||
const int DMA1_MASK = (1 << 18);
|
||||
const int DMA2_MASK = (1 << 19);
|
||||
const int DMA3_MASK = (1 << 20);
|
||||
|
||||
int system_memory_guard(int newmode)
|
||||
{
|
||||
(void)newmode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void timer4(void);
|
||||
extern void dma0(void);
|
||||
extern void dma1(void);
|
||||
extern void dma3(void);
|
||||
|
||||
void irq(void)
|
||||
{
|
||||
int intpending = INTPND;
|
||||
|
||||
SRCPND = intpending; /* Clear this interrupt. */
|
||||
INTPND = intpending; /* Clear this interrupt. */
|
||||
|
||||
/* Timer 4 */
|
||||
if ((intpending & TIMER4_MASK) != 0)
|
||||
timer4();
|
||||
else if ((intpending & DMA0_MASK) != 0)
|
||||
dma0();
|
||||
else
|
||||
{
|
||||
/* unexpected interrupt */
|
||||
}
|
||||
}
|
||||
|
||||
void system_reboot(void)
|
||||
{
|
||||
WTCON = 0;
|
||||
WTCNT = WTDAT = 1 ;
|
||||
WTCON = 0x21;
|
||||
for(;;)
|
||||
;
|
||||
}
|
||||
|
||||
void system_init(void)
|
||||
{
|
||||
/* Turn off un-needed devices */
|
||||
|
||||
/* Turn off all of the UARTS */
|
||||
CLKCON &= ~( (1<<10) | (1<<11) |(1<<12) );
|
||||
|
||||
/* Turn off AC97 and Camera */
|
||||
CLKCON &= ~( (1<<19) | (1<<20) );
|
||||
|
||||
/* Turn off USB host */
|
||||
CLKCON &= ~(1 << 6);
|
||||
|
||||
/* Turn off NAND flash controller */
|
||||
CLKCON &= ~(1 << 4);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||
|
||||
void set_cpu_frequency(long frequency)
|
||||
{
|
||||
if (frequency == CPUFREQ_MAX)
|
||||
{
|
||||
asm volatile("mov r0, #0\n"
|
||||
"mrc p15, 0, r0, c1, c0, 0\n"
|
||||
"orr r0, r0, #3<<30\n" /* set to Asynchronous mode*/
|
||||
"mcr p15, 0, r0, c1, c0, 0" : : : "r0");
|
||||
|
||||
FREQ = CPUFREQ_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
asm volatile("mov r0, #0\n"
|
||||
"mrc p15, 0, r0, c1, c0, 0\n"
|
||||
"bic r0, r0, #3<<30\n" /* set to FastBus mode*/
|
||||
"mcr p15, 0, r0, c1, c0, 0" : : : "r0");
|
||||
|
||||
FREQ = CPUFREQ_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
40
firmware/target/arm/s3c2440/gigabeat-fx/system-target.h
Normal file
40
firmware/target/arm/s3c2440/gigabeat-fx/system-target.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2007 by Greg White
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef SYSTEM_TARGET_H
|
||||
#define SYSTEM_TARGET_H
|
||||
|
||||
#include "mmu-meg-fx.h"
|
||||
#include "system-arm.h"
|
||||
|
||||
#define CPUFREQ_DEFAULT 98784000
|
||||
#define CPUFREQ_NORMAL 98784000
|
||||
#define CPUFREQ_MAX 296352000
|
||||
|
||||
#define HAVE_INVALIDATE_ICACHE
|
||||
static inline void invalidate_icache(void)
|
||||
{
|
||||
clean_dcache();
|
||||
asm volatile(
|
||||
"mov r0, #0 \n"
|
||||
"mcr p15, 0, r0, c7, c5, 0 \n"
|
||||
: : : "r0"
|
||||
);
|
||||
}
|
||||
|
||||
#endif /* SYSTEM_TARGET_H */
|
||||
94
firmware/target/arm/s3c2440/gigabeat-fx/usb-meg-fx.c
Normal file
94
firmware/target/arm/s3c2440/gigabeat-fx/usb-meg-fx.c
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Linus Nielsen Feltzing
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "config.h"
|
||||
#include <stdbool.h>
|
||||
#include "cpu.h"
|
||||
#include "system.h"
|
||||
#include "kernel.h"
|
||||
#include "ata.h"
|
||||
|
||||
#define USB_RST_ASSERT GPBDAT &= ~(1 << 4)
|
||||
#define USB_RST_DEASSERT GPBDAT |= (1 << 4)
|
||||
|
||||
#define USB_VPLUS_PWR_ASSERT GPBDAT |= (1 << 6)
|
||||
#define USB_VPLUS_PWR_DEASSERT GPBDAT &= ~(1 << 6)
|
||||
|
||||
#define USB_UNIT_IS_PRESENT !(GPFDAT & 0x01)
|
||||
#define USB_CRADLE_IS_PRESENT ((GPFDAT &0x02)&&!(GPGDAT&1<<14))
|
||||
|
||||
#define USB_CRADLE_BUS_ENABLE GPHDAT |= (1 << 8)
|
||||
#define USB_CRADLE_BUS_DISABLE GPHDAT &= ~(1 << 8)
|
||||
|
||||
/* The usb detect is one pin to the cpu active low */
|
||||
inline bool usb_detect(void)
|
||||
{
|
||||
return USB_UNIT_IS_PRESENT | USB_CRADLE_IS_PRESENT;
|
||||
}
|
||||
|
||||
void usb_init_device(void)
|
||||
{
|
||||
/* Input is the default configuration, only pullups need to be disabled */
|
||||
GPFUP|=0x02;
|
||||
|
||||
USB_VPLUS_PWR_ASSERT;
|
||||
GPBCON=( GPBCON&~(1<<13) ) | (1 << 12);
|
||||
|
||||
sleep(HZ/20);
|
||||
|
||||
/* Reset the usb port */
|
||||
USB_RST_ASSERT;
|
||||
GPBCON = (GPBCON & ~0x200) | 0x100; /* Make sure reset line is an output */
|
||||
|
||||
sleep(HZ/25);
|
||||
USB_RST_DEASSERT;
|
||||
|
||||
/* needed to complete the reset */
|
||||
ata_enable(false);
|
||||
|
||||
sleep(HZ/15); /* 66ms */
|
||||
|
||||
ata_enable(true);
|
||||
|
||||
sleep(HZ/25);
|
||||
|
||||
/* leave chip in low power mode */
|
||||
USB_VPLUS_PWR_DEASSERT;
|
||||
|
||||
sleep(HZ/25);
|
||||
}
|
||||
|
||||
void usb_enable(bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
USB_VPLUS_PWR_ASSERT;
|
||||
if(USB_CRADLE_IS_PRESENT) USB_CRADLE_BUS_ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(USB_CRADLE_IS_PRESENT) USB_CRADLE_BUS_DISABLE;
|
||||
USB_VPLUS_PWR_DEASSERT;
|
||||
}
|
||||
|
||||
/* Make sure USB_CRADLE_BUS pin is an output */
|
||||
GPHCON=( GPHCON&~(1<<17) ) | (1<<16); /* Make the pin an output */
|
||||
GPHUP|=1<<8; /* Disable pullup in SOC as we are now driving */
|
||||
|
||||
sleep(HZ/20); // > 50ms for detecting the enable state change
|
||||
}
|
||||
26
firmware/target/arm/s3c2440/gigabeat-fx/usb-target.h
Normal file
26
firmware/target/arm/s3c2440/gigabeat-fx/usb-target.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2006 by Linus Nielsen Feltzing
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef USB_TARGET_H
|
||||
#define USB_TARGET_H
|
||||
|
||||
bool usb_init_device(void);
|
||||
bool usb_detect(void);
|
||||
void usb_enable(bool on);
|
||||
|
||||
#endif
|
||||
71
firmware/target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c
Normal file
71
firmware/target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Gigabeat specific code for the Wolfson codec
|
||||
*
|
||||
* Based on code from the ipodlinux project - http://ipodlinux.org/
|
||||
* Adapted for Rockbox in December 2005
|
||||
*
|
||||
* Original file: linux/arch/armnommu/mach-ipod/audio.c
|
||||
*
|
||||
* Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org)
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "lcd.h"
|
||||
#include "cpu.h"
|
||||
#include "kernel.h"
|
||||
#include "thread.h"
|
||||
#include "power.h"
|
||||
#include "debug.h"
|
||||
#include "system.h"
|
||||
#include "sprintf.h"
|
||||
#include "button.h"
|
||||
#include "string.h"
|
||||
#include "file.h"
|
||||
#include "buffer.h"
|
||||
#include "audio.h"
|
||||
#include "i2c.h"
|
||||
#include "i2c-meg-fx.h"
|
||||
/*
|
||||
* Reset the I2S BIT.FORMAT I2S, 16bit, FIFO.FORMAT 32bit
|
||||
*/
|
||||
void i2s_reset(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the WM8975 for playback via headphone and line out.
|
||||
* Note, I'm using the WM8750 datasheet as its apparently close.
|
||||
*/
|
||||
int audiohw_init(void) {
|
||||
/* reset I2C */
|
||||
i2c_init();
|
||||
|
||||
/* GPC5 controls headphone output */
|
||||
GPCCON &= ~(0x3 << 10);
|
||||
GPCCON |= (1 << 10);
|
||||
GPCDAT |= (1 << 5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void audiohw_postinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void wmcodec_write(int reg, int data)
|
||||
{
|
||||
i2c_send(0x34, (reg<<1) | ((data&0x100)>>8), data&0xff);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue