A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2016 by Roman Stolyarov
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "jz4760b.h"
24#include "../kernel-internal.h"
25#include "backlight.h"
26#include "font.h"
27#include "lcd.h"
28#include "file.h"
29#ifdef HAVE_BOOTLOADER_USB_MODE
30#include "usb.h"
31#endif
32#include "system.h"
33#include "button.h"
34#include "common.h"
35#include "rb-loader.h"
36#include "loader_strerror.h"
37#include "storage.h"
38#include "file_internal.h"
39#include "disk.h"
40#include "string.h"
41#include "adc.h"
42#include "version.h"
43
44#include "xdebug.h"
45
46#define SHOW_LOGO
47
48extern void show_logo(void);
49extern void power_off(void);
50
51static int lcd_inited = 0;
52void init_lcd(void)
53{
54 if(lcd_inited)
55 return;
56
57 lcd_init();
58 font_init();
59 lcd_setfont(FONT_SYSFIXED);
60
61 lcd_clear_display();
62 lcd_update();
63
64 backlight_init();
65
66 lcd_inited = true;
67}
68
69#ifdef HAVE_BOOTLOADER_USB_MODE
70static void show_splash(int timeout, const char *msg)
71{
72 init_lcd();
73 reset_screen();
74 lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2,
75 (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg);
76 lcd_update();
77
78 sleep(timeout);
79}
80
81static int usb_inited = 0;
82
83static void usb_mode(void)
84{
85 int button = 0;
86
87 /* Init USB, but only once */
88 if (!usb_inited) {
89 usb_init();
90 usb_start_monitoring();
91 usb_inited = 1;
92 }
93
94 init_lcd();
95 reset_screen();
96
97 /* Wait for USB */
98 show_splash(0, "Waiting for USB");
99 while(1) {
100 button = button_get_w_tmo(HZ/2);
101 if (button == BUTTON_POWER)
102 return;
103 if (button == SYS_USB_CONNECTED)
104 break; /* Hit */
105 }
106
107 /* Got the message - wait for disconnect */
108 show_splash(0, "Bootloader USB mode");
109
110 usb_acknowledge(SYS_USB_CONNECTED_ACK);
111
112 while(1) {
113 button = button_get_w_tmo(HZ/2);
114 if (button == SYS_USB_DISCONNECTED)
115 break;
116 }
117
118 show_splash(HZ*2, "USB disconnected");
119}
120#endif
121
122/* Jump to loaded binary */
123void exec(void* addr) __attribute__((noinline, noreturn, section(".icode")));
124
125void exec(void* addr)
126{
127 commit_discard_idcache();
128 typedef void(*entry_fn)(void) __attribute__((noreturn));
129 entry_fn fn = (entry_fn)addr;
130 fn();
131}
132
133static int boot_rockbox(void)
134{
135 int rc;
136
137 printf("Mounting disk...");
138
139 while((rc = disk_mount_all()) <= 0) {
140 verbose = true;
141#ifdef HAVE_BOOTLOADER_USB_MODE
142 error(EDISK, rc, false);
143 usb_mode();
144#else
145 error(EDISK, rc, true);
146#endif
147 }
148
149 printf("Loading firmware...");
150 rc = load_firmware((unsigned char *)CONFIG_SDRAM_START, BOOTFILE, 0x400000);
151 if(rc <= EFILE_EMPTY) {
152 printf("!! " BOOTFILE);
153 return rc;
154 } else {
155 printf("Starting Rockbox...");
156 adc_close(); /* Disable SADC, seems to fix the re-init Rockbox does */
157 disable_interrupt();
158 exec((void*) CONFIG_SDRAM_START);
159 return 0; /* Shouldn't happen */
160 }
161}
162
163int main(void)
164{
165 int rc;
166
167 serial_puts("\n\nSPL Stage 2\n\n");
168
169 system_init();
170 kernel_init();
171
172 init_lcd();
173#ifdef SHOW_LOGO
174 show_logo();
175#endif
176
177 button_init();
178 enable_irq();
179
180 int btn = button_read_device();
181 if(btn & BUTTON_POWER) {
182 verbose = true;
183 }
184
185 rc = storage_init();
186 if(rc) {
187 verbose = true;
188 error(EATA, rc, true);
189 }
190
191 filesystem_init();
192
193#ifdef HAVE_BOOTLOADER_USB_MODE
194 /* Enter USB mode if USB is plugged and POWER button is pressed */
195 if (btn & BUTTON_POWER) {
196 usb_mode();
197 reset_screen();
198 }
199#endif /* HAVE_BOOTLOADER_USB_MODE */
200
201#ifndef SHOW_LOGO
202 printf(MODEL_NAME" Rockbox Bootloader");
203 printf("Version %s", rbversion);
204#endif
205
206 rc = boot_rockbox();
207
208 if(rc <= EFILE_EMPTY) {
209 verbose = true;
210 printf("Error: %s", loader_strerror(rc));
211 }
212
213 /* Power off */
214 sleep(5*HZ);
215 power_off();
216
217 return 0;
218}