summaryrefslogtreecommitdiffstats
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/as3525/lcd-ssd1303.c3
-rw-r--r--firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c3
-rw-r--r--firmware/target/arm/imx233/creative-zen/lcd-zenmozaic.c4
-rw-r--r--firmware/target/arm/imx233/creative-zen/lcd-zenv.c3
-rw-r--r--firmware/target/arm/imx233/creative-zen/lcd-zenxfistyle.c3
-rw-r--r--firmware/target/arm/imx233/creative-zenxfi2/lcd-zenxfi2.c3
-rw-r--r--firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c3
-rw-r--r--firmware/target/arm/imx233/debug-imx233.c6
-rw-r--r--firmware/target/arm/imx233/sansa-fuzeplus/lcd-fuzeplus.c3
-rw-r--r--firmware/target/arm/imx233/sony-nwz/lcd-nwze360.c3
-rw-r--r--firmware/target/arm/imx233/sony-nwz/lcd-nwze370.c3
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c49
-rw-r--r--firmware/target/arm/ipod/lcd-gray.c9
-rw-r--r--firmware/target/arm/lcd-ssd1815.c6
-rw-r--r--firmware/target/arm/olympus/mrobe-100/lcd-mr100.c6
-rw-r--r--firmware/target/arm/pp/mi4-loader.c89
-rw-r--r--firmware/target/arm/rk27xx/lcdif-rk27xx.c3
-rw-r--r--firmware/target/arm/s5l8700/debug-s5l8700.c4
-rw-r--r--firmware/target/arm/s5l8700/yps3/lcd-yps3.c11
-rw-r--r--firmware/target/arm/s5l8702/debug-s5l8702.c4
-rw-r--r--firmware/target/arm/samsung/yh920/lcd-yh920.c3
-rw-r--r--firmware/target/coldfire/iaudio/m3/lcd-m3.c6
-rw-r--r--firmware/target/coldfire/iaudio/m5/lcd-m5.c6
-rw-r--r--firmware/target/coldfire/iriver/h100/lcd-h100.c6
-rw-r--r--firmware/target/coldfire/mpio/hd300/lcd-hd300.c3
-rw-r--r--firmware/target/hosted/ibasso/dx50/adc-target.h (renamed from firmware/target/mips/ingenic_x1000/fiiom3k/powermgmt-target.h)0
-rw-r--r--firmware/target/hosted/ibasso/dx90/adc-target.h0
-rw-r--r--firmware/target/hosted/ibasso/pcm-ibasso.c2
-rw-r--r--firmware/target/hosted/ibasso/sysfs-ibasso.c2
-rw-r--r--firmware/target/hosted/rolo.c16
-rw-r--r--firmware/target/hosted/sdl/sim-ui-defines.h8
-rw-r--r--firmware/target/hosted/system-hosted.c1
-rw-r--r--firmware/target/hosted/usb-hiby.c4
-rw-r--r--firmware/target/mips/ingenic_jz47xx/xduoo_x3/lcd-xduoo_x3.c6
-rw-r--r--firmware/target/mips/ingenic_x1000/app.lds18
-rw-r--r--firmware/target/mips/ingenic_x1000/boot-x1000.c280
-rw-r--r--firmware/target/mips/ingenic_x1000/boot-x1000.h38
-rw-r--r--firmware/target/mips/ingenic_x1000/clk-x1000.c59
-rw-r--r--firmware/target/mips/ingenic_x1000/clk-x1000.h4
-rw-r--r--firmware/target/mips/ingenic_x1000/crt0.S126
-rw-r--r--firmware/target/mips/ingenic_x1000/debug-x1000.c6
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c23
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c25
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c129
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c23
-rw-r--r--firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c116
-rw-r--r--firmware/target/mips/ingenic_x1000/installer-x1000.c2
-rw-r--r--firmware/target/mips/ingenic_x1000/lcd-x1000.h8
-rw-r--r--firmware/target/mips/ingenic_x1000/nand-x1000.c17
-rw-r--r--firmware/target/mips/ingenic_x1000/nand-x1000.h3
-rw-r--r--firmware/target/mips/ingenic_x1000/pcm-x1000.c179
-rw-r--r--firmware/target/mips/ingenic_x1000/sfc-x1000.h4
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/audiohw-shanlingq1.c4
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c23
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/spl-shanlingq1.c116
-rw-r--r--firmware/target/mips/ingenic_x1000/spl-nand-x1000.c (renamed from firmware/target/mips/ingenic_x1000/erosqnative/spl-erosqnative.c)51
-rw-r--r--firmware/target/mips/ingenic_x1000/spl-x1000.c224
-rw-r--r--firmware/target/mips/ingenic_x1000/spl-x1000.h24
-rw-r--r--firmware/target/mips/ingenic_x1000/spl.lds6
-rw-r--r--firmware/target/mips/ingenic_x1000/system-x1000.c1
60 files changed, 961 insertions, 829 deletions
diff --git a/firmware/target/arm/as3525/lcd-ssd1303.c b/firmware/target/arm/as3525/lcd-ssd1303.c
index 2aa0b844c5..186fdcacbe 100644
--- a/firmware/target/arm/as3525/lcd-ssd1303.c
+++ b/firmware/target/arm/as3525/lcd-ssd1303.c
@@ -310,6 +310,7 @@ static void internal_update_rect(int x, int y, int width, int height)
const int column_high = get_column_high_byte(x);
const int column_low = get_column_low_byte(x);
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy specified rectange bitmap to hardware */
for (; y <= height; y++)
{
@@ -320,7 +321,7 @@ static void internal_update_rect(int x, int y, int width, int height)
(column_low)
);
- lcd_write_data (FBADDR(x,y), width);
+ lcd_write_data (fbaddr(x,y), width);
}
lcd_write_command (LCD_NOP); /* return to command mode */
diff --git a/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c b/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
index 03ed1de5d5..48594a2ac9 100644
--- a/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
+++ b/firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c
@@ -440,9 +440,10 @@ void lcd_update_rect(int x, int y, int width, int height)
/* setup GRAM write window */
lcd_setup_rect(x, x_end - 1, y, y_end - 1);
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* write to GRAM */
for (row = y; row < y_end; row++) {
- lcd_write_data(FBADDR(x,row), width);
+ lcd_write_data(fbaddr(x,row), width);
}
}
diff --git a/firmware/target/arm/imx233/creative-zen/lcd-zenmozaic.c b/firmware/target/arm/imx233/creative-zen/lcd-zenmozaic.c
index c1bc379a49..ab4466300b 100644
--- a/firmware/target/arm/imx233/creative-zen/lcd-zenmozaic.c
+++ b/firmware/target/arm/imx233/creative-zen/lcd-zenmozaic.c
@@ -149,6 +149,8 @@ void lcd_update_rect(int x, int y, int w, int h)
lcd_write_reg(0x17, y | (y + h - 1) << 8);
lcd_write_reg(0x21, y * LCD_WIDTH + x);
lcd_write_reg(0x22, 0);
+
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
for(int yy = y; yy < y + h; yy++)
- imx233_lcdif_pio_send(true, 2 * w, FBADDR(x, yy));
+ imx233_lcdif_pio_send(true, 2 * w, fbaddr(x,yy));
}
diff --git a/firmware/target/arm/imx233/creative-zen/lcd-zenv.c b/firmware/target/arm/imx233/creative-zen/lcd-zenv.c
index 06b0f158f3..75d2775814 100644
--- a/firmware/target/arm/imx233/creative-zen/lcd-zenv.c
+++ b/firmware/target/arm/imx233/creative-zen/lcd-zenv.c
@@ -172,8 +172,9 @@ void lcd_update_rect(int x, int y, int w, int h)
lcd_send(false, 0x75); lcd_send(true, y); lcd_send(true, y + h - 1);
lcd_send(false, 0x5c);
imx233_lcdif_set_word_length(16);
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
for(int yy = y; yy < y + h; yy++)
- imx233_lcdif_pio_send(true, w, FBADDR(x, yy));
+ imx233_lcdif_pio_send(true, w, fbaddr(x,yy));
}
#ifndef BOOTLOADER
diff --git a/firmware/target/arm/imx233/creative-zen/lcd-zenxfistyle.c b/firmware/target/arm/imx233/creative-zen/lcd-zenxfistyle.c
index ce0bcc3885..825b0072a3 100644
--- a/firmware/target/arm/imx233/creative-zen/lcd-zenxfistyle.c
+++ b/firmware/target/arm/imx233/creative-zen/lcd-zenxfistyle.c
@@ -282,8 +282,9 @@ void lcd_update_rect(int x, int y, int w, int h)
}
else
{
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
for(int i = 0; i < h; i++)
- memcpy((fb_data *)FRAME + i * w, FBADDR(x,y + i), w * sizeof(fb_data));
+ memcpy((fb_data *)FRAME + i * w, fbaddr(x,y + i), w * sizeof(fb_data));
}
/* WARNING The LCDIF has a limitation on the vertical count ! In 16-bit packed mode
* (which we used, ie 16-bit per pixel, 2 pixels per 32-bit words), the v_count
diff --git a/firmware/target/arm/imx233/creative-zenxfi2/lcd-zenxfi2.c b/firmware/target/arm/imx233/creative-zenxfi2/lcd-zenxfi2.c
index 890ff0b586..d0084900e7 100644
--- a/firmware/target/arm/imx233/creative-zenxfi2/lcd-zenxfi2.c
+++ b/firmware/target/arm/imx233/creative-zenxfi2/lcd-zenxfi2.c
@@ -241,8 +241,9 @@ void lcd_update_rect(int x, int y, int w, int h)
}
else
{
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
for(int i = 0; i < h; i++)
- memcpy((fb_data *)FRAME + i * w, FBADDR(x,y + i), w * sizeof(fb_data));
+ memcpy((fb_data *)FRAME + i * w, fbaddr(x,y + i), w * sizeof(fb_data));
}
/* WARNING The LCDIF has a limitation on the vertical count ! In 16-bit packed mode
* (which we used, ie 16-bit per pixel, 2 pixels per 32-bit words), the v_count
diff --git a/firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c b/firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c
index 59496f2d24..d5f25a523c 100644
--- a/firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c
+++ b/firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c
@@ -188,8 +188,9 @@ void lcd_update_rect(int x, int y, int w, int h)
}
else
{
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
for(int i = 0; i < h; i++)
- memcpy((fb_data *)FRAME + i * w, FBADDR(x,y + i), w * sizeof(fb_data));
+ memcpy((fb_data *)FRAME + i * w, fbaddr(x,y + i), w * sizeof(fb_data));
}
/* WARNING The LCDIF has a limitation on the vertical count ! In 16-bit packed mode
* (which we used, ie 16-bit per pixel, 2 pixels per 32-bit words), the v_count
diff --git a/firmware/target/arm/imx233/debug-imx233.c b/firmware/target/arm/imx233/debug-imx233.c
index bfc38b20dc..4487952162 100644
--- a/firmware/target/arm/imx233/debug-imx233.c
+++ b/firmware/target/arm/imx233/debug-imx233.c
@@ -940,8 +940,8 @@ bool dbg_hw_info_emi(void)
bool dbg_hw_info_audio(void)
{
- static const char *hp_sel[2] = {"DAC", "Line1"};
- static const char *mux_sel[4] = {"Mic", "Line1", "HP", "Line2"};
+ static const char * const hp_sel[2] = {"DAC", "Line1"};
+ static const char * const mux_sel[4] = {"Mic", "Line1", "HP", "Line2"};
lcd_setfont(FONT_SYSFIXED);
while(1)
@@ -1171,7 +1171,7 @@ bool dbg_hw_info_button(void)
}
else if(MAP[i].periph == IMX233_BUTTON_LRADC)
{
- static const char *op_name[] =
+ static const char * const op_name[] =
{
[IMX233_BUTTON_EQ] = "eq",
[IMX233_BUTTON_GT] = "gt",
diff --git a/firmware/target/arm/imx233/sansa-fuzeplus/lcd-fuzeplus.c b/firmware/target/arm/imx233/sansa-fuzeplus/lcd-fuzeplus.c
index 92864c9ed7..ceb7b4e090 100644
--- a/firmware/target/arm/imx233/sansa-fuzeplus/lcd-fuzeplus.c
+++ b/firmware/target/arm/imx233/sansa-fuzeplus/lcd-fuzeplus.c
@@ -637,8 +637,9 @@ void lcd_update_rect(int x, int y, int w, int h)
}
else
{
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
for(int i = 0; i < h; i++)
- memcpy((fb_data *)FRAME + i * w, FBADDR(x,y + i), w * sizeof(fb_data));
+ memcpy((fb_data *)FRAME + i * w, fbaddr(x,y + i), w * sizeof(fb_data));
}
/* WARNING The LCDIF has a limitation on the vertical count ! In 16-bit packed mode
* (which we used, ie 16-bit per pixel, 2 pixels per 32-bit words), the v_count
diff --git a/firmware/target/arm/imx233/sony-nwz/lcd-nwze360.c b/firmware/target/arm/imx233/sony-nwz/lcd-nwze360.c
index cfcf85bfc0..8f49bfa3eb 100644
--- a/firmware/target/arm/imx233/sony-nwz/lcd-nwze360.c
+++ b/firmware/target/arm/imx233/sony-nwz/lcd-nwze360.c
@@ -228,8 +228,9 @@ void lcd_update_rect(int x, int y, int w, int h)
}
else
{
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
for(int i = 0; i < h; i++)
- memcpy((fb_data *)FRAME + i * w, FBADDR(x,y + i), w * sizeof(fb_data));
+ memcpy((fb_data *)FRAME + i * w, fbaddr(x,y + i), w * sizeof(fb_data));
}
/* WARNING The LCDIF has a limitation on the vertical count ! In 16-bit packed mode
* (which we used, ie 16-bit per pixel, 2 pixels per 32-bit words), the v_count
diff --git a/firmware/target/arm/imx233/sony-nwz/lcd-nwze370.c b/firmware/target/arm/imx233/sony-nwz/lcd-nwze370.c
index 999f4ee525..862522da15 100644
--- a/firmware/target/arm/imx233/sony-nwz/lcd-nwze370.c
+++ b/firmware/target/arm/imx233/sony-nwz/lcd-nwze370.c
@@ -189,8 +189,9 @@ void lcd_update_rect(int x, int y, int w, int h)
}
else
{
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
for(int i = 0; i < h; i++)
- memcpy((fb_data *)FRAME + i * w, FBADDR(x,y + i), w * sizeof(fb_data));
+ memcpy((fb_data *)FRAME + i * w, fbaddr(x,y + i), w * sizeof(fb_data));
}
/* WARNING The LCDIF has a limitation on the vertical count ! In 16-bit packed mode
* (which we used, ie 16-bit per pixel, 2 pixels per 32-bit words), the v_count
diff --git a/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c
index 5b0c71110d..c84f1cf41c 100644
--- a/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c
@@ -125,53 +125,30 @@ bool si4700_st(void)
return (GPIO1_DR & (1 << 28)) >> 28;
}
-
/* Low-level RDS Support */
-static bool int_restore;
-
-/* Called after I2C read cycle completes */
-static void si4700_rds_read_raw_async_callback(struct i2c_transfer_desc *xfer)
-{
- if (xfer->rxcount == 0)
- si4700_rds_process();
- /* else read didn't finish */
-
- if (int_restore)
- gpio_int_enable(SI4700_EVENT_ID);
-}
-
-/* Called to read registers from ISR context */
-void si4700_rds_read_raw_async(unsigned char *buf, int count)
-{
- /* transfer descriptor for RDS async operations */
- static struct i2c_transfer_desc xfer = { .node = &si4700_i2c_node };
-
- xfer.txdata = NULL;
- xfer.txcount = 0;
- xfer.rxdata = buf;
- xfer.rxcount = count;
- xfer.callback = si4700_rds_read_raw_async_callback;
- xfer.next = NULL;
-
- i2c_transfer(&xfer);
-}
+static struct semaphore rds_sema;
+static uint32_t rds_stack[DEFAULT_STACK_SIZE/sizeof(uint32_t)];
/* RDS GPIO interrupt handler - start RDS data read */
void INT_SI4700_RDS(void)
{
- /* mask and clear the interrupt until we're done */
- gpio_int_disable(SI4700_EVENT_ID);
gpio_int_clear(SI4700_EVENT_ID);
+ semaphore_release(&rds_sema);
+}
- /* tell radio driver about it */
- si4700_rds_interrupt();
+/* Captures RDS data and processes it */
+static void NORETURN_ATTR rds_thread(void)
+{
+ while (true) {
+ semaphore_wait(&rds_sema, TIMEOUT_BLOCK);
+ si4700_rds_process();
+ }
}
/* Called with on=true after full radio power up, and with on=false before
powering down */
void si4700_rds_powerup(bool on)
{
- int_restore = on;
gpio_int_disable(SI4700_EVENT_ID);
gpio_int_clear(SI4700_EVENT_ID);
gpio_enable_event(SI4700_EVENT_ID, on);
@@ -180,5 +157,7 @@ void si4700_rds_powerup(bool on)
/* One-time RDS init at startup */
void si4700_rds_init(void)
{
- /* nothing to do */
+ semaphore_init(&rds_sema, 1, 0);
+ create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds"
+ IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU));
}
diff --git a/firmware/target/arm/ipod/lcd-gray.c b/firmware/target/arm/ipod/lcd-gray.c
index d8695cdb10..883897b997 100644
--- a/firmware/target/arm/ipod/lcd-gray.c
+++ b/firmware/target/arm/ipod/lcd-gray.c
@@ -333,17 +333,18 @@ void lcd_update_rect(int x, int y, int width, int height)
x >>= 3;
width = xmax - x + 1;
- for (; y <= ymax; y++)
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
+ for (; y <= ymax; y++)
{
lcd_cmd_and_data(R_RAM_ADDR_SET, (y << 5) + addr_offset - x);
lcd_prepare_cmd(R_RAM_DATA);
-
+ fb_data *data = fbaddr(2*x,y);
#if defined(IPOD_MINI) || defined(IPOD_MINI2G)
if (pix_offset == -2)
- lcd_write_data_shifted(FBADDR(2*x, y), width);
+ lcd_write_data_shifted(data, width);
else
#endif
- lcd_write_data(FBADDR(2*x, y), width);
+ lcd_write_data(data, width);
}
}
diff --git a/firmware/target/arm/lcd-ssd1815.c b/firmware/target/arm/lcd-ssd1815.c
index 028362f91c..0af20cd34f 100644
--- a/firmware/target/arm/lcd-ssd1815.c
+++ b/firmware/target/arm/lcd-ssd1815.c
@@ -221,6 +221,7 @@ void lcd_update(void)
{
int y;
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy display bitmap to hardware */
for (y = 0; y < LCD_FBHEIGHT; y++)
{
@@ -228,7 +229,7 @@ void lcd_update(void)
lcd_write_command (LCD_CNTL_HIGHCOL | ((xoffset >> 4) & 0xf));
lcd_write_command (LCD_CNTL_LOWCOL | (xoffset & 0xf));
- lcd_write_data (FBADDR(0, y), LCD_WIDTH);
+ lcd_write_data (fbaddr(0,y), LCD_WIDTH);
}
}
@@ -249,6 +250,7 @@ void lcd_update_rect(int x, int y, int width, int height)
if(ymax >= LCD_FBHEIGHT)
ymax = LCD_FBHEIGHT-1;
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy specified rectange bitmap to hardware */
for (; y <= ymax; y++)
{
@@ -256,6 +258,6 @@ void lcd_update_rect(int x, int y, int width, int height)
lcd_write_command (LCD_CNTL_HIGHCOL | (((x+xoffset) >> 4) & 0xf));
lcd_write_command (LCD_CNTL_LOWCOL | ((x+xoffset) & 0xf));
- lcd_write_data (FBADDR(x,y), width);
+ lcd_write_data (fbaddr(x,y), width);
}
}
diff --git a/firmware/target/arm/olympus/mrobe-100/lcd-mr100.c b/firmware/target/arm/olympus/mrobe-100/lcd-mr100.c
index d336ad7419..c10b4ca8f6 100644
--- a/firmware/target/arm/olympus/mrobe-100/lcd-mr100.c
+++ b/firmware/target/arm/olympus/mrobe-100/lcd-mr100.c
@@ -232,6 +232,7 @@ void lcd_update(void)
cmd1 = LCD_CNTL_HIGHCOL | (((xoffset) >> 4) & 0xf);
cmd2 = LCD_CNTL_LOWCOL | ((xoffset) & 0xf);
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy display bitmap to hardware */
for (y = 0; y < LCD_FBHEIGHT; y++)
{
@@ -239,7 +240,7 @@ void lcd_update(void)
lcd_write_command(cmd1);
lcd_write_command(cmd2);
- lcd_write_data (FBADDR(0, y), LCD_WIDTH);
+ lcd_write_data (fbaddr(0,y), LCD_WIDTH);
}
}
@@ -264,6 +265,7 @@ void lcd_update_rect(int x, int y, int width, int height)
cmd1 = LCD_CNTL_HIGHCOL | (((x + xoffset) >> 4) & 0xf);
cmd2 = LCD_CNTL_LOWCOL | ((x + xoffset) & 0xf);
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy specified rectange bitmap to hardware */
for (; y <= ymax; y++)
{
@@ -271,6 +273,6 @@ void lcd_update_rect(int x, int y, int width, int height)
lcd_write_command(cmd1);
lcd_write_command(cmd2);
- lcd_write_data (FBADDR(x,y), width);
+ lcd_write_data (fbaddr(x,y), width);
}
}
diff --git a/firmware/target/arm/pp/mi4-loader.c b/firmware/target/arm/pp/mi4-loader.c
index 0104496e9d..f609e3ff7a 100644
--- a/firmware/target/arm/pp/mi4-loader.c
+++ b/firmware/target/arm/pp/mi4-loader.c
@@ -30,96 +30,9 @@
#include "crc32.h"
#include "file.h"
#if defined(HAVE_BOOTDATA)
-#include "system.h"
-#include "bootdata.h"
-
-/* Write bootdata into location in FIRMWARE marked by magic header
- * Assumes buffer is already loaded with the firmware image
- * We just need to find the location and write data into the
- * payload region along with the crc for later verification and use.
- * Returns payload len on success,
- * On error returns EKEY_NOT_FOUND
- */
-int write_bootdata(unsigned char* buf, int len, unsigned int boot_volume)
-{
- struct boot_data_t bl_boot_data;
- struct boot_data_t *fw_boot_data = NULL;
- int search_len = MIN(len, BOOT_DATA_SEARCH_SIZE) - sizeof(struct boot_data_t);
- int payload_len = EKEY_NOT_FOUND;
-
- /* search for boot data header prior to search_len */
- for(int i = 0;i < search_len;i++)
- {
- fw_boot_data = (struct boot_data_t*) &buf[i];
- if (fw_boot_data->magic[0] != BOOT_DATA_MAGIC0 ||
- fw_boot_data->magic[1] != BOOT_DATA_MAGIC1)
- continue;
-
- memset(&bl_boot_data.payload, 0, BOOT_DATA_PAYLOAD_SIZE);
- bl_boot_data.boot_volume = boot_volume;
-
- memset(fw_boot_data->payload, 0, fw_boot_data->length);
- /* determine maximum bytes we can write to firmware
- BOOT_DATA_PAYLOAD_SIZE is the size the bootloader expects */
- payload_len = MIN(BOOT_DATA_PAYLOAD_SIZE, fw_boot_data->length);
- fw_boot_data->length = payload_len;
- /* copy data to FIRMWARE bootdata struct */
- memcpy(fw_boot_data->payload, &bl_boot_data.payload, payload_len);
- /* crc will be used within the firmware to check validity of bootdata */
- fw_boot_data->crc = crc_32(fw_boot_data->payload, payload_len, 0xffffffff);
- break;
-
- }
- return payload_len;
-}
+#include "multiboot.h"
#endif /* HAVE_BOOTDATA */
-#ifdef HAVE_MULTIBOOT /* defined by config.h */
-/* Check in root of this <volume> for rockbox_main.<playername>
- * if this file empty or there is a single slash '/'
- * buf = '<volume#>/<rootdir>/<firmware(name)>\0'
- * If instead '/<*DIRECTORY*>' is supplied
- * addpath will be set to this DIRECTORY buf =
- * '/<volume#>/addpath/<rootdir>/<firmware(name)>\0'
- * On error returns Negative number or 0
- * On success returns bytes from snprintf
- * and generated path will be placed in buf
- * note: if supplied buffer is too small return will be
- * the number of bytes that would have been written
- */
-int get_redirect_dir(char* buf, int buffer_size, int volume,
- const char* rootdir, const char* firmware)
-{
- int fd;
- int f_offset;
- char add_path[MAX_PATH];
- /* Check in root of volume for rockbox_main.<playername> redirect */
- snprintf(add_path, sizeof(add_path), "/<%d>/"BOOT_REDIR, volume);
- fd = open(add_path, O_RDONLY);
- if (fd < 0)
- return EFILE_NOT_FOUND;
-
- /*clear add_path for re-use*/
- memset(add_path, 0, sizeof(add_path));
- f_offset = read(fd, add_path,sizeof(add_path));
- close(fd);
-
- for(int i = f_offset - 1;i > 0; i--)
- {
- /* strip control chars < SPACE or all if path doesn't start with '/' */
- if (add_path[i] < 0x20 || add_path[0] != '/')
- add_path[i] = '\0';
- }
- /* if '/add_path' is specified in rockbox_main.<playername>
- path is /<vol#>/add_path/rootdir/firmwarename
- if add_path is empty or '/' is missing from beginning
- path is /<vol#>/rootdir/firmwarename
- */
- return snprintf(buf, buffer_size, "/<%d>%s/%s/%s", volume, add_path,
- rootdir, firmware);
-}
-#endif /* HAVE_MULTIBOOT */
-
static inline unsigned int le2int(unsigned char* buf)
{
int32_t res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
diff --git a/firmware/target/arm/rk27xx/lcdif-rk27xx.c b/firmware/target/arm/rk27xx/lcdif-rk27xx.c
index e6af0d978a..618b476480 100644
--- a/firmware/target/arm/rk27xx/lcdif-rk27xx.c
+++ b/firmware/target/arm/rk27xx/lcdif-rk27xx.c
@@ -198,9 +198,10 @@ static void create_llp(int x, int y, int width, int height)
width = width>>1;
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* build LLPs */
for (i=0; i<height; i++)
- llp_setup((void *)FBADDR(x,y+i),
+ llp_setup((void *)fbaddr(x,y+i),
(void*)(LCD_BUFF+((i%4)*4*width)),
&(scr_llp[i]),
width);
diff --git a/firmware/target/arm/s5l8700/debug-s5l8700.c b/firmware/target/arm/s5l8700/debug-s5l8700.c
index ecb15df5d0..c42eac0438 100644
--- a/firmware/target/arm/s5l8700/debug-s5l8700.c
+++ b/firmware/target/arm/s5l8700/debug-s5l8700.c
@@ -112,7 +112,7 @@ bool dbg_hw_info(void)
_DEBUG_PRINTF("PMU:");
for(i=0;i<7;i++)
{
- char *device[] = {"(unknown)",
+ static const char * const device[] = {"(unknown)",
"(CLICKWHEEL)",
"(LCD)",
"(AUDIO)",
@@ -139,7 +139,7 @@ bool dbg_hw_info(void)
char line_cfg[4];
int abr_stat;
uint32_t abr_cnt;
- char *abrstatus[] = {"Idle", "Launched", "Counting", "Abnormal"};
+ static const char * const abrstatus[] = {"Idle", "Launched", "Counting", "Abnormal"};
uartc_port_get_line_info(&ser_port,
&tx_stat, &rx_stat, &tx_speed, &rx_speed, line_cfg);
diff --git a/firmware/target/arm/s5l8700/yps3/lcd-yps3.c b/firmware/target/arm/s5l8700/yps3/lcd-yps3.c
index a9830bca57..eec11e34b8 100644
--- a/firmware/target/arm/s5l8700/yps3/lcd-yps3.c
+++ b/firmware/target/arm/s5l8700/yps3/lcd-yps3.c
@@ -299,14 +299,15 @@ void lcd_update_rect(int x, int y, int width, int height)
{
fb_data* p;
int h, w;
-
+
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
if (lcd_type == 1) {
/* TODO implement and test */
lcd_set_window1(x, y, width, height);
lcd_set_position1(x, y);
-
+
for (h = 0; h < height; h++) {
- p = FBADDR(0,y);
+ p = fbaddr(0,y);
for (w = 0; w < LCD_WIDTH; w++) {
while (LCD_STATUS & 0x10);
LCD_WDATA = *p++;
@@ -317,9 +318,9 @@ void lcd_update_rect(int x, int y, int width, int height)
else {
lcd_set_window2(x, y, width, height);
lcd_set_position2(x, y);
-
+
for (h = 0; h < height; h++) {
- p = FBADDR(x,y);
+ p = fbaddr(x,y);
for (w = 0; w < width; w++) {
while (LCD_STATUS & 0x10);
LCD_WDATA = *p++;
diff --git a/firmware/target/arm/s5l8702/debug-s5l8702.c b/firmware/target/arm/s5l8702/debug-s5l8702.c
index 68b16f39f7..26b8e557a0 100644
--- a/firmware/target/arm/s5l8702/debug-s5l8702.c
+++ b/firmware/target/arm/s5l8702/debug-s5l8702.c
@@ -104,7 +104,7 @@ bool dbg_hw_info(void)
_DEBUG_PRINTF("PMU:");
for(i=0;i<7;i++)
{
- char *device[] = {"unknown",
+ static const char *const device[] = {"unknown",
"unknown",
"LCD",
"AUDIO",
@@ -157,7 +157,7 @@ bool dbg_hw_info(void)
char line_cfg[4];
int abr_stat;
uint32_t abr_cnt;
- char *abrstatus[] = {"Idle", "Launched", "Counting", "Abnormal"};
+ static const char * const abrstatus[] = {"Idle", "Launched", "Counting", "Abnormal"};
uartc_port_get_line_info(&ser_port,
&tx_stat, &rx_stat, &tx_speed, &rx_speed, line_cfg);
diff --git a/firmware/target/arm/samsung/yh920/lcd-yh920.c b/firmware/target/arm/samsung/yh920/lcd-yh920.c
index 06aa3d718d..6a579f382a 100644
--- a/firmware/target/arm/samsung/yh920/lcd-yh920.c
+++ b/firmware/target/arm/samsung/yh920/lcd-yh920.c
@@ -253,13 +253,14 @@ void lcd_update_rect(int x, int y, int width, int height)
if(ymax >= LCD_FBHEIGHT)
ymax = LCD_FBHEIGHT-1;
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy specified rectange bitmap to hardware */
for (; y <= ymax; y++)
{
lcd_write_reg(LCD_CNTL_PAGE, y);
lcd_write_reg(LCD_CNTL_COLUMN, x);
- addr = FBADDR(x,y);
+ addr = fbaddr(x,y);
lcd_send_cmd(LCD_CNTL_DATA_WRITE);
lcd_write_data(addr, width);
diff --git a/firmware/target/coldfire/iaudio/m3/lcd-m3.c b/firmware/target/coldfire/iaudio/m3/lcd-m3.c
index 3da608a0ef..5e84cbacd3 100644
--- a/firmware/target/coldfire/iaudio/m3/lcd-m3.c
+++ b/firmware/target/coldfire/iaudio/m3/lcd-m3.c
@@ -258,6 +258,7 @@ void lcd_update(void)
int y;
if (initialized)
{
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
for(y = 0;y < LCD_FBHEIGHT;y++)
{
/* Copy display bitmap to hardware.
@@ -266,7 +267,7 @@ void lcd_update(void)
have to update one page at a time. */
lcd_write_command(LCD_SET_PAGE | (y > 5 ? y + 2 : y));
lcd_write_command_e(LCD_SET_COLUMN | 0, 0);
- lcd_write_data(FBADDR(0, y), LCD_WIDTH);
+ lcd_write_data(fbaddr(0,y), LCD_WIDTH);
}
}
}
@@ -289,6 +290,7 @@ void lcd_update_rect(int x, int y, int width, int height)
if(ymax >= LCD_FBHEIGHT)
ymax = LCD_FBHEIGHT-1;
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy specified rectangle bitmap to hardware
COM48-COM63 are not connected, so we need to skip those */
for (; y <= ymax; y++)
@@ -296,7 +298,7 @@ void lcd_update_rect(int x, int y, int width, int height)
lcd_write_command(LCD_SET_PAGE | ((y > 5 ? y + 2 : y) & 0xf));
lcd_write_command_e(LCD_SET_COLUMN | ((x >> 4) & 0xf), x & 0xf);
- lcd_write_data(FBADDR(x,y), width);
+ lcd_write_data(fbaddr(x,y), width);
}
}
}
diff --git a/firmware/target/coldfire/iaudio/m5/lcd-m5.c b/firmware/target/coldfire/iaudio/m5/lcd-m5.c
index 8f022adf96..35fd173f18 100644
--- a/firmware/target/coldfire/iaudio/m5/lcd-m5.c
+++ b/firmware/target/coldfire/iaudio/m5/lcd-m5.c
@@ -200,6 +200,7 @@ void lcd_update(void)
{
int y;
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy display bitmap to hardware */
for (y = 0; y < LCD_FBHEIGHT; y++)
{
@@ -207,7 +208,7 @@ void lcd_update(void)
lcd_write_command_ex(LCD_CNTL_COLUMN, 0, -1);
lcd_write_command(LCD_CNTL_DATA_WRITE);
- lcd_write_data (FBADDR(0, y), LCD_WIDTH);
+ lcd_write_data (fbaddr(0,y), LCD_WIDTH);
}
}
@@ -228,6 +229,7 @@ void lcd_update_rect(int x, int y, int width, int height)
if(ymax >= LCD_FBHEIGHT)
ymax = LCD_FBHEIGHT-1;
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy specified rectange bitmap to hardware */
for (; y <= ymax; y++)
{
@@ -235,6 +237,6 @@ void lcd_update_rect(int x, int y, int width, int height)
lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1);
lcd_write_command(LCD_CNTL_DATA_WRITE);
- lcd_write_data (FBADDR(x,y), width);
+ lcd_write_data (fbaddr(x,y), width);
}
}
diff --git a/firmware/target/coldfire/iriver/h100/lcd-h100.c b/firmware/target/coldfire/iriver/h100/lcd-h100.c
index b13751b9eb..b6eea1dfa3 100644
--- a/firmware/target/coldfire/iriver/h100/lcd-h100.c
+++ b/firmware/target/coldfire/iriver/h100/lcd-h100.c
@@ -209,6 +209,7 @@ void lcd_update(void)
{
int y;
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy display bitmap to hardware */
for (y = 0; y < LCD_FBHEIGHT; y++)
{
@@ -216,7 +217,7 @@ void lcd_update(void)
lcd_write_command_ex(LCD_CNTL_COLUMN, 0, -1);
lcd_write_command(LCD_CNTL_DATA_WRITE);
- lcd_write_data (FBADDR(0, y), LCD_WIDTH);
+ lcd_write_data (fbaddr(0,y), LCD_WIDTH);
}
}
@@ -237,6 +238,7 @@ void lcd_update_rect(int x, int y, int width, int height)
if(ymax >= LCD_FBHEIGHT)
ymax = LCD_FBHEIGHT-1;
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy specified rectange bitmap to hardware */
for (; y <= ymax; y++)
{
@@ -244,6 +246,6 @@ void lcd_update_rect(int x, int y, int width, int height)
lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1);
lcd_write_command(LCD_CNTL_DATA_WRITE);
- lcd_write_data (FBADDR(x,y), width);
+ lcd_write_data (fbaddr(x,y), width);
}
}
diff --git a/firmware/target/coldfire/mpio/hd300/lcd-hd300.c b/firmware/target/coldfire/mpio/hd300/lcd-hd300.c
index 509ed4cd53..9cff9cd712 100644
--- a/firmware/target/coldfire/mpio/hd300/lcd-hd300.c
+++ b/firmware/target/coldfire/mpio/hd300/lcd-hd300.c
@@ -231,6 +231,7 @@ void lcd_update_rect(int x, int y, int width, int height)
if(ymax >= LCD_FBHEIGHT)
ymax = LCD_FBHEIGHT-1;
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy specified rectange bitmap to hardware */
for (; y <= ymax; y++)
{
@@ -238,6 +239,6 @@ void lcd_update_rect(int x, int y, int width, int height)
lcd_write_command_ex(LCD_CNTL_COLUMN, x, -1);
lcd_write_command(LCD_CNTL_DATA_WRITE);
- lcd_write_data (FBADDR(x,y), width);
+ lcd_write_data (fbaddr(x,y), width);
}
}
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/powermgmt-target.h b/firmware/target/hosted/ibasso/dx50/adc-target.h
index e69de29bb2..e69de29bb2 100644
--- a/firmware/target/mips/ingenic_x1000/fiiom3k/powermgmt-target.h
+++ b/firmware/target/hosted/ibasso/dx50/adc-target.h
diff --git a/firmware/target/hosted/ibasso/dx90/adc-target.h b/firmware/target/hosted/ibasso/dx90/adc-target.h
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/firmware/target/hosted/ibasso/dx90/adc-target.h
diff --git a/firmware/target/hosted/ibasso/pcm-ibasso.c b/firmware/target/hosted/ibasso/pcm-ibasso.c
index 5c68ded3e1..889386b7c6 100644
--- a/firmware/target/hosted/ibasso/pcm-ibasso.c
+++ b/firmware/target/hosted/ibasso/pcm-ibasso.c
@@ -123,7 +123,7 @@ static void* pcm_thread_run(void* nothing)
/* https://github.com/tinyalsa/tinyalsa/blob/master/tinypcminfo.c */
-static const char* format_lookup[] =
+static const char* const format_lookup[] =
{
/*[0] =*/ "S8",
"U8",
diff --git a/firmware/target/hosted/ibasso/sysfs-ibasso.c b/firmware/target/hosted/ibasso/sysfs-ibasso.c
index 8f62e3fec2..e3a0f911af 100644
--- a/firmware/target/hosted/ibasso/sysfs-ibasso.c
+++ b/firmware/target/hosted/ibasso/sysfs-ibasso.c
@@ -32,7 +32,7 @@
#include "sysfs-ibasso.h"
-static const char* SYSFS_PATHS[] =
+static const char* const SYSFS_PATHS[] =
{
/* SYSFS_DX50_CODEC_VOLUME */
"/dev/codec_volume",
diff --git a/firmware/target/hosted/rolo.c b/firmware/target/hosted/rolo.c
index 04b21d553e..dfe483c964 100644
--- a/firmware/target/hosted/rolo.c
+++ b/firmware/target/hosted/rolo.c
@@ -37,12 +37,6 @@
//#define LOGF_ENABLE
#include "logf.h"
-#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR)
-#include "bootdata.h"
-#include "crc32.h"
-extern int write_bootdata(unsigned char* buf, int len, unsigned int boot_volume); /*rb-loader.c*/
-#endif
-
static void rolo_error(const char *text, const char *text2)
{
lcd_clear_display();
@@ -72,16 +66,6 @@ int rolo_load(const char* filename)
audio_stop();
-#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR)
- /* write the bootdata as if rolo were the bootloader */
- unsigned int crc = 0;
- if (strcmp(filename, BOOTDIR "/" BOOTFILE) == 0)
- crc = crc_32(boot_data.payload, boot_data.length, 0xffffffff);
-
- if(crc > 0 && crc == boot_data.crc)
- write_bootdata(filebuf, filebuf_size, boot_data.boot_volume); /* rb-loader.c */
-#endif
-
#ifdef HAVE_STORAGE_FLUSH
lcd_puts(0, 2, "Flushing storage buffers");
lcd_update();
diff --git a/firmware/target/hosted/sdl/sim-ui-defines.h b/firmware/target/hosted/sdl/sim-ui-defines.h
index baba357ccc..7d60deac34 100644
--- a/firmware/target/hosted/sdl/sim-ui-defines.h
+++ b/firmware/target/hosted/sdl/sim-ui-defines.h
@@ -523,10 +523,10 @@
#elif defined(FIIO_M3K) || defined(FIIO_M3K_LINUX)
#define UI_TITLE "FiiO M3K"
-#define UI_WIDTH 287 /* width of GUI window */
-#define UI_HEIGHT 589 /* height of GUI window */
-#define UI_LCD_POSX 25
-#define UI_LCD_POSY 15
+#define UI_WIDTH 334 /* width of GUI window */
+#define UI_HEIGHT 684 /* height of GUI window */
+#define UI_LCD_POSX 49
+#define UI_LCD_POSY 37
#elif defined(SHANLING_Q1)
diff --git a/firmware/target/hosted/system-hosted.c b/firmware/target/hosted/system-hosted.c
index ce47fd5f5c..c4ae5a404f 100644
--- a/firmware/target/hosted/system-hosted.c
+++ b/firmware/target/hosted/system-hosted.c
@@ -90,6 +90,7 @@ static void sig_handler(int sig, siginfo_t *siginfo, void *context)
void power_off(void)
{
backlight_hw_off();
+ sync();
system("/sbin/poweroff");
while (1); /* halt */
}
diff --git a/firmware/target/hosted/usb-hiby.c b/firmware/target/hosted/usb-hiby.c
index b82fa5c4ce..050c86e446 100644
--- a/firmware/target/hosted/usb-hiby.c
+++ b/firmware/target/hosted/usb-hiby.c
@@ -63,8 +63,8 @@ void usb_enable(bool on)
*/
int disk_mount_all(void)
{
- const char *dev[] = {"/dev/mmcblk0p1", "/dev/mmcblk0"};
- const char *fs[] = {"vfat", "exfat"};
+ const char * const dev[] = {"/dev/mmcblk0p1", "/dev/mmcblk0"};
+ const char * const fs[] = {"vfat", "exfat"};
sysfs_set_string("/sys/class/android_usb/android0/f_mass_storage/lun/file", "");
diff --git a/firmware/target/mips/ingenic_jz47xx/xduoo_x3/lcd-xduoo_x3.c b/firmware/target/mips/ingenic_jz47xx/xduoo_x3/lcd-xduoo_x3.c
index 47b646be34..2c1c3a226e 100644
--- a/firmware/target/mips/ingenic_jz47xx/xduoo_x3/lcd-xduoo_x3.c
+++ b/firmware/target/mips/ingenic_jz47xx/xduoo_x3/lcd-xduoo_x3.c
@@ -532,6 +532,7 @@ void lcd_update(void)
const int column_high = get_column_high_byte(0);
const int column_low = get_column_low_byte(0);
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy display bitmap to hardware */
for (y = 0; y < LCD_FBHEIGHT; y++)
{
@@ -542,7 +543,7 @@ void lcd_update(void)
(column_low)
);
- lcd_write_data (FBADDR(0, y), LCD_WIDTH);
+ lcd_write_data (fbaddr(0,y), LCD_WIDTH);
}
}
@@ -586,6 +587,7 @@ void lcd_update_rect(int x, int y, int width, int height)
ymax = (y + height-1) >> 3;
y >>= 3;
+ void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn;
/* Copy specified rectange bitmap to hardware */
for (; y <= ymax; y++)
{
@@ -596,6 +598,6 @@ void lcd_update_rect(int x, int y, int width, int height)
(column_low)
);
- lcd_write_data (FBADDR(x,y), width);
+ lcd_write_data (fbaddr(x,y), width);
}
}
diff --git a/firmware/target/mips/ingenic_x1000/app.lds b/firmware/target/mips/ingenic_x1000/app.lds
index 26b2854728..2943329ba7 100644
--- a/firmware/target/mips/ingenic_x1000/app.lds
+++ b/firmware/target/mips/ingenic_x1000/app.lds
@@ -6,6 +6,13 @@ OUTPUT_ARCH(MIPS)
ENTRY(_start)
STARTUP(target/mips/ingenic_x1000/crt0.o)
+#ifdef BOOTLOADER
+# undef PLUGIN_BUFFER_SIZE
+# undef CODEC_SIZE
+# define PLUGIN_BUFFER_SIZE 0
+# define CODEC_SIZE 0
+#endif
+
/* End of the audio buffer, where the codec buffer starts */
#define ENDAUDIOADDR (X1000_DRAM_END - PLUGIN_BUFFER_SIZE - CODEC_SIZE)
@@ -16,6 +23,7 @@ MEMORY
{
IRAM : ORIGIN = X1000_IRAM_BASE, LENGTH = X1000_IRAM_SIZE
DRAM : ORIGIN = X1000_DRAM_BASE, LENGTH = X1000_DRAM_SIZE
+ TCSM : ORIGIN = X1000_TCSM_BASE, LENGTH = X1000_TCSM_SIZE
}
SECTIONS
@@ -61,6 +69,14 @@ SECTIONS
} > IRAM
_iramcopy = LOADADDR(.iram);
+ .tcsm X1000_TCSM_BASE: AT (_bssbegin + SIZEOF(.iram))
+ {
+ _tcsmstart = .;
+ KEEP(*(.tcsm*));
+ _tcsmend = .;
+ } > TCSM
+ _tcsmcopy = LOADADDR(.tcsm);
+
. = ALIGN(4);
.stack (NOLOAD) :
{
@@ -88,10 +104,8 @@ SECTIONS
{
. = ALIGN(4);
audiobuffer = .;
- loadbuffer = .;
} > DRAM
- loadbufferend = ENDAUDIOADDR;
audiobufend = ENDAUDIOADDR;
codecbuf = ENDAUDIOADDR;
pluginbuf = ENDCODECADDR;
diff --git a/firmware/target/mips/ingenic_x1000/boot-x1000.c b/firmware/target/mips/ingenic_x1000/boot-x1000.c
new file mode 100644
index 0000000000..aa97bfcd85
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/boot-x1000.c
@@ -0,0 +1,280 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2022 Aidan MacDonald
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "system.h"
+#include "boot-x1000.h"
+#include "nand-x1000.h"
+#include "gpio-x1000.h"
+#include "clk-x1000.h"
+#include "x1000/cpm.h"
+#include "x1000/lcd.h"
+#include "x1000/uart.h"
+#include <string.h>
+
+#define HDR_BEGIN 128 /* header must begin within this many bytes */
+#define HDR_LEN 256 /* header length cannot exceed this */
+
+/* search for header value, label must be a 4-character string.
+ * Returns the found value or 0 if the label wasn't found. */
+static uint32_t search_header(const unsigned char* source, size_t length,
+ const char* label)
+{
+ size_t search_len = MIN(length, HDR_BEGIN);
+ if(search_len < 8)
+ return 0;
+ search_len -= 7;
+
+ /* find the beginning marker */
+ size_t i;
+ for(i = 8; i < search_len; i += 4)
+ if(!memcmp(&source[i], "BEGINHDR", 8))
+ break;
+ if(i >= search_len)
+ return 0;
+ i += 8;
+
+ /* search within the header */
+ search_len = MIN(length, i + HDR_LEN) - 7;
+ for(; i < search_len; i += 8) {
+ if(!memcmp(&source[i], "ENDH", 4)) {
+ break;
+ } else if(!memcmp(&source[i], label, 4)) {
+ i += 4;
+ /* read little-endian value */
+ uint32_t ret = source[i];
+ ret |= source[i+1] << 8;
+ ret |= source[i+2] << 16;
+ ret |= source[i+3] << 24;
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static void iram_memmove(void* dest, const void* source, size_t length)
+ __attribute__((section(".icode")));
+
+static void iram_memmove(void* dest, const void* source, size_t length)
+{
+ unsigned char* d = dest;
+ const unsigned char* s = source;
+
+ if(s < d && d < s + length) {
+ d += length;
+ s += length;
+ while(length--)
+ *--d = *--s;
+ } else {
+ while(length--)
+ *d++ = *s++;
+ }
+}
+
+void x1000_boot_rockbox(const void* source, size_t length)
+{
+ uint32_t load_addr = search_header(source, length, "LOAD");
+ if(!load_addr)
+ load_addr = X1000_STANDARD_DRAM_BASE;
+
+ disable_irq();
+
+ /* --- Beyond this point, do not call into DRAM --- */
+
+ iram_memmove((void*)load_addr, source, length);
+ commit_discard_idcache();
+
+ typedef void(*entry_fn)(void);
+ entry_fn fn = (entry_fn)load_addr;
+ fn();
+ while(1);
+}
+
+void x1000_boot_linux(const void* source, size_t length,
+ void* load, void* entry, const char* args)
+{
+ size_t args_len = strlen(args);
+
+ disable_irq();
+
+ /* --- Beyond this point, do not call into DRAM --- */
+
+ void* safe_mem = (void*)X1000_IRAM_END;
+
+ /* copy argument string to a safe location */
+ char* args_copy = safe_mem + 32;
+ iram_memmove(args_copy, args, args_len);
+
+ /* generate argv array */
+ char** argv = safe_mem;
+ argv[0] = NULL;
+ argv[1] = args_copy;
+
+ iram_memmove(load, source, length);
+ commit_discard_idcache();
+
+ typedef void(*entry_fn)(long, char**, long, long);
+ entry_fn fn = (entry_fn)entry;
+ fn(2, argv, 0, 0);
+ while(1);
+}
+
+void rolo_restart(const unsigned char* source, unsigned char* dest, int length)
+{
+ (void)dest;
+ x1000_boot_rockbox(source, length);
+}
+
+void x1000_dualboot_cleanup(void)
+{
+ /* - disable all LCD interrupts since the M3K can't cope with them
+ * - disable BEDN bit since it creates garbled graphics on the Q1 */
+ jz_writef(CPM_CLKGR, LCD(0));
+ jz_writef(LCD_CTRL, BEDN(0), EOFM(0), SOFM(0), IFUM(0), QDM(0));
+ jz_writef(CPM_CLKGR, LCD(1));
+
+ /* clear USB PHY voodoo bits, not all kernels use them */
+ jz_writef(CPM_OPCR, GATE_USBPHY_CLK(0));
+ jz_writef(CPM_USBCDR, PHY_GATE(0));
+
+#if defined(FIIO_M3K) || defined(EROS_QN)
+ /*
+ * Need to bring up MPLL before booting Linux
+ * (Doesn't apply to Q1 since it sticks with the default Ingenic config)
+ */
+
+ /* 24 MHz * 25 = 600 MHz */
+ jz_writef(CPM_MPCR, BS(1), PLLM(25 - 1), PLLN(0), PLLOD(0), ENABLE(1));
+ while(jz_readf(CPM_MPCR, ON) == 0);
+
+ /* 600 MHz / 3 = 200 MHz */
+ clk_set_ddr(X1000_CLK_MPLL, 3);
+
+ clk_set_ccr_mux(CLKMUX_SCLK_A(APLL) |
+ CLKMUX_CPU(SCLK_A) |
+ CLKMUX_AHB0(MPLL) |
+ CLKMUX_AHB2(MPLL));
+ clk_set_ccr_div(CLKDIV_CPU(1) | /* 1008 MHz */
+ CLKDIV_L2(2) | /* 504 MHz */
+ CLKDIV_AHB0(3) | /* 200 MHz */
+ CLKDIV_AHB2(3) | /* 200 MHz */
+ CLKDIV_PCLK(6)); /* 100 MHz */
+#endif
+}
+
+void x1000_dualboot_init_clocktree(void)
+{
+ /* Make sure these are gated to match the OF behavior. */
+ jz_writef(CPM_CLKGR, PCM(1), MAC(1), LCD(1), MSC0(1), MSC1(1), OTG(1), CIM(1));
+
+ /* Set clock sources, and make sure every clock starts out stopped */
+ jz_writef(CPM_I2SCDR, CS_V(EXCLK));
+ jz_writef(CPM_PCMCDR, CS_V(EXCLK));
+
+ jz_writef(CPM_MACCDR, CLKSRC_V(MPLL), CE(1), STOP(1), CLKDIV(0xfe));
+ while(jz_readf(CPM_MACCDR, BUSY));
+
+ jz_writef(CPM_LPCDR, CLKSRC_V(MPLL), CE(1), STOP(1), CLKDIV(0xfe));
+ while(jz_readf(CPM_LPCDR, BUSY));
+
+ jz_writef(CPM_MSC0CDR, CLKSRC_V(MPLL), CE(1), STOP(1), CLKDIV(0xfe));
+ while(jz_readf(CPM_MSC0CDR, BUSY));
+
+ jz_writef(CPM_MSC1CDR, CE(1), STOP(1), CLKDIV(0xfe));
+ while(jz_readf(CPM_MSC1CDR, BUSY));
+
+ jz_writef(CPM_CIMCDR, CLKSRC_V(MPLL), CE(1), STOP(1), CLKDIV(0xfe));
+ while(jz_readf(CPM_CIMCDR, BUSY));
+
+ jz_writef(CPM_USBCDR, CLKSRC_V(EXCLK), CE(1), STOP(1));
+ while(jz_readf(CPM_USBCDR, BUSY));
+}
+
+void x1000_dualboot_init_uart2(void)
+{
+ /* Ungate the clock and select UART2 device function */
+ jz_writef(CPM_CLKGR, UART2(0));
+ gpioz_configure(GPIO_C, 3 << 30, GPIOF_DEVICE(1));
+
+ /* Disable all interrupts */
+ jz_write(UART_UIER(2), 0);
+
+ /* FIFO configuration */
+ jz_overwritef(UART_UFCR(2),
+ RDTR(3), /* FIFO trigger level = 60? */
+ UME(0), /* UART module disable */
+ DME(1), /* DMA mode enable? */
+ TFRT(1), /* transmit FIFO reset */
+ RFRT(1), /* receive FIFO reset */
+ FME(1)); /* FIFO mode enable */
+
+ /* IR mode configuration */
+ jz_overwritef(UART_ISR(2),
+ RDPL(1), /* Zero is negative pulse for receive */
+ TDPL(1), /* ... and for transmit */
+ XMODE(1), /* Pulse width 1.6us */
+ RCVEIR(0), /* Disable IR for recieve */
+ XMITIR(0)); /* ... and for transmit */
+
+ /* Line configuration */
+ jz_overwritef(UART_ULCR(2), DLAB(0),
+ WLS_V(8BITS), /* 8 bit words */
+ SBLS_V(1_STOP_BIT), /* 1 stop bit */
+ PARE(0), /* no parity */
+ SBK(0)); /* don't set break */
+
+ /* Set the baud rate... not too sure how this works. (Docs unclear!) */
+ const unsigned divisor = 0x0004;
+ jz_writef(UART_ULCR(2), DLAB(1));
+ jz_write(UART_UDLHR(2), (divisor >> 8) & 0xff);
+ jz_write(UART_UDLLR(2), divisor & 0xff);
+ jz_write(UART_UMR(2), 16);
+ jz_write(UART_UACR(2), 0);
+ jz_writef(UART_ULCR(2), DLAB(0));
+
+ /* Enable UART */
+ jz_overwritef(UART_UFCR(2),
+ RDTR(0), /* FIFO trigger level = 1 */
+ DME(0), /* DMA mode disable */
+ UME(1), /* UART module enable */
+ TFRT(1), /* transmit FIFO reset */
+ RFRT(1), /* receive FIFO reset */
+ FME(1)); /* FIFO mode enable */
+}
+
+int x1000_dualboot_load_pdma_fw(void)
+{
+ nand_drv* n = nand_init();
+ nand_lock(n);
+
+ int ret = nand_open(n);
+ if(ret != NAND_SUCCESS)
+ goto err_unlock;
+
+ /* NOTE: hardcoded address is used by all current targets */
+ jz_writef(CPM_CLKGR, PDMA(0));
+ ret = nand_read_bytes(n, 0x4000, 0x2000, (void*)0xb3422000);
+
+ nand_close(n);
+ err_unlock:
+ nand_unlock(n);
+ return ret;
+}
diff --git a/firmware/target/mips/ingenic_x1000/boot-x1000.h b/firmware/target/mips/ingenic_x1000/boot-x1000.h
index 400eb93dc1..1b7a0db1e9 100644
--- a/firmware/target/mips/ingenic_x1000/boot-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/boot-x1000.h
@@ -24,18 +24,10 @@
#include "x1000/cpm.h"
#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
enum {
- BOOT_OPTION_ROCKBOX = 0,
- BOOT_OPTION_OFW_PLAYER,
- BOOT_OPTION_OFW_RECOVERY,
-};
-
-enum {
- /* 3 bits to store the boot option selected by the SPL */
- BOOT_OPTION_MASK = 0x7,
- BOOT_OPTION_SHIFT = 0,
-
/* Set after running clk_init() and setting up system clocks */
BOOT_FLAG_CLK_INIT = (1 << 31),
@@ -43,6 +35,18 @@ enum {
BOOT_FLAG_USB_BOOT = (1 << 30),
};
+void x1000_boot_rockbox(const void* source, size_t length)
+ __attribute__((section(".icode")));
+void x1000_boot_linux(const void* source, size_t length,
+ void* load, void* entry, const char* args)
+ __attribute__((section(".icode")));
+
+/* dual boot support code */
+void x1000_dualboot_cleanup(void);
+void x1000_dualboot_init_clocktree(void);
+void x1000_dualboot_init_uart2(void);
+int x1000_dualboot_load_pdma_fw(void);
+
/* Note: these functions are inlined to minimize SPL code size.
* They are private to the X1000 early boot code anyway... */
@@ -74,18 +78,4 @@ static inline void clr_boot_flag(uint32_t bit)
cpm_scratch_set(REG_CPM_SCRATCH & ~bit);
}
-static inline void set_boot_option(int opt)
-{
- uint32_t r = REG_CPM_SCRATCH;
- r &= ~(BOOT_OPTION_MASK << BOOT_OPTION_SHIFT);
- r |= (opt & BOOT_OPTION_MASK) << BOOT_OPTION_SHIFT;
- cpm_scratch_set(r);
-}
-
-static inline int get_boot_option(void)
-{
- uint32_t r = REG_CPM_SCRATCH;
- return (r >> BOOT_OPTION_SHIFT) & BOOT_OPTION_MASK;
-}
-
#endif /* __BOOT_X1000_H__ */
diff --git a/firmware/target/mips/ingenic_x1000/clk-x1000.c b/firmware/target/mips/ingenic_x1000/clk-x1000.c
index 4988e7c3bf..e3b0f792bb 100644
--- a/firmware/target/mips/ingenic_x1000/clk-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/clk-x1000.c
@@ -265,39 +265,36 @@ void clk_init(void)
jz_writef(CPM_APCR, BS(1), PLLM(42 - 1), PLLN(0), PLLOD(0), ENABLE(1));
while(jz_readf(CPM_APCR, ON) == 0);
-#if (defined(FIIO_M3K) || defined(EROS_QN))
+#if defined(FIIO_M3K) || defined(EROS_QN)
/* TODO: Allow targets to define their clock frequencies in their config,
* instead of having this be a random special case. */
- if(get_boot_option() == BOOT_OPTION_ROCKBOX) {
- clk_set_ccr_div(CLKDIV_CPU(1) | /* 1008 MHz */
- CLKDIV_L2(2) | /* 504 MHz */
- CLKDIV_AHB0(5) | /* 201.6 MHz */
- CLKDIV_AHB2(5) | /* 201.6 MHz */
- CLKDIV_PCLK(10)); /* 100.8 MHz */
- clk_set_ccr_mux(CLKMUX_SCLK_A(APLL) |
- CLKMUX_CPU(SCLK_A) |
- CLKMUX_AHB0(SCLK_A) |
- CLKMUX_AHB2(SCLK_A));
-
- /* DDR to 201.6 MHz */
- clk_set_ddr(X1000_CLK_SCLK_A, 5);
-
- /* Disable MPLL */
- jz_writef(CPM_MPCR, ENABLE(0));
- while(jz_readf(CPM_MPCR, ON));
- } else {
-#endif
- clk_set_ccr_div(CLKDIV_CPU(1) | /* 1008 MHz */
- CLKDIV_L2(2) | /* 504 MHz */
- CLKDIV_AHB0(3) | /* 200 MHz */
- CLKDIV_AHB2(3) | /* 200 MHz */
- CLKDIV_PCLK(6)); /* 100 MHz */
- clk_set_ccr_mux(CLKMUX_SCLK_A(APLL) |
- CLKMUX_CPU(SCLK_A) |
- CLKMUX_AHB0(MPLL) |
- CLKMUX_AHB2(MPLL));
-#if (defined(FIIO_M3K) || defined(EROS_QN))
- }
+ clk_set_ccr_div(CLKDIV_CPU(1) | /* 1008 MHz */
+ CLKDIV_L2(2) | /* 504 MHz */
+ CLKDIV_AHB0(5) | /* 201.6 MHz */
+ CLKDIV_AHB2(5) | /* 201.6 MHz */
+ CLKDIV_PCLK(10)); /* 100.8 MHz */
+ clk_set_ccr_mux(CLKMUX_SCLK_A(APLL) |
+ CLKMUX_CPU(SCLK_A) |
+ CLKMUX_AHB0(SCLK_A) |
+ CLKMUX_AHB2(SCLK_A));
+
+ /* DDR to 201.6 MHz */
+ clk_set_ddr(X1000_CLK_SCLK_A, 5);
+
+ /* Disable MPLL */
+ jz_writef(CPM_MPCR, ENABLE(0));
+ while(jz_readf(CPM_MPCR, ON));
+#else
+ /* Default configuration matching the Ingenic OF */
+ clk_set_ccr_div(CLKDIV_CPU(1) | /* 1008 MHz */
+ CLKDIV_L2(2) | /* 504 MHz */
+ CLKDIV_AHB0(3) | /* 200 MHz */
+ CLKDIV_AHB2(3) | /* 200 MHz */
+ CLKDIV_PCLK(6)); /* 100 MHz */
+ clk_set_ccr_mux(CLKMUX_SCLK_A(APLL) |
+ CLKMUX_CPU(SCLK_A) |
+ CLKMUX_AHB0(MPLL) |
+ CLKMUX_AHB2(MPLL));
#endif
/* mark that clocks have been initialized */
diff --git a/firmware/target/mips/ingenic_x1000/clk-x1000.h b/firmware/target/mips/ingenic_x1000/clk-x1000.h
index e19c56d0ba..f7153da564 100644
--- a/firmware/target/mips/ingenic_x1000/clk-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/clk-x1000.h
@@ -80,13 +80,13 @@ extern void clk_set_ccr_div(uint32_t divbits);
extern void clk_set_ddr(x1000_clk_t src, uint32_t div);
/* Returns the smallest n such that infreq/n <= outfreq */
-inline uint32_t clk_calc_div(uint32_t infreq, uint32_t outfreq)
+static inline uint32_t clk_calc_div(uint32_t infreq, uint32_t outfreq)
{
return (infreq + (outfreq - 1)) / outfreq;
}
/* Returns the smallest n such that (infreq >> n) <= outfreq */
-inline uint32_t clk_calc_shift(uint32_t infreq, uint32_t outfreq)
+static inline uint32_t clk_calc_shift(uint32_t infreq, uint32_t outfreq)
{
uint32_t div = clk_calc_div(infreq, outfreq);
return __builtin_clz(div) ^ 31;
diff --git a/firmware/target/mips/ingenic_x1000/crt0.S b/firmware/target/mips/ingenic_x1000/crt0.S
index 304f8d682f..d079b01e2a 100644
--- a/firmware/target/mips/ingenic_x1000/crt0.S
+++ b/firmware/target/mips/ingenic_x1000/crt0.S
@@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/
* $Id$
*
- * Copyright (C) 2021 Aidan MacDonald
+ * Copyright (C) 2021-2022 Aidan MacDonald
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -21,10 +21,12 @@
#include "config.h"
#include "mips.h"
+#include "bootdata.h"
.text
.extern main
.extern system_early_init
+ .extern _loadaddress
.global _start
.set push
@@ -35,62 +37,74 @@
.section .init.text
_start:
- /* Cache init */
- li v0, 0x80000000
- ori v1, v0, 0x4000
- mtc0 zero, C0_TAGLO
- mtc0 zero, C0_TAGHI
-_cache_loop:
- cache ICIndexStTag, 0(v0)
- cache DCIndexStTag, 0(v0)
- addiu v0, v0, 32
- bne v0, v1, _cache_loop
+ b _realstart
nop
- /* Invalidate BTB */
- mfc0 v0, C0_Config, 7
- nop
- ori v0, v0, 2
- mtc0 v0, C0_Config, 7
- nop
+ /* Header entries are 4-byte string labels (not null terminated!) followed
+ * by 4-byte values. Header should begin in the first 128 bytes and should
+ * be no more than 256 bytes in length. */
+_header:
+ .ascii "BEGINHDR" /* beginning of header */
+ .ascii "LOAD"
+ .word _loadaddress
+ .ascii "ENDH" /* end of header structure */
+
+#ifndef BOOTLOADER
+ /* Multiboot support header; this is not part of the above header. */
+ put_boot_data_here
+#endif
+_realstart:
/* Copy IRAM from BSS to low memory. */
- la t0, _iramcopy
- la t1, _iramstart
- la t2, _iramend
-_iram_loop:
- lw t3, 0(t0)
- addiu t1, 4
- addiu t0, 4
- bne t1, t2, _iram_loop
- sw t3, -4(t1)
+ la a0, _iramcopy
+ la a1, _iramstart
+ la a2, _iramend
+ bal _copy
+ nop
+
+ /* Copy TCSM from BSS */
+ la a0, _tcsmcopy
+ la a1, _tcsmstart
+ la a2, _tcsmend
+ bal _copy
+ nop
/* Clear the BSS segment (needed to zero-initialize C static values) */
- la t0, _bssbegin
- la t1, _bssend
- beq t0, t1, _bss_done
-_bss_loop:
- addiu t0, 4
- bne t0, t1, _bss_loop
- sw zero, -4(t0)
-_bss_done:
+ la a0, _bssbegin
+ la a1, _bssend
+ bal _clear
+ move a2, $0
/* Set stack pointer and clear the stack */
la sp, stackend
- la t0, stackbegin
- li t1, 0xDEADBEEF
-_stack_loop:
- addiu t0, 4
- bne t0, sp, _stack_loop
- sw t1, -4(t0)
+ la a0, stackbegin
+ li a2, 0xDEADBEEF
+ bal _clear
+ move a1, sp
/* Clear the IRQ stack */
la k0, _irqstackend
- la t0, _irqstackbegin
-_irqstack_loop:
- addiu t0, 4
- bne t0, k0, _irqstack_loop
- sw t1, -4(t0)
+ la a0, _irqstackbegin
+ bal _clear
+ move a1, k0
+
+ /* Write back D-cache and invalidate I-cache */
+ li v0, 0x80000000
+ ori v1, v0, (0x4000 - 32)
+ mtc0 zero, C0_TAGLO
+ mtc0 zero, C0_TAGHI
+1:
+ cache DCIndexWBInv, 0(v0)
+ cache ICIndexStTag, 0(v0)
+ bne v0, v1, 1b
+ addiu v0, v0, 32
+
+ /* Invalidate BTB */
+ mfc0 v0, C0_Config, 7
+ nop
+ ori v0, v0, 2
+ mtc0 v0, C0_Config, 7
+ nop
/* Jump to C code */
jal system_early_init
@@ -98,6 +112,28 @@ _irqstack_loop:
j main
nop
+ /* copy(void* src, void* dst, void* dst_end) */
+_copy:
+ beq a1, a2, 1f
+ addiu a1, 4
+ lw t0, 0(a0)
+ addiu a0, 4
+ b _copy
+ sw t0, -4(a1)
+1:
+ jr ra
+ nop
+
+ /* clear(void* dst, void* dst_end, int value) */
+_clear:
+ beq a0, a1, 1f
+ addiu a0, 4
+ b _clear
+ sw a2, -4(a0)
+1:
+ jr ra
+ nop
+
/* Exception entry points */
.section .vectors.1, "ax", %progbits
j tlb_refill_handler
diff --git a/firmware/target/mips/ingenic_x1000/debug-x1000.c b/firmware/target/mips/ingenic_x1000/debug-x1000.c
index 98b8f95fb5..236442a880 100644
--- a/firmware/target/mips/ingenic_x1000/debug-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/debug-x1000.c
@@ -118,12 +118,18 @@ static bool dbg_gpios(void)
}
extern volatile unsigned aic_tx_underruns;
+#ifdef HAVE_RECORDING
+extern volatile unsigned aic_rx_overruns;
+#endif
static bool dbg_audio(void)
{
do {
lcd_clear_display();
lcd_putsf(0, 0, "TX underruns: %u", aic_tx_underruns);
+#ifdef HAVE_RECORDING
+ lcd_putsf(0, 1, "RX overruns: %u", aic_rx_overruns);
+#endif
lcd_update();
} while(get_action(CONTEXT_STD, HZ) != ACTION_STD_CANCEL);
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c
index 073bddb8b4..0d43a3f010 100644
--- a/firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c
@@ -99,6 +99,20 @@ static const uint32_t erosqnative_lcd_cmd_enable[] = {
/* Display On */
LCD_INSTR_CMD, 0x29,
LCD_INSTR_UDELAY, 20000,
+ LCD_INSTR_END,
+};
+
+static const uint32_t erosqnative_lcd_of_compat_cmd[] = {
+ /* Pixel Format Set */
+ LCD_INSTR_CMD, 0x3a,
+ LCD_INSTR_DAT, 0x66, /* 18 bpp */
+ /* Exit Sleep */
+ LCD_INSTR_CMD, 0x11,
+ LCD_INSTR_UDELAY, 120000,
+ /* Display On */
+ LCD_INSTR_CMD, 0x29,
+ LCD_INSTR_UDELAY, 20000,
+ LCD_INSTR_END,
};
/* sleep and wake copied directly from m3k */
@@ -179,6 +193,15 @@ void lcd_tgt_enable(bool enable)
}
}
+void lcd_tgt_enable_of(bool enable)
+{
+ /* silence the unused parameter warning */
+ if (enable)
+ {}
+
+ lcd_exec_commands(&erosqnative_lcd_of_compat_cmd[0]);
+}
+
void lcd_tgt_sleep(bool sleep)
{
if(sleep)
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c
index 5573919aa2..ab6393a9fe 100644
--- a/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c
@@ -63,10 +63,15 @@ void power_init(void)
/* Set lowest sample rate */
axp_adc_set_rate(AXP_ADC_RATE_25HZ);
- /* Ensure battery voltage ADC is enabled */
- int bits = axp_adc_get_enabled();
- bits |= (1 << ADC_BATTERY_VOLTAGE);
- axp_adc_set_enabled(bits);
+ /* Enable required ADCs */
+ axp_adc_set_enabled(
+ (1 << ADC_BATTERY_VOLTAGE) |
+ (1 << ADC_CHARGE_CURRENT) |
+ (1 << ADC_DISCHARGE_CURRENT) |
+ (1 << ADC_VBUS_VOLTAGE) |
+ (1 << ADC_VBUS_CURRENT) |
+ (1 << ADC_INTERNAL_TEMP) |
+ (1 << ADC_APS_VOLTAGE));
/* Turn on all power outputs */
i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR,
@@ -78,11 +83,13 @@ void power_init(void)
* OF's setting, although it's not strictly within the USB spec. */
axp_set_charge_current(780);
+#ifdef BOOTLOADER
/* Delay to give power outputs time to stabilize.
* With the power thread delay, this can apparently go as low as 50,
* Keeping a higher value here just to ensure the bootloader works
* correctly. */
mdelay(200);
+#endif
}
#ifdef HAVE_USB_CHARGING_ENABLE
@@ -111,3 +118,13 @@ int _battery_voltage(void)
{
return axp_adc_read(ADC_BATTERY_VOLTAGE);
}
+
+#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE
+int _battery_current(void)
+{
+ if(charging_state())
+ return axp_adc_read(ADC_CHARGE_CURRENT);
+ else
+ return axp_adc_read(ADC_DISCHARGE_CURRENT);
+}
+#endif
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c
index 8528b803f7..9374d23a81 100644
--- a/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c
+++ b/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c
@@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/
* $Id$
*
- * Copyright (C) 2021 Aidan MacDonald
+ * Copyright (C) 2021-2022 Aidan MacDonald
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -20,6 +20,7 @@
****************************************************************************/
#include "audiohw.h"
+#include "audio.h"
#include "system.h"
#include "pcm_sampr.h"
#include "aic-x1000.h"
@@ -27,8 +28,13 @@
#include "gpio-x1000.h"
#include "logf.h"
+static int cur_audio_source = AUDIO_SRC_PLAYBACK;
+static int cur_vol_r = AK4376_MIN_VOLUME;
+static int cur_vol_l = AK4376_MIN_VOLUME;
+static int cur_recvol = 0;
+static int cur_filter_roll_off = 0;
static int cur_fsel = HW_FREQ_48;
-static int cur_power_mode = 0;
+static int cur_power_mode = SOUND_HIGH_POWER;
static void set_ak_freqmode(void)
{
@@ -60,29 +66,138 @@ void audiohw_postinit(void)
void audiohw_close(void)
{
- ak4376_close();
+ if(cur_audio_source == AUDIO_SRC_PLAYBACK)
+ ak4376_close();
+ else if(cur_audio_source == AUDIO_SRC_MIC)
+ x1000_icodec_close();
+}
+
+void audio_set_output_source(int source)
+{
+ /* this is a no-op */
+ (void)source;
+}
+
+void audio_input_mux(int source, unsigned flags)
+{
+ (void)flags;
+
+ if(source == cur_audio_source)
+ return;
+
+ /* close whatever codec is currently in use */
+ audiohw_close();
+ aic_enable_i2s_bit_clock(false);
+
+ /* switch to new source */
+ cur_audio_source = source;
+
+ if(source == AUDIO_SRC_PLAYBACK) {
+ /* power on DAC */
+ aic_set_external_codec(true);
+ aic_set_i2s_mode(AIC_I2S_MASTER_MODE);
+ ak4376_open();
+
+ /* apply the old settings */
+ audiohw_set_volume(cur_vol_l, cur_vol_r);
+ audiohw_set_filter_roll_off(cur_filter_roll_off);
+ set_ak_freqmode();
+ } else if(source == AUDIO_SRC_MIC) {
+ aic_set_external_codec(false);
+ aic_set_i2s_mode(AIC_I2S_SLAVE_MODE);
+ /* Note: Sampling frequency is irrelevant here */
+ aic_set_i2s_clock(X1000_CLK_EXCLK, 48000, 0);
+ aic_enable_i2s_bit_clock(true);
+
+ x1000_icodec_open();
+
+ /* configure the mic */
+ x1000_icodec_mic1_enable(true);
+ x1000_icodec_mic1_bias_enable(true);
+ x1000_icodec_mic1_configure(JZCODEC_MIC1_DIFFERENTIAL |
+ JZCODEC_MIC1_BIAS_2_08V);
+
+ /* configure the ADC */
+ x1000_icodec_adc_mic_sel(JZCODEC_MIC_SEL_ANALOG);
+ x1000_icodec_adc_highpass_filter(true);
+ x1000_icodec_adc_frequency(cur_fsel);
+ x1000_icodec_adc_enable(true);
+
+ /* configure the mixer to put mic input in both channels */
+ x1000_icodec_mixer_enable(true);
+ x1000_icodec_write(JZCODEC_MIX2, 0x10);
+
+ /* set gain and unmute */
+ audiohw_set_recvol(cur_recvol, 0, AUDIO_GAIN_MIC);
+ x1000_icodec_adc_mute(false);
+ } else {
+ logf("bad audio input source: %d (flags: %x)", source, flags);
+ }
}
void audiohw_set_volume(int vol_l, int vol_r)
{
- ak4376_set_volume(vol_l, vol_r);
+ cur_vol_l = vol_l;
+ cur_vol_r = vol_r;
+
+ if(cur_audio_source == AUDIO_SRC_PLAYBACK)
+ ak4376_set_volume(vol_l, vol_r);
}
void audiohw_set_filter_roll_off(int val)
{
- ak4376_set_filter_roll_off(val);
+ cur_filter_roll_off = val;
+
+ if(cur_audio_source == AUDIO_SRC_PLAYBACK)
+ ak4376_set_filter_roll_off(val);
}
void audiohw_set_frequency(int fsel)
{
cur_fsel = fsel;
- set_ak_freqmode();
+
+ if(cur_audio_source == AUDIO_SRC_PLAYBACK)
+ set_ak_freqmode();
+ else
+ x1000_icodec_adc_frequency(fsel);
}
void audiohw_set_power_mode(int mode)
{
cur_power_mode = mode;
- set_ak_freqmode();
+
+ if(cur_audio_source == AUDIO_SRC_PLAYBACK)
+ set_ak_freqmode();
+}
+
+static int round_step_up(int x, int step)
+{
+ int rem = x % step;
+ if(rem > 0)
+ rem -= step;
+ return x - rem;
+}
+
+void audiohw_set_recvol(int left, int right, int type)
+{
+ (void)right;
+
+ if(type == AUDIO_GAIN_MIC) {
+ cur_recvol = left;
+
+ if(cur_audio_source == AUDIO_SRC_MIC) {
+ int mic_gain = round_step_up(left, X1000_ICODEC_MIC_GAIN_STEP);
+ mic_gain = MIN(mic_gain, X1000_ICODEC_MIC_GAIN_MAX);
+ mic_gain = MAX(mic_gain, X1000_ICODEC_MIC_GAIN_MIN);
+
+ int adc_gain = left - mic_gain;
+ adc_gain = MIN(adc_gain, X1000_ICODEC_ADC_GAIN_MAX);
+ adc_gain = MAX(adc_gain, X1000_ICODEC_ADC_GAIN_MIN);
+
+ x1000_icodec_adc_gain(adc_gain);
+ x1000_icodec_mic1_gain(mic_gain);
+ }
+ }
}
void ak4376_set_pdn_pin(int level)
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c
index 5c92fa81e2..840be36a75 100644
--- a/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c
+++ b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c
@@ -61,10 +61,15 @@ void power_init(void)
/* Set lowest sample rate */
axp_adc_set_rate(AXP_ADC_RATE_25HZ);
- /* Ensure battery voltage ADC is enabled */
- int bits = axp_adc_get_enabled();
- bits |= (1 << ADC_BATTERY_VOLTAGE);
- axp_adc_set_enabled(bits);
+ /* Enable required ADCs */
+ axp_adc_set_enabled(
+ (1 << ADC_BATTERY_VOLTAGE) |
+ (1 << ADC_CHARGE_CURRENT) |
+ (1 << ADC_DISCHARGE_CURRENT) |
+ (1 << ADC_VBUS_VOLTAGE) |
+ (1 << ADC_VBUS_CURRENT) |
+ (1 << ADC_INTERNAL_TEMP) |
+ (1 << ADC_APS_VOLTAGE));
/* Turn on all power outputs */
i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR,
@@ -106,3 +111,13 @@ int _battery_voltage(void)
{
return axp_adc_read(ADC_BATTERY_VOLTAGE);
}
+
+#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE
+int _battery_current(void)
+{
+ if(charging_state())
+ return axp_adc_read(ADC_CHARGE_CURRENT);
+ else
+ return axp_adc_read(ADC_DISCHARGE_CURRENT);
+}
+#endif
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c
deleted file mode 100644
index cbbe8b1d5d..0000000000
--- a/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2021 Aidan MacDonald
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include "system.h"
-#include "clk-x1000.h"
-#include "spl-x1000.h"
-#include "gpio-x1000.h"
-
-#define CMDLINE_COMMON \
- "mem=64M@0x0 no_console_suspend console=ttyS2,115200n8 lpj=5009408 ip=off"
-#define CMDLINE_NORMAL \
- " init=/linuxrc ubi.mtd=3 root=ubi0:rootfs ubi.mtd=4 rootfstype=ubifs rw loglevel=8"
-
-static int dualboot_setup(void)
-{
- spl_dualboot_init_clocktree();
- spl_dualboot_init_uart2();
-
- /* load PDMA MCU firmware */
- jz_writef(CPM_CLKGR, PDMA(0));
- return spl_storage_read(0x4000, 0x2000, (void*)0xb3422000);
-}
-
-const struct spl_boot_option spl_boot_options[] = {
- [BOOT_OPTION_ROCKBOX] = {
- .storage_addr = 0x6800,
- .storage_size = 102 * 1024,
- .load_addr = X1000_DRAM_BASE,
- .exec_addr = X1000_DRAM_BASE,
- .flags = BOOTFLAG_UCLPACK,
- },
- [BOOT_OPTION_OFW_PLAYER] = {
- .storage_addr = 0x20000,
- .storage_size = 4 * 1024 * 1024,
- .load_addr = 0x80efffc0,
- .exec_addr = 0x80f00000,
- .cmdline = CMDLINE_COMMON CMDLINE_NORMAL,
- .cmdline_addr = 0x80004000,
- .setup = dualboot_setup,
- },
- [BOOT_OPTION_OFW_RECOVERY] = {
- .storage_addr = 0x420000,
- .storage_size = 5 * 1024 * 1024,
- .load_addr = 0x80efffc0,
- .exec_addr = 0x80f00000,
- .cmdline = CMDLINE_COMMON,
- .cmdline_addr = 0x80004000,
- .setup = dualboot_setup,
- },
-};
-
-int spl_get_boot_option(void)
-{
- /* Button debounce time in OST clock cycles */
- const uint32_t btn_stable_time = 100 * (X1000_EXCLK_FREQ / 4000);
-
- /* Buttons to poll */
- const unsigned port = GPIO_A;
- const uint32_t recov_pin = (1 << 19); /* Volume Up */
- const uint32_t orig_fw_pin = (1 << 17); /* Play */
-
- uint32_t pin = -1, lastpin = 0;
- uint32_t deadline = 0;
- int iter_count = 30; /* to avoid an infinite loop */
-
- /* set GPIOs to input state */
- gpioz_configure(port, recov_pin|orig_fw_pin, GPIOF_INPUT);
-
- /* Poll until we get a stable reading */
- do {
- lastpin = pin;
- pin = ~REG_GPIO_PIN(port) & (recov_pin|orig_fw_pin);
- if(pin != lastpin) {
- deadline = __ost_read32() + btn_stable_time;
- iter_count -= 1;
- }
- } while(iter_count > 0 && __ost_read32() < deadline);
-
- if(iter_count >= 0 && (pin & orig_fw_pin)) {
- if(pin & recov_pin)
- return BOOT_OPTION_OFW_RECOVERY;
- else
- return BOOT_OPTION_OFW_PLAYER;
- }
-
- return BOOT_OPTION_ROCKBOX;
-}
-
-void spl_error(void)
-{
- /* Flash the buttonlight */
- int level = 0;
- while(1) {
- gpio_set_function(GPIO_PC(24), GPIOF_OUTPUT(level));
- mdelay(100);
- level = 1 - level;
- }
-}
diff --git a/firmware/target/mips/ingenic_x1000/installer-x1000.c b/firmware/target/mips/ingenic_x1000/installer-x1000.c
index 0a09ad0e91..66aa42d4a1 100644
--- a/firmware/target/mips/ingenic_x1000/installer-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/installer-x1000.c
@@ -148,7 +148,7 @@ static int updater_init(struct updater* u)
/* buf_len is a bit oversized here, but it's not really important */
u->buf_len = u->img_len + sizeof(mtar_t) + 2*CACHEALIGN_SIZE;
- u->buf_hnd = core_alloc("boot_image", u->buf_len);
+ u->buf_hnd = core_alloc_ex("boot_image", u->buf_len, &buflib_ops_locked);
if(u->buf_hnd < 0) {
rc = IERR_OUT_OF_MEMORY;
goto error;
diff --git a/firmware/target/mips/ingenic_x1000/lcd-x1000.h b/firmware/target/mips/ingenic_x1000/lcd-x1000.h
index 749fac8240..e88a8733ed 100644
--- a/firmware/target/mips/ingenic_x1000/lcd-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/lcd-x1000.h
@@ -105,6 +105,14 @@ extern void lcd_exec_commands(const uint32_t* cmdseq);
*/
extern void lcd_tgt_enable(bool on);
+/* Enable/disable the LCD controller, but intended for booting the OF.
+ *
+ * This is only used for the Eros Q Native port, as the OF seems to be
+ * unable to initialize the LCD in the kernel boot rather than having
+ * the bootloader do it.
+ */
+extern void lcd_tgt_enable_of(bool on);
+
/* Enter or exit sleep mode to save power, normally by sending the necessary
* commands with lcd_exec_commands().
*/
diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.c b/firmware/target/mips/ingenic_x1000/nand-x1000.c
index a818ba10aa..5838b21b39 100644
--- a/firmware/target/mips/ingenic_x1000/nand-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/nand-x1000.c
@@ -69,6 +69,7 @@ const nand_chip supported_nand_chips[] = {
.page_size = 2048,
.oob_size = 64,
.nr_blocks = 1024,
+ .bbm_pos = 2048,
.clock_freq = 150000000,
.dev_conf = jz_orf(SFC_DEV_CONF,
CE_DL(1), HOLD_DL(1), WP_DL(1),
@@ -190,8 +191,10 @@ static void setup_chip_registers(nand_drv* drv)
int nand_open(nand_drv* drv)
{
- if(drv->refcount > 0)
+ if(drv->refcount > 0) {
+ drv->refcount++;
return NAND_SUCCESS;
+ }
/* Initialize the controller */
sfc_open();
@@ -222,7 +225,8 @@ int nand_open(nand_drv* drv)
void nand_close(nand_drv* drv)
{
- if(drv->refcount == 0)
+ --drv->refcount;
+ if(drv->refcount > 0)
return;
/* Let's reset the chip... the idea is to restore the registers
@@ -231,7 +235,6 @@ void nand_close(nand_drv* drv)
mdelay(10);
sfc_close();
- drv->refcount--;
}
static uint8_t nand_wait_busy(nand_drv* drv)
@@ -290,14 +293,14 @@ int nand_read_bytes(nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, void*
if(rc < 0)
return rc;
- memcpy(buffer, &drv->page_buf[offset], MIN(pg_size, byte_len));
+ memcpy(buffer, &drv->page_buf[offset], MIN(pg_size - offset, byte_len));
- if(byte_len <= pg_size)
+ if(byte_len <= pg_size - offset)
break;
+ byte_len -= pg_size - offset;
+ buffer += pg_size - offset;
offset = 0;
- byte_len -= pg_size;
- buffer += pg_size;
page++;
}
diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.h b/firmware/target/mips/ingenic_x1000/nand-x1000.h
index 711bf190b5..668b3e3f82 100644
--- a/firmware/target/mips/ingenic_x1000/nand-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/nand-x1000.h
@@ -78,6 +78,9 @@ typedef struct nand_chip {
/* Total number of blocks in the chip */
unsigned nr_blocks;
+ /* Bad block marker offset within the 1st page of a bad block */
+ unsigned bbm_pos;
+
/* Clock frequency to use */
uint32_t clock_freq;
diff --git a/firmware/target/mips/ingenic_x1000/pcm-x1000.c b/firmware/target/mips/ingenic_x1000/pcm-x1000.c
index ef54d45e62..7d1c83a35a 100644
--- a/firmware/target/mips/ingenic_x1000/pcm-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/pcm-x1000.c
@@ -7,7 +7,7 @@
* \/ \/ \/ \/ \/
* $Id$
*
- * Copyright (C) 2021 Aidan MacDonald
+ * Copyright (C) 2021-2022 Aidan MacDonald
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -31,28 +31,31 @@
#include "x1000/aic.h"
#include "x1000/cpm.h"
-#define AIC_STATE_STOPPED 0
-#define AIC_STATE_PLAYING 1
+#define AIC_STATE_STOPPED 0x00
+#define AIC_STATE_PLAYING 0x01
+#define AIC_STATE_RECORDING 0x02
volatile unsigned aic_tx_underruns = 0;
static int aic_state = AIC_STATE_STOPPED;
-static int aic_lock = 0;
-static volatile int aic_dma_pending_event = DMA_EVENT_NONE;
-
-static dma_desc aic_dma_desc;
-
+static int play_lock = 0;
+static volatile int play_dma_pending_event = DMA_EVENT_NONE;
+static dma_desc play_dma_desc;
static void pcm_play_dma_int_cb(int event);
+
#ifdef HAVE_RECORDING
+volatile unsigned aic_rx_overruns = 0;
+static int rec_lock = 0;
+static volatile int rec_dma_pending_event = DMA_EVENT_NONE;
+static dma_desc rec_dma_desc;
+
static void pcm_rec_dma_int_cb(int event);
#endif
void pcm_play_dma_init(void)
{
- /* Ungate clock, assign pins. NB this overlaps with pins labeled "sa0-sa4"
- * on Ingenic's datasheets but I'm not sure what they are. Probably safe to
- * assume they are not useful to Rockbox... */
+ /* Ungate clock */
jz_writef(CPM_CLKGR, AIC(0));
/* Configure AIC with some sane defaults */
@@ -79,7 +82,7 @@ void pcm_play_dma_init(void)
#endif
/* Set DMA settings */
- jz_writef(AIC_CFG, TFTH(16), RFTH(16));
+ jz_writef(AIC_CFG, TFTH(16), RFTH(15));
dma_set_callback(DMA_CHANNEL_AUDIO, pcm_play_dma_int_cb);
#ifdef HAVE_RECORDING
dma_set_callback(DMA_CHANNEL_RECORD, pcm_rec_dma_int_cb);
@@ -106,23 +109,23 @@ void pcm_dma_apply_settings(void)
audiohw_set_frequency(pcm_fsel);
}
-static void pcm_dma_start(const void* addr, size_t size)
+static void play_dma_start(const void* addr, size_t size)
{
- aic_dma_desc.cm = jz_orf(DMA_CHN_CM, SAI(1), DAI(0), RDIL(9),
- SP_V(32BIT), DP_V(32BIT), TSZ_V(AUTO),
- STDE(0), TIE(1), LINK(0));
- aic_dma_desc.sa = PHYSADDR(addr);
- aic_dma_desc.ta = PHYSADDR(JA_AIC_DR);
- aic_dma_desc.tc = size;
- aic_dma_desc.sd = 0;
- aic_dma_desc.rt = jz_orf(DMA_CHN_RT, TYPE_V(I2S_TX));
- aic_dma_desc.pad0 = 0;
- aic_dma_desc.pad1 = 0;
-
- commit_dcache_range(&aic_dma_desc, sizeof(dma_desc));
+ play_dma_desc.cm = jz_orf(DMA_CHN_CM, SAI(1), DAI(0), RDIL(9),
+ SP_V(32BIT), DP_V(32BIT), TSZ_V(AUTO),
+ STDE(0), TIE(1), LINK(0));
+ play_dma_desc.sa = PHYSADDR(addr);
+ play_dma_desc.ta = PHYSADDR(JA_AIC_DR);
+ play_dma_desc.tc = size;
+ play_dma_desc.sd = 0;
+ play_dma_desc.rt = jz_orf(DMA_CHN_RT, TYPE_V(I2S_TX));
+ play_dma_desc.pad0 = 0;
+ play_dma_desc.pad1 = 0;
+
+ commit_dcache_range(&play_dma_desc, sizeof(dma_desc));
commit_dcache_range(addr, size);
- REG_DMA_CHN_DA(DMA_CHANNEL_AUDIO) = PHYSADDR(&aic_dma_desc);
+ REG_DMA_CHN_DA(DMA_CHANNEL_AUDIO) = PHYSADDR(&play_dma_desc);
jz_writef(DMA_CHN_CS(DMA_CHANNEL_AUDIO), DES8(1), NDES(0));
jz_set(DMA_DB, 1 << DMA_CHANNEL_AUDIO);
jz_writef(DMA_CHN_CS(DMA_CHANNEL_AUDIO), CTE(1));
@@ -130,13 +133,13 @@ static void pcm_dma_start(const void* addr, size_t size)
pcm_play_dma_status_callback(PCM_DMAST_STARTED);
}
-static void pcm_dma_handle_event(int event)
+static void play_dma_handle_event(int event)
{
if(event == DMA_EVENT_COMPLETE) {
const void* addr;
size_t size;
if(pcm_play_dma_complete_callback(PCM_DMAST_OK, &addr, &size))
- pcm_dma_start(addr, size);
+ play_dma_start(addr, size);
} else if(event == DMA_EVENT_NONE) {
/* ignored, so callers don't need to check for this */
} else {
@@ -146,20 +149,20 @@ static void pcm_dma_handle_event(int event)
static void pcm_play_dma_int_cb(int event)
{
- if(aic_lock) {
- aic_dma_pending_event = event;
+ if(play_lock) {
+ play_dma_pending_event = event;
return;
} else {
- pcm_dma_handle_event(event);
+ play_dma_handle_event(event);
}
}
void pcm_play_dma_start(const void* addr, size_t size)
{
- aic_dma_pending_event = DMA_EVENT_NONE;
- aic_state = AIC_STATE_PLAYING;
+ play_dma_pending_event = DMA_EVENT_NONE;
+ aic_state |= AIC_STATE_PLAYING;
- pcm_dma_start(addr, size);
+ play_dma_start(addr, size);
jz_writef(AIC_CCR, TDMS(1), ETUR(1), ERPL(1));
}
@@ -168,21 +171,23 @@ void pcm_play_dma_stop(void)
jz_writef(AIC_CCR, TDMS(0), ETUR(0), ERPL(0));
jz_writef(AIC_CCR, TFLUSH(1));
- aic_dma_pending_event = DMA_EVENT_NONE;
- aic_state = AIC_STATE_STOPPED;
+ play_dma_pending_event = DMA_EVENT_NONE;
+ aic_state &= ~AIC_STATE_PLAYING;
}
void pcm_play_lock(void)
{
- ++aic_lock;
+ int irq = disable_irq_save();
+ ++play_lock;
+ restore_irq(irq);
}
void pcm_play_unlock(void)
{
int irq = disable_irq_save();
- if(--aic_lock == 0 && aic_state == AIC_STATE_PLAYING) {
- pcm_dma_handle_event(aic_dma_pending_event);
- aic_dma_pending_event = DMA_EVENT_NONE;
+ if(--play_lock == 0 && (aic_state & AIC_STATE_PLAYING)) {
+ play_dma_handle_event(play_dma_pending_event);
+ play_dma_pending_event = DMA_EVENT_NONE;
}
restore_irq(irq);
@@ -193,11 +198,56 @@ void pcm_play_unlock(void)
* Recording
*/
-/* FIXME need to implement this!! */
+static void rec_dma_start(void* addr, size_t size)
+{
+ /* NOTE: Rockbox always records in stereo and the AIC pushes in the
+ * sample for each channel separately. One frame therefore requires
+ * two 16-bit transfers from the AIC. */
+ rec_dma_desc.cm = jz_orf(DMA_CHN_CM, SAI(0), DAI(1), RDIL(6),
+ SP_V(16BIT), DP_V(16BIT), TSZ_V(16BIT),
+ STDE(0), TIE(1), LINK(0));
+ rec_dma_desc.sa = PHYSADDR(JA_AIC_DR);
+ rec_dma_desc.ta = PHYSADDR(addr);
+ rec_dma_desc.tc = size / 2;
+ rec_dma_desc.sd = 0;
+ rec_dma_desc.rt = jz_orf(DMA_CHN_RT, TYPE_V(I2S_RX));
+ rec_dma_desc.pad0 = 0;
+ rec_dma_desc.pad1 = 0;
+
+ commit_dcache_range(&rec_dma_desc, sizeof(dma_desc));
+ if((unsigned long)addr < 0xa0000000ul)
+ discard_dcache_range(addr, size);
+
+ REG_DMA_CHN_DA(DMA_CHANNEL_RECORD) = PHYSADDR(&rec_dma_desc);
+ jz_writef(DMA_CHN_CS(DMA_CHANNEL_RECORD), DES8(1), NDES(0));
+ jz_set(DMA_DB, 1 << DMA_CHANNEL_RECORD);
+ jz_writef(DMA_CHN_CS(DMA_CHANNEL_RECORD), CTE(1));
+
+ pcm_rec_dma_status_callback(PCM_DMAST_STARTED);
+}
+
+static void rec_dma_handle_event(int event)
+{
+ if(event == DMA_EVENT_COMPLETE) {
+ void* addr;
+ size_t size;
+ if(pcm_rec_dma_complete_callback(PCM_DMAST_OK, &addr, &size))
+ rec_dma_start(addr, size);
+ } else if(event == DMA_EVENT_NONE) {
+ /* ignored, so callers don't need to check for this */
+ } else {
+ pcm_rec_dma_status_callback(PCM_DMAST_ERR_DMA);
+ }
+}
static void pcm_rec_dma_int_cb(int event)
{
- (void)event;
+ if(rec_lock) {
+ rec_dma_pending_event = event;
+ return;
+ } else {
+ rec_dma_handle_event(event);
+ }
}
void pcm_rec_dma_init(void)
@@ -210,40 +260,52 @@ void pcm_rec_dma_close(void)
void pcm_rec_dma_start(void* addr, size_t size)
{
- (void)addr;
- (void)size;
+ rec_dma_pending_event = DMA_EVENT_NONE;
+ aic_state |= AIC_STATE_RECORDING;
+
+ rec_dma_start(addr, size);
+ jz_writef(AIC_CCR, RDMS(1), EROR(1), EREC(1));
}
void pcm_rec_dma_stop(void)
{
+ jz_writef(AIC_CCR, RDMS(0), EROR(0), EREC(0));
+ jz_writef(AIC_CCR, RFLUSH(1));
+
+ rec_dma_pending_event = DMA_EVENT_NONE;
+ aic_state &= ~AIC_STATE_RECORDING;
}
void pcm_rec_lock(void)
{
-
+ int irq = disable_irq_save();
+ ++rec_lock;
+ restore_irq(irq);
}
void pcm_rec_unlock(void)
{
+ int irq = disable_irq_save();
+ if(--rec_lock == 0 && (aic_state & AIC_STATE_RECORDING)) {
+ rec_dma_handle_event(rec_dma_pending_event);
+ rec_dma_pending_event = DMA_EVENT_NONE;
+ }
+ restore_irq(irq);
}
const void* pcm_rec_dma_get_peak_buffer(void)
{
- return NULL;
-}
-
-void audio_set_output_source(int source)
-{
- (void)source;
+ return (const void*)UNCACHEDADDR(REG_DMA_CHN_TA(DMA_CHANNEL_RECORD));
}
+#endif /* HAVE_RECORDING */
-void audio_input_mux(int source, unsigned flags)
+#ifdef HAVE_PCM_DMA_ADDRESS
+void* pcm_dma_addr(void* addr)
{
- (void)source;
- (void)flags;
+ return (void*)UNCACHEDADDR(addr);
}
-#endif /* HAVE_RECORDING */
+#endif
void AIC(void)
{
@@ -251,4 +313,11 @@ void AIC(void)
aic_tx_underruns += 1;
jz_writef(AIC_SR, TUR(0));
}
+
+#ifdef HAVE_RECORDING
+ if(jz_readf(AIC_SR, ROR)) {
+ aic_rx_overruns += 1;
+ jz_writef(AIC_SR, ROR(0));
+ }
+#endif /* HAVE_RECORDING */
}
diff --git a/firmware/target/mips/ingenic_x1000/sfc-x1000.h b/firmware/target/mips/ingenic_x1000/sfc-x1000.h
index d28bcb6740..afb4aa3ce6 100644
--- a/firmware/target/mips/ingenic_x1000/sfc-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/sfc-x1000.h
@@ -87,13 +87,13 @@ extern void sfc_irq_end(void);
extern void sfc_set_clock(uint32_t freq);
/* Set the device configuration register */
-inline void sfc_set_dev_conf(uint32_t conf)
+static inline void sfc_set_dev_conf(uint32_t conf)
{
REG_SFC_DEV_CONF = conf;
}
/* Control the state of the write protect pin */
-inline void sfc_set_wp_enable(bool en)
+static inline void sfc_set_wp_enable(bool en)
{
jz_writef(SFC_GLB, WP_EN(en ? 1 : 0));
}
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/audiohw-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/audiohw-shanlingq1.c
index 7314f20412..787c35c494 100644
--- a/firmware/target/mips/ingenic_x1000/shanlingq1/audiohw-shanlingq1.c
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/audiohw-shanlingq1.c
@@ -59,7 +59,7 @@ static void codec_stop(void)
{
es9218_mute(true);
es9218_close();
- mdelay(1);
+ mdelay(4);
}
void audiohw_init(void)
@@ -154,7 +154,7 @@ void audiohw_set_filter_roll_off(int value)
void audiohw_set_power_mode(int mode)
{
enum es9218_amp_mode new_amp_mode;
- if(mode == 0)
+ if(mode == SOUND_HIGH_POWER)
new_amp_mode = ES9218_AMP_MODE_2VRMS;
else
new_amp_mode = ES9218_AMP_MODE_1VRMS;
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c
index 17fbe1cede..59a2262f25 100644
--- a/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c
@@ -78,6 +78,19 @@ void power_init(void)
cw2015_init();
#endif
+ /* Set lowest sample rate */
+ axp_adc_set_rate(AXP_ADC_RATE_25HZ);
+
+ /* Enable required ADCs */
+ axp_adc_set_enabled(
+ (1 << ADC_BATTERY_VOLTAGE) |
+ (1 << ADC_CHARGE_CURRENT) |
+ (1 << ADC_DISCHARGE_CURRENT) |
+ (1 << ADC_VBUS_VOLTAGE) |
+ (1 << ADC_VBUS_CURRENT) |
+ (1 << ADC_INTERNAL_TEMP) |
+ (1 << ADC_APS_VOLTAGE));
+
/* Change supply voltage from the default of 1250 mV to 1200 mV,
* this matches the original firmware's settings. Didn't observe
* any obviously bad behavior at 1250 mV, but better to be safe. */
@@ -121,6 +134,16 @@ int _battery_voltage(void)
return axp_adc_read(ADC_BATTERY_VOLTAGE);
}
+#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE
+int _battery_current(void)
+{
+ if(charging_state())
+ return axp_adc_read(ADC_CHARGE_CURRENT);
+ else
+ return axp_adc_read(ADC_DISCHARGE_CURRENT);
+}
+#endif
+
#if defined(HAVE_CW2015) && (CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) != 0
int _battery_level(void)
{
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/spl-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/spl-shanlingq1.c
deleted file mode 100644
index 33303c5e6b..0000000000
--- a/firmware/target/mips/ingenic_x1000/shanlingq1/spl-shanlingq1.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2021 Aidan MacDonald
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include "system.h"
-#include "clk-x1000.h"
-#include "spl-x1000.h"
-#include "gpio-x1000.h"
-
-#define CMDLINE_COMMON \
- "mem=64M@0x0 no_console_suspend console=ttyS2,115200n8 lpj=5009408 ip=off"
-#define CMDLINE_NORMAL \
- " init=/linuxrc ubi.mtd=5 root=ubi0:rootfs ubi.mtd=6 rootfstype=ubifs rw"
-
-static int dualboot_setup(void)
-{
- spl_dualboot_init_clocktree();
- spl_dualboot_init_uart2();
-
- /* load PDMA MCU firmware */
- jz_writef(CPM_CLKGR, PDMA(0));
- return spl_storage_read(0x4000, 0x2000, (void*)0xb3422000);
-}
-
-const struct spl_boot_option spl_boot_options[] = {
- [BOOT_OPTION_ROCKBOX] = {
- .storage_addr = 0x6800,
- .storage_size = 102 * 1024,
- .load_addr = X1000_DRAM_BASE,
- .exec_addr = X1000_DRAM_BASE,
- .flags = BOOTFLAG_UCLPACK,
- },
- [BOOT_OPTION_OFW_PLAYER] = {
- .storage_addr = 0x140000,
- .storage_size = 8 * 1024 * 1024,
- .load_addr = 0x80efffc0,
- .exec_addr = 0x80f00000,
- .cmdline = CMDLINE_COMMON CMDLINE_NORMAL,
- .cmdline_addr = 0x80004000,
- .setup = dualboot_setup,
- },
- [BOOT_OPTION_OFW_RECOVERY] = {
- .storage_addr = 0x940000,
- .storage_size = 10 * 1024 * 1024,
- .load_addr = 0x80efffc0,
- .exec_addr = 0x80f00000,
- .cmdline = CMDLINE_COMMON,
- .cmdline_addr = 0x80004000,
- .setup = dualboot_setup,
- },
-};
-
-int spl_get_boot_option(void)
-{
- /* Button debounce time in OST clock cycles */
- const uint32_t btn_stable_time = 100 * (X1000_EXCLK_FREQ / 4000);
-
- /* Buttons to poll */
- const unsigned port = GPIO_B;
- const uint32_t recov_pin = (1 << 22); /* Next */
- const uint32_t orig_fw_pin = (1 << 21); /* Prev */
-
- uint32_t pin = -1, lastpin = 0;
- uint32_t deadline = 0;
- int iter_count = 30; /* to avoid an infinite loop */
-
- /* set GPIOs to input state */
- gpioz_configure(port, recov_pin|orig_fw_pin, GPIOF_INPUT);
-
- /* Poll until we get a stable reading */
- do {
- lastpin = pin;
- pin = ~REG_GPIO_PIN(port) & (recov_pin|orig_fw_pin);
- if(pin != lastpin) {
- deadline = __ost_read32() + btn_stable_time;
- iter_count -= 1;
- }
- } while(iter_count > 0 && __ost_read32() < deadline);
-
- if(iter_count >= 0 && (pin & orig_fw_pin)) {
- if(pin & recov_pin)
- return BOOT_OPTION_OFW_RECOVERY;
- else
- return BOOT_OPTION_OFW_PLAYER;
- }
-
- return BOOT_OPTION_ROCKBOX;
-}
-
-void spl_error(void)
-{
- /* Flash the backlight */
- int level = 0;
- while(1) {
- gpio_set_function(GPIO_PC(25), GPIOF_OUTPUT(level));
- mdelay(100);
- level = 1 - level;
- }
-}
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/spl-erosqnative.c b/firmware/target/mips/ingenic_x1000/spl-nand-x1000.c
index 9d7a1d118a..82a05abf75 100644
--- a/firmware/target/mips/ingenic_x1000/erosqnative/spl-erosqnative.c
+++ b/firmware/target/mips/ingenic_x1000/spl-nand-x1000.c
@@ -19,45 +19,32 @@
*
****************************************************************************/
-#include "system.h"
-#include "clk-x1000.h"
#include "spl-x1000.h"
#include "gpio-x1000.h"
+#include "nand-x1000.h"
-/* TODO: get dual-boot working */
+static nand_drv* ndrv = NULL;
-const struct spl_boot_option spl_boot_options[] = {
- [BOOT_OPTION_ROCKBOX] = {
- .storage_addr = 0x6800,
- .storage_size = 102 * 1024,
- .load_addr = X1000_DRAM_BASE,
- .exec_addr = X1000_DRAM_BASE,
- .flags = BOOTFLAG_UCLPACK,
- },
-};
-
-int spl_get_boot_option(void)
+int spl_storage_open(void)
{
- return BOOT_OPTION_ROCKBOX;
-}
+ /* We need to assign the GPIOs manually */
+ gpioz_configure(GPIO_A, 0x3f << 26, GPIOF_DEVICE(1));
-void spl_error(void)
-{
- const uint32_t pin = (1 << 25);
+ /* Allocate NAND driver manually in DRAM */
+ ndrv = spl_alloc(sizeof(nand_drv));
+ ndrv->page_buf = spl_alloc(NAND_DRV_MAXPAGESIZE);
+ ndrv->scratch_buf = spl_alloc(NAND_DRV_SCRATCHSIZE);
+ ndrv->refcount = 0;
- /* Turn on backlight */
- jz_clr(GPIO_INT(GPIO_C), pin);
- jz_set(GPIO_MSK(GPIO_C), pin);
- jz_clr(GPIO_PAT1(GPIO_C), pin);
- jz_set(GPIO_PAT0(GPIO_C), pin);
+ return nand_open(ndrv);
+}
- while(1) {
- /* Turn it off */
- mdelay(100);
- jz_set(GPIO_PAT0(GPIO_C), pin);
+void spl_storage_close(void)
+{
+ nand_close(ndrv);
+}
- /* Turn it on */
- mdelay(100);
- jz_clr(GPIO_PAT0(GPIO_C), pin);
- }
+int spl_storage_read(uint32_t addr, uint32_t length, void* buffer)
+{
+ return nand_read_bytes(ndrv, addr, length, buffer);
}
diff --git a/firmware/target/mips/ingenic_x1000/spl-x1000.c b/firmware/target/mips/ingenic_x1000/spl-x1000.c
index afaf5a7dd6..b9ee6cc1c1 100644
--- a/firmware/target/mips/ingenic_x1000/spl-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/spl-x1000.c
@@ -34,20 +34,49 @@
#include "ucl_decompress.h"
#include <string.h>
-#if defined(FIIO_M3K) || defined(SHANLING_Q1)
-# define SPL_DDR_MEMORYSIZE 64
-# define SPL_DDR_AUTOSR_EN 1
-# define SPL_DDR_NEED_BYPASS 1
+#if defined(FIIO_M3K)
+/* Size of memory, either 64 or 32 is legal. */
+# define SPL_DDR_MEMORYSIZE 64
+/* Pin to flash on spl_error(). Should be a backlight. */
+# define SPL_ERROR_PIN GPIO_PC(24)
+/* Address and size of the bootloader on the storage medium used by the SPL */
+# define BOOT_STORAGE_ADDR 0x6800
+# define BOOT_STORAGE_SIZE (102 * 1024)
+#elif defined(SHANLING_Q1)
+# define SPL_DDR_MEMORYSIZE 64
+# define SPL_ERROR_PIN GPIO_PC(25)
+# define BOOT_STORAGE_ADDR 0x6800
+# define BOOT_STORAGE_SIZE (102 * 1024)
#elif defined(EROS_QN)
-# define SPL_DDR_MEMORYSIZE 32
-# define SPL_DDR_AUTOSR_EN 1
-# define SPL_DDR_NEED_BYPASS 1
+# define SPL_DDR_MEMORYSIZE 32
+# define SPL_ERROR_PIN GPIO_PC(25)
+# define BOOT_STORAGE_ADDR 0x6800
+# define BOOT_STORAGE_SIZE (102 * 1024)
#else
-# error "please define DRAM settings"
+# error "please define SPL config"
+#endif
+
+/* Hardcode this since the SPL is considered part of the bootloader,
+ * and should never get built or updated separately. */
+#define BOOT_LOAD_ADDR X1000_DRAM_BASE
+#define BOOT_EXEC_ADDR BOOT_LOAD_ADDR
+
+/* Whether the bootloader is UCL-compressed */
+#ifndef SPL_USE_UCLPACK
+# define SPL_USE_UCLPACK 1
+#endif
+
+/* Whether auto-self-refresh should be enabled (seems it always should be?) */
+#ifndef SPL_DDR_AUTOSR_EN
+# define SPL_DDR_AUTOSR_EN 1
+#endif
+
+/* Whether DLL bypass is necessary (probably always?) */
+#ifndef SPL_DDR_NEED_BYPASS
+# define SPL_DDR_NEED_BYPASS 1
#endif
static void* heap = (void*)(X1000_SDRAM_BASE + X1000_SDRAM_SIZE);
-static nand_drv* ndrv = NULL;
void* spl_alloc(size_t count)
{
@@ -56,114 +85,14 @@ void* spl_alloc(size_t count)
return heap;
}
-int spl_storage_open(void)
-{
- /* We need to assign the GPIOs manually */
- gpioz_configure(GPIO_A, 0x3f << 26, GPIOF_DEVICE(1));
-
- /* Allocate NAND driver manually in DRAM */
- ndrv = spl_alloc(sizeof(nand_drv));
- ndrv->page_buf = spl_alloc(NAND_DRV_MAXPAGESIZE);
- ndrv->scratch_buf = spl_alloc(NAND_DRV_SCRATCHSIZE);
- ndrv->refcount = 0;
-
- return nand_open(ndrv);
-}
-
-void spl_storage_close(void)
-{
- nand_close(ndrv);
-}
-
-int spl_storage_read(uint32_t addr, uint32_t length, void* buffer)
-{
- return nand_read_bytes(ndrv, addr, length, buffer);
-}
-
-/* Used by:
- * - FiiO M3K
- * - Shanling Q1
- *
- * Amend it and add #ifdefs for other targets if needed.
- */
-void spl_dualboot_init_clocktree(void)
+void spl_error(void)
{
- /* Make sure these are gated to match the OF behavior. */
- jz_writef(CPM_CLKGR, PCM(1), MAC(1), LCD(1), MSC0(1), MSC1(1), OTG(1), CIM(1));
-
- /* Set clock sources, and make sure every clock starts out stopped */
- jz_writef(CPM_I2SCDR, CS_V(EXCLK));
- jz_writef(CPM_PCMCDR, CS_V(EXCLK));
-
- jz_writef(CPM_MACCDR, CLKSRC_V(MPLL), CE(1), STOP(1), CLKDIV(0xfe));
- while(jz_readf(CPM_MACCDR, BUSY));
-
- jz_writef(CPM_LPCDR, CLKSRC_V(MPLL), CE(1), STOP(1), CLKDIV(0xfe));
- while(jz_readf(CPM_LPCDR, BUSY));
-
- jz_writef(CPM_MSC0CDR, CLKSRC_V(MPLL), CE(1), STOP(1), CLKDIV(0xfe));
- while(jz_readf(CPM_MSC0CDR, BUSY));
-
- jz_writef(CPM_MSC1CDR, CE(1), STOP(1), CLKDIV(0xfe));
- while(jz_readf(CPM_MSC1CDR, BUSY));
-
- jz_writef(CPM_CIMCDR, CLKSRC_V(MPLL), CE(1), STOP(1), CLKDIV(0xfe));
- while(jz_readf(CPM_CIMCDR, BUSY));
-
- jz_writef(CPM_USBCDR, CLKSRC_V(EXCLK), CE(1), STOP(1));
- while(jz_readf(CPM_USBCDR, BUSY));
-}
-
-void spl_dualboot_init_uart2(void)
-{
- /* Ungate the clock and select UART2 device function */
- jz_writef(CPM_CLKGR, UART2(0));
- gpioz_configure(GPIO_C, 3 << 30, GPIOF_DEVICE(1));
-
- /* Disable all interrupts */
- jz_write(UART_UIER(2), 0);
-
- /* FIFO configuration */
- jz_overwritef(UART_UFCR(2),
- RDTR(3), /* FIFO trigger level = 60? */
- UME(0), /* UART module disable */
- DME(1), /* DMA mode enable? */
- TFRT(1), /* transmit FIFO reset */
- RFRT(1), /* receive FIFO reset */
- FME(1)); /* FIFO mode enable */
-
- /* IR mode configuration */
- jz_overwritef(UART_ISR(2),
- RDPL(1), /* Zero is negative pulse for receive */
- TDPL(1), /* ... and for transmit */
- XMODE(1), /* Pulse width 1.6us */
- RCVEIR(0), /* Disable IR for recieve */
- XMITIR(0)); /* ... and for transmit */
-
- /* Line configuration */
- jz_overwritef(UART_ULCR(2), DLAB(0),
- WLS_V(8BITS), /* 8 bit words */
- SBLS_V(1_STOP_BIT), /* 1 stop bit */
- PARE(0), /* no parity */
- SBK(0)); /* don't set break */
-
- /* Set the baud rate... not too sure how this works. (Docs unclear!) */
- const unsigned divisor = 0x0004;
- jz_writef(UART_ULCR(2), DLAB(1));
- jz_write(UART_UDLHR(2), (divisor >> 8) & 0xff);
- jz_write(UART_UDLLR(2), divisor & 0xff);
- jz_write(UART_UMR(2), 16);
- jz_write(UART_UACR(2), 0);
- jz_writef(UART_ULCR(2), DLAB(0));
-
- /* Enable UART */
- jz_overwritef(UART_UFCR(2),
- RDTR(0), /* FIFO trigger level = 1 */
- DME(0), /* DMA mode disable */
- UME(1), /* UART module enable */
- TFRT(1), /* transmit FIFO reset */
- RFRT(1), /* receive FIFO reset */
- FME(1)); /* FIFO mode enable */
+ int level = 0;
+ while(1) {
+ gpio_set_function(SPL_ERROR_PIN, GPIOF_OUTPUT(level));
+ mdelay(100);
+ level = 1 - level;
+ }
}
static void init_ost(void)
@@ -346,14 +275,14 @@ static int init_dram(void)
return 0;
}
-static void* get_load_buffer(const struct spl_boot_option* opt)
+static void* get_load_buffer(void)
{
/* read to a temporary location if we need to decompress,
* otherwise simply read directly to the load address. */
- if(opt->flags & BOOTFLAG_UCLPACK)
- return spl_alloc(opt->storage_size);
+ if(SPL_USE_UCLPACK)
+ return spl_alloc(BOOT_STORAGE_SIZE);
else
- return (void*)opt->load_addr;
+ return (void*)BOOT_LOAD_ADDR;
}
/* Mapping of boot_sel[1:0] pins.
@@ -377,15 +306,10 @@ static uint32_t get_boot_sel(void)
return (*(uint32_t*)0xf40001ec) & 3;
}
-typedef void(*entry_fn)(int, char**, int, int) __attribute__((noreturn));
-
void spl_main(void)
{
- int rc, boot_option;
- const struct spl_boot_option* opt;
+ int rc;
void* load_buffer;
- char** kargv = NULL;
- int kargc = 0;
/* magic */
REG_CPM_PSWC0ST = 0x00;
@@ -395,7 +319,6 @@ void spl_main(void)
/* set up boot flags */
init_boot_flags();
- set_boot_option(BOOT_OPTION_ROCKBOX);
/* early clock and DRAM init */
clk_init_early();
@@ -409,14 +332,6 @@ void spl_main(void)
return;
}
- /* find out what we should boot */
- boot_option = spl_get_boot_option();
- opt = &spl_boot_options[boot_option];
- load_buffer = get_load_buffer(opt);
-
- /* save the selection for later */
- set_boot_option(boot_option);
-
/* finish up clock init */
clk_init();
@@ -425,44 +340,29 @@ void spl_main(void)
if(rc != 0)
spl_error();
- rc = spl_storage_read(opt->storage_addr, opt->storage_size, load_buffer);
+ load_buffer = get_load_buffer();
+ rc = spl_storage_read(BOOT_STORAGE_ADDR, BOOT_STORAGE_SIZE, load_buffer);
if(rc != 0)
spl_error();
- /* handle compression */
- switch(opt->flags & BOOTFLAG_COMPRESSED) {
- case BOOTFLAG_UCLPACK: {
- uint32_t out_size = X1000_DRAM_END - opt->load_addr;
- rc = ucl_unpack((uint8_t*)load_buffer, opt->storage_size,
- (uint8_t*)opt->load_addr, &out_size);
- } break;
-
- default:
- break;
+ /* decompress */
+ if(SPL_USE_UCLPACK) {
+ uint32_t out_size = X1000_SDRAM_END - BOOT_LOAD_ADDR;
+ rc = ucl_unpack((uint8_t*)load_buffer, BOOT_STORAGE_SIZE,
+ (uint8_t*)BOOT_LOAD_ADDR, &out_size);
+ } else {
+ rc = 0;
}
if(rc != 0)
spl_error();
- /* call the setup hook */
- if(opt->setup) {
- rc = opt->setup();
- if(rc != 0)
- spl_error();
- }
-
/* close off storage access */
spl_storage_close();
- /* handle kernel command line, if specified */
- if(opt->cmdline) {
- kargv = (char**)opt->cmdline_addr;
- kargv[kargc++] = 0;
- kargv[kargc++] = (char*)opt->cmdline;
- }
-
/* jump to the entry point */
- entry_fn fn = (entry_fn)opt->exec_addr;
+ typedef void(*entry_fn)(void);
+ entry_fn fn = (entry_fn)BOOT_EXEC_ADDR;
commit_discard_idcache();
- fn(kargc, kargv, 0, 0);
+ fn();
}
diff --git a/firmware/target/mips/ingenic_x1000/spl-x1000.h b/firmware/target/mips/ingenic_x1000/spl-x1000.h
index 6d60dbf880..9ee1aa768e 100644
--- a/firmware/target/mips/ingenic_x1000/spl-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/spl-x1000.h
@@ -26,23 +26,6 @@
#include <stddef.h>
#include <stdint.h>
-#define BOOTFLAG_COMPRESSED 0x0f /* mask for compression flags */
-#define BOOTFLAG_UCLPACK 0x01 /* image is compressed with 'uclpack' */
-
-struct spl_boot_option {
- uint32_t storage_addr; /* image's location in storage */
- uint32_t storage_size; /* number of bytes to load */
- uint32_t load_addr; /* address to load image to */
- uint32_t exec_addr; /* address of the entry point */
- uint32_t flags; /* any special flags */
- const char* cmdline; /* command line; use NULL if not needed */
- uint32_t cmdline_addr; /* address to contain command line 'argv[]' */
- int(*setup)(void); /* setup hook, called before jumping to image */
-};
-
-/* array of boot option descriptions */
-extern const struct spl_boot_option spl_boot_options[];
-
/* Memory allocator. Allocation starts from the top of DRAM and counts down.
* Allocation sizes are rounded up to a multiple of the cacheline size, so
* the returned address is always suitably aligned for DMA. */
@@ -58,13 +41,6 @@ extern int spl_storage_open(void);
extern void spl_storage_close(void);
extern int spl_storage_read(uint32_t addr, uint32_t length, void* buffer);
-/* Helpers for dual-booting with the Ingenic Linux OF */
-extern void spl_dualboot_init_clocktree(void);
-extern void spl_dualboot_init_uart2(void);
-
-/* Get the boot option selected by the user, eg. by a key press */
-extern int spl_get_boot_option(void);
-
/* Called on a fatal error -- it should do something visible to the user
* like flash the backlight repeatedly. */
extern void spl_error(void) __attribute__((noreturn));
diff --git a/firmware/target/mips/ingenic_x1000/spl.lds b/firmware/target/mips/ingenic_x1000/spl.lds
index b0169ab1aa..09ab75d520 100644
--- a/firmware/target/mips/ingenic_x1000/spl.lds
+++ b/firmware/target/mips/ingenic_x1000/spl.lds
@@ -7,10 +7,8 @@ ENTRY(_spl_start)
STARTUP(target/mips/ingenic_x1000/spl-start.o)
MEMORY {
- /* First 4k of TCSM is used by mask ROM for stack + variables,
- * and the next 2k are occupied by SPL header */
- TCSM : ORIGIN = X1000_TCSM_BASE + 0x1800,
- LENGTH = X1000_TCSM_SIZE - 0x1800
+ TCSM : ORIGIN = X1000_SPL_EXEC_ADDR,
+ LENGTH = X1000_SPL_SIZE
}
SECTIONS
diff --git a/firmware/target/mips/ingenic_x1000/system-x1000.c b/firmware/target/mips/ingenic_x1000/system-x1000.c
index d43c8e67e4..7542b97a3d 100644
--- a/firmware/target/mips/ingenic_x1000/system-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/system-x1000.c
@@ -72,7 +72,6 @@ void system_early_init(void)
* This hack should keep everything working as usual. */
if(jz_readf(CPM_MPCR, ON) == 0) {
init_boot_flags();
- set_boot_option(BOOT_OPTION_ROCKBOX);
set_boot_flag(BOOT_FLAG_CLK_INIT);
}
#endif