summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s3c2440/gigabeat-fx
diff options
context:
space:
mode:
authorMarcoen Hirschberg <marcoen@gmail.com>2007-04-18 12:22:27 +0000
committerMarcoen Hirschberg <marcoen@gmail.com>2007-04-18 12:22:27 +0000
commitf44f961812c059b69df19ac5bd828986ba10513f (patch)
tree9b19de69126ed041992f31a7c690db841a36af6f /firmware/target/arm/s3c2440/gigabeat-fx
parentc3dcc87aa494934943769b70fd752af1271d196a (diff)
downloadrockbox-f44f961812c059b69df19ac5bd828986ba10513f.tar.gz
rockbox-f44f961812c059b69df19ac5bd828986ba10513f.zip
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
Diffstat (limited to 'firmware/target/arm/s3c2440/gigabeat-fx')
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c144
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/adc-target.h37
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c143
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/ata-target.h70
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c692
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/backlight-target.h87
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/button-meg-fx.c157
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/button-target.h89
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/dma_start.c8
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c134
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.h22
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c25
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S222
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c367
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/lcd-target.h21
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.c222
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.h35
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c376
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/power-meg-fx.c90
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c225
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.h28
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c96
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/system-target.h40
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/usb-meg-fx.c94
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/usb-target.h26
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c71
26 files changed, 3521 insertions, 0 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c
new file mode 100644
index 0000000000..4c448c2e41
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c
@@ -0,0 +1,144 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Wade Brown
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "cpu.h"
20#include "adc-target.h"
21#include "kernel.h"
22
23
24
25static unsigned short adc_readings[NUM_ADC_CHANNELS];
26
27/* prototypes */
28static unsigned short __adc_read(int channel);
29static void adc_tick(void);
30
31
32
33void adc_init(void)
34{
35 int i;
36
37 /* Turn on the ADC PCLK */
38 CLKCON |= (1<<15);
39
40 /* Set channel 0, normal mode, disable "start by read" */
41 ADCCON &= ~(0x3F);
42
43 /* No start delay. Use normal conversion mode. */
44 ADCDLY = 0x1;
45
46 /* Set and enable the prescaler */
47 ADCCON = (ADCCON & ~(0xff<<6)) | (0x19<<6);
48 ADCCON |= (1<<14);
49
50 /* prefill the adc channels */
51 for (i = 0; i < NUM_ADC_CHANNELS; i++)
52 {
53 adc_readings[i] = __adc_read(i);
54 }
55
56 /* start at zero so when the tick starts it is at zero */
57 adc_readings[0] = __adc_read(0);
58
59 /* attach the adc reading to the tick */
60 tick_add_task(adc_tick);
61
62
63}
64
65
66
67/* Called to get the recent ADC reading */
68inline unsigned short adc_read(int channel)
69{
70 return adc_readings[channel];
71}
72
73
74
75/**
76 * Read the ADC by polling
77 * @param channel The ADC channel to read
78 * @return 10bit reading from ADC channel or ADC_READ_ERROR if timeout
79 */
80static unsigned short __adc_read(int channel)
81{
82 int i;
83
84 /* Set the channel */
85 ADCCON = (ADCCON & ~(0x7<<3)) | (channel<<3);
86
87 /* Start the conversion process */
88 ADCCON |= 0x1;
89
90 /* Wait for a low Enable_start */
91 for (i = 20000;;) {
92 if(0 == (ADCCON & 0x1)) {
93 break;
94 }
95 else {
96 i--;
97 if (0 == i) {
98 /* Ran out of time */
99 return ADC_READ_ERROR;
100 }
101 }
102 }
103
104 /* Wait for high End_of_Conversion */
105 for(i = 20000;;) {
106 if(ADCCON & (1<<15)) {
107 break;
108 }
109 else {
110 i--;
111 if(0 == i) {
112 /* Ran out of time */
113 return ADC_READ_ERROR;
114 }
115 }
116 }
117
118 return (ADCDAT0 & 0x3ff);
119}
120
121
122
123/* add this to the tick so that the ADC converts are done in the background */
124static void adc_tick(void)
125{
126 static unsigned channel;
127
128 /* Check if the End Of Conversion is set */
129 if (ADCCON & (1<<15))
130 {
131 adc_readings[channel] = (ADCDAT0 & 0x3FF);
132 if (++channel >= NUM_ADC_CHANNELS)
133 {
134 channel = 0;
135 }
136
137 /* setup the next conversion and start it*/
138 ADCCON = (ADCCON & ~(0x7<<3)) | (channel<<3) | 0x01;
139 }
140}
141
142
143
144
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/adc-target.h b/firmware/target/arm/s3c2440/gigabeat-fx/adc-target.h
new file mode 100644
index 0000000000..8d2beaf320
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/adc-target.h
@@ -0,0 +1,37 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Barry Wardell
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef _ADC_TARGET_H_
20#define _ADC_TARGET_H_
21
22/* only two channels used by the Gigabeat */
23#define NUM_ADC_CHANNELS 2
24
25#define ADC_BATTERY 0
26#define ADC_HPREMOTE 1
27#define ADC_UNKNOWN_3 2
28#define ADC_UNKNOWN_4 3
29#define ADC_UNKNOWN_5 4
30#define ADC_UNKNOWN_6 5
31#define ADC_UNKNOWN_7 6
32#define ADC_UNKNOWN_8 7
33
34#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
35#define ADC_READ_ERROR 0xFFFF
36
37#endif
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c
new file mode 100644
index 0000000000..bc2b53d776
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c
@@ -0,0 +1,143 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id $
9 *
10 * Copyright (C) 2006,2007 by Marcoen Hirschberg
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "config.h"
20#include "cpu.h"
21#include <stdbool.h>
22#include "kernel.h"
23#include "system.h"
24#include "power.h"
25#include "panic.h"
26#include "pcf50606.h"
27#include "ata-target.h"
28#include "mmu-meg-fx.h"
29#include "backlight-target.h"
30
31/* ARESET on C7C68300 and RESET on ATA interface (Active Low) */
32#define ATA_RESET_ENABLE GPGDAT &= ~(1 << 10)
33#define ATA_RESET_DISABLE GPGDAT |= (1 << 10)
34
35/* ATA_EN on C7C68300 */
36#define USB_ATA_ENABLE GPBDAT |= (1 << 5)
37#define USB_ATA_DISABLE GPBDAT &= ~(1 << 5)
38
39void ata_reset(void)
40{
41 ATA_RESET_ENABLE;
42 sleep(1); /* > 25us */
43 ATA_RESET_DISABLE;
44 sleep(1); /* > 2ms */
45}
46
47/* This function is called before enabling the USB bus */
48void ata_enable(bool on)
49{
50 if(on)
51 USB_ATA_DISABLE;
52 else
53 USB_ATA_ENABLE;
54
55 GPBCON=( GPGCON&~(1<<11) ) | (1<<10); /* Make the pin an output */
56// GPBUP|=1<<5; /* Disable pullup in SOC as we are now driving */
57}
58
59bool ata_is_coldstart(void)
60{
61 /* Check the pin configuration - return true when pin is unconfigured */
62 return (GPGCON & 0x00300000) == 0;
63}
64
65void ata_device_init(void)
66{
67 /* ATA reset */
68 ATA_RESET_DISABLE; /* Set the pin to disable an active low reset */
69 GPGCON=( GPGCON&~(1<<21) ) | (1<<20); /* Make the pin an output */
70 GPGUP |= 1<<10; /* Disable pullup in SOC as we are now driving */
71}
72
73#if !defined(BOOTLOADER)
74void copy_read_sectors(unsigned char* buf, int wordcount)
75{
76 __buttonlight_trigger();
77
78 /* Unaligned transfer - slow copy */
79 if ( (unsigned long)buf & 1)
80 { /* not 16-bit aligned, copy byte by byte */
81 unsigned short tmp = 0;
82 unsigned char* bufend = buf + wordcount*2;
83 do
84 {
85 tmp = ATA_DATA;
86 *buf++ = tmp & 0xff; /* I assume big endian */
87 *buf++ = tmp >> 8; /* and don't use the SWAB16 macro */
88 } while (buf < bufend); /* tail loop is faster */
89 return;
90 }
91 /* This should never happen, but worth watching for */
92 if(wordcount > (1 << 18))
93 panicf("atd-meg-fx.c: copy_read_sectors: too many sectors per read!");
94
95//#define GIGABEAT_DEBUG_ATA
96#ifdef GIGABEAT_DEBUG_ATA
97 static int line = 0;
98 static char str[256];
99 snprintf(str, sizeof(str), "ODD DMA to %08x, %d", buf, wordcount);
100 lcd_puts(10, line, str);
101 line = (line+1) % 32;
102 lcd_update();
103#endif
104 /* Reset the channel */
105 DMASKTRIG0 |= 4;
106 /* Wait for DMA controller to be ready */
107 while(DMASKTRIG0 & 0x2)
108 ;
109 while(DSTAT0 & (1 << 20))
110 ;
111 /* Source is ATA_DATA, on AHB Bus, Fixed */
112 DISRC0 = (int) 0x18000000;
113 DISRCC0 = 0x1;
114 /* Dest mapped to physical address, on AHB bus, increment */
115 DIDST0 = (int) buf;
116 if(DIDST0 < 0x30000000)
117 DIDST0 += 0x30000000;
118 DIDSTC0 = 0;
119
120 /* DACK/DREQ Sync to AHB, Int on Transfer complete, Whole service, No reload, 16-bit transfers */
121 DCON0 = ((1 << 30) | (1<< 29) | (1<<27) | (1<<22) | (1<<20)) | wordcount;
122
123 /* Activate the channel */
124 DMASKTRIG0 = 0x2;
125
126 invalidate_dcache_range((void *)buf, wordcount*2);
127
128 INTMSK &= ~(1<<17); /* unmask the interrupt */
129 SRCPND = (1<<17); /* clear any pending interrupts */
130 /* Start DMA */
131 DMASKTRIG0 |= 0x1;
132
133 /* Wait for transfer to complete */
134 while((DSTAT0 & 0x000fffff))
135 yield();
136 /* Dump cache for the buffer */
137}
138#endif
139void dma0(void)
140{
141}
142
143
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/ata-target.h b/firmware/target/arm/s3c2440/gigabeat-fx/ata-target.h
new file mode 100644
index 0000000000..95e3e110f2
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/ata-target.h
@@ -0,0 +1,70 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef ATA_TARGET_H
20#define ATA_TARGET_H
21
22/* Plain C read & write loops */
23#define PREFER_C_READING
24#define PREFER_C_WRITING
25#if !defined(BOOTLOADER)
26#define ATA_OPTIMIZED_READING
27void copy_read_sectors(unsigned char* buf, int wordcount);
28#endif
29
30#define ATA_IOBASE 0x18000000
31#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE)))
32#define ATA_ERROR (*((volatile unsigned char*)(ATA_IOBASE + 0x02)))
33#define ATA_NSECTOR (*((volatile unsigned char*)(ATA_IOBASE + 0x04)))
34#define ATA_SECTOR (*((volatile unsigned char*)(ATA_IOBASE + 0x06)))
35#define ATA_LCYL (*((volatile unsigned char*)(ATA_IOBASE + 0x08)))
36#define ATA_HCYL (*((volatile unsigned char*)(ATA_IOBASE + 0x0A)))
37#define ATA_SELECT (*((volatile unsigned char*)(ATA_IOBASE + 0x0C)))
38#define ATA_COMMAND (*((volatile unsigned char*)(ATA_IOBASE + 0x0E)))
39#define ATA_CONTROL (*((volatile unsigned char*)(0x20000000 + 0x1C)))
40
41#define STATUS_BSY 0x80
42#define STATUS_RDY 0x40
43#define STATUS_DF 0x20
44#define STATUS_DRQ 0x08
45#define STATUS_ERR 0x01
46#define ERROR_ABRT 0x04
47
48#define WRITE_PATTERN1 0xa5
49#define WRITE_PATTERN2 0x5a
50#define WRITE_PATTERN3 0xaa
51#define WRITE_PATTERN4 0x55
52
53#define READ_PATTERN1 0xa5
54#define READ_PATTERN2 0x5a
55#define READ_PATTERN3 0xaa
56#define READ_PATTERN4 0x55
57
58#define READ_PATTERN1_MASK 0xff
59#define READ_PATTERN2_MASK 0xff
60#define READ_PATTERN3_MASK 0xff
61#define READ_PATTERN4_MASK 0xff
62
63#define SET_REG(reg,val) reg = (val)
64#define SET_16BITREG(reg,val) reg = (val)
65
66void ata_reset(void);
67void ata_device_init(void);
68bool ata_is_coldstart(void);
69
70#endif
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c
new file mode 100644
index 0000000000..a1b6a8a583
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c
@@ -0,0 +1,692 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "config.h"
20#include "cpu.h"
21#include "system.h"
22#include "backlight-target.h"
23#include "backlight.h"
24#include "lcd.h"
25#include "sc606-meg-fx.h"
26#include "power.h"
27
28
29#define FLICKER_PERIOD 15
30#define BUTTONLIGHT_MENU (SC606_LED_B1)
31#define BUTTONLIGHT_ALL (SC606_LED_B1 | SC606_LED_B2 | SC606_LED_C1 | SC606_LED_C2)
32
33static void led_control_service(void);
34static unsigned short backlight_brightness;
35static unsigned short backlight_current;
36static unsigned short backlight_target;
37static unsigned short time_til_fade;
38static unsigned short fade_interval;
39static unsigned short initial_tick_delay;
40static unsigned char backlight_leds;
41
42static enum backlight_states
43{
44 BACKLIGHT_CONTROL_IDLE,
45 BACKLIGHT_CONTROL_OFF,
46 BACKLIGHT_CONTROL_ON,
47 BACKLIGHT_CONTROL_SET,
48 BACKLIGHT_CONTROL_FADE_OFF,
49 BACKLIGHT_CONTROL_FADE_ON,
50 BACKLIGHT_CONTROL_FADE_ON_FROM_OFF
51} backlight_control;
52
53
54
55enum buttonlight_states
56{
57 /* turn button lights off */
58 BUTTONLIGHT_MODE_OFF_ENTRY,
59 BUTTONLIGHT_MODE_OFF,
60
61 /* turns button lights on to setting */
62 BUTTONLIGHT_MODE_ON_ENTRY,
63 BUTTONLIGHT_MODE_ON,
64
65 /* turns button lights on to minimum */
66 BUTTONLIGHT_MODE_FAINT_ENTRY,
67 BUTTONLIGHT_MODE_FAINT,
68
69 /* allows button lights to flicker when triggered */
70 BUTTONLIGHT_MODE_FLICKER_ENTRY,
71 BUTTONLIGHT_MODE_FLICKER,
72 BUTTONLIGHT_MODE_FLICKERING,
73
74 /* button lights solid */
75 BUTTONLIGHT_MODE_SOLID_ENTRY,
76 BUTTONLIGHT_MODE_SOLID,
77
78 /* button light charing */
79 BUTTONLIGHT_MODE_CHARGING_ENTRY,
80 BUTTONLIGHT_MODE_CHARGING,
81 BUTTONLIGHT_MODE_CHARGING_WAIT,
82
83 /* internal use only */
84 BUTTONLIGHT_HELPER_SET,
85 BUTTONLIGHT_HELPER_SET_FINAL,
86 BUTTONLIGHT_MODE_STOP,
87
88 /* buttonlights follow the backlight settings */
89 BUTTONLIGHT_MODE_FOLLOW_ENTRY,
90 BUTTONLIGHT_MODE_FOLLOW,
91};
92
93
94
95static char buttonlight_leds;
96static unsigned short buttonlight_setting;
97static unsigned short buttonlight_current;
98static unsigned char buttonlight_selected;
99static enum buttonlight_states buttonlight_state;
100static enum buttonlight_states buttonlight_saved_state;
101static unsigned short buttonlight_flickering;
102
103static unsigned short buttonlight_trigger_now;
104static unsigned short buttonlight_trigger_brightness;
105
106
107
108static unsigned short charging_led_index;
109static unsigned short buttonlight_charging_counter;
110
111#define CHARGING_LED_COUNT 60
112unsigned char charging_leds[] = { 0x00, 0x20, 0x38, 0x3C };
113
114
115
116bool __backlight_init(void)
117{
118 backlight_control = BACKLIGHT_CONTROL_IDLE;
119
120 backlight_current = DEFAULT_BRIGHTNESS_SETTING;
121
122 buttonlight_state = BUTTONLIGHT_MODE_OFF;
123
124 buttonlight_selected = 0x04;
125
126 /* delay 4 seconds before any fading */
127 initial_tick_delay = 400;
128 /* put the led control on the tick list */
129 tick_add_task(led_control_service);
130
131 return true;
132}
133
134
135
136void __backlight_on(void)
137{
138 /* now go turn the backlight on */
139 backlight_control = BACKLIGHT_CONTROL_ON;
140}
141
142
143
144void __backlight_off(void)
145{
146 backlight_control = BACKLIGHT_CONTROL_OFF;
147}
148
149
150
151/* Assumes that the backlight has been initialized */
152void __backlight_set_brightness(int brightness)
153{
154 /* stop the interrupt from messing us up */
155 backlight_control = BACKLIGHT_CONTROL_IDLE;
156
157 backlight_brightness = brightness + 1;
158
159 /* only set the brightness if it is different from the current */
160 if (backlight_brightness != backlight_current)
161 {
162 backlight_control = BACKLIGHT_CONTROL_SET;
163 }
164}
165
166
167
168/* only works if the buttonlight mode is set to triggered mode */
169void __buttonlight_trigger(void)
170{
171 buttonlight_trigger_now = 1;
172}
173
174
175
176
177/* map the mode from the command into the state machine entries */
178void __buttonlight_mode(enum buttonlight_mode mode,
179 enum buttonlight_selection selection,
180 unsigned short brightness)
181{
182 /* choose stop to setup mode */
183 buttonlight_state = BUTTONLIGHT_MODE_STOP;
184
185
186 /* clip brightness */
187 if (brightness > MAX_BRIGHTNESS_SETTING)
188 {
189 brightness = MAX_BRIGHTNESS_SETTING;
190 }
191
192 brightness++;
193
194 /* Select which LEDs to use */
195 switch (selection)
196 {
197 case BUTTONLIGHT_LED_ALL:
198 buttonlight_selected = BUTTONLIGHT_ALL;
199 break;
200
201 case BUTTONLIGHT_LED_MENU:
202 buttonlight_selected = BUTTONLIGHT_MENU;
203 break;
204 }
205
206 /* which mode to use */
207 switch (mode)
208 {
209 case BUTTONLIGHT_OFF:
210 buttonlight_state = BUTTONLIGHT_MODE_OFF_ENTRY;
211 break;
212
213 case BUTTONLIGHT_ON:
214 buttonlight_trigger_brightness = brightness;
215 buttonlight_state = BUTTONLIGHT_MODE_ON_ENTRY;
216 break;
217
218 /* faint is just a quick way to set ON to 1 */
219 case BUTTONLIGHT_FAINT:
220 buttonlight_trigger_brightness = 1;
221 buttonlight_state = BUTTONLIGHT_MODE_ON_ENTRY;
222 break;
223
224 case BUTTONLIGHT_FLICKER:
225 buttonlight_trigger_brightness = brightness;
226 buttonlight_state = BUTTONLIGHT_MODE_FLICKER_ENTRY;
227 break;
228
229 case BUTTONLIGHT_SIGNAL:
230 buttonlight_trigger_brightness = brightness;
231 buttonlight_state = BUTTONLIGHT_MODE_SOLID_ENTRY;
232 break;
233
234 case BUTTONLIGHT_FOLLOW:
235 buttonlight_state = BUTTONLIGHT_MODE_FOLLOW_ENTRY;
236 break;
237
238 case BUTTONLIGHT_CHARGING:
239 buttonlight_state = BUTTONLIGHT_MODE_CHARGING_ENTRY;
240 break;
241
242 default:
243 return; /* unknown mode */
244 }
245
246
247}
248
249
250
251/*
252 * The button lights have 'modes' of operation. Each mode must setup and
253 * execute its own operation - taking care that this is all done in an ISR.
254 *
255 */
256
257
258
259/* led_control_service runs in interrupt context - be brief!
260 * This service is called once per interrupt timer tick - 100 times a second.
261 *
262 * There should be at most only one i2c operation per call - if more are need
263 * the calls should be spread across calls.
264 *
265 * Putting all led servicing in one thread means that we wont step on any
266 * i2c operations - they are all serialized here in the ISR tick. It also
267 * insures that we get called at equal timing for good visual effect.
268 *
269 * The buttonlight service runs only after all backlight services have finished.
270 * Fading the buttonlights is possible, but not recommended because of the
271 * additional calls needed during the ISR
272 */
273static void led_control_service(void)
274{
275 if(initial_tick_delay) {
276 initial_tick_delay--;
277 return;
278 }
279 switch (backlight_control)
280 {
281 case BACKLIGHT_CONTROL_IDLE:
282 switch (buttonlight_state)
283 {
284 case BUTTONLIGHT_MODE_STOP: break;
285
286 /* Buttonlight mode: OFF */
287 case BUTTONLIGHT_MODE_OFF_ENTRY:
288 if (buttonlight_current)
289 {
290 buttonlight_leds = 0x00;
291 sc606_write(SC606_REG_CONF, backlight_leds);
292 buttonlight_current = 0;
293 }
294 buttonlight_state = BUTTONLIGHT_MODE_OFF;
295 break;
296
297 case BUTTONLIGHT_MODE_OFF:
298 break;
299
300
301 /* button mode: CHARGING - show charging sequence */
302 case BUTTONLIGHT_MODE_CHARGING_ENTRY:
303 /* start turned off */
304 buttonlight_leds = 0x00;
305 sc606_write(SC606_REG_CONF, backlight_leds);
306 buttonlight_current = 0;
307
308 /* temporary save for the next mode - then to do settings */
309 buttonlight_setting = DEFAULT_BRIGHTNESS_SETTING;
310 buttonlight_saved_state = BUTTONLIGHT_MODE_CHARGING_WAIT;
311 buttonlight_state = BUTTONLIGHT_HELPER_SET;
312 break;
313
314
315 case BUTTONLIGHT_MODE_CHARGING:
316 if (--buttonlight_charging_counter == 0)
317 {
318 /* change led */
319 if (charging_state())
320 {
321 buttonlight_leds = charging_leds[charging_led_index];
322 if (++charging_led_index >= sizeof(charging_leds))
323 {
324 charging_led_index = 0;
325 }
326 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
327 buttonlight_charging_counter = CHARGING_LED_COUNT;
328 }
329 else
330 {
331 buttonlight_state = BUTTONLIGHT_MODE_CHARGING_ENTRY;
332 }
333 }
334 break;
335
336 /* wait for the charget to be plugged in */
337 case BUTTONLIGHT_MODE_CHARGING_WAIT:
338 if (charging_state())
339 {
340 charging_led_index = 0;
341 buttonlight_charging_counter = CHARGING_LED_COUNT;
342 buttonlight_state = BUTTONLIGHT_MODE_CHARGING;
343 }
344 break;
345
346
347 /* Buttonlight mode: FOLLOW - try to stay current with backlight
348 * since this runs in the idle of the backlight it will not really
349 * follow in real time
350 */
351 case BUTTONLIGHT_MODE_FOLLOW_ENTRY:
352 /* case 1 - backlight on, but buttonlight is off */
353 if (backlight_current)
354 {
355 /* Turn the buttonlights on */
356 buttonlight_leds = buttonlight_selected;
357 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
358
359 /* temporary save for the next mode - then to do settings */
360 buttonlight_setting = backlight_current;
361 buttonlight_saved_state = BUTTONLIGHT_MODE_FOLLOW;
362 buttonlight_state = BUTTONLIGHT_HELPER_SET;
363 }
364 /* case 2 - backlight off, but buttonlight is on */
365 else
366 {
367 buttonlight_current = 0;
368 buttonlight_leds = 0x00;
369 sc606_write(SC606_REG_CONF, backlight_leds);
370 buttonlight_state = BUTTONLIGHT_MODE_FOLLOW;
371 }
372 break;
373
374 case BUTTONLIGHT_MODE_FOLLOW:
375 if (buttonlight_current != backlight_current)
376 {
377 /* case 1 - backlight on, but buttonlight is off */
378 if (backlight_current)
379 {
380 if (0 == buttonlight_current)
381 {
382 /* Turn the buttonlights on */
383 buttonlight_leds = buttonlight_selected;
384 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
385 }
386
387 /* temporary save for the next mode - then to do settings */
388 buttonlight_setting = backlight_current;
389 buttonlight_saved_state = BUTTONLIGHT_MODE_FOLLOW;
390 buttonlight_state = BUTTONLIGHT_HELPER_SET;
391 }
392
393 /* case 2 - backlight off, but buttonlight is on */
394 else
395 {
396 buttonlight_current = 0;
397 buttonlight_leds = 0x00;
398 sc606_write(SC606_REG_CONF, backlight_leds);
399 }
400
401 }
402 break;
403
404
405
406 /* Buttonlight mode: ON - stays at the set brightness */
407 case BUTTONLIGHT_MODE_ON_ENTRY:
408 buttonlight_leds = buttonlight_selected;
409 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
410
411 /* temporary save for the next mode - then to do settings */
412 buttonlight_setting = buttonlight_trigger_brightness;
413 buttonlight_saved_state = BUTTONLIGHT_MODE_ON;
414 buttonlight_state = BUTTONLIGHT_HELPER_SET;
415 break;
416
417 case BUTTONLIGHT_MODE_ON:
418 break;
419
420
421
422 /* Buttonlight mode: FLICKER */
423 case BUTTONLIGHT_MODE_FLICKER_ENTRY:
424 /* already on? turn it off */
425 if (buttonlight_current)
426 {
427 buttonlight_leds = 0x00;
428 sc606_write(SC606_REG_CONF, backlight_leds);
429 buttonlight_current = 0;
430 }
431
432 /* set the brightness if not already set */
433 if (buttonlight_current != buttonlight_trigger_brightness)
434 {
435 /* temporary save for the next mode - then to do settings */
436 buttonlight_setting = buttonlight_trigger_brightness;
437 buttonlight_saved_state = BUTTONLIGHT_MODE_FLICKER;
438 buttonlight_state = BUTTONLIGHT_HELPER_SET;
439 }
440 else buttonlight_state = BUTTONLIGHT_MODE_FLICKER;
441 break;
442
443
444 case BUTTONLIGHT_MODE_FLICKER:
445 /* wait for the foreground to trigger flickering */
446 if (buttonlight_trigger_now)
447 {
448 /* turn them on */
449 buttonlight_leds = buttonlight_selected;
450 buttonlight_current = buttonlight_setting;
451 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
452
453 /* reset the trigger and go flicker the LEDs */
454 buttonlight_trigger_now = 0;
455 buttonlight_flickering = FLICKER_PERIOD;
456 buttonlight_state = BUTTONLIGHT_MODE_FLICKERING;
457 }
458 break;
459
460
461 case BUTTONLIGHT_MODE_FLICKERING:
462 /* flicker the LEDs for as long as we get triggered */
463 if (buttonlight_flickering)
464 {
465 /* turn the leds off if they are on */
466 if (buttonlight_current)
467 {
468 buttonlight_leds = 0x00;
469 sc606_write(SC606_REG_CONF, backlight_leds);
470 buttonlight_current = 0;
471 }
472
473 buttonlight_flickering--;
474 }
475 else
476 {
477 /* is flickering triggered again? */
478 if (!buttonlight_trigger_now)
479 {
480 /* completed a cycle - no new triggers - go back and wait */
481 buttonlight_state = BUTTONLIGHT_MODE_FLICKER;
482 }
483 else
484 {
485 /* reset flickering */
486 buttonlight_trigger_now = 0;
487 buttonlight_flickering = FLICKER_PERIOD;
488
489 /* turn buttonlights on */
490 buttonlight_leds = buttonlight_selected;
491 buttonlight_current = buttonlight_setting;
492 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
493 }
494 }
495 break;
496
497
498 /* Buttonlight mode: SIGNAL / SOLID */
499 case BUTTONLIGHT_MODE_SOLID_ENTRY:
500 /* already on? turn it off */
501 if (buttonlight_current)
502 {
503 buttonlight_leds = 0x00;
504 sc606_write(SC606_REG_CONF, backlight_leds);
505 buttonlight_current = 0;
506 }
507
508 /* set the brightness if not already set */
509 /* temporary save for the next mode - then to do settings */
510 buttonlight_setting = buttonlight_trigger_brightness;
511 buttonlight_saved_state = BUTTONLIGHT_MODE_SOLID;
512 buttonlight_state = BUTTONLIGHT_HELPER_SET;
513 break;
514
515
516 case BUTTONLIGHT_MODE_SOLID:
517 /* wait for the foreground to trigger */
518 if (buttonlight_trigger_now)
519 {
520 /* turn them on if not already on */
521 if (0 == buttonlight_current)
522 {
523 buttonlight_leds = buttonlight_selected;
524 buttonlight_current = buttonlight_setting;
525 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
526 }
527
528 /* reset the trigger */
529 buttonlight_trigger_now = 0;
530 }
531 else
532 {
533 if (buttonlight_current)
534 {
535 buttonlight_leds = 0x00;
536 sc606_write(SC606_REG_CONF, backlight_leds);
537 buttonlight_current = 0;
538 }
539 }
540 break;
541
542
543 /* set the brightness for the buttonlights - takes 2 passes */
544 case BUTTONLIGHT_HELPER_SET:
545 sc606_write(SC606_REG_B, buttonlight_setting-1);
546 buttonlight_state = BUTTONLIGHT_HELPER_SET_FINAL;
547 break;
548
549 case BUTTONLIGHT_HELPER_SET_FINAL:
550 sc606_write(SC606_REG_C, buttonlight_setting-1);
551 buttonlight_current = buttonlight_setting;
552 buttonlight_state = buttonlight_saved_state;
553 break;
554
555 default:
556 break;
557
558 }
559 break;
560
561
562 case BACKLIGHT_CONTROL_FADE_ON_FROM_OFF:
563 backlight_leds = 0x03;
564 sc606_write(SC606_REG_CONF, 0x03 | buttonlight_leds);
565 backlight_control = BACKLIGHT_CONTROL_FADE_ON;
566 break;
567
568
569 case BACKLIGHT_CONTROL_OFF:
570 backlight_current = 0;
571 backlight_leds = 0x00;
572 sc606_write(SC606_REG_CONF, buttonlight_leds);
573 backlight_control = BACKLIGHT_CONTROL_IDLE;
574
575 break;
576
577
578 case BACKLIGHT_CONTROL_ON:
579 backlight_leds = 0x03;
580 sc606_write(SC606_REG_CONF, 0x03 | buttonlight_leds);
581 backlight_current = backlight_brightness;
582 backlight_control = BACKLIGHT_CONTROL_IDLE;
583 break;
584
585
586 case BACKLIGHT_CONTROL_SET:
587 /* The SC606 LED driver can set the brightness in 64 steps */
588 sc606_write(SC606_REG_A, backlight_brightness-1);
589
590 /* if we were turned off - turn the backlight on */
591 if (backlight_current)
592 {
593 backlight_current = backlight_brightness;
594 backlight_control = BACKLIGHT_CONTROL_IDLE;
595 }
596 else
597 {
598 backlight_control = BACKLIGHT_CONTROL_ON;
599 }
600 break;
601
602
603 case BACKLIGHT_CONTROL_FADE_ON:
604 if (--time_til_fade) return;
605
606 /* The SC606 LED driver can set the brightness in 64 steps */
607 sc606_write(SC606_REG_A, backlight_current++);
608
609 /* have we hit the target? */
610 if (backlight_current == backlight_target)
611 {
612 backlight_control = BACKLIGHT_CONTROL_IDLE;
613 }
614 else
615 {
616 time_til_fade = fade_interval;
617 }
618 break;
619
620
621 case BACKLIGHT_CONTROL_FADE_OFF:
622 if (--time_til_fade) return;
623
624 /* The SC606 LED driver can set the brightness in 64 steps */
625 sc606_write(SC606_REG_A, --backlight_current);
626
627 /* have we hit the target? */
628 if (backlight_current == backlight_target)
629 {
630 if (backlight_current)
631 {
632 backlight_control = BACKLIGHT_CONTROL_IDLE;
633 }
634 else
635 {
636 backlight_control = BACKLIGHT_CONTROL_OFF;
637 }
638
639 }
640 else
641 {
642 time_til_fade = fade_interval;
643 }
644 break;
645 }
646
647 if(backlight_current)
648 lcd_enable(true);
649 else
650 lcd_enable(false);
651}
652
653
654
655
656
657void __backlight_dim(bool dim_now)
658{
659 unsigned short target;
660
661 /* dont let the interrupt tick happen */
662 backlight_control = BACKLIGHT_CONTROL_IDLE;
663
664 target = (dim_now == true) ? 0 : backlight_brightness;
665
666 /* only try and fade if the target is different */
667 if (backlight_current != target)
668 {
669 backlight_target = target;
670
671 if (backlight_current > backlight_target)
672 {
673 time_til_fade = fade_interval = 4;
674 backlight_control = BACKLIGHT_CONTROL_FADE_OFF;
675 }
676 else
677 {
678 time_til_fade = fade_interval = 1;
679 if (backlight_current)
680 {
681 backlight_control = BACKLIGHT_CONTROL_FADE_ON;
682 }
683 else
684 {
685 backlight_control = BACKLIGHT_CONTROL_FADE_ON_FROM_OFF;
686 }
687 }
688 }
689
690}
691
692
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/backlight-target.h b/firmware/target/arm/s3c2440/gigabeat-fx/backlight-target.h
new file mode 100644
index 0000000000..5f92cee935
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/backlight-target.h
@@ -0,0 +1,87 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef BACKLIGHT_TARGET_H
20#define BACKLIGHT_TARGET_H
21
22
23/* select the led */
24enum buttonlight_selection
25{
26 /* all leds */
27 BUTTONLIGHT_LED_ALL,
28
29 /* only the menu/power led (two buttons for one LED) */
30 BUTTONLIGHT_LED_MENU
31};
32
33
34/* Use these to set the buttonlight mode */
35enum buttonlight_mode
36{
37 /* ON follows the setting */
38 BUTTONLIGHT_ON,
39
40 /* buttonlights always off */
41 BUTTONLIGHT_OFF,
42
43 /* buttonlights always on but set at lowest brightness */
44 BUTTONLIGHT_FAINT,
45
46 /* buttonlights flicker when triggered - continues to flicker
47 * even if the flicker is still asserted.
48 */
49 BUTTONLIGHT_FLICKER,
50
51 /* buttonlights solid for as long as triggered */
52 BUTTONLIGHT_SIGNAL,
53
54 /* buttonlights follow backlight */
55 BUTTONLIGHT_FOLLOW,
56
57 /* buttonlights show battery charging */
58 BUTTONLIGHT_CHARGING,
59};
60
61
62/* Call this to flicker or signal the button lights. Only is effective for
63 * modes that take a trigger input.
64 */
65void __buttonlight_trigger(void);
66
67
68/* select which led to use on the button lights. Other combinations are
69 * possible, but don't look very good.
70 */
71
72/* map the mode from the command into the state machine entries */
73/* See enum buttonlight_mode for available functions */
74void __buttonlight_mode(enum buttonlight_mode mode,
75 enum buttonlight_selection selection,
76 unsigned short brightness);
77
78
79bool __backlight_init(void);
80void __backlight_on(void);
81void __backlight_off(void);
82void __backlight_set_brightness(int val);
83
84/* true: backlight fades off - false: backlight fades on */
85void __backlight_dim(bool dim);
86
87#endif
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/button-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/button-meg-fx.c
new file mode 100644
index 0000000000..71d45c385c
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/button-meg-fx.c
@@ -0,0 +1,157 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <stdlib.h>
21#include "config.h"
22#include "cpu.h"
23#include "system.h"
24#include "button.h"
25#include "kernel.h"
26#include "backlight.h"
27#include "adc.h"
28#include "system.h"
29#include "backlight-target.h"
30
31static bool headphones_detect;
32static bool hold_button = false;
33
34static int const remote_buttons[] =
35{
36 BUTTON_NONE, /* Headphones connected - remote disconnected */
37 BUTTON_SELECT,
38 BUTTON_MENU, /* could be changed to BUTTON_A */
39 BUTTON_LEFT,
40 BUTTON_RIGHT,
41 BUTTON_UP, /* could be changed to BUTTON_VOL_UP */
42 BUTTON_DOWN, /* could be changed to BUTTON_VOL_DOWN */
43 BUTTON_NONE, /* Remote control attached - no buttons pressed */
44 BUTTON_NONE, /* Nothing in the headphone socket */
45};
46
47
48
49
50
51void button_init_device(void)
52{
53 /* Power, Remote Play & Hold switch */
54}
55
56
57
58inline bool button_hold(void)
59{
60 return (GPGDAT & (1 << 15));
61}
62
63
64
65int button_read_device(void)
66{
67 int touchpad;
68 int buttons;
69 static int lastbutton;
70 unsigned short remote_adc;
71 int btn = BUTTON_NONE;
72 bool hold_button_old;
73
74 /* normal buttons */
75 hold_button_old = hold_button;
76 hold_button = button_hold();
77
78#ifndef BOOTLOADER
79 /* give BL notice if HB state chaged */
80 if (hold_button != hold_button_old)
81 backlight_hold_changed(hold_button);
82#endif
83
84 /* See header for ADC values when remote control buttons are pressed */
85 /* Only one button can be sensed at a time on the remote. */
86 /* Need to filter the remote button because the ADC is so fast */
87 remote_adc = adc_read(ADC_HPREMOTE);
88 btn = remote_buttons[(remote_adc + 64) / 128];
89 if (btn != lastbutton)
90 {
91 /* if the buttons dont agree twice in a row, then its none */
92 lastbutton = btn;
93 btn = BUTTON_NONE;
94 }
95
96 /* Check for hold first - exit if asserted with no button pressed */
97 if (hold_button)
98 return btn;
99
100 /* the side buttons - Check before doing all of the work on each bit */
101 buttons = GPGDAT & 0x1F;
102 if (buttons)
103 {
104 if (buttons & (1 << 0))
105 btn |= BUTTON_POWER;
106
107 if (buttons & (1 << 1))
108 btn |= BUTTON_MENU;
109
110 if (buttons & (1 << 2))
111 btn |= BUTTON_VOL_UP;
112
113 if (buttons & (1 << 3))
114 btn |= BUTTON_VOL_DOWN;
115
116 if (buttons & (1 << 4))
117 btn |= BUTTON_A;
118 }
119
120 /* the touchpad */
121 touchpad = GPJDAT & 0x10C9;
122 if (touchpad)
123 {
124 if (touchpad & (1 << 0))
125 btn |= BUTTON_UP;
126
127 if (touchpad & (1 << 12))
128 btn |= BUTTON_RIGHT;
129
130 if (touchpad & (1 << 6))
131 btn |= BUTTON_DOWN;
132
133 if (touchpad & (1 << 7))
134 btn |= BUTTON_LEFT;
135
136 if (touchpad & (1 << 3))
137 btn |= BUTTON_SELECT;
138 }
139
140 return btn;
141}
142
143
144
145bool headphones_inserted(void)
146{
147 unsigned short remote_adc = adc_read(ADC_HPREMOTE);
148 if (remote_adc != ADC_READ_ERROR)
149 {
150 /* If there is nothing in the headphone socket, the ADC reads high */
151 if (remote_adc < 940)
152 headphones_detect = true;
153 else
154 headphones_detect = false;
155 }
156 return headphones_detect;
157}
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/button-target.h b/firmware/target/arm/s3c2440/gigabeat-fx/button-target.h
new file mode 100644
index 0000000000..ab68e8050f
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/button-target.h
@@ -0,0 +1,89 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef _BUTTON_TARGET_H_
20#define _BUTTON_TARGET_H_
21
22#include <stdbool.h>
23#include "config.h"
24
25#define HAS_BUTTON_HOLD
26
27bool button_hold(void);
28void button_init_device(void);
29int button_read_device(void);
30
31/* Toshiba Gigabeat specific button codes */
32
33#define BUTTON_POWER 0x00000001
34#define BUTTON_MENU 0x00000002
35
36#define BUTTON_LEFT 0x00000004
37#define BUTTON_RIGHT 0x00000008
38#define BUTTON_UP 0x00000010
39#define BUTTON_DOWN 0x00000020
40
41#define BUTTON_VOL_UP 0x00000040
42#define BUTTON_VOL_DOWN 0x00000080
43
44#define BUTTON_SELECT 0x00000100
45#define BUTTON_A 0x00000200
46
47
48/* Toshiba Gigabeat specific remote button ADC values */
49/* The remote control uses ADC 1 to emulate button pushes
50 Reading (approx) Button HP plugged in? Remote plugged in?
51 0 N/A Yes No
52 125 Play/Pause Cant tell Yes
53 241 Speaker+ Cant tell Yes
54 369 Rewind Cant tell Yes
55 492 Fast Fwd Cant tell Yes
56 616 Vol + Cant tell Yes
57 742 Vol - Cant tell Yes
58 864 None Cant tell Yes
59 1023 N/A No No
60*/
61
62/*
63 Notes:
64
65 Buttons on the remote are translated into equivalent button presses just
66 as if you were pressing them on the Gigabeat itself.
67
68 We cannot tell if the hold is asserted on the remote. The Hold function on
69 the remote is to block the output of the buttons changing.
70
71 Only one button can be sensed at a time. If another is pressed, the button
72 with the lowest reading is dominant. So, if Rewind and Vol + are pressed
73 at the same time, Rewind value is the one that is read.
74*/
75
76
77
78
79#define BUTTON_MAIN (BUTTON_POWER|BUTTON_MENU|BUTTON_LEFT|BUTTON_RIGHT\
80 |BUTTON_UP|BUTTON_DOWN|BUTTON_VOL_UP|BUTTON_VOL_DOWN\
81 |BUTTON_SELECT|BUTTON_A)
82
83
84#define BUTTON_REMOTE 0
85
86#define POWEROFF_BUTTON BUTTON_POWER
87#define POWEROFF_COUNT 10
88
89#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/dma_start.c b/firmware/target/arm/s3c2440/gigabeat-fx/dma_start.c
new file mode 100644
index 0000000000..c1ab6c15cb
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/dma_start.c
@@ -0,0 +1,8 @@
1#include <sys/types.h>
2
3void dma_start(const void* addr, size_t size) {
4 (void) addr;
5 (void) size;
6 //TODO:
7}
8
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c
new file mode 100644
index 0000000000..670d6cd04c
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c
@@ -0,0 +1,134 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "config.h"
20#include "cpu.h"
21#include <stdbool.h>
22#include "kernel.h"
23#include "system.h"
24#include "logf.h"
25#include "debug.h"
26#include "string.h"
27#include "generic_i2c.h"
28
29static void i2c_sda_output(void)
30{
31 GPECON |= (1 << 30);
32}
33
34static void i2c_sda_input(void)
35{
36 GPECON &= ~(3 << 30);
37}
38
39static void i2c_sda_lo(void)
40{
41 GPEDAT &= ~(1 << 15);
42}
43
44static void i2c_sda_hi(void)
45{
46 GPEDAT |= (1 << 15);
47}
48
49static int i2c_sda(void)
50{
51 return GPEDAT & (1 << 15);
52}
53
54static void i2c_scl_output(void)
55{
56 GPECON |= (1 << 28);
57}
58
59static void i2c_scl_input(void)
60{
61 GPECON &= ~(3 << 28);
62}
63
64static void i2c_scl_lo(void)
65{
66 GPEDAT &= ~(1 << 14);
67}
68
69static int i2c_scl(void)
70{
71 return GPEDAT & (1 << 14);
72}
73
74static void i2c_scl_hi(void)
75{
76 i2c_scl_input();
77 while(!i2c_scl());
78 GPEDAT |= (1 << 14);
79 i2c_scl_output();
80}
81
82
83
84static void i2c_delay(void)
85{
86 unsigned _x;
87
88 /* The i2c can clock at 500KHz: 2uS period -> 1uS half period */
89 /* about 30 cycles overhead + X * 7 */
90 /* 300MHz: 1000nS @3.36nS/cyc = 297cyc: X = 38*/
91 /* 100MHz: 1000nS @10nS/cyc = 100cyc : X = 10 */
92 for (_x = 38; _x; _x--)
93 {
94 /* burn CPU cycles */
95 /* gcc makes it an inc loop - check with objdump for asm timing */
96 }
97}
98
99
100
101struct i2c_interface s3c2440_i2c = {
102 0x34, /* Address */
103
104 /* Bit-banged interface definitions */
105 i2c_scl_hi, /* Drive SCL high, might sleep on clk stretch */
106 i2c_scl_lo, /* Drive SCL low */
107 i2c_sda_hi, /* Drive SDA high */
108 i2c_sda_lo, /* Drive SDA low */
109 i2c_sda_input, /* Set SDA as input */
110 i2c_sda_output, /* Set SDA as output */
111 i2c_scl_input, /* Set SCL as input */
112 i2c_scl_output, /* Set SCL as output */
113 i2c_scl, /* Read SCL, returns 0 or nonzero */
114 i2c_sda, /* Read SDA, returns 0 or nonzero */
115
116 i2c_delay, /* START SDA hold time (tHD:SDA) */
117 i2c_delay, /* SDA hold time (tHD:DAT) */
118 i2c_delay, /* SDA setup time (tSU:DAT) */
119 i2c_delay, /* STOP setup time (tSU:STO) */
120 i2c_delay, /* Rep. START setup time (tSU:STA) */
121 i2c_delay, /* SCL high period (tHIGH) */
122};
123
124void i2c_init(void)
125{
126 /* Set GPE15 (SDA) and GPE14 (SCL) to 1 */
127 GPECON = (GPECON & ~(0xF<<28)) | 5<<28;
128 i2c_add_node(&s3c2440_i2c);
129}
130
131void i2c_send(int bus_address, int reg_address, const unsigned char buf)
132{
133 i2c_write_data(bus_address, reg_address, &buf, 1);
134}
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.h b/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.h
new file mode 100644
index 0000000000..cf69230487
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.h
@@ -0,0 +1,22 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20/* chip-specific i2c functions */
21
22void i2c_send(int bus_address, int reg_address, const unsigned char buf);
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
new file mode 100644
index 0000000000..9df90a2344
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
@@ -0,0 +1,25 @@
1#include "kernel.h"
2#include "thread.h"
3
4#include <stdio.h>
5#include "lcd.h"
6
7extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
8
9void timer4(void) {
10 int i;
11 /* Run through the list of tick tasks */
12 for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
13 {
14 if(tick_funcs[i])
15 {
16 tick_funcs[i]();
17 }
18 }
19
20 current_tick++;
21
22 /* following needs to be fixed. */
23 /*wake_up_thread();*/
24}
25
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S
new file mode 100644
index 0000000000..d431c95f29
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-as-meg-fx.S
@@ -0,0 +1,222 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Michael Sevakis
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "config.h"
21#include "cpu.h"
22
23/****************************************************************************
24 * void lcd_write_yuv_420_lines(fb_data *dst,
25 * unsigned char chroma_buf[LCD_HEIGHT/2*3],
26 unsigned char const * const src[3],
27 * int width,
28 * int stride);
29 *
30 * |R| |1.000000 -0.000001 1.402000| |Y'|
31 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
32 * |B| |1.000000 1.772000 0.000000| |Pr|
33 * Scaled, normalized, rounded and tweaked to yield RGB 565:
34 * |R| |74 0 101| |Y' - 16| >> 9
35 * |G| = |74 -24 -51| |Cb - 128| >> 8
36 * |B| |74 128 0| |Cr - 128| >> 9
37 */
38 .section .icode, "ax", %progbits
39 .align 2
40 .global lcd_write_yuv420_lines
41 .type lcd_write_yuv420_lines, %function
42lcd_write_yuv420_lines:
43 @ r0 = dst
44 @ r1 = chroma_buf
45 @ r2 = yuv_src
46 @ r3 = width
47 @ [sp] = stride
48 stmdb sp!, { r4-r12, lr } @ save non-scratch
49 stmdb sp!, { r0, r3 } @ save dst and width
50 mov r14, #74 @ r14 = Y factor
51 ldmia r2, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p
52 @ r5 = yuv_src[1] = Cb_p
53 @ r6 = yuv_src[2] = Cr_p
5410: @ loop line 1 @
55 ldrb r2, [r4], #1 @ r2 = *Y'_p++;
56 ldrb r8, [r5], #1 @ r8 = *Cb_p++;
57 ldrb r11, [r6], #1 @ r11 = *Cr_p++;
58 @
59 @ compute Y
60 sub r2, r2, #16 @ r7 = Y = (Y' - 16)*74
61 mul r7, r2, r14 @
62 @
63 sub r8, r8, #128 @ Cb -= 128
64 sub r11, r11, #128 @ Cr -= 128
65 @
66 mvn r2, #24 @ compute guv
67 mul r10, r2, r8 @ r10 = Cb*-24
68 mvn r2, #51 @
69 mla r10, r2, r11, r10 @ r10 = r10 + Cr*-51
70 @
71 mov r2, #101 @ compute rv
72 mul r9, r11, r2 @ r9 = rv = Cr*101
73 @
74 @ store chromas in line buffer
75 add r8, r8, #2 @ bu = (Cb + 2) >> 2
76 mov r8, r8, asr #2 @
77 strb r8, [r1], #1 @
78 add r9, r9, #256 @ rv = (Cr + 256) >> 9
79 mov r9, r9, asr #9 @
80 strb r9, [r1], #1 @
81 mov r10, r10, asr #8 @ guv >>= 8
82 strb r10, [r1], #1 @
83 @ compute R, G, and B
84 add r2, r8, r7, asr #9 @ r2 = b = (Y >> 9) + bu
85 add r11, r9, r7, asr #9 @ r11 = r = (Y >> 9) + rv
86 add r7, r10, r7, asr #8 @ r7 = g = (Y >> 8) + guv
87 @
88 orr r12, r2, r11 @ check if clamping is needed...
89 orr r12, r12, r7, asr #1 @ ...at all
90 cmp r12, #31 @
91 bls 15f @ no clamp @
92 mov r12, #31 @
93 cmp r12, r2 @ clamp b
94 andlo r2, r12, r2, asr #31 @
95 eorlo r2, r2, r12 @
96 cmp r12, r11 @ clamp r
97 andlo r11, r12, r11, asr #31 @
98 eorlo r11, r11, r12 @
99 cmp r12, r7, asr #1 @ clamp g
100 andlo r7, r12, r7, asr #31 @
101 eorlo r7, r7, r12 @
102 orrlo r7, r7, r7, asl #1 @
10315: @ no clamp @
104 @
105 orr r12, r2, r7, lsl #5 @ r4 |= (g << 5)
106 ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++
107 orr r12, r12, r11, lsl #11 @ r4 = b | (r << 11)
108 strh r12, [r0], #240 @ store pixel
109 @
110 sub r2, r2, #16 @ r7 = Y = (Y' - 16)*74
111 mul r7, r2, r14 @ next Y
112 @ compute R, G, and B
113 add r2, r8, r7, asr #9 @ r2 = b = (Y >> 9) + bu
114 add r11, r9, r7, asr #9 @ r11 = r = (Y >> 9) + rv
115 add r7, r10, r7, asr #8 @ r7 = g = (Y >> 8) + guv
116 @
117 orr r12, r2, r11 @ check if clamping is needed...
118 orr r12, r12, r7, asr #1 @ ...at all
119 cmp r12, #31 @
120 bls 15f @ no clamp @
121 mov r12, #31 @
122 cmp r12, r2 @ clamp b
123 andlo r2, r12, r2, asr #31 @
124 eorlo r2, r2, r12 @
125 cmp r12, r11 @ clamp r
126 andlo r11, r12, r11, asr #31 @
127 eorlo r11, r11, r12 @
128 cmp r12, r7, asr #1 @ clamp g
129 andlo r7, r12, r7, asr #31 @
130 eorlo r7, r7, r12 @
131 orrlo r7, r7, r7, asl #1 @
13215: @ no clamp @
133 @
134 orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11)
135 orr r12, r12, r7, lsl #5 @ r4 |= (g << 5)
136 strh r12, [r0, #240]! @ store pixel
137 add r0, r0, #2*240 @
138 @
139 subs r3, r3, #2 @
140 bgt 10b @ loop line 1 @
141 @ do second line
142 @
143 ldmia sp!, { r0, r3 } @ pop dst and width
144 sub r0, r0, #2 @ set dst to start of next line
145 sub r1, r1, r3, asl #1 @ rewind chroma pointer...
146 ldr r2, [sp, #40] @ r2 = stride
147 add r1, r1, r3, asr #1 @ ... (r1 -= width/2*3)
148 @ move sources to start of next line
149 sub r2, r2, r3 @ r2 = skip = stride - width
150 add r4, r4, r2 @ r4 = Y'_p + skip
151 @
15220: @ loop line 2 @
153 ldrb r2, [r4], #1 @ r7 = Y' = *Y'_p++
154 ldrsb r8, [r1], #1 @ reload saved chromas
155 ldrsb r9, [r1], #1 @
156 ldrsb r10, [r1], #1 @
157 @
158 sub r2, r2, #16 @ r2 = Y = (Y' - 16)*74
159 mul r7, r2, r14 @
160 @ compute R, G, and B
161 add r2, r8, r7, asr #9 @ r2 = b = (Y >> 9) + bu
162 add r11, r9, r7, asr #9 @ r11 = r = (Y >> 9) + rv
163 add r7, r10, r7, asr #8 @ r7 = g = (Y >> 8) + guv
164 @
165 orr r12, r2, r11 @ check if clamping is needed...
166 orr r12, r12, r7, asr #1 @ ...at all
167 cmp r12, #31 @
168 bls 25f @ no clamp @
169 mov r12, #31 @
170 cmp r12, r2 @ clamp b
171 andlo r2, r12, r2, asr #31 @
172 eorlo r2, r2, r12 @
173 cmp r12, r11 @ clamp r
174 andlo r11, r12, r11, asr #31 @
175 eorlo r11, r11, r12 @
176 cmp r12, r7, asr #1 @ clamp g
177 andlo r7, r12, r7, asr #31 @
178 eorlo r7, r7, r12 @
179 orrlo r7, r7, r7, asl #1 @
18025: @ no clamp @
181 @
182 orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11)
183 ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++
184 orr r12, r12, r7, lsl #5 @ r4 |= (g << 5)
185 strh r12, [r0], #240 @ store pixel
186 @
187 @ do second pixel
188 @
189 sub r2, r2, #16 @ r2 = Y = (Y' - 16)*74
190 mul r7, r2, r14 @
191 @ compute R, G, and B
192 add r2, r8, r7, asr #9 @ r2 = b = (Y >> 9) + bu
193 add r11, r9, r7, asr #9 @ r11 = r = (Y >> 9) + rv
194 add r7, r10, r7, asr #8 @ r7 = g = (Y >> 8) + guv
195 @
196 orr r12, r2, r11 @ check if clamping is needed...
197 orr r12, r12, r7, asr #1 @ ...at all
198 cmp r12, #31 @
199 bls 25f @ no clamp @
200 mov r12, #31 @
201 cmp r12, r2 @ clamp b
202 andlo r2, r12, r2, asr #31 @
203 eorlo r2, r2, r12 @
204 cmp r12, r11 @ clamp r
205 andlo r11, r12, r11, asr #31 @
206 eorlo r11, r11, r12 @
207 cmp r12, r7, asr #1 @ clamp g
208 andlo r7, r12, r7, asr #31 @
209 eorlo r7, r7, r12 @
210 orrlo r7, r7, r7, asl #1 @
21125: @ no clamp @
212 @
213 orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11)
214 orr r12, r12, r7, lsl #5 @ r4 |= (g << 5)
215 strh r12, [r0, #240]! @ store pixel
216 add r0, r0, #2*240 @
217 @
218 subs r3, r3, #2 @
219 bgt 20b @ loop line 2 @
220 @
221 ldmia sp!, { r4-r12, pc } @ restore registers and return
222 .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
new file mode 100644
index 0000000000..1bb68f9686
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
@@ -0,0 +1,367 @@
1#include "config.h"
2#include <string.h>
3#include "cpu.h"
4#include "lcd.h"
5#include "kernel.h"
6#include "system.h"
7#include "mmu-meg-fx.h"
8#include <stdlib.h>
9#include "memory.h"
10#include "lcd-target.h"
11#include "font.h"
12#include "rbunicode.h"
13#include "bidi.h"
14
15#define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)])
16/*
17** We prepare foreground and background fills ahead of time - DMA fills in 16 byte groups
18*/
19unsigned long fg_pattern_blit[4];
20unsigned long bg_pattern_blit[4];
21
22volatile bool use_dma_blit = false;
23static volatile bool lcd_on = true;
24volatile bool lcd_poweroff = false;
25/*
26** These are imported from lcd-16bit.c
27*/
28extern unsigned fg_pattern;
29extern unsigned bg_pattern;
30
31bool lcd_enabled()
32{
33 return lcd_on;
34}
35
36unsigned int LCDBANK(unsigned int address)
37{
38 return ((address >> 22) & 0xff);
39}
40
41unsigned int LCDBASEU(unsigned int address)
42{
43 return (address & ((1 << 22)-1)) >> 1;
44}
45
46unsigned int LCDBASEL(unsigned int address)
47{
48 address += 320*240*2;
49 return (address & ((1 << 22)-1)) >> 1;
50}
51
52
53/* LCD init */
54void lcd_init_device(void)
55{
56 LCDSADDR1 = (LCDBANK((unsigned)FRAME) << 21) | (LCDBASEU((unsigned)FRAME));
57 LCDSADDR2 = LCDBASEL((unsigned)FRAME);
58 LCDSADDR3 = 0x000000F0;
59
60 LCDCON5 |= 1 << 11; /* Switch from 555I mode to 565 mode */
61
62#if !defined(BOOTLOADER)
63 memset16(fg_pattern_blit, fg_pattern, sizeof(fg_pattern_blit)/2);
64 memset16(bg_pattern_blit, bg_pattern, sizeof(bg_pattern_blit)/2);
65 clean_dcache_range((void *)fg_pattern_blit, sizeof(fg_pattern_blit));
66 clean_dcache_range((void *)bg_pattern_blit, sizeof(bg_pattern_blit));
67 use_dma_blit = true;
68 lcd_poweroff = false;
69#endif
70}
71
72/* Update a fraction of the display. */
73void lcd_update_rect(int x, int y, int width, int height)
74{
75 (void)x;
76 (void)width;
77 (void)y;
78 (void)height;
79
80 if(!lcd_on)
81 {
82 sleep(200);
83 return;
84 }
85 if (use_dma_blit)
86 {
87 /* Wait for this controller to stop pending transfer */
88 while((DSTAT1 & 0x000fffff))
89 CLKCON |= (1 << 2); /* set IDLE bit */
90
91 /* Flush DCache */
92 invalidate_dcache_range((void *)(((int) &lcd_framebuffer[0][0])+(y * sizeof(fb_data) * LCD_WIDTH)), (height * sizeof(fb_data) * LCD_WIDTH));
93
94 /* set DMA dest */
95 DIDST1 = ((int) FRAME) + (y * sizeof(fb_data) * LCD_WIDTH);
96
97 /* FRAME on AHB buf, increment */
98 DIDSTC1 = 0;
99 /* Handshake on AHB, Burst transfer, Whole service, Don't reload, transfer 32-bits */
100 DCON1 = ((1<<30) | (1<<28) | (1<<27) | (1<<22) | (2<<20)) | ((height * sizeof(fb_data) * LCD_WIDTH) >> 4);
101
102 /* set DMA source */
103 DISRC1 = ((int) &lcd_framebuffer[0][0]) + (y * sizeof(fb_data) * LCD_WIDTH) + 0x30000000;
104 /* memory is on AHB bus, increment addresses */
105 DISRCC1 = 0x00;
106
107 /* Activate the channel */
108 DMASKTRIG1 = 0x2;
109
110 /* Start DMA */
111 DMASKTRIG1 |= 0x1;
112
113 /* Wait for transfer to complete */
114 while((DSTAT1 & 0x000fffff))
115 CLKCON |= (1 << 2); /* set IDLE bit */
116 }
117 else
118 memcpy(((char*)FRAME) + (y * sizeof(fb_data) * LCD_WIDTH), ((char *)&lcd_framebuffer) + (y * sizeof(fb_data) * LCD_WIDTH), ((height * sizeof(fb_data) * LCD_WIDTH)));
119}
120
121
122void lcd_enable(bool state)
123{
124 if(!lcd_poweroff)
125 return;
126 if(state) {
127 if(!lcd_on) {
128 lcd_on = true;
129 memcpy(FRAME, lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT*2);
130 LCDCON1 |= 1;
131 }
132 }
133 else {
134 if(lcd_on) {
135 lcd_on = false;
136 LCDCON1 &= ~1;
137 }
138 }
139}
140
141void lcd_set_foreground(unsigned color)
142{
143 fg_pattern = color;
144
145 memset16(fg_pattern_blit, fg_pattern, sizeof(fg_pattern_blit)/2);
146 invalidate_dcache_range((void *)fg_pattern_blit, sizeof(fg_pattern_blit));
147}
148
149void lcd_set_background(unsigned color)
150{
151 bg_pattern = color;
152 memset16(bg_pattern_blit, bg_pattern, sizeof(bg_pattern_blit)/2);
153 invalidate_dcache_range((void *)bg_pattern_blit, sizeof(bg_pattern_blit));
154}
155
156void lcd_device_prepare_backdrop(fb_data* backdrop)
157{
158 if(backdrop)
159 invalidate_dcache_range((void *)backdrop, (LCD_HEIGHT * sizeof(fb_data) * LCD_WIDTH));
160}
161
162void lcd_clear_display_dma(void)
163{
164 void *src;
165 bool inc = false;
166
167 if(!lcd_on) {
168 sleep(200);
169 }
170 if (lcd_get_drawmode() & DRMODE_INVERSEVID)
171 src = fg_pattern_blit;
172 else
173 {
174 fb_data* lcd_backdrop = lcd_get_backdrop();
175
176 if (!lcd_backdrop)
177 src = bg_pattern_blit;
178 else
179 {
180 src = lcd_backdrop;
181 inc = true;
182 }
183 }
184 /* Wait for any pending transfer to complete */
185 while((DSTAT3 & 0x000fffff))
186 CLKCON |= (1 << 2); /* set IDLE bit */
187 DMASKTRIG3 |= 0x4; /* Stop controller */
188 DIDST3 = ((int) &lcd_framebuffer[0][0]) + 0x30000000; /* set DMA dest, physical address */
189 DIDSTC3 = 0; /* Dest on AHB, increment */
190
191 DISRC3 = ((int) src) + 0x30000000; /* Set source, in physical space */
192 DISRCC3 = inc ? 0x00 : 0x01; /* memory is on AHB bus, increment addresses based on backdrop */
193
194 /* Handshake on AHB, Burst mode, whole service mode, no reload, move 32-bits */
195 DCON3 = ((1<<30) | (1<<28) | (1<<27) | (1<<22) | (2<<20)) | ((LCD_WIDTH*LCD_HEIGHT*sizeof(fb_data)) >> 4);
196
197 /* Dump DCache for dest, we are about to overwrite it with DMA */
198 invalidate_dcache_range((void *)lcd_framebuffer, sizeof(lcd_framebuffer));
199 /* Activate the channel */
200 DMASKTRIG3 = 2;
201 /* Start DMA */
202 DMASKTRIG3 |= 1;
203
204 /* Wait for transfer to complete */
205 while((DSTAT3 & 0x000fffff))
206 CLKCON |= (1 << 2); /* set IDLE bit */
207}
208
209void lcd_clear_display(void)
210{
211 lcd_stop_scroll();
212
213 if(use_dma_blit)
214 {
215 lcd_clear_display_dma();
216 return;
217 }
218
219 fb_data *dst = &lcd_framebuffer[0][0];
220
221 if (lcd_get_drawmode() & DRMODE_INVERSEVID)
222 {
223 memset16(dst, fg_pattern, LCD_WIDTH*LCD_HEIGHT);
224 }
225 else
226 {
227 fb_data* lcd_backdrop = lcd_get_backdrop();
228 if (!lcd_backdrop)
229 memset16(dst, bg_pattern, LCD_WIDTH*LCD_HEIGHT);
230 else
231 memcpy(dst, lcd_backdrop, sizeof(lcd_framebuffer));
232 }
233}
234
235
236/* Update the display.
237 This must be called after all other LCD functions that change the display. */
238void lcd_update(void)
239{
240 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
241}
242
243void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y,
244 int stride, int x, int y, int width,
245 int height)
246{
247 fb_data *dst, *dst_end;
248 unsigned int transcolor;
249
250 /* nothing to draw? */
251 if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT)
252 || (x + width <= 0) || (y + height <= 0))
253 return;
254
255 /* clipping */
256 if (x < 0)
257 {
258 width += x;
259 src_x -= x;
260 x = 0;
261 }
262 if (y < 0)
263 {
264 height += y;
265 src_y -= y;
266 y = 0;
267 }
268 if (x + width > LCD_WIDTH)
269 width = LCD_WIDTH - x;
270 if (y + height > LCD_HEIGHT)
271 height = LCD_HEIGHT - y;
272
273 src += stride * src_y + src_x; /* move starting point */
274 dst = &lcd_framebuffer[(y)][(x)];
275 dst_end = dst + height * LCD_WIDTH;
276 width *= 2;
277 stride *= 2;
278 transcolor = TRANSPARENT_COLOR;
279 asm volatile(
280 "rowstart: \n"
281 "mov r0, #0 \n"
282 "nextpixel: \n"
283 "ldrh r1, [%0, r0] \n" /* Load word src+r0 */
284 "cmp r1, %5 \n" /* Compare to transparent color */
285 "strneh r1, [%1, r0] \n" /* Store dst+r0 if not transparent */
286 "add r0, r0, #2 \n"
287 "cmp r0, %2 \n" /* r0 == width? */
288 "bne nextpixel \n" /* More in this row? */
289 "add %0, %0, %4 \n" /* src += stride */
290 "add %1, %1, #480 \n" /* dst += LCD_WIDTH (x2) */
291 "cmp %1, %3 \n"
292 "bne rowstart \n" /* if(dst != dst_end), keep going */
293 : : "r" (src), "r" (dst), "r" (width), "r" (dst_end), "r" (stride), "r" (transcolor) : "r0", "r1" );
294}
295
296/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
297extern void lcd_write_yuv420_lines(fb_data *dst,
298 unsigned char chroma_buf[LCD_HEIGHT/2*3],
299 unsigned char const * const src[3],
300 int width,
301 int stride);
302/* Performance function to blit a YUV bitmap directly to the LCD */
303/* For the Gigabeat - show it rotated */
304/* So the LCD_WIDTH is now the height */
305void lcd_yuv_blit(unsigned char * const src[3],
306 int src_x, int src_y, int stride,
307 int x, int y, int width, int height)
308{
309 /* Caches for chroma data so it only need be recaculated every other
310 line */
311 unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */
312 unsigned char const * yuv_src[3];
313 off_t z;
314
315 if (!lcd_on)
316 return;
317
318 /* Sorry, but width and height must be >= 2 or else */
319 width &= ~1;
320 height >>= 1;
321
322 fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1;
323
324 z = stride*src_y;
325 yuv_src[0] = src[0] + z + src_x;
326 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
327 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
328
329 do
330 {
331 lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width,
332 stride);
333 yuv_src[0] += stride << 1; /* Skip down two luma lines */
334 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
335 yuv_src[2] += stride >> 1;
336 dst -= 2;
337 }
338 while (--height > 0);
339}
340
341void lcd_set_contrast(int val) {
342 (void) val;
343 // TODO:
344}
345
346void lcd_set_invert_display(bool yesno) {
347 (void) yesno;
348 // TODO:
349}
350
351void lcd_blit(const fb_data* data, int bx, int y, int bwidth,
352 int height, int stride)
353{
354 (void) data;
355 (void) bx;
356 (void) y;
357 (void) bwidth;
358 (void) height;
359 (void) stride;
360 //TODO:
361}
362
363void lcd_set_flip(bool yesno) {
364 (void) yesno;
365 // TODO:
366}
367
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-target.h b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-target.h
new file mode 100644
index 0000000000..cb2a89f349
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-target.h
@@ -0,0 +1,21 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id $
9 *
10 * Copyright (C) 2007 by Greg White
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20extern void lcd_enable(bool state);
21
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.c
new file mode 100644
index 0000000000..6142213f0c
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.c
@@ -0,0 +1,222 @@
1#include <string.h>
2#include "s3c2440.h"
3#include "mmu-meg-fx.h"
4#include "panic.h"
5
6void map_memory(void);
7static void enable_mmu(void);
8static void set_ttb(void);
9static void set_page_tables(void);
10static void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags);
11
12#define SECTION_ADDRESS_MASK (-1 << 20)
13#define CACHE_ALL (1 << 3 | 1 << 2 )
14#define CACHE_NONE 0
15#define BUFFERED (1 << 2)
16#define MB (1 << 20)
17
18void map_memory(void) {
19 set_ttb();
20 set_page_tables();
21 enable_mmu();
22}
23
24unsigned int* ttb_base = (unsigned int *) TTB_BASE;
25const int ttb_size = 4096;
26
27void set_ttb() {
28 int i;
29 int* ttbPtr;
30 int domain_access;
31
32 /* must be 16Kb (0x4000) aligned */
33 ttb_base = (int*) TTB_BASE;
34 for (i=0; i<ttb_size; i++,ttbPtr++)
35 ttbPtr = 0;
36 asm volatile("mcr p15, 0, %0, c2, c0, 0" : : "r" (ttb_base));
37
38 /* set domain D0 to "client" permission access */
39
40 domain_access = 3;
41 asm volatile("mcr p15, 0, %0, c3, c0, 0" : : "r" (domain_access));
42
43}
44
45void set_page_tables() {
46
47 map_section(0, 0, 0x1000, CACHE_NONE); /* map every memory region to itself */
48 map_section(0x30000000, 0, 32, CACHE_ALL); /* map RAM to 0 and enable caching for it */
49 map_section((int)FRAME, (int)FRAME, 1, BUFFERED); /* enable buffered writing for the framebuffer */
50}
51
52void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags) {
53 unsigned int* ttbPtr;
54 int i;
55 int section_no;
56
57 section_no = va >> 20; /* sections are 1Mb size */
58 ttbPtr = ttb_base + section_no;
59 pa &= SECTION_ADDRESS_MASK; /* align to 1Mb */
60 for(i=0; i<mb; i++, pa += MB) {
61 *(ttbPtr + i) =
62 pa |
63 1 << 10 | /* superuser - r/w, user - no access */
64 0 << 5 | /* domain 0th */
65 1 << 4 | /* should be "1" */
66 cache_flags |
67 1 << 1; /* Section signature */
68 }
69}
70
71static void enable_mmu(void) {
72 asm volatile("mov r0, #0\n"
73 "mcr p15, 0, r0, c8, c7, 0\n" /* invalidate TLB */
74
75 "mcr p15, 0, r0, c7, c7,0\n" /* invalidate both icache and dcache */
76
77 "mrc p15, 0, r0, c1, c0, 0\n"
78 "orr r0, r0, #1<<0\n" /* enable mmu bit, icache and dcache */
79 "orr r0, r0, #1<<2\n" /* enable dcache */
80 "orr r0, r0, #1<<12\n" /* enable icache */
81 "mcr p15, 0, r0, c1, c0, 0" : : : "r0");
82 asm volatile("nop \n nop \n nop \n nop");
83}
84
85/* Invalidate DCache for this range */
86/* Will do write back */
87void invalidate_dcache_range(const void *base, unsigned int size) {
88 unsigned int addr = (((int) base) & ~31); /* Align start to cache line*/
89 unsigned int end = ((addr+size) & ~31)+64; /* Align end to cache line, pad */
90 asm volatile(
91"inv_start: \n"
92 "mcr p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
93 "add %0, %0, #32 \n"
94 "cmp %0, %1 \n"
95 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
96 "addne %0, %0, #32 \n"
97 "cmpne %0, %1 \n"
98 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
99 "addne %0, %0, #32 \n"
100 "cmpne %0, %1 \n"
101 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
102 "addne %0, %0, #32 \n"
103 "cmpne %0, %1 \n"
104 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
105 "addne %0, %0, #32 \n"
106 "cmpne %0, %1 \n"
107 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
108 "addne %0, %0, #32 \n"
109 "cmpne %0, %1 \n"
110 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
111 "addne %0, %0, #32 \n"
112 "cmpne %0, %1 \n"
113 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
114 "addne %0, %0, #32 \n"
115 "cmpne %0, %1 \n"
116 "bne inv_start \n"
117 "mov %0, #0\n"
118 "mcr p15,0,%0,c7,c10,4\n" /* Drain write buffer */
119 : : "r" (addr), "r" (end));
120}
121
122/* clean DCache for this range */
123/* forces DCache writeback for the specified range */
124void clean_dcache_range(const void *base, unsigned int size) {
125 unsigned int addr = (int) base;
126 unsigned int end = addr+size+32;
127 asm volatile(
128 "bic %0, %0, #31 \n"
129"clean_start: \n"
130 "mcr p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
131 "add %0, %0, #32 \n"
132 "cmp %0, %1 \n"
133 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
134 "addlo %0, %0, #32 \n"
135 "cmplo %0, %1 \n"
136 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
137 "addlo %0, %0, #32 \n"
138 "cmplo %0, %1 \n"
139 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
140 "addlo %0, %0, #32 \n"
141 "cmplo %0, %1 \n"
142 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
143 "addlo %0, %0, #32 \n"
144 "cmplo %0, %1 \n"
145 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
146 "addlo %0, %0, #32 \n"
147 "cmplo %0, %1 \n"
148 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
149 "addlo %0, %0, #32 \n"
150 "cmplo %0, %1 \n"
151 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
152 "addlo %0, %0, #32 \n"
153 "cmplo %0, %1 \n"
154 "blo clean_start \n"
155 "mov %0, #0\n"
156 "mcr p15,0,%0,c7,c10,4 \n" /* Drain write buffer */
157 : : "r" (addr), "r" (end));
158}
159
160/* Dump DCache for this range */
161/* Will *NOT* do write back */
162void dump_dcache_range(const void *base, unsigned int size) {
163 unsigned int addr = (int) base;
164 unsigned int end = addr+size;
165 asm volatile(
166 "tst %0, #31 \n" /* Check to see if low five bits are set */
167 "bic %0, %0, #31 \n" /* Clear them */
168 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line, if those bits were set */
169 "add %0, %0, #32 \n" /* Move to the next cache line */
170 "tst %1, #31 \n" /* Check last line for bits set */
171 "bic %1, %1, #31 \n" /* Clear those bits */
172 "mcrne p15, 0, %1, c7, c14, 1 \n" /* Clean and invalidate this line, if not cache aligned */
173"dump_start: \n"
174 "mcr p15, 0, %0, c7, c6, 1 \n" /* Invalidate this line */
175 "add %0, %0, #32 \n" /* Next cache line */
176 "cmp %0, %1 \n"
177 "bne dump_start \n"
178"dump_end: \n"
179 "mcr p15,0,%0,c7,c10,4 \n" /* Drain write buffer */
180 : : "r" (addr), "r" (end));
181}
182/* Cleans entire DCache */
183void clean_dcache(void)
184{
185 unsigned int index, addr;
186
187 for(index = 0; index <= 63; index++) {
188 addr = (0 << 5) | (index << 26);
189 asm volatile(
190 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
191 : : "r" (addr));
192 addr = (1 << 5) | (index << 26);
193 asm volatile(
194 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
195 : : "r" (addr));
196 addr = (2 << 5) | (index << 26);
197 asm volatile(
198 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
199 : : "r" (addr));
200 addr = (3 << 5) | (index << 26);
201 asm volatile(
202 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
203 : : "r" (addr));
204 addr = (4 << 5) | (index << 26);
205 asm volatile(
206 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
207 : : "r" (addr));
208 addr = (5 << 5) | (index << 26);
209 asm volatile(
210 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
211 : : "r" (addr));
212 addr = (6 << 5) | (index << 26);
213 asm volatile(
214 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
215 : : "r" (addr));
216 addr = (7 << 5) | (index << 26);
217 asm volatile(
218 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
219 : : "r" (addr));
220 }
221}
222
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.h b/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.h
new file mode 100644
index 0000000000..71b1b83801
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.h
@@ -0,0 +1,35 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006,2007 by Greg White
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20/* Invalidate DCache for this range */
21/* Will do write back */
22void invalidate_dcache_range(const void *base, unsigned int size);
23
24/* clean DCache for this range */
25/* forces DCache writeback for the specified range */
26void clean_dcache_range(const void *base, unsigned int size);
27
28/* Dump DCache for this range */
29/* Will *NOT* do write back */
30void dump_dcache_range(const void *base, unsigned int size);
31
32/* Cleans entire DCache */
33void clean_dcache(void);
34
35
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
new file mode 100644
index 0000000000..0f22aa5c5c
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
@@ -0,0 +1,376 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Michael Sevakis
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "system.h"
20#include "kernel.h"
21#include "logf.h"
22#include "audio.h"
23#include "sound.h"
24#include "file.h"
25#include "mmu-meg-fx.h"
26
27static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
28
29#define GIGABEAT_8000HZ 0x4d
30#define GIGABEAT_11025HZ 0x32
31#define GIGABEAT_12000HZ 0x61
32#define GIGABEAT_16000HZ 0x55
33#define GIGABEAT_22050HZ 0x36
34#define GIGABEAT_24000HZ 0x79
35#define GIGABEAT_32000HZ 0x59
36#define GIGABEAT_44100HZ 0x22
37#define GIGABEAT_48000HZ 0x41
38#define GIGABEAT_88200HZ 0x3e
39#define GIGABEAT_96000HZ 0x5d
40
41#define FIFO_COUNT ((IISFCON >> 6) & 0x01F)
42
43/* number of bytes in FIFO */
44#define IIS_FIFO_SIZE 64
45
46/* Setup for the DMA controller */
47#define DMA_CONTROL_SETUP ((1<<31) | (1<<29) | (1<<23) | (1<<22) | (1<<20))
48
49unsigned short * p;
50size_t p_size;
51
52
53
54/* DMA count has hit zero - no more data */
55/* Get more data from the callback and top off the FIFO */
56//void fiq(void) __attribute__ ((interrupt ("naked")));
57void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ")));
58void fiq(void)
59{
60 /* clear any pending interrupt */
61 SRCPND = (1<<19);
62
63 /* Buffer empty. Try to get more. */
64 if (pcm_callback_for_more)
65 {
66 pcm_callback_for_more((unsigned char**)&p, &p_size);
67 }
68 else
69 {
70 /* callback func is missing? */
71 pcm_play_dma_stop();
72 return;
73 }
74
75 if (p_size)
76 {
77 /* Flush any pending cache writes */
78 clean_dcache_range(p, p_size);
79
80 /* set the new DMA values */
81 DCON2 = DMA_CONTROL_SETUP | (p_size >> 1);
82 DISRC2 = (int)p + 0x30000000;
83
84 /* Re-Activate the channel */
85 DMASKTRIG2 = 0x2;
86 }
87 else
88 {
89 /* No more DMA to do */
90 pcm_play_dma_stop();
91 }
92
93}
94
95
96
97void pcm_init(void)
98{
99 pcm_playing = false;
100 pcm_paused = false;
101 pcm_callback_for_more = NULL;
102
103 audiohw_init();
104 audiohw_enable_output(true);
105
106 /* cannot use the WM8975 defaults since our clock is not the same */
107 /* the input master clock is 16.9344MHz - we can divide exact for that */
108 pcm_set_frequency(SAMPR_44);
109
110 /* init GPIO */
111 GPCCON = (GPCCON & ~(3<<14)) | (1<<14);
112 GPCDAT |= 1<<7;
113 GPECON |= 0x2aa;
114
115 /* Do not service DMA requests, yet */
116 /* clear any pending int and mask it */
117 INTMSK |= (1<<19); /* mask the interrupt */
118 SRCPND = (1<<19); /* clear any pending interrupts */
119 INTMOD |= (1<<19); /* connect to FIQ */
120
121}
122
123void pcm_postinit(void)
124{
125 audiohw_postinit();
126}
127
128void pcm_play_dma_start(const void *addr, size_t size)
129{
130 /* sanity check: bad pointer or too small file */
131 if (NULL == addr || size <= IIS_FIFO_SIZE) return;
132
133 p = (unsigned short *)addr;
134 p_size = size;
135
136 /* Enable the IIS clock */
137 CLKCON |= (1<<17);
138
139 /* IIS interface setup and set to idle */
140 IISCON = (1<<5) | (1<<3);
141
142 /* slave, transmit mode, 16 bit samples - 384fs - use 16.9344Mhz */
143 IISMOD = (1<<9) | (1<<8) | (2<<6) | (1<<3) | (1<<2);
144
145 /* connect DMA to the FIFO and enable the FIFO */
146 IISFCON = (1<<15) | (1<<13);
147
148 /* set DMA dest */
149 DIDST2 = (int)&IISFIFO;
150
151 /* IIS is on the APB bus, INT when TC reaches 0, fixed dest addr */
152 DIDSTC2 = 0x03;
153
154 /* How many transfers to make - we transfer half-word at a time = 2 bytes */
155 /* DMA control: CURR_TC int, single service mode, I2SSDO int, HW trig */
156 /* no auto-reload, half-word (16bit) */
157 DCON2 = DMA_CONTROL_SETUP | (p_size / 2);
158
159 /* set DMA source and options */
160 DISRC2 = (int)p + 0x30000000;
161 DISRCC2 = 0x00; /* memory is on AHB bus, increment addresses */
162
163 /* clear pending DMA interrupt */
164 SRCPND = 1<<19;
165
166 set_fiq_handler(fiq);
167 enable_fiq();
168
169 /* unmask the DMA interrupt */
170 INTMSK &= ~(1<<19);
171
172 /* Flush any pending writes */
173 clean_dcache_range(addr, size);
174
175 /* Activate the channel */
176 DMASKTRIG2 = 0x2;
177
178 /* turn off the idle */
179 IISCON &= ~(1<<3);
180
181 pcm_playing = true;
182
183 /* start the IIS */
184 IISCON |= (1<<0);
185
186}
187
188
189
190/* Disconnect the DMA and wait for the FIFO to clear */
191void pcm_play_dma_stop(void)
192{
193 /* mask the DMA interrupt */
194 INTMSK |= (1<<19);
195
196 /* are we playing? wait for the chunk to finish */
197 if (pcm_playing)
198 {
199 /* wait for the FIFO to empty before turning things off */
200 while (IISCON & (1<<7)) ;
201
202 pcm_playing = false;
203 }
204
205 /* De-Activate the DMA channel */
206 DMASKTRIG2 = 0x4;
207
208 /* Disconnect the IIS clock */
209 CLKCON &= ~(1<<17);
210
211 disable_fiq();
212
213}
214
215
216
217void pcm_play_pause_pause(void)
218{
219 /* stop servicing refills */
220 INTMSK |= (1<<19);
221}
222
223
224
225void pcm_play_pause_unpause(void)
226{
227 /* refill buffer and keep going */
228 INTMSK &= ~(1<<19);
229}
230
231void pcm_set_frequency(unsigned int frequency)
232{
233 int sr_ctrl;
234
235 switch(frequency)
236 {
237 case SAMPR_8:
238 sr_ctrl = GIGABEAT_8000HZ;
239 break;
240 case SAMPR_11:
241 sr_ctrl = GIGABEAT_11025HZ;
242 break;
243 case SAMPR_12:
244 sr_ctrl = GIGABEAT_12000HZ;
245 break;
246 case SAMPR_16:
247 sr_ctrl = GIGABEAT_16000HZ;
248 break;
249 case SAMPR_22:
250 sr_ctrl = GIGABEAT_22050HZ;
251 break;
252 case SAMPR_24:
253 sr_ctrl = GIGABEAT_24000HZ;
254 break;
255 case SAMPR_32:
256 sr_ctrl = GIGABEAT_32000HZ;
257 break;
258 default:
259 frequency = SAMPR_44;
260 case SAMPR_44:
261 sr_ctrl = GIGABEAT_44100HZ;
262 break;
263 case SAMPR_48:
264 sr_ctrl = GIGABEAT_48000HZ;
265 break;
266 case SAMPR_88:
267 sr_ctrl = GIGABEAT_88200HZ;
268 break;
269 case SAMPR_96:
270 sr_ctrl = GIGABEAT_96000HZ;
271 break;
272 }
273
274 audiohw_set_sample_rate(sr_ctrl);
275 pcm_freq = frequency;
276}
277
278
279
280size_t pcm_get_bytes_waiting(void)
281{
282 return (DSTAT2 & 0xFFFFF) * 2;
283}
284
285
286
287/* dummy functions for those not actually supporting all this yet */
288void pcm_apply_settings(void)
289{
290}
291
292void pcm_set_monitor(int monitor)
293{
294 (void)monitor;
295}
296/** **/
297
298void pcm_mute(bool mute)
299{
300 audiohw_mute(mute);
301 if (mute)
302 sleep(HZ/16);
303}
304
305/*
306 * This function goes directly into the DMA buffer to calculate the left and
307 * right peak values. To avoid missing peaks it tries to look forward two full
308 * peek periods (2/HZ sec, 100% overlap), although it's always possible that
309 * the entire period will not be visible. To reduce CPU load it only looks at
310 * every third sample, and this can be reduced even further if needed (even
311 * every tenth sample would still be pretty accurate).
312 */
313
314/* Check for a peak every PEAK_STRIDE samples */
315#define PEAK_STRIDE 3
316/* Up to 1/50th of a second of audio for peak calculation */
317/* This should use NATIVE_FREQUENCY, or eventually an adjustable freq. value */
318#define PEAK_SAMPLES (44100/50)
319void pcm_calculate_peaks(int *left, int *right)
320{
321 short *addr;
322 short *end;
323 {
324 size_t samples = p_size / 4;
325 addr = p;
326
327 if (samples > PEAK_SAMPLES)
328 samples = PEAK_SAMPLES - (PEAK_STRIDE - 1);
329 else
330 samples -= MIN(PEAK_STRIDE - 1, samples);
331
332 end = &addr[samples * 2];
333 }
334
335 if (left && right) {
336 int left_peak = 0, right_peak = 0;
337
338 while (addr < end) {
339 int value;
340 if ((value = addr [0]) > left_peak)
341 left_peak = value;
342 else if (-value > left_peak)
343 left_peak = -value;
344
345 if ((value = addr [PEAK_STRIDE | 1]) > right_peak)
346 right_peak = value;
347 else if (-value > right_peak)
348 right_peak = -value;
349
350 addr = &addr[PEAK_STRIDE * 2];
351 }
352
353 *left = left_peak;
354 *right = right_peak;
355 }
356 else if (left || right) {
357 int peak_value = 0, value;
358
359 if (right)
360 addr += (PEAK_STRIDE | 1);
361
362 while (addr < end) {
363 if ((value = addr [0]) > peak_value)
364 peak_value = value;
365 else if (-value > peak_value)
366 peak_value = -value;
367
368 addr += PEAK_STRIDE * 2;
369 }
370
371 if (left)
372 *left = peak_value;
373 else
374 *right = peak_value;
375 }
376}
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/power-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/power-meg-fx.c
new file mode 100644
index 0000000000..eb2ffb5238
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/power-meg-fx.c
@@ -0,0 +1,90 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "config.h"
20#include "cpu.h"
21#include <stdbool.h>
22#include "kernel.h"
23#include "system.h"
24#include "power.h"
25#include "pcf50606.h"
26#include "backlight.h"
27#include "backlight-target.h"
28
29#ifndef SIMULATOR
30
31void power_init(void)
32{
33 /* Charger detect */
34}
35
36bool charger_inserted(void)
37{
38 return (GPFDAT & (1 << 4)) ? false : true;
39}
40
41/* Returns true if the unit is charging the batteries. */
42bool charging_state(void) {
43 return (GPGDAT & (1 << 8)) ? false : true;
44}
45
46void ide_power_enable(bool on)
47{
48 if (on)
49 GPGDAT |= (1 << 11);
50 else
51 GPGDAT &= ~(1 << 11);
52}
53
54bool ide_powered(void)
55{
56 return (GPGDAT & (1 << 11)) != 0;
57}
58
59void power_off(void)
60{
61 /* turn off backlight and wait for 1 second */
62 __backlight_off();
63 sleep(HZ/2);
64 /* set SLEEP bit to on in CLKCON to turn off */
65 CLKCON |=(1<<3);
66}
67
68#else /* SIMULATOR */
69
70bool charger_inserted(void)
71{
72 return false;
73}
74
75void charger_enable(bool on)
76{
77 (void)on;
78}
79
80void power_off(void)
81{
82}
83
84void ide_power_enable(bool on)
85{
86 (void)on;
87}
88
89#endif /* SIMULATOR */
90
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c
new file mode 100644
index 0000000000..e69eab432a
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.c
@@ -0,0 +1,225 @@
1#include "config.h"
2#include "cpu.h"
3#include <stdbool.h>
4#include "kernel.h"
5#include "system.h"
6#include "logf.h"
7#include "debug.h"
8#include "string.h"
9
10#define SLAVE_ADDRESS 0xCC
11
12#define SDA_LO (GPHDAT &= ~(1 << 9))
13#define SDA_HI (GPHDAT |= (1 << 9))
14#define SDA_INPUT (GPHCON &= ~(3 << 18))
15#define SDA_OUTPUT (GPHCON |= (1 << 18))
16#define SDA (GPHDAT & (1 << 9))
17
18#define SCL_LO (GPHDAT &= ~(1 << 10))
19#define SCL_HI (GPHDAT |= (1 << 10))
20#define SCL_INPUT (GPHCON &= ~(3 << 20))
21#define SCL_OUTPUT (GPHCON |= (1 << 20))
22#define SCL (GPHDAT & (1 << 10))
23
24#define SCL_SDA_HI (GPHDAT |= (3 << 9))
25
26/* The SC606 can clock at 400KHz: */
27/* Clock period high is 600nS and low is 1300nS */
28/* The high and low times are different enough to need different timings */
29/* cycles delayed = 30 + 7 * loops */
30/* 100MHz = 10nS per cycle: LO:1300nS=130:14 HI:600nS=60:9 */
31/* 300MHz = 3.36nS per cycle: LO:1300nS=387:51 HI:600nS=179:21 */
32#define DELAY_LO do{int x;for(x=51;x;x--);} while (0)
33#define DELAY do{int x;for(x=35;x;x--);} while (0)
34#define DELAY_HI do{int x;for(x=21;x;x--);} while (0)
35
36
37
38static void sc606_i2c_start(void)
39{
40 SCL_SDA_HI;
41 DELAY;
42 SDA_LO;
43 DELAY;
44 SCL_LO;
45}
46
47static void sc606_i2c_restart(void)
48{
49 SCL_SDA_HI;
50 DELAY;
51 SDA_LO;
52 DELAY;
53 SCL_LO;
54}
55
56static void sc606_i2c_stop(void)
57{
58 SDA_LO;
59 SCL_HI;
60 DELAY_HI;
61 SDA_HI;
62}
63
64static void sc606_i2c_ack(void)
65{
66
67 SDA_LO;
68 SCL_HI;
69 DELAY_HI;
70 SCL_LO;
71}
72
73
74
75static int sc606_i2c_getack(void)
76{
77 int ret;
78
79 /* Don't need a delay since follows a data bit with a delay on the end */
80 SDA_INPUT; /* And set to input */
81 DELAY;
82 SCL_HI;
83
84 ret = (SDA != 0); /* ack failed if SDA is not low */
85 DELAY_HI;
86
87 SCL_LO;
88 DELAY_LO;
89
90 SDA_HI;
91 SDA_OUTPUT;
92 DELAY_LO;
93
94 return ret;
95}
96
97
98
99static void sc606_i2c_outb(unsigned char byte)
100{
101 int i;
102
103 /* clock out each bit, MSB first */
104 for (i = 0x80; i; i >>= 1)
105 {
106 if (i & byte)
107 {
108 SDA_HI;
109 }
110 else
111 {
112 SDA_LO;
113 }
114 DELAY;
115
116 SCL_HI;
117 DELAY_HI;
118
119 SCL_LO;
120 DELAY_LO;
121 }
122
123 SDA_HI;
124
125}
126
127
128
129static unsigned char sc606_i2c_inb(void)
130{
131 int i;
132 unsigned char byte = 0;
133
134 SDA_INPUT; /* And set to input */
135 /* clock in each bit, MSB first */
136 for (i = 0x80; i; i >>= 1) {
137 SCL_HI;
138
139 if (SDA)
140 byte |= i;
141
142 SCL_LO;
143 }
144 SDA_OUTPUT;
145
146 sc606_i2c_ack();
147
148 return byte;
149}
150
151
152
153/* returns number of acks that were bad */
154int sc606_write(unsigned char reg, unsigned char data)
155{
156 int x;
157
158 sc606_i2c_start();
159
160 sc606_i2c_outb(SLAVE_ADDRESS);
161 x = sc606_i2c_getack();
162
163 sc606_i2c_outb(reg);
164 x += sc606_i2c_getack();
165
166 sc606_i2c_restart();
167
168 sc606_i2c_outb(SLAVE_ADDRESS);
169 x += sc606_i2c_getack();
170
171 sc606_i2c_outb(data);
172 x += sc606_i2c_getack();
173
174 sc606_i2c_stop();
175
176 return x;
177}
178
179
180
181int sc606_read(unsigned char reg, unsigned char* data)
182{
183 int x;
184
185 sc606_i2c_start();
186 sc606_i2c_outb(SLAVE_ADDRESS);
187 x = sc606_i2c_getack();
188
189 sc606_i2c_outb(reg);
190 x += sc606_i2c_getack();
191
192 sc606_i2c_restart();
193 sc606_i2c_outb(SLAVE_ADDRESS | 1);
194 x += sc606_i2c_getack();
195
196 *data = sc606_i2c_inb();
197 sc606_i2c_stop();
198
199 return x;
200}
201
202
203
204void sc606_init(void)
205{
206 volatile int i;
207
208 /* Set GPB2 (EN) to 1 */
209 GPBCON = (GPBCON & ~(3<<4)) | 1<<4;
210
211 /* Turn enable line on */
212 GPBDAT |= 1<<2;
213 /* OFF GPBDAT &= ~(1 << 2); */
214
215 /* About 400us - needs 350us */
216 for (i = 200; i; i--)
217 {
218 DELAY_LO;
219 }
220
221 /* Set GPH9 (SDA) and GPH10 (SCL) to 1 */
222 GPHUP &= ~(3<<9);
223 GPHCON = (GPHCON & ~(0xF<<18)) | 5<<18;
224}
225
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.h b/firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.h
new file mode 100644
index 0000000000..3ea0917e86
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/sc606-meg-fx.h
@@ -0,0 +1,28 @@
1#include "config.h"
2#include "cpu.h"
3#include <stdbool.h>
4#include "kernel.h"
5#include "system.h"
6#include "logf.h"
7#include "debug.h"
8#include "string.h"
9
10#define SC606_REG_A 0
11#define SC606_REG_B 1
12#define SC606_REG_C 2
13#define SC606_REG_CONF 3
14
15#define SC606_LED_A1 (1 << 0)
16#define SC606_LED_A2 (1 << 1)
17#define SC606_LED_B1 (1 << 2)
18#define SC606_LED_B2 (1 << 3)
19#define SC606_LED_C1 (1 << 4)
20#define SC606_LED_C2 (1 << 5)
21
22#define SC606_LOW_FREQ (1 << 6)
23
24int sc606_write(unsigned char reg, unsigned char data);
25
26int sc606_read(unsigned char reg, unsigned char* data);
27
28void sc606_init(void);
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c
new file mode 100644
index 0000000000..b7e59e66ea
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c
@@ -0,0 +1,96 @@
1#include "kernel.h"
2#include "system.h"
3#include "panic.h"
4
5#include "lcd.h"
6#include <stdio.h>
7
8const int TIMER4_MASK = (1 << 14);
9const int LCD_MASK = (1 << 16);
10const int DMA0_MASK = (1 << 17);
11const int DMA1_MASK = (1 << 18);
12const int DMA2_MASK = (1 << 19);
13const int DMA3_MASK = (1 << 20);
14
15int system_memory_guard(int newmode)
16{
17 (void)newmode;
18 return 0;
19}
20
21extern void timer4(void);
22extern void dma0(void);
23extern void dma1(void);
24extern void dma3(void);
25
26void irq(void)
27{
28 int intpending = INTPND;
29
30 SRCPND = intpending; /* Clear this interrupt. */
31 INTPND = intpending; /* Clear this interrupt. */
32
33 /* Timer 4 */
34 if ((intpending & TIMER4_MASK) != 0)
35 timer4();
36 else if ((intpending & DMA0_MASK) != 0)
37 dma0();
38 else
39 {
40 /* unexpected interrupt */
41 }
42}
43
44void system_reboot(void)
45{
46 WTCON = 0;
47 WTCNT = WTDAT = 1 ;
48 WTCON = 0x21;
49 for(;;)
50 ;
51}
52
53void system_init(void)
54{
55 /* Turn off un-needed devices */
56
57 /* Turn off all of the UARTS */
58 CLKCON &= ~( (1<<10) | (1<<11) |(1<<12) );
59
60 /* Turn off AC97 and Camera */
61 CLKCON &= ~( (1<<19) | (1<<20) );
62
63 /* Turn off USB host */
64 CLKCON &= ~(1 << 6);
65
66 /* Turn off NAND flash controller */
67 CLKCON &= ~(1 << 4);
68
69}
70
71
72#ifdef HAVE_ADJUSTABLE_CPU_FREQ
73
74void set_cpu_frequency(long frequency)
75{
76 if (frequency == CPUFREQ_MAX)
77 {
78 asm volatile("mov r0, #0\n"
79 "mrc p15, 0, r0, c1, c0, 0\n"
80 "orr r0, r0, #3<<30\n" /* set to Asynchronous mode*/
81 "mcr p15, 0, r0, c1, c0, 0" : : : "r0");
82
83 FREQ = CPUFREQ_MAX;
84 }
85 else
86 {
87 asm volatile("mov r0, #0\n"
88 "mrc p15, 0, r0, c1, c0, 0\n"
89 "bic r0, r0, #3<<30\n" /* set to FastBus mode*/
90 "mcr p15, 0, r0, c1, c0, 0" : : : "r0");
91
92 FREQ = CPUFREQ_NORMAL;
93 }
94}
95
96#endif
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/system-target.h b/firmware/target/arm/s3c2440/gigabeat-fx/system-target.h
new file mode 100644
index 0000000000..215b5a4daa
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/system-target.h
@@ -0,0 +1,40 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Greg White
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef SYSTEM_TARGET_H
20#define SYSTEM_TARGET_H
21
22#include "mmu-meg-fx.h"
23#include "system-arm.h"
24
25#define CPUFREQ_DEFAULT 98784000
26#define CPUFREQ_NORMAL 98784000
27#define CPUFREQ_MAX 296352000
28
29#define HAVE_INVALIDATE_ICACHE
30static inline void invalidate_icache(void)
31{
32 clean_dcache();
33 asm volatile(
34 "mov r0, #0 \n"
35 "mcr p15, 0, r0, c7, c5, 0 \n"
36 : : : "r0"
37 );
38}
39
40#endif /* SYSTEM_TARGET_H */
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/usb-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/usb-meg-fx.c
new file mode 100644
index 0000000000..3aed8c3256
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/usb-meg-fx.c
@@ -0,0 +1,94 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "config.h"
20#include <stdbool.h>
21#include "cpu.h"
22#include "system.h"
23#include "kernel.h"
24#include "ata.h"
25
26#define USB_RST_ASSERT GPBDAT &= ~(1 << 4)
27#define USB_RST_DEASSERT GPBDAT |= (1 << 4)
28
29#define USB_VPLUS_PWR_ASSERT GPBDAT |= (1 << 6)
30#define USB_VPLUS_PWR_DEASSERT GPBDAT &= ~(1 << 6)
31
32#define USB_UNIT_IS_PRESENT !(GPFDAT & 0x01)
33#define USB_CRADLE_IS_PRESENT ((GPFDAT &0x02)&&!(GPGDAT&1<<14))
34
35#define USB_CRADLE_BUS_ENABLE GPHDAT |= (1 << 8)
36#define USB_CRADLE_BUS_DISABLE GPHDAT &= ~(1 << 8)
37
38/* The usb detect is one pin to the cpu active low */
39inline bool usb_detect(void)
40{
41 return USB_UNIT_IS_PRESENT | USB_CRADLE_IS_PRESENT;
42}
43
44void usb_init_device(void)
45{
46 /* Input is the default configuration, only pullups need to be disabled */
47 GPFUP|=0x02;
48
49 USB_VPLUS_PWR_ASSERT;
50 GPBCON=( GPBCON&~(1<<13) ) | (1 << 12);
51
52 sleep(HZ/20);
53
54 /* Reset the usb port */
55 USB_RST_ASSERT;
56 GPBCON = (GPBCON & ~0x200) | 0x100; /* Make sure reset line is an output */
57
58 sleep(HZ/25);
59 USB_RST_DEASSERT;
60
61 /* needed to complete the reset */
62 ata_enable(false);
63
64 sleep(HZ/15); /* 66ms */
65
66 ata_enable(true);
67
68 sleep(HZ/25);
69
70 /* leave chip in low power mode */
71 USB_VPLUS_PWR_DEASSERT;
72
73 sleep(HZ/25);
74}
75
76void usb_enable(bool on)
77{
78 if (on)
79 {
80 USB_VPLUS_PWR_ASSERT;
81 if(USB_CRADLE_IS_PRESENT) USB_CRADLE_BUS_ENABLE;
82 }
83 else
84 {
85 if(USB_CRADLE_IS_PRESENT) USB_CRADLE_BUS_DISABLE;
86 USB_VPLUS_PWR_DEASSERT;
87 }
88
89 /* Make sure USB_CRADLE_BUS pin is an output */
90 GPHCON=( GPHCON&~(1<<17) ) | (1<<16); /* Make the pin an output */
91 GPHUP|=1<<8; /* Disable pullup in SOC as we are now driving */
92
93 sleep(HZ/20); // > 50ms for detecting the enable state change
94}
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/usb-target.h b/firmware/target/arm/s3c2440/gigabeat-fx/usb-target.h
new file mode 100644
index 0000000000..baeb539b38
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/usb-target.h
@@ -0,0 +1,26 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef USB_TARGET_H
20#define USB_TARGET_H
21
22bool usb_init_device(void);
23bool usb_detect(void);
24void usb_enable(bool on);
25
26#endif
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c
new file mode 100644
index 0000000000..fe42b7527a
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/wmcodec-meg-fx.c
@@ -0,0 +1,71 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Gigabeat specific code for the Wolfson codec
11 *
12 * Based on code from the ipodlinux project - http://ipodlinux.org/
13 * Adapted for Rockbox in December 2005
14 *
15 * Original file: linux/arch/armnommu/mach-ipod/audio.c
16 *
17 * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org)
18 *
19 * All files in this archive are subject to the GNU General Public License.
20 * See the file COPYING in the source tree root for full license agreement.
21 *
22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
23 * KIND, either express or implied.
24 *
25 ****************************************************************************/
26#include "lcd.h"
27#include "cpu.h"
28#include "kernel.h"
29#include "thread.h"
30#include "power.h"
31#include "debug.h"
32#include "system.h"
33#include "sprintf.h"
34#include "button.h"
35#include "string.h"
36#include "file.h"
37#include "buffer.h"
38#include "audio.h"
39#include "i2c.h"
40#include "i2c-meg-fx.h"
41/*
42 * Reset the I2S BIT.FORMAT I2S, 16bit, FIFO.FORMAT 32bit
43 */
44void i2s_reset(void)
45{
46}
47
48/*
49 * Initialise the WM8975 for playback via headphone and line out.
50 * Note, I'm using the WM8750 datasheet as its apparently close.
51 */
52int audiohw_init(void) {
53 /* reset I2C */
54 i2c_init();
55
56 /* GPC5 controls headphone output */
57 GPCCON &= ~(0x3 << 10);
58 GPCCON |= (1 << 10);
59 GPCDAT |= (1 << 5);
60
61 return 0;
62}
63
64void audiohw_postinit(void)
65{
66}
67
68void wmcodec_write(int reg, int data)
69{
70 i2c_send(0x34, (reg<<1) | ((data&0x100)>>8), data&0xff);
71}