New Port: Eros Q Native
What works: - LCD: 16-bit RGB565 - all buttons, including scrollwheel - SD Card - Battery level and charging/not charging status - USB - audio - sample rate switching - HP / LO detect, with "safe" fixed LO volume - LO volume will only be put to user-defined max volume if headphones are not present. - rtc - Plugins build, tried a couple and they seem OK - Bootloader, installable to nand via usbboot What doesn't work: - Dual Boot - power on/off has intermittent, low volume audio click (sometimes it's completely silent, sometimes there's a click) - Audio uses 16-bit volume scaling, so clicking/popping is pretty bad at lower volumes - need 32 bit volume scaling, 24 bit I2S data - USB HID keys not yet defined - no jztool support Unknowns: - Stereo Switch pins: Direction select, AC_DC (probably not even hooked up) - What is the actual purpose of the Stereo Swtich? - How does the bluetooth module connect? "Someday" stuff: - get LCD working at higher bit depth - Bluetooth Change-Id: I70dda8fc092c6e3f4352f2245e4164193f803c33
This commit is contained in:
parent
64a24591ae
commit
3e7a09cb0d
28 changed files with 1283 additions and 5 deletions
|
@ -407,6 +407,17 @@
|
|||
#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
|
||||
/* use touchscreen */
|
||||
|
||||
#elif CONFIG_KEYPAD == EROSQ_PAD
|
||||
#define ROCKPAINT_QUIT BUTTON_POWER
|
||||
#define ROCKPAINT_DRAW BUTTON_PLAY
|
||||
#define ROCKPAINT_MENU BUTTON_MENU
|
||||
#define ROCKPAINT_TOOLBAR BUTTON_VOL_UP
|
||||
#define ROCKPAINT_TOOLBAR2 BUTTON_VOL_DOWN
|
||||
#define ROCKPAINT_UP BUTTON_PREV
|
||||
#define ROCKPAINT_DOWN BUTTON_NEXT
|
||||
#define ROCKPAINT_LEFT BUTTON_SCROLL_BACK
|
||||
#define ROCKPAINT_RIGHT BUTTON_SCROLL_FWD
|
||||
|
||||
#else
|
||||
#error "Please define keys for this keypad"
|
||||
#endif
|
||||
|
|
|
@ -89,6 +89,6 @@ show_logo.c
|
|||
#elif defined(SANSA_CONNECT)
|
||||
sansaconnect.c
|
||||
show_logo.c
|
||||
#elif defined(FIIO_M3K) || defined(SHANLING_Q1)
|
||||
#elif defined(FIIO_M3K) || defined(SHANLING_Q1) || defined(EROS_QN)
|
||||
x1000.c
|
||||
#endif
|
||||
|
|
|
@ -77,6 +77,17 @@
|
|||
# define BL_SELECT_NAME "PLAY"
|
||||
# define BL_QUIT_NAME "POWER"
|
||||
# define BOOTBACKUP_FILE "/shanlingq1-boot.bin"
|
||||
#elif defined(EROS_QN)
|
||||
# define BL_RECOVERY BUTTON_VOL_UP
|
||||
# define BL_UP BUTTON_SCROLL_BACK
|
||||
# define BL_DOWN BUTTON_SCROLL_FWD
|
||||
# define BL_SELECT BUTTON_PLAY
|
||||
# define BL_QUIT BUTTON_POWER
|
||||
# define BL_UP_NAME "Up"
|
||||
# define BL_DOWN_NAME "Scroll Down"
|
||||
# define BL_SELECT_NAME "PLAY"
|
||||
# define BL_QUIT_NAME "POWER"
|
||||
# define BOOTBACKUP_FILE "/erosqnative-boot.bin"
|
||||
#else
|
||||
# error "Missing keymap!"
|
||||
#endif
|
||||
|
|
|
@ -505,6 +505,8 @@ drivers/audio/cs4398.c
|
|||
drivers/audio/es9018.c
|
||||
#elif defined (HAVE_ES9218)
|
||||
drivers/audio/es9218.c
|
||||
#elif defined (HAVE_EROS_QN_CODEC)
|
||||
drivers/audio/eros_qn_codec.c
|
||||
#endif /* defined(HAVE_*) */
|
||||
#else /* PLATFORM_HOSTED */
|
||||
#if defined(SAMSUNG_YPR0) && defined(HAVE_AS3514)
|
||||
|
@ -1727,6 +1729,15 @@ target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c
|
|||
target/mips/ingenic_x1000/shanlingq1/spl-shanlingq1.c
|
||||
#endif /* SHANLING_Q1 */
|
||||
|
||||
#if defined(EROS_QN)
|
||||
target/mips/ingenic_x1000/erosqnative/audiohw-erosqnative.c
|
||||
target/mips/ingenic_x1000/erosqnative/backlight-erosqnative.c
|
||||
target/mips/ingenic_x1000/erosqnative/button-erosqnative.c
|
||||
target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c
|
||||
target/mips/ingenic_x1000/erosqnative/power-erosqnative.c
|
||||
target/mips/ingenic_x1000/erosqnative/spl-erosqnative.c
|
||||
#endif /* EROS_QN */
|
||||
|
||||
#if defined(LYRE_PROTO1)
|
||||
target/arm/at91sam/lyre_proto1/adc-lyre_proto1.c
|
||||
target/arm/at91sam/lyre_proto1/backlight-lyre_proto1.c
|
||||
|
|
65
firmware/drivers/audio/eros_qn_codec.c
Normal file
65
firmware/drivers/audio/eros_qn_codec.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Ryabinin, Dana Conrad
|
||||
*
|
||||
* 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 "eros_qn_codec.h"
|
||||
#include "config.h"
|
||||
#include "audio.h"
|
||||
#include "audiohw.h"
|
||||
#include "settings.h"
|
||||
#include "pcm_sw_volume.h"
|
||||
|
||||
static long int vol_l_hw = 0;
|
||||
static long int vol_r_hw = 0;
|
||||
|
||||
void pcm5102_set_outputs(void)
|
||||
{
|
||||
audiohw_set_volume(vol_l_hw, vol_r_hw);
|
||||
}
|
||||
|
||||
/* this makes less sense here than it does in the audiohw-*.c file,
|
||||
* but we need access to settings.h */
|
||||
void audiohw_set_volume(int vol_l, int vol_r)
|
||||
{
|
||||
int l, r;
|
||||
|
||||
vol_l_hw = vol_l;
|
||||
vol_r_hw = vol_r;
|
||||
|
||||
l = vol_l;
|
||||
r = vol_r;
|
||||
|
||||
#if (defined(HAVE_HEADPHONE_DETECTION) && defined(HAVE_LINEOUT_DETECTION))
|
||||
/* make sure headphones aren't present - don't want to
|
||||
* blow out our eardrums cranking it to full */
|
||||
if (lineout_inserted() && !headphones_inserted())
|
||||
{
|
||||
l = r = global_settings.volume_limit * 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = vol_l;
|
||||
r = vol_r;
|
||||
}
|
||||
#endif
|
||||
|
||||
pcm_set_master_volume(l, r);
|
||||
}
|
|
@ -210,6 +210,8 @@ struct sound_settings_info
|
|||
#include "df1704.h"
|
||||
#elif defined(HAVE_PCM1792_CODEC)
|
||||
#include "pcm1792.h"
|
||||
#elif defined(HAVE_EROS_QN_CODEC)
|
||||
#include "eros_qn_codec.h"
|
||||
#elif defined(HAVE_NWZ_LINUX_CODEC)
|
||||
#include "nwzlinux_codec.h"
|
||||
#elif defined(HAVE_CS4398)
|
||||
|
|
|
@ -276,6 +276,7 @@
|
|||
#define LCD_IHIFI800 68 /* as used by IHIFI 800 */
|
||||
#define LCD_FIIOM3K 69 /* as used by the FiiO M3K */
|
||||
#define LCD_SHANLING_Q1 70 /* as used by the Shanling Q1 */
|
||||
#define LCD_EROSQ 71 /* as used by the ErosQ (native) */
|
||||
|
||||
/* LCD_PIXELFORMAT */
|
||||
#define HORIZONTAL_PACKING 1
|
||||
|
@ -596,6 +597,8 @@ Lyre prototype 1 */
|
|||
#include "config/aigoerosq.h"
|
||||
#elif defined(SHANLING_Q1)
|
||||
#include "config/shanlingq1.h"
|
||||
#elif defined(EROS_QN)
|
||||
#include "config/erosqnative.h"
|
||||
#else
|
||||
//#error "unknown hwardware platform!"
|
||||
#endif
|
||||
|
|
125
firmware/export/config/erosqnative.h
Normal file
125
firmware/export/config/erosqnative.h
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* This config file is for the AIGO EROS Q / EROS K (and its clones)
|
||||
*/
|
||||
|
||||
/* For Rolo and boot loader */
|
||||
#define MODEL_NAME "AIGO Eros Q Native"
|
||||
#define MODEL_NUMBER 116
|
||||
#define BOOTFILE_EXT "erosq"
|
||||
#define BOOTFILE "rockbox." BOOTFILE_EXT
|
||||
#define BOOTDIR "/.rockbox"
|
||||
#define FIRMWARE_OFFSET_FILE_CRC 0
|
||||
#define FIRMWARE_OFFSET_FILE_DATA 8
|
||||
|
||||
/* CPU defines */
|
||||
#define CONFIG_CPU X1000
|
||||
#define X1000_EXCLK_FREQ 24000000
|
||||
#define CPU_FREQ 1008000000
|
||||
#define HAVE_FPU
|
||||
|
||||
#ifndef SIMULATOR
|
||||
#define TIMER_FREQ X1000_EXCLK_FREQ
|
||||
#endif
|
||||
|
||||
/* kernel defines */
|
||||
#define INCLUDE_TIMEOUT_API
|
||||
#define HAVE_SEMAPHORE_OBJECTS
|
||||
|
||||
/* drivers */
|
||||
#define HAVE_I2C_ASYNC
|
||||
|
||||
/* Buffers for plugsins and codecs */
|
||||
#define PLUGIN_BUFFER_SIZE 0x200000 /* 2 MiB */
|
||||
#define CODEC_SIZE 0x100000 /* 1 MiB */
|
||||
|
||||
/* LCD defines */
|
||||
#define CONFIG_LCD LCD_EROSQ
|
||||
#define LCD_WIDTH 320
|
||||
#define LCD_HEIGHT 240
|
||||
#define LCD_DEPTH 16 /* Future Improvement: 18 or 24 bpp if display supports it */
|
||||
#define LCD_PIXELFORMAT RGB565
|
||||
/* sqrt(240^2 + 320^2) / 2.0 = 200 */
|
||||
#define LCD_DPI 200
|
||||
#define HAVE_LCD_COLOR
|
||||
#define HAVE_LCD_BITMAP
|
||||
#define HAVE_LCD_ENABLE
|
||||
#define HAVE_LCD_SHUTDOWN
|
||||
#define LCD_X1000_FASTSLEEP
|
||||
//#define LCD_X1000_DMA_WAITFORFRAME
|
||||
|
||||
#define HAVE_BACKLIGHT
|
||||
#define HAVE_BACKLIGHT_BRIGHTNESS
|
||||
#define MIN_BRIGHTNESS_SETTING 1
|
||||
#define MAX_BRIGHTNESS_SETTING 255
|
||||
#define BRIGHTNESS_STEP 5
|
||||
#define DEFAULT_BRIGHTNESS_SETTING 70
|
||||
#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING
|
||||
|
||||
/* RTC settings */
|
||||
#define CONFIG_RTC RTC_X1000
|
||||
|
||||
/* Codec / audio hardware defines */
|
||||
#define HW_SAMPR_CAPS SAMPR_CAP_ALL_192
|
||||
#define HAVE_EROS_QN_CODEC
|
||||
#define HAVE_SW_TONE_CONTROLS
|
||||
#define HAVE_SW_VOLUME_CONTROL
|
||||
|
||||
/* Button defines */
|
||||
#define CONFIG_KEYPAD EROSQ_PAD
|
||||
#define HAVE_SCROLLWHEEL
|
||||
#define HAVE_HEADPHONE_DETECTION
|
||||
#define HAVE_LINEOUT_DETECTION
|
||||
|
||||
/* Storage defines */
|
||||
#define CONFIG_STORAGE STORAGE_SD
|
||||
#define HAVE_HOTSWAP
|
||||
#define HAVE_HOTSWAP_STORAGE_AS_MAIN
|
||||
#define HAVE_MULTIDRIVE
|
||||
#define NUM_DRIVES 1
|
||||
#define STORAGE_WANTS_ALIGN
|
||||
#define STORAGE_NEEDS_BOUNCE_BUFFER
|
||||
|
||||
/* Power management */
|
||||
#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE
|
||||
#define CONFIG_CHARGING CHARGING_MONITOR
|
||||
#define HAVE_SW_POWEROFF
|
||||
|
||||
#ifndef SIMULATOR
|
||||
#define HAVE_AXP_PMU 192
|
||||
#define HAVE_POWEROFF_WHILE_CHARGING
|
||||
#endif
|
||||
|
||||
/* Battery */
|
||||
#define BATTERY_TYPES_COUNT 1
|
||||
#define BATTERY_CAPACITY_DEFAULT 1300 /* default battery capacity */
|
||||
#define BATTERY_CAPACITY_MIN 1300 /* min. capacity selectable */
|
||||
#define BATTERY_CAPACITY_MAX 1300 /* max. capacity selectable */
|
||||
#define BATTERY_CAPACITY_INC 0 /* capacity increment */
|
||||
|
||||
#define CURRENT_NORMAL 100 // 1.7mA * 60s
|
||||
#define CURRENT_BACKLIGHT 180
|
||||
#define CURRENT_MAX_CHG 500 // bursts higher if needed
|
||||
|
||||
/* USB support */
|
||||
#ifndef SIMULATOR
|
||||
#define CONFIG_USBOTG USBOTG_DESIGNWARE
|
||||
#define USB_DW_ARCH_SLAVE
|
||||
#define USB_DW_TURNAROUND 5
|
||||
#define HAVE_USBSTACK
|
||||
#define USB_VENDOR_ID 0xc502
|
||||
#define USB_PRODUCT_ID 0x0023
|
||||
#define USB_DEVBSS_ATTR __attribute__((aligned(32)))
|
||||
#define HAVE_USB_POWER
|
||||
#define HAVE_USB_CHARGING_ENABLE
|
||||
#define HAVE_BOOTLOADER_USB_MODE
|
||||
#endif
|
||||
|
||||
/* Rockbox capabilities */
|
||||
#define HAVE_VOLUME_IN_LIST
|
||||
#define HAVE_FAT16SUPPORT
|
||||
#define HAVE_ALBUMART
|
||||
#define HAVE_BMP_SCALING
|
||||
#define HAVE_JPEG
|
||||
#define HAVE_TAGCACHE
|
||||
#define HAVE_QUICKSCREEN
|
||||
#define HAVE_HOTKEY
|
35
firmware/export/eros_qn_codec.h
Normal file
35
firmware/export/eros_qn_codec.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2021 Andrew Ryabinin, Dana Conrad
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _EROS_QN_CODEC_H
|
||||
#define _EROS_QN_CODEC_H
|
||||
|
||||
#define PCM5102A_VOLUME_MIN -740
|
||||
#define PCM5102A_VOLUME_MAX 0
|
||||
|
||||
AUDIOHW_SETTING(VOLUME, "dB", 0, 1, PCM5102A_VOLUME_MIN/10, PCM5102A_VOLUME_MAX/10, 0)
|
||||
|
||||
/* this just calls audiohw_set_volume() with the last (locally) known volume,
|
||||
* used for switching to/from fixed line out volume. */
|
||||
void pcm5102_set_outputs(void);
|
||||
|
||||
#endif
|
|
@ -265,7 +265,7 @@ 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)
|
||||
#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) {
|
||||
|
@ -296,7 +296,7 @@ void clk_init(void)
|
|||
CLKMUX_CPU(SCLK_A) |
|
||||
CLKMUX_AHB0(MPLL) |
|
||||
CLKMUX_AHB2(MPLL));
|
||||
#if defined(FIIO_M3K)
|
||||
#if (defined(FIIO_M3K) || defined(EROS_QN))
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2021 Aidan MacDonald, Dana Conrad
|
||||
*
|
||||
* 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 "audiohw.h"
|
||||
#include "system.h"
|
||||
#include "pcm_sampr.h"
|
||||
#include "aic-x1000.h"
|
||||
#include "i2c-x1000.h"
|
||||
#include "gpio-x1000.h"
|
||||
#include "logf.h"
|
||||
|
||||
/* Audio path appears to be:
|
||||
* DAC --> HP Amp --> Stereo Switch --> HP OUT
|
||||
* \--> LO OUT
|
||||
*
|
||||
* The real purpose of the Stereo Switch is not clear.
|
||||
* It appears to switch sources between the HP amp and something,
|
||||
* likely something unimplemented. */
|
||||
|
||||
void audiohw_init(void)
|
||||
{
|
||||
/* explicitly mute everything */
|
||||
gpio_set_level(GPIO_MAX97220_SHDN, 0);
|
||||
gpio_set_level(GPIO_ISL54405_MUTE, 1);
|
||||
gpio_set_level(GPIO_PCM5102A_XMIT, 0);
|
||||
|
||||
aic_set_external_codec(true);
|
||||
aic_set_i2s_mode(AIC_I2S_MASTER_MODE);
|
||||
audiohw_set_frequency(HW_FREQ_48);
|
||||
|
||||
aic_enable_i2s_master_clock(true);
|
||||
aic_enable_i2s_bit_clock(true);
|
||||
|
||||
mdelay(10);
|
||||
|
||||
/* power on DAC and HP Amp */
|
||||
gpio_set_level(GPIO_PCM5102A_ANALOG_PWR, 1);
|
||||
gpio_set_level(GPIO_MAX97220_POWER, 1);
|
||||
}
|
||||
|
||||
void audiohw_postinit(void)
|
||||
{
|
||||
/* unmute - attempt to make power-on pop-free */
|
||||
gpio_set_level(GPIO_ISL54405_SEL, 0);
|
||||
gpio_set_level(GPIO_MAX97220_SHDN, 1);
|
||||
mdelay(10);
|
||||
gpio_set_level(GPIO_PCM5102A_XMIT, 1);
|
||||
mdelay(10);
|
||||
gpio_set_level(GPIO_ISL54405_MUTE, 0);
|
||||
}
|
||||
|
||||
/* TODO: get shutdown just right according to dac datasheet */
|
||||
void audiohw_close(void)
|
||||
{
|
||||
/* mute - attempt to make power-off pop-free */
|
||||
gpio_set_level(GPIO_ISL54405_MUTE, 1);
|
||||
mdelay(10);
|
||||
gpio_set_level(GPIO_PCM5102A_XMIT, 0);
|
||||
mdelay(10);
|
||||
gpio_set_level(GPIO_MAX97220_SHDN, 0);
|
||||
}
|
||||
|
||||
void audiohw_set_frequency(int fsel)
|
||||
{
|
||||
int sampr = hw_freq_sampr[fsel];
|
||||
int mult = 256;
|
||||
|
||||
aic_enable_i2s_bit_clock(false);
|
||||
aic_set_i2s_clock(X1000_CLK_SCLK_A, sampr, mult);
|
||||
aic_enable_i2s_bit_clock(true);
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2021 Aidan MacDonald, Dana Conrad
|
||||
*
|
||||
* 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 "backlight.h"
|
||||
#include "backlight-target.h"
|
||||
#include "lcd.h"
|
||||
#include "pwm-x1000.h"
|
||||
|
||||
#define BL_LCD_CHN 0
|
||||
#define BL_LCD_PERIOD 30000
|
||||
|
||||
static int backlight_calc_duty(int period, int min_duty, int brightness)
|
||||
{
|
||||
return min_duty + (period - min_duty) * brightness / MAX_BRIGHTNESS_SETTING;
|
||||
}
|
||||
|
||||
bool backlight_hw_init(void)
|
||||
{
|
||||
pwm_init(BL_LCD_CHN);
|
||||
pwm_enable(BL_LCD_CHN);
|
||||
backlight_hw_brightness(MAX_BRIGHTNESS_SETTING);
|
||||
return true;
|
||||
}
|
||||
|
||||
void backlight_hw_on(void)
|
||||
{
|
||||
pwm_enable(BL_LCD_CHN);
|
||||
#ifdef HAVE_LCD_ENABLE
|
||||
lcd_enable(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void backlight_hw_off(void)
|
||||
{
|
||||
pwm_disable(BL_LCD_CHN);
|
||||
#ifdef HAVE_LCD_ENABLE
|
||||
lcd_enable(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void backlight_hw_brightness(int brightness)
|
||||
{
|
||||
int duty_ns = backlight_calc_duty(BL_LCD_PERIOD, 0, brightness);
|
||||
pwm_set_period(BL_LCD_CHN, BL_LCD_PERIOD, duty_ns);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2021 Aidan MacDonald, Dana Conrad
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __BACKLIGHT_TARGET_H__
|
||||
#define __BACKLIGHT_TARGET_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
extern bool backlight_hw_init(void);
|
||||
|
||||
extern void backlight_hw_on(void);
|
||||
extern void backlight_hw_off(void);
|
||||
extern void backlight_hw_brightness(int brightness);
|
||||
|
||||
#endif /* __BACKLIGHT_TARGET_H__ */
|
30
firmware/target/mips/ingenic_x1000/erosqnative/boot.make
Normal file
30
firmware/target/mips/ingenic_x1000/erosqnative/boot.make
Normal file
|
@ -0,0 +1,30 @@
|
|||
# __________ __ ___.
|
||||
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
# \/ \/ \/ \/ \/
|
||||
# $Id$
|
||||
#
|
||||
|
||||
include $(ROOTDIR)/lib/microtar/microtar.make
|
||||
|
||||
.SECONDEXPANSION:
|
||||
|
||||
$(BUILDDIR)/spl.erosq: $(BUILDDIR)/spl.bin
|
||||
$(call PRINTS,MKSPL $(@F))$(TOOLSDIR)/mkspl-x1000 -type=nand -ppb=2 -bpp=2 $< $@
|
||||
|
||||
$(BUILDDIR)/bootloader.ucl: $(BUILDDIR)/bootloader.bin
|
||||
$(call PRINTS,UCLPACK $(@F))$(TOOLSDIR)/uclpack --nrv2e -9 $< $@ >/dev/null
|
||||
|
||||
.PHONY: $(BUILDDIR)/bootloader-info.txt
|
||||
$(BUILDDIR)/bootloader-info.txt:
|
||||
$(call PRINTS,GEN $(@F))echo $(SVNVERSION) > $@
|
||||
|
||||
$(BUILDDIR)/$(BINARY): $(BUILDDIR)/spl.erosq \
|
||||
$(BUILDDIR)/bootloader.ucl \
|
||||
$(BUILDDIR)/bootloader-info.txt
|
||||
$(call PRINTS,TAR $(@F))tar -C $(BUILDDIR) \
|
||||
--numeric-owner --no-acls --no-xattrs --no-selinux \
|
||||
--mode=0644 --owner=0 --group=0 \
|
||||
-cf $@ $(call full_path_subst,$(BUILDDIR)/%,%,$^)
|
|
@ -0,0 +1,247 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2021 Aidan MacDonald, Dana Conrad
|
||||
*
|
||||
* 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 "button.h"
|
||||
#include "kernel.h"
|
||||
#include "backlight.h"
|
||||
#include "powermgmt.h"
|
||||
#include "panic.h"
|
||||
#include "axp-pmu.h"
|
||||
#include "gpio-x1000.h"
|
||||
#include "irq-x1000.h"
|
||||
#include "i2c-x1000.h"
|
||||
#include "eros_qn_codec.h"
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef BOOTLOADER
|
||||
# include "lcd.h"
|
||||
# include "font.h"
|
||||
#endif
|
||||
|
||||
/* ===========================================
|
||||
* | OLD STATE | NEW STATE | DIRECTION |
|
||||
* | 0 0 | 0 0 | 0: NO CHANGE |
|
||||
* | 0 0 | 0 1 | -1: CCW |
|
||||
* | 0 0 | 1 0 | 1: CW |
|
||||
* | 0 0 | 1 1 | 0: INVALID |
|
||||
* | 0 1 | 0 0 | 1: CW |
|
||||
* | 0 1 | 0 1 | 0: NO CHANGE |
|
||||
* | 0 1 | 1 0 | 0: INVALID |
|
||||
* | 0 1 | 1 1 | -1: CCW |
|
||||
* | 1 0 | 0 0 | -1: CCW |
|
||||
* | 1 0 | 0 1 | 0: INVALID |
|
||||
* | 1 0 | 1 0 | 0: NO CHANGE |
|
||||
* | 1 0 | 1 1 | 1: CW |
|
||||
* | 1 1 | 0 0 | 0: INVALID |
|
||||
* | 1 1 | 0 1 | 1: CW |
|
||||
* | 1 1 | 1 0 | -1: CCW |
|
||||
* | 1 1 | 1 1 | 0: NO CHANGE |
|
||||
* ===========================================
|
||||
*
|
||||
* Quadrature explanation since it's not plainly obvious how this works:
|
||||
*
|
||||
* If either of the quadrature lines change, we can look up the combination
|
||||
* of previous state and new state in the table above (enc_state[] below)
|
||||
* and it tells us whether to add 1, subtract 1, or no change from the sum (enc_position).
|
||||
* This also gives us a nice debounce, since each state can only have 1 pin change
|
||||
* at a time. I didn't come up with this, but I've used it before and it works well.
|
||||
*
|
||||
* Old state is 2 higher bits, new state is 2 lower bits of enc_current_state. */
|
||||
|
||||
/* list of valid quadrature states and their directions */
|
||||
signed char enc_state[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};
|
||||
volatile unsigned char enc_current_state = 0;
|
||||
volatile signed int enc_position = 0;
|
||||
|
||||
/* Value of headphone detect register */
|
||||
static uint8_t hp_detect_reg = 0x00;
|
||||
static uint8_t hp_detect_reg_old = 0x00;
|
||||
|
||||
/* Interval to poll the register */
|
||||
#define HPD_POLL_TIME (HZ/2)
|
||||
|
||||
static int hp_detect_tmo_cb(struct timeout* tmo)
|
||||
{
|
||||
i2c_descriptor* d = (i2c_descriptor*)tmo->data;
|
||||
i2c_async_queue(AXP_PMU_BUS, TIMEOUT_NOBLOCK, I2C_Q_ADD, 0, d);
|
||||
return HPD_POLL_TIME;
|
||||
}
|
||||
|
||||
static void hp_detect_init(void)
|
||||
{
|
||||
static struct timeout tmo;
|
||||
static const uint8_t gpio_reg = AXP192_REG_GPIOSTATE1;
|
||||
static i2c_descriptor desc = {
|
||||
.slave_addr = AXP_PMU_ADDR,
|
||||
.bus_cond = I2C_START | I2C_STOP,
|
||||
.tran_mode = I2C_READ,
|
||||
.buffer[0] = (void*)&gpio_reg,
|
||||
.count[0] = 1,
|
||||
.buffer[1] = &hp_detect_reg,
|
||||
.count[1] = 1,
|
||||
.callback = NULL,
|
||||
.arg = 0,
|
||||
.next = NULL,
|
||||
};
|
||||
|
||||
/* Headphone and LO detects are wired to AXP192 GPIOs 0 and 1,
|
||||
* set them to inputs. */
|
||||
i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO0FUNCTION, 0x01); /* HP detect */
|
||||
i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO1FUNCTION, 0x01); /* LO detect */
|
||||
|
||||
/* Get an initial reading before startup */
|
||||
int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, gpio_reg);
|
||||
if(r >= 0)
|
||||
{
|
||||
hp_detect_reg = r;
|
||||
hp_detect_reg_old = hp_detect_reg;
|
||||
}
|
||||
|
||||
/* Poll the register every second */
|
||||
timeout_register(&tmo, &hp_detect_tmo_cb, HPD_POLL_TIME, (intptr_t)&desc);
|
||||
}
|
||||
|
||||
bool headphones_inserted(void)
|
||||
{
|
||||
/* if the status has changed, set the output volume accordingly */
|
||||
if ((hp_detect_reg & 0x30) != (hp_detect_reg_old & 0x30))
|
||||
{
|
||||
hp_detect_reg_old = hp_detect_reg;
|
||||
#if !defined(BOOTLOADER)
|
||||
pcm5102_set_outputs();
|
||||
#endif
|
||||
}
|
||||
return hp_detect_reg & 0x10 ? false : true;
|
||||
}
|
||||
|
||||
bool lineout_inserted(void)
|
||||
{
|
||||
/* if the status has changed, set the output volume accordingly */
|
||||
if ((hp_detect_reg & 0x30) != (hp_detect_reg_old & 0x30))
|
||||
{
|
||||
hp_detect_reg_old = hp_detect_reg;
|
||||
#if !defined(BOOTLOADER)
|
||||
pcm5102_set_outputs();
|
||||
#endif
|
||||
}
|
||||
return hp_detect_reg & 0x20 ? false : true;
|
||||
}
|
||||
|
||||
/* Rockbox interface */
|
||||
void button_init_device(void)
|
||||
{
|
||||
/* set both quadrature lines to interrupts */
|
||||
gpio_set_function(GPIO_BTN_SCROLL_A, GPIOF_IRQ_EDGE(1));
|
||||
gpio_set_function(GPIO_BTN_SCROLL_B, GPIOF_IRQ_EDGE(1));
|
||||
|
||||
/* set interrupts to fire on the next edge based on current state */
|
||||
gpio_flip_edge_irq(GPIO_BTN_SCROLL_A);
|
||||
gpio_flip_edge_irq(GPIO_BTN_SCROLL_B);
|
||||
|
||||
/* get current state of both encoder gpios */
|
||||
enc_current_state = (REG_GPIO_PIN(GPIO_B)>>21) & 0x0c;
|
||||
|
||||
/* enable quadrature interrupts */
|
||||
gpio_enable_irq(GPIO_BTN_SCROLL_A);
|
||||
gpio_enable_irq(GPIO_BTN_SCROLL_B);
|
||||
|
||||
/* Set up headphone and line out detect polling */
|
||||
hp_detect_init();
|
||||
}
|
||||
|
||||
/* wheel Quadrature line A interrupt */
|
||||
void GPIOB24(void)
|
||||
{
|
||||
/* fill state with previous (2 higher bits) and current (2 lower bits) */
|
||||
enc_current_state = (enc_current_state & 0x0c) | ((REG_GPIO_PIN(GPIO_B)>>23) & 0x03);
|
||||
|
||||
/* look up in table */
|
||||
enc_position = enc_position + enc_state[(enc_current_state)];
|
||||
|
||||
/* move current state to previous state if valid data */
|
||||
if (enc_state[(enc_current_state)] != 0)
|
||||
enc_current_state = (enc_current_state << 2);
|
||||
|
||||
/* we want the other edge next time */
|
||||
gpio_flip_edge_irq(GPIO_BTN_SCROLL_A);
|
||||
}
|
||||
|
||||
/* wheel Quadrature line B interrupt */
|
||||
void GPIOB23(void)
|
||||
{
|
||||
/* fill state with previous (2 higher bits) and current (2 lower bits) */
|
||||
enc_current_state = (enc_current_state & 0x0c) | ((REG_GPIO_PIN(GPIO_B)>>23) & 0x03);
|
||||
|
||||
/* look up in table */
|
||||
enc_position = enc_position + enc_state[(enc_current_state)];
|
||||
|
||||
/* move current state to previous state if valid data */
|
||||
if (enc_state[(enc_current_state)] != 0)
|
||||
enc_current_state = (enc_current_state << 2);
|
||||
|
||||
/* we want the other edge next time */
|
||||
gpio_flip_edge_irq(GPIO_BTN_SCROLL_B);
|
||||
}
|
||||
|
||||
int button_read_device(void)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
/* Read GPIOs for normal buttons */
|
||||
uint32_t a = REG_GPIO_PIN(GPIO_A);
|
||||
uint32_t b = REG_GPIO_PIN(GPIO_B);
|
||||
uint32_t c = REG_GPIO_PIN(GPIO_C);
|
||||
uint32_t d = REG_GPIO_PIN(GPIO_D);
|
||||
|
||||
/* All buttons are active low */
|
||||
if((a & (1 << 16)) == 0) r |= BUTTON_PLAY;
|
||||
if((a & (1 << 17)) == 0) r |= BUTTON_VOL_UP;
|
||||
if((a & (1 << 19)) == 0) r |= BUTTON_VOL_DOWN;
|
||||
|
||||
if((b & (1 << 7)) == 0) r |= BUTTON_POWER;
|
||||
if((b & (1 << 28)) == 0) r |= BUTTON_MENU;
|
||||
if((b & (1 << 28)) == 0) r |= BUTTON_MENU;
|
||||
|
||||
if((d & (1 << 4)) == 0) r |= BUTTON_PREV;
|
||||
|
||||
if((d & (1 << 5)) == 0) r |= BUTTON_BACK;
|
||||
if((c & (1 << 24)) == 0) r |= BUTTON_NEXT;
|
||||
|
||||
/* check encoder - from testing, each indent is 2 state changes or so */
|
||||
if (enc_position > 1)
|
||||
{
|
||||
/* need to use queue_post() in order to do BUTTON_SCROLL_*,
|
||||
* Rockbox treats these buttons differently. */
|
||||
queue_post(&button_queue, BUTTON_SCROLL_FWD, 0);
|
||||
enc_position = 0;
|
||||
}
|
||||
else if (enc_position < -1)
|
||||
{
|
||||
/* need to use queue_post() in order to do BUTTON_SCROLL_*,
|
||||
* Rockbox treats these buttons differently. */
|
||||
queue_post(&button_queue, BUTTON_SCROLL_BACK, 0);
|
||||
enc_position = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
*
|
||||
* Copyright (C) 2021 Solomon Peachy, Dana Conrad
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef _BUTTON_TARGET_H_
|
||||
#define _BUTTON_TARGET_H_
|
||||
|
||||
/* Main unit's buttons */
|
||||
#define BUTTON_POWER 0x00000001
|
||||
#define BUTTON_MENU 0x00000002
|
||||
#define BUTTON_BACK 0x00000004
|
||||
#define BUTTON_PLAY 0x00000008
|
||||
#define BUTTON_NEXT 0x00000010
|
||||
#define BUTTON_PREV 0x00000020
|
||||
#define BUTTON_VOL_UP 0x00000040
|
||||
#define BUTTON_VOL_DOWN 0x00000080
|
||||
#define BUTTON_SCROLL_BACK 0x00000100
|
||||
#define BUTTON_SCROLL_FWD 0x00000200
|
||||
|
||||
#define BUTTON_MAIN (BUTTON_POWER | BUTTON_MENU | BUTTON_BACK | BUTTON_PREV | \
|
||||
BUTTON_NEXT | BUTTON_PLAY | BUTTON_VOL_UP | BUTTON_VOL_DOWN | BUTTON_SCROLL_BACK | BUTTON_SCROLL_FWD)
|
||||
|
||||
#define BUTTON_LEFT BUTTON_PREV
|
||||
#define BUTTON_RIGHT BUTTON_NEXT
|
||||
|
||||
/* Software power-off */
|
||||
#define POWEROFF_BUTTON BUTTON_POWER
|
||||
#define POWEROFF_COUNT 25
|
||||
|
||||
#endif /* _BUTTON_TARGET_H_ */
|
71
firmware/target/mips/ingenic_x1000/erosqnative/gpio-target.h
Normal file
71
firmware/target/mips/ingenic_x1000/erosqnative/gpio-target.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* -------------------- NOTES ------------------- */
|
||||
|
||||
/* I don't think we have any devices on I2C1, the pins /may/ be reused. */
|
||||
/* DEFINE_PINGROUP(I2C1, GPIO_C, 3 << 26, GPIOF_DEVICE(0)) */
|
||||
|
||||
/* OF has SD Card power listed as 0x2a - PB10, but it seems to work without. */
|
||||
|
||||
/* I think BT power reg is pin 0x53 - C19 */
|
||||
|
||||
/* USB_DETECT D3 chosen by trial-and-error. */
|
||||
|
||||
/* I have a suspicion this isn't right for AXP_IRQ,
|
||||
* and it's not used right now anyway. copied from m3k. */
|
||||
/* DEFINE_GPIO(AXP_IRQ, GPIO_PB(10), GPIOF_INPUT) */
|
||||
|
||||
/* ---------------------------------------------- */
|
||||
|
||||
/* Name Port Pins Function */
|
||||
DEFINE_PINGROUP(LCD_DATA, GPIO_A, 0xffff << 0, GPIOF_DEVICE(1))
|
||||
DEFINE_PINGROUP(LCD_CONTROL, GPIO_B, 0x1a << 16, GPIOF_DEVICE(1))
|
||||
DEFINE_PINGROUP(MSC0, GPIO_A, 0x3f << 20, GPIOF_DEVICE(1))
|
||||
DEFINE_PINGROUP(SFC, GPIO_A, 0x3f << 26, GPIOF_DEVICE(1))
|
||||
DEFINE_PINGROUP(I2S, GPIO_B, 0x1f << 0, GPIOF_DEVICE(1))
|
||||
DEFINE_PINGROUP(I2C2, GPIO_D, 3 << 0, GPIOF_DEVICE(1))
|
||||
|
||||
/* Name Pin Function */
|
||||
/* mute DAC - 0 - mute, 1 - play. Affects both HP and LO. */
|
||||
DEFINE_GPIO(PCM5102A_XMIT, GPIO_PB(12), GPIOF_OUTPUT(0))
|
||||
|
||||
/* mute HP amp, no effect on LO. 0 - mute, 1 - play */
|
||||
DEFINE_GPIO(MAX97220_SHDN, GPIO_PB(8), GPIOF_OUTPUT(0))
|
||||
|
||||
/* mute audio mux, only affects Headphone out.
|
||||
* 0 - play, 1 - mute */
|
||||
DEFINE_GPIO(ISL54405_MUTE, GPIO_PB(15), GPIOF_OUTPUT(1))
|
||||
|
||||
/* switches HP on/off - 0 HP on, 1 hp off, has no effect on LO.
|
||||
* As best I can tell, it switches HP Out sources between HP amp and something
|
||||
* not implemented - there seem to be resistors missing. */
|
||||
DEFINE_GPIO(ISL54405_SEL, GPIO_PB(5), GPIOF_OUTPUT(0))
|
||||
|
||||
/* DAC AVDD */
|
||||
DEFINE_GPIO(PCM5102A_ANALOG_PWR, GPIO_PB(9), GPIOF_OUTPUT(0))
|
||||
|
||||
/* Headphone Amp power */
|
||||
DEFINE_GPIO(MAX97220_POWER, GPIO_PB(6), GPIOF_OUTPUT(0))
|
||||
|
||||
/* SD card */
|
||||
DEFINE_GPIO(MSC0_CD, GPIO_PB(11), GPIOF_INPUT)
|
||||
|
||||
/* USB */
|
||||
DEFINE_GPIO(USB_DETECT, GPIO_PD(3), GPIOF_INPUT)
|
||||
DEFINE_GPIO(USB_DRVVBUS, GPIO_PB(25), GPIOF_OUTPUT(0))
|
||||
|
||||
/* LCD */
|
||||
DEFINE_GPIO(LCD_PWR, GPIO_PB(14), GPIOF_OUTPUT(0))
|
||||
DEFINE_GPIO(LCD_RESET, GPIO_PB(13), GPIOF_OUTPUT(0))
|
||||
DEFINE_GPIO(LCD_CE, GPIO_PB(18), GPIOF_OUTPUT(1))
|
||||
DEFINE_GPIO(LCD_RD, GPIO_PB(16), GPIOF_OUTPUT(1))
|
||||
|
||||
/* Buttons */
|
||||
DEFINE_GPIO(BTN_PLAY, GPIO_PA(16), GPIOF_INPUT)
|
||||
DEFINE_GPIO(BTN_VOL_UP, GPIO_PA(17), GPIOF_INPUT)
|
||||
DEFINE_GPIO(BTN_VOL_DOWN, GPIO_PA(19), GPIOF_INPUT)
|
||||
DEFINE_GPIO(BTN_POWER, GPIO_PB(7), GPIOF_INPUT)
|
||||
DEFINE_GPIO(BTN_MENU, GPIO_PB(28), GPIOF_INPUT)
|
||||
DEFINE_GPIO(BTN_BACK, GPIO_PD(5), GPIOF_INPUT)
|
||||
DEFINE_GPIO(BTN_PREV, GPIO_PD(4), GPIOF_INPUT)
|
||||
DEFINE_GPIO(BTN_NEXT, GPIO_PC(24), GPIOF_INPUT)
|
||||
DEFINE_GPIO(BTN_SCROLL_A, GPIO_PB(24), GPIOF_INPUT)
|
||||
DEFINE_GPIO(BTN_SCROLL_B, GPIO_PB(23), GPIOF_INPUT)
|
31
firmware/target/mips/ingenic_x1000/erosqnative/i2c-target.h
Normal file
31
firmware/target/mips/ingenic_x1000/erosqnative/i2c-target.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2021 Aidan MacDonald, Dana Conrad
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __I2C_TARGET_H__
|
||||
#define __I2C_TARGET_H__
|
||||
|
||||
#define I2C_ASYNC_BUS_COUNT 3
|
||||
#define I2C_ASYNC_QUEUE_SIZE 4
|
||||
|
||||
#define AXP_PMU_BUS 2
|
||||
#define AXP_PMU_ADDR 0x34
|
||||
|
||||
#endif /* __I2C_TARGET_H__ */
|
188
firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c
Normal file
188
firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c
Normal file
|
@ -0,0 +1,188 @@
|
|||
|
||||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2021 Aidan MacDonald, Dana Conrad
|
||||
*
|
||||
* 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 "lcd.h"
|
||||
#include "kernel.h"
|
||||
#include "lcd-x1000.h"
|
||||
#include "gpio-x1000.h"
|
||||
#include "system.h"
|
||||
|
||||
/* for reference on these command/data hex values, see the mipi dcs lcd spec. *
|
||||
* Not everything here is there, but all the standard stuff is. */
|
||||
|
||||
static const uint32_t erosqnative_lcd_cmd_enable[] = {
|
||||
/* Set EXTC? */
|
||||
LCD_INSTR_CMD, 0xc8,
|
||||
LCD_INSTR_DAT, 0xff,
|
||||
LCD_INSTR_DAT, 0x93,
|
||||
LCD_INSTR_DAT, 0x42,
|
||||
/* Set Address Mode */
|
||||
LCD_INSTR_CMD, 0x36,
|
||||
LCD_INSTR_DAT, 0xd8,
|
||||
/* Pixel Format Set */
|
||||
LCD_INSTR_CMD, 0x3a,
|
||||
//LCD_INSTR_DAT, 0x66, /* OF specified 18 bpp */
|
||||
LCD_INSTR_DAT, 0x05, /* RB seems to be happier dealing with 16 bits/pixel */
|
||||
/* Power Control 1? */
|
||||
LCD_INSTR_CMD, 0xc0,
|
||||
LCD_INSTR_DAT, 0x15,
|
||||
LCD_INSTR_DAT, 0x15,
|
||||
/* Power Control 2? */
|
||||
LCD_INSTR_CMD, 0xc1,
|
||||
LCD_INSTR_DAT, 0x01,
|
||||
/* VCOM? */
|
||||
LCD_INSTR_CMD, 0xc5,
|
||||
LCD_INSTR_DAT, 0xda,
|
||||
/* ?? */
|
||||
LCD_INSTR_CMD, 0xb1,
|
||||
LCD_INSTR_DAT, 0x00,
|
||||
LCD_INSTR_DAT, 0x1b,
|
||||
/* ?? */
|
||||
LCD_INSTR_CMD, 0xb4,
|
||||
LCD_INSTR_DAT, 0x02,
|
||||
/* Positive gamma correction? */
|
||||
LCD_INSTR_CMD, 0xe0,
|
||||
LCD_INSTR_DAT, 0x0f,
|
||||
LCD_INSTR_DAT, 0x13,
|
||||
LCD_INSTR_DAT, 0x17,
|
||||
LCD_INSTR_DAT, 0x04,
|
||||
LCD_INSTR_DAT, 0x13,
|
||||
LCD_INSTR_DAT, 0x07,
|
||||
LCD_INSTR_DAT, 0x40,
|
||||
LCD_INSTR_DAT, 0x39,
|
||||
LCD_INSTR_DAT, 0x4f,
|
||||
LCD_INSTR_DAT, 0x06,
|
||||
LCD_INSTR_DAT, 0x0d,
|
||||
LCD_INSTR_DAT, 0x0a,
|
||||
LCD_INSTR_DAT, 0x1f,
|
||||
LCD_INSTR_DAT, 0x22,
|
||||
LCD_INSTR_DAT, 0x00,
|
||||
/* Negative gamma correction? */
|
||||
LCD_INSTR_CMD, 0xe1,
|
||||
LCD_INSTR_DAT, 0x00,
|
||||
LCD_INSTR_DAT, 0x21,
|
||||
LCD_INSTR_DAT, 0x24,
|
||||
LCD_INSTR_DAT, 0x03,
|
||||
LCD_INSTR_DAT, 0x0f,
|
||||
LCD_INSTR_DAT, 0x05,
|
||||
LCD_INSTR_DAT, 0x38,
|
||||
LCD_INSTR_DAT, 0x32,
|
||||
LCD_INSTR_DAT, 0x49,
|
||||
LCD_INSTR_DAT, 0x00,
|
||||
LCD_INSTR_DAT, 0x09,
|
||||
LCD_INSTR_DAT, 0x08,
|
||||
LCD_INSTR_DAT, 0x32,
|
||||
LCD_INSTR_DAT, 0x35,
|
||||
LCD_INSTR_DAT, 0x0f,
|
||||
/* Exit Sleep */
|
||||
LCD_INSTR_CMD, 0x11,
|
||||
LCD_INSTR_UDELAY, 120000,
|
||||
/* Display On */
|
||||
LCD_INSTR_CMD, 0x29,
|
||||
LCD_INSTR_UDELAY, 20000,
|
||||
};
|
||||
|
||||
/* sleep and wake copied directly from m3k */
|
||||
static const uint32_t erosqnative_lcd_cmd_sleep[] = {
|
||||
/* Display OFF */
|
||||
LCD_INSTR_CMD, 0x28,
|
||||
/* Sleep IN */
|
||||
LCD_INSTR_CMD, 0x10,
|
||||
LCD_INSTR_UDELAY, 5000,
|
||||
LCD_INSTR_END,
|
||||
};
|
||||
|
||||
static const uint32_t erosqnative_lcd_cmd_wake[] = {
|
||||
/* Sleep OUT */
|
||||
LCD_INSTR_CMD, 0x11,
|
||||
LCD_INSTR_UDELAY, 5000,
|
||||
/* Display ON */
|
||||
LCD_INSTR_CMD, 0x29,
|
||||
LCD_INSTR_END,
|
||||
};
|
||||
|
||||
/* As far as I can tell, this is a sequence of commands sent before each
|
||||
* DMA set. Original in OF was:
|
||||
* {0x2c, 0x2c, 0x2c, 0x2c}
|
||||
* But this set from the m3k seems to work the same, and makes more sense
|
||||
* to me:
|
||||
* {0x00, 0x00, 0x00, 0x2c}
|
||||
* This command is more than likely going to be the same
|
||||
* for any old mipi lcd on the market, maybe. I really don't think we need
|
||||
* to send "write_memory_start four times in a row. */
|
||||
static const uint8_t __attribute__((aligned(64)))
|
||||
erosqnative_lcd_dma_wr_cmd[] = {0x2c, 0x2c, 0x2c, 0x2c};
|
||||
|
||||
const struct lcd_tgt_config lcd_tgt_config = {
|
||||
.bus_width = 8,
|
||||
.cmd_width = 8,
|
||||
.use_6800_mode = 0,
|
||||
.use_serial = 0,
|
||||
.clk_polarity = 0,
|
||||
.dc_polarity = 0,
|
||||
.wr_polarity = 1,
|
||||
.te_enable = 0, /* OF had TE enabled (1) */
|
||||
.te_polarity = 1,
|
||||
.te_narrow = 0,
|
||||
.dma_wr_cmd_buf = &erosqnative_lcd_dma_wr_cmd,
|
||||
.dma_wr_cmd_size = sizeof(erosqnative_lcd_dma_wr_cmd),
|
||||
};
|
||||
|
||||
void lcd_tgt_enable(bool enable)
|
||||
{
|
||||
if(enable) {
|
||||
/* power up the panel */
|
||||
gpio_set_level(GPIO_LCD_PWR, 1);
|
||||
mdelay(20);
|
||||
gpio_set_level(GPIO_LCD_RESET, 1);
|
||||
mdelay(12);
|
||||
|
||||
/* set the clock */
|
||||
lcd_set_clock(X1000_CLK_SCLK_A, 20000000);
|
||||
|
||||
/* toggle chip select low (active) */
|
||||
gpio_set_level(GPIO_LCD_RD, 1);
|
||||
gpio_set_level(GPIO_LCD_CE, 1);
|
||||
mdelay(5);
|
||||
gpio_set_level(GPIO_LCD_CE, 0);
|
||||
|
||||
lcd_exec_commands(&erosqnative_lcd_cmd_enable[0]);
|
||||
} else {
|
||||
/* doesn't flash white if we don't do anything... */
|
||||
#if 0
|
||||
lcd_exec_commands(&erosqnative_lcd_cmd_sleep[0]);
|
||||
|
||||
mdelay(115); // copied from m3k
|
||||
|
||||
gpio_set_level(GPIO_LCD_PWR, 0);
|
||||
gpio_set_level(GPIO_LCD_RESET, 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_tgt_sleep(bool sleep)
|
||||
{
|
||||
if(sleep)
|
||||
lcd_exec_commands(&erosqnative_lcd_cmd_sleep[0]);
|
||||
else
|
||||
lcd_exec_commands(&erosqnative_lcd_cmd_wake[0]);
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2021 Aidan MacDonald, Dana Conrad
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
// whole file copied from m3k
|
||||
|
||||
#include "power.h"
|
||||
#include "adc.h"
|
||||
#include "system.h"
|
||||
#include "kernel.h"
|
||||
#ifdef HAVE_USB_CHARGING_ENABLE
|
||||
# include "usb_core.h"
|
||||
#endif
|
||||
#include "axp-pmu.h"
|
||||
#include "i2c-x1000.h"
|
||||
|
||||
const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
|
||||
{
|
||||
3470
|
||||
};
|
||||
|
||||
/* the OF shuts down at this voltage */
|
||||
const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
|
||||
{
|
||||
3400
|
||||
};
|
||||
|
||||
/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
|
||||
const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
|
||||
{
|
||||
{ 3400, 3639, 3697, 3723, 3757, 3786, 3836, 3906, 3980, 4050, 4159 }
|
||||
};
|
||||
|
||||
/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
|
||||
const unsigned short percent_to_volt_charge[11] =
|
||||
{
|
||||
3485, 3780, 3836, 3857, 3890, 3930, 3986, 4062, 4158, 4185, 4196
|
||||
};
|
||||
|
||||
void power_init(void)
|
||||
{
|
||||
/* Initialize driver */
|
||||
i2c_x1000_set_freq(2, I2C_FREQ_400K);
|
||||
axp_init();
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Turn on all power outputs */
|
||||
i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR,
|
||||
AXP_REG_PWROUTPUTCTRL2, 0, 0x5f, NULL);
|
||||
i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR,
|
||||
AXP_REG_DCDCWORKINGMODE, 0, 0xc0, NULL);
|
||||
|
||||
/* Set the default charging current. This is the same as the
|
||||
* OF's setting, although it's not strictly within the USB spec. */
|
||||
axp_set_charge_current(780);
|
||||
|
||||
/* Short delay to give power outputs time to stabilize */
|
||||
mdelay(5);
|
||||
}
|
||||
|
||||
#ifdef HAVE_USB_CHARGING_ENABLE
|
||||
void usb_charging_maxcurrent_change(int maxcurrent)
|
||||
{
|
||||
axp_set_charge_current(maxcurrent);
|
||||
}
|
||||
#endif
|
||||
|
||||
void adc_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void power_off(void)
|
||||
{
|
||||
axp_power_off();
|
||||
while(1);
|
||||
}
|
||||
|
||||
bool charging_state(void)
|
||||
{
|
||||
return axp_battery_status() == AXP_BATT_CHARGING;
|
||||
}
|
||||
|
||||
int _battery_voltage(void)
|
||||
{
|
||||
return axp_adc_read(ADC_BATTERY_VOLTAGE);
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* 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"
|
||||
|
||||
/* TODO: get dual-boot working */
|
||||
|
||||
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)
|
||||
{
|
||||
return BOOT_OPTION_ROCKBOX;
|
||||
}
|
||||
|
||||
void spl_error(void)
|
||||
{
|
||||
const uint32_t pin = (1 << 25);
|
||||
|
||||
/* 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);
|
||||
|
||||
while(1) {
|
||||
/* Turn it off */
|
||||
mdelay(100);
|
||||
jz_set(GPIO_PAT0(GPIO_C), pin);
|
||||
|
||||
/* Turn it on */
|
||||
mdelay(100);
|
||||
jz_clr(GPIO_PAT0(GPIO_C), pin);
|
||||
}
|
||||
}
|
|
@ -457,6 +457,10 @@ void lcd_update(void)
|
|||
jz_writef(LCD_MCTRL, DMA_START(1), DMA_MODE(1));
|
||||
}
|
||||
|
||||
/* We can do partial updates even though the DMA doesn't seem to handle it well,
|
||||
* due to the fact that this is actually putting it into a buffer, and then
|
||||
* it gets transferred via DMA to a secondary buffer, which gets transferred in
|
||||
* its entirety to the LCD through a different DMA process. */
|
||||
void lcd_update_rect(int x, int y, int width, int height)
|
||||
{
|
||||
/* Clamp the coordinates */
|
||||
|
|
|
@ -63,6 +63,16 @@ static const msc_config msc_configs[] = {
|
|||
.cd_active_level = 0,
|
||||
},
|
||||
/* NOTE: SDIO wifi card is on msc1 */
|
||||
#elif defined(EROS_QN)
|
||||
#define MSC_CLOCK_SOURCE X1000_CLK_SCLK_A
|
||||
{
|
||||
.msc_nr = 0,
|
||||
.msc_type = MSC_TYPE_SD,
|
||||
.bus_width = 4,
|
||||
.label = "microSD",
|
||||
.cd_gpio = GPIO_MSC0_CD,
|
||||
.cd_active_level = 0,
|
||||
},
|
||||
#else
|
||||
# error "Please add X1000 MSC config"
|
||||
#endif
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
#define FREG_STATUS_ECC_UNCOR_ERR (2 << 4)
|
||||
|
||||
const nand_chip supported_nand_chips[] = {
|
||||
#if defined(FIIO_M3K) || defined(SHANLING_Q1)
|
||||
#if defined(FIIO_M3K) || defined(SHANLING_Q1) || defined(EROS_QN)
|
||||
{
|
||||
/* ATO25D1GA */
|
||||
.mf_id = 0x9b,
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
# define SPL_DDR_MEMORYSIZE 64
|
||||
# define SPL_DDR_AUTOSR_EN 1
|
||||
# define SPL_DDR_NEED_BYPASS 1
|
||||
#elif defined(EROS_QN)
|
||||
# define SPL_DDR_MEMORYSIZE 32
|
||||
# define SPL_DDR_AUTOSR_EN 1
|
||||
# define SPL_DDR_NEED_BYPASS 1
|
||||
#else
|
||||
# error "please define DRAM settings"
|
||||
#endif
|
||||
|
|
26
tools/configure
vendored
26
tools/configure
vendored
|
@ -1598,7 +1598,7 @@ cat <<EOF
|
|||
==FiiO== 229) NWZ-S750 series
|
||||
==AIGO== 244) M3K Linux
|
||||
245) Eros Q / K 246) M3K baremetal ==Shanling==
|
||||
260) Q1
|
||||
247) Eros Q / K native 260) Q1
|
||||
EOF
|
||||
|
||||
buildfor=`input`;
|
||||
|
@ -4133,6 +4133,30 @@ fi
|
|||
t_model="shanlingq1"
|
||||
;;
|
||||
|
||||
247|erosqnative)
|
||||
target_id=116
|
||||
modelname="erosqnative"
|
||||
target="EROS_QN"
|
||||
memory=32
|
||||
mipsr2elcc
|
||||
appextra="recorder:gui"
|
||||
plugins="yes"
|
||||
tool="$rootdir/tools/scramble -add=erosqnative "
|
||||
boottool="" # not used
|
||||
output="rockbox.erosq"
|
||||
bootoutput="bootloader.erosq"
|
||||
sysfontbl="16-Terminus"
|
||||
# toolset is the tools within the tools directory that we build for
|
||||
# this particular target.
|
||||
toolset="$x1000tools"
|
||||
bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
|
||||
bmp2rb_native="$rootdir/tools/bmp2rb -f 4"
|
||||
# architecture, manufacturer and model for the target-tree build
|
||||
t_cpu="mips"
|
||||
t_manufacturer="ingenic_x1000"
|
||||
t_model="erosqnative"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Please select a supported target platform!"
|
||||
exit 7
|
||||
|
|
|
@ -335,6 +335,8 @@ int main (int argc, char** argv)
|
|||
modelnum = 114;
|
||||
else if (!strcmp(&argv[1][5], "shq1")) /* Shanling Q1 */
|
||||
modelnum = 115;
|
||||
else if (!strcmp(&argv[1][5], "erosqnative")) /* Aigo Eros Q Native */
|
||||
modelnum = 116;
|
||||
else {
|
||||
fprintf(stderr, "unsupported model: %s\n", &argv[1][5]);
|
||||
return 2;
|
||||
|
|
Loading…
Reference in a new issue