wpsbuild: Rewrite to fix various issues and support .fms
[maemo-rb.git] / bootloader / samsung_yps3.c
blobb80fbf542116dbee2cb73076c6770bcf027daf60
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2009 by Bertrik Sikken
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <string.h>
27 #include "config.h"
29 #include "inttypes.h"
30 #include "cpu.h"
31 #include "system.h"
32 #include "lcd.h"
33 #include "kernel.h"
34 #include "thread.h"
35 #include "backlight.h"
36 #include "backlight-target.h"
37 #include "button.h"
38 #include "panic.h"
39 #include "power.h"
40 #include "common.h"
41 #include "usb.h"
42 #include "bitmaps/rockboxlogo.h"
44 #include "adc.h"
45 #include "adc-target.h"
47 #include "timer.h"
49 #include "i2c-s5l8700.h"
50 #include "dma-target.h"
51 #include "pcm.h"
52 #include "audiohw.h"
53 #include "rtc.h"
54 #include "tuner.h"
55 #include "si4700.h"
56 #include "fmradio_i2c.h"
57 #include "wmcodec.h"
58 #include "nand-target.h"
60 #define LONG_DELAY 200000
61 #define SHORT_DELAY 50000
62 #define PAUSE_DELAY 50000
64 static inline void delay(unsigned int duration)
66 volatile unsigned int i;
67 for(i=0;i<duration;i++);
70 // forward declaration
71 static int rds_decode(int line, struct si4700_dbg_info *nfo);
73 void main(void)
75 char mystring[64];
76 int line, col;
77 struct tm dt;
78 int i;
79 struct si4700_dbg_info si4700_info;
80 int brightness = DEFAULT_BRIGHTNESS_SETTING;
81 unsigned int button;
82 unsigned int fm_frequency = 100700000;
83 int audiovol = 0x60;
84 unsigned nand_ids[4];
86 // enable all peripherals
87 PWRCON = 0;
89 // disable all interrupts
90 INTMSK = 0;
92 // start with all GPIOs as input
93 PCON0 = 0;
94 PCON1 = 0;
95 PCON2 = 0;
96 PCON3 = 0;
97 PCON4 = 0;
98 PCON5 = 0;
99 PCON6 = 0;
100 PCON7 = 0;
102 system_init();
103 kernel_init();
105 asm volatile("msr cpsr_c, #0x13\n\t"); // enable interrupts
107 lcd_init();
109 lcd_clear_display();
110 lcd_bitmap(rockboxlogo, 0, 160, BMPWIDTH_rockboxlogo, BMPHEIGHT_rockboxlogo);
111 lcd_update();
113 power_init();
115 i2c_init();
116 fmradio_i2c_init();
117 adc_init();
118 _backlight_init();
119 button_init_device();
121 // FM power
122 si4700_init();
123 tuner_power(true);
124 si4700_set(RADIO_SLEEP, 0);
125 si4700_set(RADIO_MUTE, 0);
126 si4700_set(RADIO_REGION, 0);
127 si4700_set(RADIO_FREQUENCY, fm_frequency);
129 lcd_puts_scroll(0,0,"+++ this is a very very long line to test scrolling. ---");
131 // WM1800 codec configuration
132 wmcodec_write(0x0F, 0); // codec reset
133 wmcodec_write(0x19, 0xF0); // pwr mgmt1: VMID = 1, VREF, AINL, AINR
134 wmcodec_write(0x1A, 0x60); // pwr mgmt2: LOUT1, ROUT1
135 wmcodec_write(0x2F, 0x0C); // pwr mgmt3: LOMIX, ROMIX
136 wmcodec_write(0x02, audiovol); // LOUT1VOL
137 wmcodec_write(0x03, audiovol | (1 << 8)); // ROUT1VOL
138 wmcodec_write(0x22, (1 << 7) | (7 << 4)); // left out mix (1)
139 wmcodec_write(0x25, (1 << 7) | (7 << 4)); // right out mix (2)
141 // enable audio
142 PCON5 = (PCON5 & ~0x0000000F) | 0x00000001;
143 PDAT5 |= 1;
145 nand_ll_init();
146 for (i = 0; i < 4; i++) {
147 nand_ids[i] = nand_ll_read_id(i);
150 while (true)
152 line = 1;
154 #if 1 /* enable to see GPIOs */
155 snprintf(mystring, 64, "%02X %02X %02X %02X %02X %02X %02X %02X",
156 PDAT0, PDAT1, PDAT2, PDAT3, PDAT4, PDAT5, PDAT6, PDAT7);
157 lcd_puts(0, line++, mystring);
158 #endif
160 #if 1 /* enable this to see info about the RTC */
161 rtc_read_datetime(&dt);
162 snprintf(mystring, 64, "RTC: %04d-%02d-%02d %02d:%02d:%02d",
163 dt.tm_year + 1900, dt.tm_mon+1, dt.tm_mday,
164 dt.tm_hour, dt.tm_min, dt.tm_sec);
165 lcd_puts(0, line++, mystring);
166 #endif
168 #if 1 /* enable this to see radio debug info */
169 button = button_read_device();
170 if (button & BUTTON_RIGHT) {
171 fm_frequency += 100000;
172 si4700_set(RADIO_FREQUENCY, fm_frequency);
174 if (button & BUTTON_LEFT) {
175 fm_frequency -= 100000;
176 si4700_set(RADIO_FREQUENCY, fm_frequency);
178 snprintf(mystring, 64, "FM frequency: %9d", fm_frequency);
179 lcd_puts(0, line++, mystring);
181 si4700_dbg_info(&si4700_info);
182 col = snprintf(mystring, 64, "FM: ");
183 for (i = 0; i < 16; i++) {
184 col += snprintf(mystring + col, 64, "%04X ", si4700_info.regs[i]);
185 if (((i + 1) % 4) == 0) {
186 lcd_puts(0, line++, mystring);
187 col = 4;
190 line = rds_decode(line, &si4700_info);
191 #endif
193 #if 1 /* volume control with up/down keys */
194 button = button_read_device();
195 if (button & BUTTON_UP) {
196 if (audiovol < 127) {
197 audiovol++;
198 wmcodec_write(0x02, audiovol);
199 wmcodec_write(0x03, (1 << 8) | audiovol);
202 if (button & BUTTON_DOWN) {
203 if (audiovol > 0) {
204 audiovol--;
205 wmcodec_write(0x02, audiovol);
206 wmcodec_write(0x03, (1 << 8) | audiovol);
209 snprintf(mystring, 64, "volume %3d", audiovol);
210 lcd_puts(0, line++, mystring);
211 #endif
213 #if 1 /* enable this to see ADC info */
214 snprintf(mystring, 64, "ADC: %04X %04X %04X %04X",
215 adc_read(0), adc_read(1), adc_read(2), adc_read(3));
216 lcd_puts(0, line++, mystring);
217 snprintf(mystring, 64, "ADC:USB %4d mV BAT %4d mV",
218 (adc_read(0) * 6000) >> 10, (adc_read(2) * 4650) >> 10);
219 lcd_puts(0, line++, mystring);
220 #endif
222 #if 1 /* enable this so see USB info */
223 snprintf(mystring, 64, "CLK %08X CLK2 %08X", CLKCON, CLKCON2);
224 lcd_puts(0, line++, mystring);
226 snprintf(mystring, 64, "%04X %04X %04X %04X", PHYCTRL, PHYPWR, URSTCON, UCLKCON);
227 lcd_puts(0, line++, mystring);
229 snprintf(mystring, 64, "SCR %04X SSR %04X EIR %04X", USB_SCR, USB_SSR, USB_EIR);
230 lcd_puts(0, line++, mystring);
232 snprintf(mystring, 64, "FAR %04X FNR %04X EP0 %04X", USB_FAR, USB_FNR, USB_EP0SR);
233 lcd_puts(0, line++, mystring);
234 #endif
236 #if 1 /* button lights controlled by keypad */
237 button = button_read_device();
238 if (button & (BUTTON_UP | BUTTON_DOWN | BUTTON_LEFT | BUTTON_RIGHT)) {
239 PDAT3 |= (1 << 3);
241 else {
242 PDAT3 &= ~(1 << 3);
244 if (button & (BUTTON_BACK | BUTTON_MENU)) {
245 PDAT3 |= (1 << 2);
247 else {
248 PDAT3 &= ~(1 << 2);
250 if (button & (BUTTON_SELECT)) {
251 PDAT4 |= (1 << 2);
253 else {
254 PDAT4 &= ~(1 << 2);
256 #endif
258 #if 1 /* backlight brightness controlled by up/down keys */
259 button = button_read_device();
260 if (button & BUTTON_MENU) {
261 if (brightness < MAX_BRIGHTNESS_SETTING) {
262 brightness++;
263 _backlight_set_brightness(brightness);
266 else if (button & BUTTON_BACK) {
267 if (brightness > MIN_BRIGHTNESS_SETTING) {
268 brightness--;
269 _backlight_set_brightness(brightness);
272 snprintf(mystring, 64, "brightness %3d", brightness);
273 lcd_puts(0, line++, mystring);
274 #endif
276 #if 1 /* power off using power button */
277 button = button_read_device();
278 if (button & BUTTON_POWER) {
279 power_off();
281 #endif
283 #if 1 /* button info */
284 snprintf(mystring, 64, "BUTTONS %08X, %s", button_read_device(),
285 headphones_inserted() ? "HP" : "hp");
286 lcd_puts(0, line++, mystring);
287 #endif
289 #if 1 /* NAND debug */
290 snprintf(mystring, 64, "NAND ID: %08X %08X", nand_ids[0], nand_ids[1]);
291 lcd_puts(0, line++, mystring);
292 snprintf(mystring, 64, "NAND ID: %08X %08X", nand_ids[2], nand_ids[3]);
293 lcd_puts(0, line++, mystring);
294 #endif
296 #if 1
297 snprintf(mystring, 64, "TIMER A:%08X B:%08X", TACNT, TBCNT);
298 lcd_puts(0, line++, mystring);
299 snprintf(mystring, 64, "TIMER C:%08X D:%08X", TCCNT, TDCNT);
300 lcd_puts(0, line++, mystring);
301 #endif
303 lcd_update();
308 static int rds_decode(int line, struct si4700_dbg_info *nfo)
310 unsigned short rdsdata[4];
311 unsigned int pi, group, tp, pty, segment, abflag;
312 static unsigned int af1 = 0, af2 = 0;
313 static unsigned int day = 0, hour = 0, minute = 0;
314 static unsigned int abflag_prev = -1;
315 static char mystring[64];
317 /* big RDS arrays */
318 static char ps[9];
319 static char rt[65];
321 rdsdata[0] = nfo->regs[12];
322 rdsdata[1] = nfo->regs[13];
323 rdsdata[2] = nfo->regs[14];
324 rdsdata[3] = nfo->regs[15];
326 pi = rdsdata[0];
327 group = (rdsdata[1] >> 11) & 0x1F;
328 tp = (rdsdata[1] >> 10) & 1;
329 pty = (rdsdata[1] >> 5) & 0x1F;
331 switch (group) {
333 case 0: /* group 0A: basic info */
334 af1 = (rdsdata[2] >> 8) & 0xFF;
335 af2 = (rdsdata[2] >> 0) & 0xFF;
336 /* fall through */
337 case 1: /* group 0B: basic info */
338 segment = rdsdata[1] & 3;
339 ps[segment * 2 + 0] = (rdsdata[3] >> 8) & 0xFF;
340 ps[segment * 2 + 1] = (rdsdata[3] >> 0) & 0xFF;
341 break;
343 case 2: /* group 1A: programme item */
344 case 3: /* group 1B: programme item */
345 day = (rdsdata[3] >> 11) & 0x1F;
346 hour = (rdsdata[3] >> 6) & 0x1F;
347 minute = (rdsdata[3] >> 0) & 0x3F;
348 break;
350 case 4: /* group 2A: radio text */
351 segment = rdsdata[1] & 0xF;
352 abflag = (rdsdata[1] >> 4) & 1;
353 if (abflag != abflag_prev) {
354 memset(rt, '.', 64);
355 abflag_prev = abflag;
357 rt[segment * 4 + 0] = (rdsdata[2] >> 8) & 0xFF;
358 rt[segment * 4 + 1] = (rdsdata[2] >> 0) & 0xFF;
359 rt[segment * 4 + 2] = (rdsdata[3] >> 8) & 0xFF;
360 rt[segment * 4 + 3] = (rdsdata[3] >> 0) & 0xFF;
361 break;
363 case 5: /* group 2B: radio text */
364 segment = rdsdata[1] & 0xF;
365 abflag = (rdsdata[1] >> 4) & 1;
366 if (abflag != abflag_prev) {
367 memset(rt, '.', 64);
368 abflag_prev = abflag;
370 rt[segment * 2 + 0] = (rdsdata[3] >> 8) & 0xFF;
371 rt[segment * 2 + 1] = (rdsdata[3] >> 0) & 0xFF;
372 break;
374 default:
375 break;
378 snprintf(mystring, 64, "PI:%04X,TP:%d,PTY:%2d,AF:%02X/%02X", pi, tp, pty, af1, af2);
379 lcd_puts(0, line++, mystring);
380 snprintf(mystring, 64, "PS:%s,ITEM:%02d-%02d:%02d", ps, day, hour, minute);
381 lcd_puts(0, line++, mystring);
382 snprintf(mystring, 64, "RT:%s", rt);
383 lcd_puts(0, line++, mystring);
385 return line;