summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_x1000/erosqnative
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/erosqnative')
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/adc-target.h0
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/audiohw-erosqnative.c90
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/backlight-erosqnative.c63
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/backlight-target.h33
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/boot.make30
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c247
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/button-target.h45
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/gpio-target.h71
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/i2c-target.h31
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c188
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c110
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/spl-erosqnative.c63
12 files changed, 971 insertions, 0 deletions
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/adc-target.h b/firmware/target/mips/ingenic_x1000/erosqnative/adc-target.h
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/adc-target.h
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/audiohw-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/audiohw-erosqnative.c
new file mode 100644
index 0000000000..7bb985650c
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/audiohw-erosqnative.c
@@ -0,0 +1,90 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald, Dana Conrad
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "audiohw.h"
23#include "system.h"
24#include "pcm_sampr.h"
25#include "aic-x1000.h"
26#include "i2c-x1000.h"
27#include "gpio-x1000.h"
28#include "logf.h"
29
30/* Audio path appears to be:
31 * DAC --> HP Amp --> Stereo Switch --> HP OUT
32 * \--> LO OUT
33 *
34 * The real purpose of the Stereo Switch is not clear.
35 * It appears to switch sources between the HP amp and something,
36 * likely something unimplemented. */
37
38void audiohw_init(void)
39{
40 /* explicitly mute everything */
41 gpio_set_level(GPIO_MAX97220_SHDN, 0);
42 gpio_set_level(GPIO_ISL54405_MUTE, 1);
43 gpio_set_level(GPIO_PCM5102A_XMIT, 0);
44
45 aic_set_external_codec(true);
46 aic_set_i2s_mode(AIC_I2S_MASTER_MODE);
47 audiohw_set_frequency(HW_FREQ_48);
48
49 aic_enable_i2s_master_clock(true);
50 aic_enable_i2s_bit_clock(true);
51
52 mdelay(10);
53
54 /* power on DAC and HP Amp */
55 gpio_set_level(GPIO_PCM5102A_ANALOG_PWR, 1);
56 gpio_set_level(GPIO_MAX97220_POWER, 1);
57}
58
59void audiohw_postinit(void)
60{
61 /* unmute - attempt to make power-on pop-free */
62 gpio_set_level(GPIO_ISL54405_SEL, 0);
63 gpio_set_level(GPIO_MAX97220_SHDN, 1);
64 mdelay(10);
65 gpio_set_level(GPIO_PCM5102A_XMIT, 1);
66 mdelay(10);
67 gpio_set_level(GPIO_ISL54405_MUTE, 0);
68}
69
70/* TODO: get shutdown just right according to dac datasheet */
71void audiohw_close(void)
72{
73 /* mute - attempt to make power-off pop-free */
74 gpio_set_level(GPIO_ISL54405_MUTE, 1);
75 mdelay(10);
76 gpio_set_level(GPIO_PCM5102A_XMIT, 0);
77 mdelay(10);
78 gpio_set_level(GPIO_MAX97220_SHDN, 0);
79}
80
81void audiohw_set_frequency(int fsel)
82{
83 int sampr = hw_freq_sampr[fsel];
84 int mult = 256;
85
86 aic_enable_i2s_bit_clock(false);
87 aic_set_i2s_clock(X1000_CLK_SCLK_A, sampr, mult);
88 aic_enable_i2s_bit_clock(true);
89}
90
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/backlight-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/backlight-erosqnative.c
new file mode 100644
index 0000000000..2c86a995db
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/backlight-erosqnative.c
@@ -0,0 +1,63 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald, Dana Conrad
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "backlight.h"
23#include "backlight-target.h"
24#include "lcd.h"
25#include "pwm-x1000.h"
26
27#define BL_LCD_CHN 0
28#define BL_LCD_PERIOD 30000
29
30static int backlight_calc_duty(int period, int min_duty, int brightness)
31{
32 return min_duty + (period - min_duty) * brightness / MAX_BRIGHTNESS_SETTING;
33}
34
35bool backlight_hw_init(void)
36{
37 pwm_init(BL_LCD_CHN);
38 pwm_enable(BL_LCD_CHN);
39 backlight_hw_brightness(MAX_BRIGHTNESS_SETTING);
40 return true;
41}
42
43void backlight_hw_on(void)
44{
45 pwm_enable(BL_LCD_CHN);
46#ifdef HAVE_LCD_ENABLE
47 lcd_enable(true);
48#endif
49}
50
51void backlight_hw_off(void)
52{
53 pwm_disable(BL_LCD_CHN);
54#ifdef HAVE_LCD_ENABLE
55 lcd_enable(false);
56#endif
57}
58
59void backlight_hw_brightness(int brightness)
60{
61 int duty_ns = backlight_calc_duty(BL_LCD_PERIOD, 0, brightness);
62 pwm_set_period(BL_LCD_CHN, BL_LCD_PERIOD, duty_ns);
63}
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/backlight-target.h b/firmware/target/mips/ingenic_x1000/erosqnative/backlight-target.h
new file mode 100644
index 0000000000..05d6e36679
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/backlight-target.h
@@ -0,0 +1,33 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald, Dana Conrad
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __BACKLIGHT_TARGET_H__
23#define __BACKLIGHT_TARGET_H__
24
25#include <stdbool.h>
26
27extern bool backlight_hw_init(void);
28
29extern void backlight_hw_on(void);
30extern void backlight_hw_off(void);
31extern void backlight_hw_brightness(int brightness);
32
33#endif /* __BACKLIGHT_TARGET_H__ */
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/boot.make b/firmware/target/mips/ingenic_x1000/erosqnative/boot.make
new file mode 100644
index 0000000000..b6d0844cd0
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/boot.make
@@ -0,0 +1,30 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7# $Id$
8#
9
10include $(ROOTDIR)/lib/microtar/microtar.make
11
12.SECONDEXPANSION:
13
14$(BUILDDIR)/spl.erosq: $(BUILDDIR)/spl.bin
15 $(call PRINTS,MKSPL $(@F))$(TOOLSDIR)/mkspl-x1000 -type=nand -ppb=2 -bpp=2 $< $@
16
17$(BUILDDIR)/bootloader.ucl: $(BUILDDIR)/bootloader.bin
18 $(call PRINTS,UCLPACK $(@F))$(TOOLSDIR)/uclpack --nrv2e -9 $< $@ >/dev/null
19
20.PHONY: $(BUILDDIR)/bootloader-info.txt
21$(BUILDDIR)/bootloader-info.txt:
22 $(call PRINTS,GEN $(@F))echo $(SVNVERSION) > $@
23
24$(BUILDDIR)/$(BINARY): $(BUILDDIR)/spl.erosq \
25 $(BUILDDIR)/bootloader.ucl \
26 $(BUILDDIR)/bootloader-info.txt
27 $(call PRINTS,TAR $(@F))tar -C $(BUILDDIR) \
28 --numeric-owner --no-acls --no-xattrs --no-selinux \
29 --mode=0644 --owner=0 --group=0 \
30 -cf $@ $(call full_path_subst,$(BUILDDIR)/%,%,$^)
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c
new file mode 100644
index 0000000000..1583db175a
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/button-erosqnative.c
@@ -0,0 +1,247 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald, Dana Conrad
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "button.h"
23#include "kernel.h"
24#include "backlight.h"
25#include "powermgmt.h"
26#include "panic.h"
27#include "axp-pmu.h"
28#include "gpio-x1000.h"
29#include "irq-x1000.h"
30#include "i2c-x1000.h"
31#include "eros_qn_codec.h"
32#include <string.h>
33#include <stdbool.h>
34
35#ifndef BOOTLOADER
36# include "lcd.h"
37# include "font.h"
38#endif
39
40/* ===========================================
41 * | OLD STATE | NEW STATE | DIRECTION |
42 * | 0 0 | 0 0 | 0: NO CHANGE |
43 * | 0 0 | 0 1 | -1: CCW |
44 * | 0 0 | 1 0 | 1: CW |
45 * | 0 0 | 1 1 | 0: INVALID |
46 * | 0 1 | 0 0 | 1: CW |
47 * | 0 1 | 0 1 | 0: NO CHANGE |
48 * | 0 1 | 1 0 | 0: INVALID |
49 * | 0 1 | 1 1 | -1: CCW |
50 * | 1 0 | 0 0 | -1: CCW |
51 * | 1 0 | 0 1 | 0: INVALID |
52 * | 1 0 | 1 0 | 0: NO CHANGE |
53 * | 1 0 | 1 1 | 1: CW |
54 * | 1 1 | 0 0 | 0: INVALID |
55 * | 1 1 | 0 1 | 1: CW |
56 * | 1 1 | 1 0 | -1: CCW |
57 * | 1 1 | 1 1 | 0: NO CHANGE |
58 * ===========================================
59 *
60 * Quadrature explanation since it's not plainly obvious how this works:
61 *
62 * If either of the quadrature lines change, we can look up the combination
63 * of previous state and new state in the table above (enc_state[] below)
64 * and it tells us whether to add 1, subtract 1, or no change from the sum (enc_position).
65 * This also gives us a nice debounce, since each state can only have 1 pin change
66 * at a time. I didn't come up with this, but I've used it before and it works well.
67 *
68 * Old state is 2 higher bits, new state is 2 lower bits of enc_current_state. */
69
70/* list of valid quadrature states and their directions */
71signed char enc_state[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};
72volatile unsigned char enc_current_state = 0;
73volatile signed int enc_position = 0;
74
75/* Value of headphone detect register */
76static uint8_t hp_detect_reg = 0x00;
77static uint8_t hp_detect_reg_old = 0x00;
78
79/* Interval to poll the register */
80#define HPD_POLL_TIME (HZ/2)
81
82static int hp_detect_tmo_cb(struct timeout* tmo)
83{
84 i2c_descriptor* d = (i2c_descriptor*)tmo->data;
85 i2c_async_queue(AXP_PMU_BUS, TIMEOUT_NOBLOCK, I2C_Q_ADD, 0, d);
86 return HPD_POLL_TIME;
87}
88
89static void hp_detect_init(void)
90{
91 static struct timeout tmo;
92 static const uint8_t gpio_reg = AXP192_REG_GPIOSTATE1;
93 static i2c_descriptor desc = {
94 .slave_addr = AXP_PMU_ADDR,
95 .bus_cond = I2C_START | I2C_STOP,
96 .tran_mode = I2C_READ,
97 .buffer[0] = (void*)&gpio_reg,
98 .count[0] = 1,
99 .buffer[1] = &hp_detect_reg,
100 .count[1] = 1,
101 .callback = NULL,
102 .arg = 0,
103 .next = NULL,
104 };
105
106 /* Headphone and LO detects are wired to AXP192 GPIOs 0 and 1,
107 * set them to inputs. */
108 i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO0FUNCTION, 0x01); /* HP detect */
109 i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO1FUNCTION, 0x01); /* LO detect */
110
111 /* Get an initial reading before startup */
112 int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, gpio_reg);
113 if(r >= 0)
114 {
115 hp_detect_reg = r;
116 hp_detect_reg_old = hp_detect_reg;
117 }
118
119 /* Poll the register every second */
120 timeout_register(&tmo, &hp_detect_tmo_cb, HPD_POLL_TIME, (intptr_t)&desc);
121}
122
123bool headphones_inserted(void)
124{
125 /* if the status has changed, set the output volume accordingly */
126 if ((hp_detect_reg & 0x30) != (hp_detect_reg_old & 0x30))
127 {
128 hp_detect_reg_old = hp_detect_reg;
129#if !defined(BOOTLOADER)
130 pcm5102_set_outputs();
131#endif
132 }
133 return hp_detect_reg & 0x10 ? false : true;
134}
135
136bool lineout_inserted(void)
137{
138 /* if the status has changed, set the output volume accordingly */
139 if ((hp_detect_reg & 0x30) != (hp_detect_reg_old & 0x30))
140 {
141 hp_detect_reg_old = hp_detect_reg;
142#if !defined(BOOTLOADER)
143 pcm5102_set_outputs();
144#endif
145 }
146 return hp_detect_reg & 0x20 ? false : true;
147}
148
149/* Rockbox interface */
150void button_init_device(void)
151{
152 /* set both quadrature lines to interrupts */
153 gpio_set_function(GPIO_BTN_SCROLL_A, GPIOF_IRQ_EDGE(1));
154 gpio_set_function(GPIO_BTN_SCROLL_B, GPIOF_IRQ_EDGE(1));
155
156 /* set interrupts to fire on the next edge based on current state */
157 gpio_flip_edge_irq(GPIO_BTN_SCROLL_A);
158 gpio_flip_edge_irq(GPIO_BTN_SCROLL_B);
159
160 /* get current state of both encoder gpios */
161 enc_current_state = (REG_GPIO_PIN(GPIO_B)>>21) & 0x0c;
162
163 /* enable quadrature interrupts */
164 gpio_enable_irq(GPIO_BTN_SCROLL_A);
165 gpio_enable_irq(GPIO_BTN_SCROLL_B);
166
167 /* Set up headphone and line out detect polling */
168 hp_detect_init();
169}
170
171/* wheel Quadrature line A interrupt */
172void GPIOB24(void)
173{
174 /* fill state with previous (2 higher bits) and current (2 lower bits) */
175 enc_current_state = (enc_current_state & 0x0c) | ((REG_GPIO_PIN(GPIO_B)>>23) & 0x03);
176
177 /* look up in table */
178 enc_position = enc_position + enc_state[(enc_current_state)];
179
180 /* move current state to previous state if valid data */
181 if (enc_state[(enc_current_state)] != 0)
182 enc_current_state = (enc_current_state << 2);
183
184 /* we want the other edge next time */
185 gpio_flip_edge_irq(GPIO_BTN_SCROLL_A);
186}
187
188/* wheel Quadrature line B interrupt */
189void GPIOB23(void)
190{
191 /* fill state with previous (2 higher bits) and current (2 lower bits) */
192 enc_current_state = (enc_current_state & 0x0c) | ((REG_GPIO_PIN(GPIO_B)>>23) & 0x03);
193
194 /* look up in table */
195 enc_position = enc_position + enc_state[(enc_current_state)];
196
197 /* move current state to previous state if valid data */
198 if (enc_state[(enc_current_state)] != 0)
199 enc_current_state = (enc_current_state << 2);
200
201 /* we want the other edge next time */
202 gpio_flip_edge_irq(GPIO_BTN_SCROLL_B);
203}
204
205int button_read_device(void)
206{
207 int r = 0;
208
209 /* Read GPIOs for normal buttons */
210 uint32_t a = REG_GPIO_PIN(GPIO_A);
211 uint32_t b = REG_GPIO_PIN(GPIO_B);
212 uint32_t c = REG_GPIO_PIN(GPIO_C);
213 uint32_t d = REG_GPIO_PIN(GPIO_D);
214
215 /* All buttons are active low */
216 if((a & (1 << 16)) == 0) r |= BUTTON_PLAY;
217 if((a & (1 << 17)) == 0) r |= BUTTON_VOL_UP;
218 if((a & (1 << 19)) == 0) r |= BUTTON_VOL_DOWN;
219
220 if((b & (1 << 7)) == 0) r |= BUTTON_POWER;
221 if((b & (1 << 28)) == 0) r |= BUTTON_MENU;
222 if((b & (1 << 28)) == 0) r |= BUTTON_MENU;
223
224 if((d & (1 << 4)) == 0) r |= BUTTON_PREV;
225
226 if((d & (1 << 5)) == 0) r |= BUTTON_BACK;
227 if((c & (1 << 24)) == 0) r |= BUTTON_NEXT;
228
229 /* check encoder - from testing, each indent is 2 state changes or so */
230 if (enc_position > 1)
231 {
232 /* need to use queue_post() in order to do BUTTON_SCROLL_*,
233 * Rockbox treats these buttons differently. */
234 queue_post(&button_queue, BUTTON_SCROLL_FWD, 0);
235 enc_position = 0;
236 }
237 else if (enc_position < -1)
238 {
239 /* need to use queue_post() in order to do BUTTON_SCROLL_*,
240 * Rockbox treats these buttons differently. */
241 queue_post(&button_queue, BUTTON_SCROLL_BACK, 0);
242 enc_position = 0;
243 }
244
245 return r;
246}
247
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/button-target.h b/firmware/target/mips/ingenic_x1000/erosqnative/button-target.h
new file mode 100644
index 0000000000..9c39a40296
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/button-target.h
@@ -0,0 +1,45 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2021 Solomon Peachy, Dana Conrad
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20#ifndef _BUTTON_TARGET_H_
21#define _BUTTON_TARGET_H_
22
23/* Main unit's buttons */
24#define BUTTON_POWER 0x00000001
25#define BUTTON_MENU 0x00000002
26#define BUTTON_BACK 0x00000004
27#define BUTTON_PLAY 0x00000008
28#define BUTTON_NEXT 0x00000010
29#define BUTTON_PREV 0x00000020
30#define BUTTON_VOL_UP 0x00000040
31#define BUTTON_VOL_DOWN 0x00000080
32#define BUTTON_SCROLL_BACK 0x00000100
33#define BUTTON_SCROLL_FWD 0x00000200
34
35#define BUTTON_MAIN (BUTTON_POWER | BUTTON_MENU | BUTTON_BACK | BUTTON_PREV | \
36 BUTTON_NEXT | BUTTON_PLAY | BUTTON_VOL_UP | BUTTON_VOL_DOWN | BUTTON_SCROLL_BACK | BUTTON_SCROLL_FWD)
37
38#define BUTTON_LEFT BUTTON_PREV
39#define BUTTON_RIGHT BUTTON_NEXT
40
41/* Software power-off */
42#define POWEROFF_BUTTON BUTTON_POWER
43#define POWEROFF_COUNT 25
44
45#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/gpio-target.h b/firmware/target/mips/ingenic_x1000/erosqnative/gpio-target.h
new file mode 100644
index 0000000000..376eae136e
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/gpio-target.h
@@ -0,0 +1,71 @@
1/* -------------------- NOTES ------------------- */
2
3/* I don't think we have any devices on I2C1, the pins /may/ be reused. */
4/* DEFINE_PINGROUP(I2C1, GPIO_C, 3 << 26, GPIOF_DEVICE(0)) */
5
6/* OF has SD Card power listed as 0x2a - PB10, but it seems to work without. */
7
8/* I think BT power reg is pin 0x53 - C19 */
9
10/* USB_DETECT D3 chosen by trial-and-error. */
11
12/* I have a suspicion this isn't right for AXP_IRQ,
13 * and it's not used right now anyway. copied from m3k. */
14/* DEFINE_GPIO(AXP_IRQ, GPIO_PB(10), GPIOF_INPUT) */
15
16/* ---------------------------------------------- */
17
18/* Name Port Pins Function */
19DEFINE_PINGROUP(LCD_DATA, GPIO_A, 0xffff << 0, GPIOF_DEVICE(1))
20DEFINE_PINGROUP(LCD_CONTROL, GPIO_B, 0x1a << 16, GPIOF_DEVICE(1))
21DEFINE_PINGROUP(MSC0, GPIO_A, 0x3f << 20, GPIOF_DEVICE(1))
22DEFINE_PINGROUP(SFC, GPIO_A, 0x3f << 26, GPIOF_DEVICE(1))
23DEFINE_PINGROUP(I2S, GPIO_B, 0x1f << 0, GPIOF_DEVICE(1))
24DEFINE_PINGROUP(I2C2, GPIO_D, 3 << 0, GPIOF_DEVICE(1))
25
26/* Name Pin Function */
27/* mute DAC - 0 - mute, 1 - play. Affects both HP and LO. */
28DEFINE_GPIO(PCM5102A_XMIT, GPIO_PB(12), GPIOF_OUTPUT(0))
29
30/* mute HP amp, no effect on LO. 0 - mute, 1 - play */
31DEFINE_GPIO(MAX97220_SHDN, GPIO_PB(8), GPIOF_OUTPUT(0))
32
33/* mute audio mux, only affects Headphone out.
34 * 0 - play, 1 - mute */
35DEFINE_GPIO(ISL54405_MUTE, GPIO_PB(15), GPIOF_OUTPUT(1))
36
37/* switches HP on/off - 0 HP on, 1 hp off, has no effect on LO.
38 * As best I can tell, it switches HP Out sources between HP amp and something
39 * not implemented - there seem to be resistors missing. */
40DEFINE_GPIO(ISL54405_SEL, GPIO_PB(5), GPIOF_OUTPUT(0))
41
42/* DAC AVDD */
43DEFINE_GPIO(PCM5102A_ANALOG_PWR, GPIO_PB(9), GPIOF_OUTPUT(0))
44
45/* Headphone Amp power */
46DEFINE_GPIO(MAX97220_POWER, GPIO_PB(6), GPIOF_OUTPUT(0))
47
48/* SD card */
49DEFINE_GPIO(MSC0_CD, GPIO_PB(11), GPIOF_INPUT)
50
51/* USB */
52DEFINE_GPIO(USB_DETECT, GPIO_PD(3), GPIOF_INPUT)
53DEFINE_GPIO(USB_DRVVBUS, GPIO_PB(25), GPIOF_OUTPUT(0))
54
55/* LCD */
56DEFINE_GPIO(LCD_PWR, GPIO_PB(14), GPIOF_OUTPUT(0))
57DEFINE_GPIO(LCD_RESET, GPIO_PB(13), GPIOF_OUTPUT(0))
58DEFINE_GPIO(LCD_CE, GPIO_PB(18), GPIOF_OUTPUT(1))
59DEFINE_GPIO(LCD_RD, GPIO_PB(16), GPIOF_OUTPUT(1))
60
61/* Buttons */
62DEFINE_GPIO(BTN_PLAY, GPIO_PA(16), GPIOF_INPUT)
63DEFINE_GPIO(BTN_VOL_UP, GPIO_PA(17), GPIOF_INPUT)
64DEFINE_GPIO(BTN_VOL_DOWN, GPIO_PA(19), GPIOF_INPUT)
65DEFINE_GPIO(BTN_POWER, GPIO_PB(7), GPIOF_INPUT)
66DEFINE_GPIO(BTN_MENU, GPIO_PB(28), GPIOF_INPUT)
67DEFINE_GPIO(BTN_BACK, GPIO_PD(5), GPIOF_INPUT)
68DEFINE_GPIO(BTN_PREV, GPIO_PD(4), GPIOF_INPUT)
69DEFINE_GPIO(BTN_NEXT, GPIO_PC(24), GPIOF_INPUT)
70DEFINE_GPIO(BTN_SCROLL_A, GPIO_PB(24), GPIOF_INPUT)
71DEFINE_GPIO(BTN_SCROLL_B, GPIO_PB(23), GPIOF_INPUT)
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/i2c-target.h b/firmware/target/mips/ingenic_x1000/erosqnative/i2c-target.h
new file mode 100644
index 0000000000..8d0b8a6e20
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/i2c-target.h
@@ -0,0 +1,31 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald, Dana Conrad
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __I2C_TARGET_H__
23#define __I2C_TARGET_H__
24
25#define I2C_ASYNC_BUS_COUNT 3
26#define I2C_ASYNC_QUEUE_SIZE 4
27
28#define AXP_PMU_BUS 2
29#define AXP_PMU_ADDR 0x34
30
31#endif /* __I2C_TARGET_H__ */
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c
new file mode 100644
index 0000000000..073bddb8b4
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c
@@ -0,0 +1,188 @@
1
2/***************************************************************************
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2021 Aidan MacDonald, Dana Conrad
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "lcd.h"
24#include "kernel.h"
25#include "lcd-x1000.h"
26#include "gpio-x1000.h"
27#include "system.h"
28
29/* for reference on these command/data hex values, see the mipi dcs lcd spec. *
30 * Not everything here is there, but all the standard stuff is. */
31
32static const uint32_t erosqnative_lcd_cmd_enable[] = {
33 /* Set EXTC? */
34 LCD_INSTR_CMD, 0xc8,
35 LCD_INSTR_DAT, 0xff,
36 LCD_INSTR_DAT, 0x93,
37 LCD_INSTR_DAT, 0x42,
38 /* Set Address Mode */
39 LCD_INSTR_CMD, 0x36,
40 LCD_INSTR_DAT, 0xd8,
41 /* Pixel Format Set */
42 LCD_INSTR_CMD, 0x3a,
43 //LCD_INSTR_DAT, 0x66, /* OF specified 18 bpp */
44 LCD_INSTR_DAT, 0x05, /* RB seems to be happier dealing with 16 bits/pixel */
45 /* Power Control 1? */
46 LCD_INSTR_CMD, 0xc0,
47 LCD_INSTR_DAT, 0x15,
48 LCD_INSTR_DAT, 0x15,
49 /* Power Control 2? */
50 LCD_INSTR_CMD, 0xc1,
51 LCD_INSTR_DAT, 0x01,
52 /* VCOM? */
53 LCD_INSTR_CMD, 0xc5,
54 LCD_INSTR_DAT, 0xda,
55 /* ?? */
56 LCD_INSTR_CMD, 0xb1,
57 LCD_INSTR_DAT, 0x00,
58 LCD_INSTR_DAT, 0x1b,
59 /* ?? */
60 LCD_INSTR_CMD, 0xb4,
61 LCD_INSTR_DAT, 0x02,
62 /* Positive gamma correction? */
63 LCD_INSTR_CMD, 0xe0,
64 LCD_INSTR_DAT, 0x0f,
65 LCD_INSTR_DAT, 0x13,
66 LCD_INSTR_DAT, 0x17,
67 LCD_INSTR_DAT, 0x04,
68 LCD_INSTR_DAT, 0x13,
69 LCD_INSTR_DAT, 0x07,
70 LCD_INSTR_DAT, 0x40,
71 LCD_INSTR_DAT, 0x39,
72 LCD_INSTR_DAT, 0x4f,
73 LCD_INSTR_DAT, 0x06,
74 LCD_INSTR_DAT, 0x0d,
75 LCD_INSTR_DAT, 0x0a,
76 LCD_INSTR_DAT, 0x1f,
77 LCD_INSTR_DAT, 0x22,
78 LCD_INSTR_DAT, 0x00,
79 /* Negative gamma correction? */
80 LCD_INSTR_CMD, 0xe1,
81 LCD_INSTR_DAT, 0x00,
82 LCD_INSTR_DAT, 0x21,
83 LCD_INSTR_DAT, 0x24,
84 LCD_INSTR_DAT, 0x03,
85 LCD_INSTR_DAT, 0x0f,
86 LCD_INSTR_DAT, 0x05,
87 LCD_INSTR_DAT, 0x38,
88 LCD_INSTR_DAT, 0x32,
89 LCD_INSTR_DAT, 0x49,
90 LCD_INSTR_DAT, 0x00,
91 LCD_INSTR_DAT, 0x09,
92 LCD_INSTR_DAT, 0x08,
93 LCD_INSTR_DAT, 0x32,
94 LCD_INSTR_DAT, 0x35,
95 LCD_INSTR_DAT, 0x0f,
96 /* Exit Sleep */
97 LCD_INSTR_CMD, 0x11,
98 LCD_INSTR_UDELAY, 120000,
99 /* Display On */
100 LCD_INSTR_CMD, 0x29,
101 LCD_INSTR_UDELAY, 20000,
102};
103
104/* sleep and wake copied directly from m3k */
105static const uint32_t erosqnative_lcd_cmd_sleep[] = {
106 /* Display OFF */
107 LCD_INSTR_CMD, 0x28,
108 /* Sleep IN */
109 LCD_INSTR_CMD, 0x10,
110 LCD_INSTR_UDELAY, 5000,
111 LCD_INSTR_END,
112};
113
114static const uint32_t erosqnative_lcd_cmd_wake[] = {
115 /* Sleep OUT */
116 LCD_INSTR_CMD, 0x11,
117 LCD_INSTR_UDELAY, 5000,
118 /* Display ON */
119 LCD_INSTR_CMD, 0x29,
120 LCD_INSTR_END,
121};
122
123/* As far as I can tell, this is a sequence of commands sent before each
124 * DMA set. Original in OF was:
125 * {0x2c, 0x2c, 0x2c, 0x2c}
126 * But this set from the m3k seems to work the same, and makes more sense
127 * to me:
128 * {0x00, 0x00, 0x00, 0x2c}
129 * This command is more than likely going to be the same
130 * for any old mipi lcd on the market, maybe. I really don't think we need
131 * to send "write_memory_start four times in a row. */
132static const uint8_t __attribute__((aligned(64)))
133 erosqnative_lcd_dma_wr_cmd[] = {0x2c, 0x2c, 0x2c, 0x2c};
134
135const struct lcd_tgt_config lcd_tgt_config = {
136 .bus_width = 8,
137 .cmd_width = 8,
138 .use_6800_mode = 0,
139 .use_serial = 0,
140 .clk_polarity = 0,
141 .dc_polarity = 0,
142 .wr_polarity = 1,
143 .te_enable = 0, /* OF had TE enabled (1) */
144 .te_polarity = 1,
145 .te_narrow = 0,
146 .dma_wr_cmd_buf = &erosqnative_lcd_dma_wr_cmd,
147 .dma_wr_cmd_size = sizeof(erosqnative_lcd_dma_wr_cmd),
148};
149
150void lcd_tgt_enable(bool enable)
151{
152 if(enable) {
153 /* power up the panel */
154 gpio_set_level(GPIO_LCD_PWR, 1);
155 mdelay(20);
156 gpio_set_level(GPIO_LCD_RESET, 1);
157 mdelay(12);
158
159 /* set the clock */
160 lcd_set_clock(X1000_CLK_SCLK_A, 20000000);
161
162 /* toggle chip select low (active) */
163 gpio_set_level(GPIO_LCD_RD, 1);
164 gpio_set_level(GPIO_LCD_CE, 1);
165 mdelay(5);
166 gpio_set_level(GPIO_LCD_CE, 0);
167
168 lcd_exec_commands(&erosqnative_lcd_cmd_enable[0]);
169 } else {
170 /* doesn't flash white if we don't do anything... */
171#if 0
172 lcd_exec_commands(&erosqnative_lcd_cmd_sleep[0]);
173
174 mdelay(115); // copied from m3k
175
176 gpio_set_level(GPIO_LCD_PWR, 0);
177 gpio_set_level(GPIO_LCD_RESET, 0);
178#endif
179 }
180}
181
182void lcd_tgt_sleep(bool sleep)
183{
184 if(sleep)
185 lcd_exec_commands(&erosqnative_lcd_cmd_sleep[0]);
186 else
187 lcd_exec_commands(&erosqnative_lcd_cmd_wake[0]);
188}
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c
new file mode 100644
index 0000000000..c466db66b1
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c
@@ -0,0 +1,110 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald, Dana Conrad
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22// whole file copied from m3k
23
24#include "power.h"
25#include "adc.h"
26#include "system.h"
27#include "kernel.h"
28#ifdef HAVE_USB_CHARGING_ENABLE
29# include "usb_core.h"
30#endif
31#include "axp-pmu.h"
32#include "i2c-x1000.h"
33
34const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
35{
36 3470
37};
38
39/* the OF shuts down at this voltage */
40const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
41{
42 3400
43};
44
45/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
46const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
47{
48 { 3400, 3639, 3697, 3723, 3757, 3786, 3836, 3906, 3980, 4050, 4159 }
49};
50
51/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
52const unsigned short percent_to_volt_charge[11] =
53{
54 3485, 3780, 3836, 3857, 3890, 3930, 3986, 4062, 4158, 4185, 4196
55};
56
57void power_init(void)
58{
59 /* Initialize driver */
60 i2c_x1000_set_freq(2, I2C_FREQ_400K);
61 axp_init();
62
63 /* Set lowest sample rate */
64 axp_adc_set_rate(AXP_ADC_RATE_25HZ);
65
66 /* Ensure battery voltage ADC is enabled */
67 int bits = axp_adc_get_enabled();
68 bits |= (1 << ADC_BATTERY_VOLTAGE);
69 axp_adc_set_enabled(bits);
70
71 /* Turn on all power outputs */
72 i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR,
73 AXP_REG_PWROUTPUTCTRL2, 0, 0x5f, NULL);
74 i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR,
75 AXP_REG_DCDCWORKINGMODE, 0, 0xc0, NULL);
76
77 /* Set the default charging current. This is the same as the
78 * OF's setting, although it's not strictly within the USB spec. */
79 axp_set_charge_current(780);
80
81 /* Short delay to give power outputs time to stabilize */
82 mdelay(5);
83}
84
85#ifdef HAVE_USB_CHARGING_ENABLE
86void usb_charging_maxcurrent_change(int maxcurrent)
87{
88 axp_set_charge_current(maxcurrent);
89}
90#endif
91
92void adc_init(void)
93{
94}
95
96void power_off(void)
97{
98 axp_power_off();
99 while(1);
100}
101
102bool charging_state(void)
103{
104 return axp_battery_status() == AXP_BATT_CHARGING;
105}
106
107int _battery_voltage(void)
108{
109 return axp_adc_read(ADC_BATTERY_VOLTAGE);
110}
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/spl-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/spl-erosqnative.c
new file mode 100644
index 0000000000..9d7a1d118a
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/spl-erosqnative.c
@@ -0,0 +1,63 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "system.h"
23#include "clk-x1000.h"
24#include "spl-x1000.h"
25#include "gpio-x1000.h"
26
27/* TODO: get dual-boot working */
28
29const struct spl_boot_option spl_boot_options[] = {
30 [BOOT_OPTION_ROCKBOX] = {
31 .storage_addr = 0x6800,
32 .storage_size = 102 * 1024,
33 .load_addr = X1000_DRAM_BASE,
34 .exec_addr = X1000_DRAM_BASE,
35 .flags = BOOTFLAG_UCLPACK,
36 },
37};
38
39int spl_get_boot_option(void)
40{
41 return BOOT_OPTION_ROCKBOX;
42}
43
44void spl_error(void)
45{
46 const uint32_t pin = (1 << 25);
47
48 /* Turn on backlight */
49 jz_clr(GPIO_INT(GPIO_C), pin);
50 jz_set(GPIO_MSK(GPIO_C), pin);
51 jz_clr(GPIO_PAT1(GPIO_C), pin);
52 jz_set(GPIO_PAT0(GPIO_C), pin);
53
54 while(1) {
55 /* Turn it off */
56 mdelay(100);
57 jz_set(GPIO_PAT0(GPIO_C), pin);
58
59 /* Turn it on */
60 mdelay(100);
61 jz_clr(GPIO_PAT0(GPIO_C), pin);
62 }
63}