From d4942cc74c82c465ea395637c77ed06565b8b497 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Fri, 29 Jun 2018 16:09:28 -0400 Subject: Add Xuelin iHIFI 770/770C/800 support Taken from the xvortex fork (Roman Stolyarov) Ported, rebased, and cleaned up by myself. Change-Id: I7b2bca2d29502f2e4544e42f3d122786dd4b7978 --- firmware/SOURCES | 25 + firmware/drivers/audio/es9018.c | 134 ++++ firmware/drivers/audio/wm8740.c | 106 +++ firmware/export/audiohw.h | 6 +- firmware/export/config.h | 17 +- firmware/export/config/ihifi770.h | 197 ++++++ firmware/export/config/ihifi770c.h | 197 ++++++ firmware/export/config/ihifi800.h | 198 ++++++ firmware/export/config/rk27generic.h | 2 +- firmware/export/es9018.h | 39 + firmware/export/rk27xx.h | 5 +- firmware/export/wm8740.h | 83 +++ firmware/target/arm/rk27xx/backlight-rk27xx.c | 7 + firmware/target/arm/rk27xx/debug-rk27xx.c | 2 + firmware/target/arm/rk27xx/ihifi2/audio-ihifi770.c | 88 +++ firmware/target/arm/rk27xx/ihifi2/audio-ihifi800.c | 67 ++ firmware/target/arm/rk27xx/ihifi2/button-ihifi.c | 99 +++ firmware/target/arm/rk27xx/ihifi2/button-target.h | 50 ++ firmware/target/arm/rk27xx/ihifi2/lcd-ihifi770.c | 285 ++++++++ firmware/target/arm/rk27xx/ihifi2/lcd-ihifi770c.c | 248 +++++++ firmware/target/arm/rk27xx/ihifi2/lcd-ihifi800.c | 228 ++++++ firmware/target/arm/rk27xx/ihifi2/lcd-target.h | 26 + firmware/target/arm/rk27xx/ihifi2/power-ihifi.c | 53 ++ .../target/arm/rk27xx/ihifi2/powermgmt-ihifi770.c | 64 ++ .../target/arm/rk27xx/ihifi2/powermgmt-ihifi770c.c | 64 ++ .../target/arm/rk27xx/ihifi2/powermgmt-ihifi800.c | 64 ++ firmware/target/arm/rk27xx/sd-rk27xx.c | 18 +- firmware/target/arm/rk27xx/usb-drv-rk27xx.c | 787 ++++++++------------- firmware/target/arm/rk27xx/usb-rk27xx.c | 14 + firmware/target/hosted/sdl/sim-ui-defines.h | 22 + 30 files changed, 2687 insertions(+), 508 deletions(-) create mode 100644 firmware/drivers/audio/es9018.c create mode 100644 firmware/drivers/audio/wm8740.c create mode 100644 firmware/export/config/ihifi770.h create mode 100644 firmware/export/config/ihifi770c.h create mode 100644 firmware/export/config/ihifi800.h create mode 100644 firmware/export/es9018.h create mode 100644 firmware/export/wm8740.h create mode 100644 firmware/target/arm/rk27xx/ihifi2/audio-ihifi770.c create mode 100644 firmware/target/arm/rk27xx/ihifi2/audio-ihifi800.c create mode 100644 firmware/target/arm/rk27xx/ihifi2/button-ihifi.c create mode 100644 firmware/target/arm/rk27xx/ihifi2/button-target.h create mode 100644 firmware/target/arm/rk27xx/ihifi2/lcd-ihifi770.c create mode 100644 firmware/target/arm/rk27xx/ihifi2/lcd-ihifi770c.c create mode 100644 firmware/target/arm/rk27xx/ihifi2/lcd-ihifi800.c create mode 100644 firmware/target/arm/rk27xx/ihifi2/lcd-target.h create mode 100644 firmware/target/arm/rk27xx/ihifi2/power-ihifi.c create mode 100644 firmware/target/arm/rk27xx/ihifi2/powermgmt-ihifi770.c create mode 100644 firmware/target/arm/rk27xx/ihifi2/powermgmt-ihifi770c.c create mode 100644 firmware/target/arm/rk27xx/ihifi2/powermgmt-ihifi800.c (limited to 'firmware') diff --git a/firmware/SOURCES b/firmware/SOURCES index 33d59fa429..16ae4cc350 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -442,6 +442,8 @@ drivers/audio/audiohw-swcodec.c #if (CONFIG_PLATFORM & PLATFORM_NATIVE) && !defined(BOOTLOADER) #if defined(HAVE_UDA1380) drivers/audio/uda1380.c +#elif defined(HAVE_WM8740) +drivers/audio/wm8740.c #elif defined(HAVE_WM8751) \ || defined(HAVE_WM8750) drivers/audio/wm8751.c @@ -481,6 +483,8 @@ drivers/audio/df1704.c drivers/audio/pcm1792.c #elif defined (HAVE_CS4398) drivers/audio/cs4398.c +#elif defined (HAVE_ES9018) +drivers/audio/es9018.c #endif /* defined(HAVE_*) */ #else /* PLATFORM_HOSTED */ #if defined(SAMSUNG_YPR0) && defined(HAVE_AS3514) @@ -791,6 +795,12 @@ target/arm/s3c2440/lcd-s3c2440.c target/arm/rk27xx/ma/lcd-ma.c #elif CONFIG_LCD == LCD_IHIFI target/arm/rk27xx/ihifi/lcd-ihifi.c +#elif CONFIG_LCD == LCD_IHIFI770 +target/arm/rk27xx/ihifi2/lcd-ihifi770.c +#elif CONFIG_LCD == LCD_IHIFI770C +target/arm/rk27xx/ihifi2/lcd-ihifi770c.c +#elif CONFIG_LCD == LCD_IHIFI800 +target/arm/rk27xx/ihifi2/lcd-ihifi800.c #endif /* USB Stack */ @@ -1904,6 +1914,21 @@ target/arm/rk27xx/ihifi/powermgmt-ihifi960.c #endif #endif +#if defined(IHIFI770) || defined(IHIFI770C) || defined(IHIFI800) +target/arm/rk27xx/ihifi2/button-ihifi.c +target/arm/rk27xx/ihifi2/power-ihifi.c +#if defined(IHIFI770) +target/arm/rk27xx/ihifi2/powermgmt-ihifi770.c +target/arm/rk27xx/ihifi2/audio-ihifi770.c +#elif defined(IHIFI770C) +target/arm/rk27xx/ihifi2/powermgmt-ihifi770c.c +target/arm/rk27xx/ihifi2/audio-ihifi770.c +#elif defined(IHIFI800) +target/arm/rk27xx/ihifi2/powermgmt-ihifi800.c +target/arm/rk27xx/ihifi2/audio-ihifi800.c +#endif +#endif + #if (CONFIG_PLATFORM & PLATFORM_ANDROID) target/hosted/kernel-unix.c target/hosted/filesystem-unix.c diff --git a/firmware/drivers/audio/es9018.c b/firmware/drivers/audio/es9018.c new file mode 100644 index 0000000000..89e8c1d46f --- /dev/null +++ b/firmware/drivers/audio/es9018.c @@ -0,0 +1,134 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 "es9018.h" +#include "config.h" +#include "audio.h" +#include "audiohw.h" + +/* NOTE: The register names are not known, as the register numbering + listed in the ES9018 datasheet does not match what is described below.. */ + +static uint8_t reg0 = 0x00; /* System settings. Default value of register 0 */ +static uint8_t reg1 = 0x80; /* Input settings. Manual input, I2S, 32-bit (?) */ +static uint8_t reg4 = 0x00; /* Automute time. Default = disabled */ +static uint8_t reg5 = 0x68; /* Automute level. Default is some level */ +static uint8_t reg6 = 0x4A; /* Deemphasis. Default = disabled */ +static uint8_t reg7 = 0x83; /* General settings. Default sharp fir, pcm iir and muted */ +static uint8_t reg8 = 0x10; /* GPIO configuration */ +static uint8_t reg10 = 0x05; /* Master Mode Control. Default value: master mode off */ +static uint8_t reg11 = 0x02; /* Channel Mapping. Default stereo is Ch1=left, Ch2=right */ +static uint8_t reg12 = 0x50; /* DPLL Settings. Default = 005 for I2S, OFF for DSD */ +static uint8_t reg13 = 0x40; /* THD Compensation */ +static uint8_t reg14 = 0x8A; /* Soft Start Settings */ +static uint8_t reg21 = 0x00; /* Oversampling filter. Default: oversampling ON */ + +#define bitSet(value, bit) ((value) |= (1UL << (bit))) +#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) + +static int vol_tenthdb2hw(const int tdb) +{ + if (tdb < ES9018_VOLUME_MIN) { + return 0xff; + } else if (tdb > ES9018_VOLUME_MAX) { + return 0x00; + } else { + return (-tdb/5); + } +} + +void audiohw_set_volume(int vol_l, int vol_r) +{ + es9018_write_reg(15, vol_tenthdb2hw(vol_l)); + es9018_write_reg(16, vol_tenthdb2hw(vol_r)); +} + +void audiohw_mute(void) +{ + bitSet(reg7, 0); /* Mute Channel 1 */ + bitSet(reg7, 1); /* Mute Channel 2 */ + es9018_write_reg(0x07, reg7); +} + +void audiohw_unmute(void) +{ + bitClear(reg7, 0); /* Unmute Channel 1 */ + bitClear(reg7, 1); /* Unmute Channel 2 */ + es9018_write_reg(0x07, reg7); +} + +void audiohw_init(void) +{ + es9018_write_reg(0x00, reg0); + es9018_write_reg(0x01, reg1); + es9018_write_reg(0x04, reg4); + es9018_write_reg(0x05, reg5); + es9018_write_reg(0x06, reg6); + es9018_write_reg(0x07, reg7); + es9018_write_reg(0x08, reg8); + es9018_write_reg(0x0A, reg10); + es9018_write_reg(0x0B, reg11); + es9018_write_reg(0x0C, reg12); + es9018_write_reg(0x0D, reg13); + es9018_write_reg(0x0E, reg14); + es9018_write_reg(0x15, reg21); +} + +void audiohw_preinit(void) +{ +} + +void audiohw_set_frequency(int fsel) +{ + (void)fsel; +} + +void audiohw_set_filter_roll_off(int value) +{ + /* 0 = Sharp (Default) + 1 = Slow + 2 = Short + 3 = Bypass */ + switch(value) + { + case 0: + bitClear(reg7, 5); + bitClear(reg7, 6); + bitClear(reg21, 0); + break; + case 1: + bitSet(reg7, 5); + bitClear(reg7, 6); + bitClear(reg21, 0); + break; + case 2: + bitClear(reg7, 5); + bitSet(reg7, 6); + bitClear(reg21, 0); + break; + case 3: + bitSet(reg21, 0); + break; + } + es9018_write_reg(0x07, reg7); + es9018_write_reg(0x15, reg21); +} diff --git a/firmware/drivers/audio/wm8740.c b/firmware/drivers/audio/wm8740.c new file mode 100644 index 0000000000..d88f53bd75 --- /dev/null +++ b/firmware/drivers/audio/wm8740.c @@ -0,0 +1,106 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 "wm8740.h" +#include "config.h" +#include "audio.h" +#include "audiohw.h" + +static void wm8740_write_reg(const int reg, const unsigned int value) +{ + int i; + + for (i = (1<<15); i; i >>= 1) { + udelay(1); + wm8740_set_mc(0); + if ((reg|value) & i) { + wm8740_set_md(1); + } else { + wm8740_set_md(0); + } + udelay(1); + wm8740_set_mc(1); + } + udelay(1); + wm8740_set_ml(0); + udelay(1); + wm8740_set_mc(0); + udelay(1); + wm8740_set_ml(1); + udelay(1); +} + +static int vol_tenthdb2hw(const int tdb) +{ + if (tdb < WM8740_VOLUME_MIN) { + return 0x00; + } else if (tdb > WM8740_VOLUME_MAX) { + return 0xff; + } else { + return ((tdb / 5 + 0xff) & 0xff); + } +} + +void audiohw_set_volume(int vol_l, int vol_r) +{ + wm8740_write_reg(WM8740_REG0, vol_tenthdb2hw(vol_l)); + wm8740_write_reg(WM8740_REG1, vol_tenthdb2hw(vol_r) | WM8740_LDR); +} + +void audiohw_mute(void) +{ + wm8740_write_reg(WM8740_REG2, WM8740_MUT); +} + +void audiohw_unmute(void) +{ + wm8740_write_reg(WM8740_REG2, 0x00); +} + +void audiohw_init(void) +{ + wm8740_write_reg(WM8740_REG0, 0x00); + wm8740_write_reg(WM8740_REG1, 0x00); + wm8740_write_reg(WM8740_REG2, WM8740_MUT); + wm8740_write_reg(WM8740_REG3, WM8740_I2S); + wm8740_write_reg(WM8740_REG4, 0x00); +} + +void audiohw_preinit(void) +{ +} + +void audiohw_set_frequency(int fsel) +{ + (void)fsel; +} + +void audiohw_set_filter_roll_off(int value) +{ + /* 0 = fast (sharp); + 1 = slow */ + if (value == 0) { + wm8740_write_reg(WM8740_REG3, WM8740_I2S); + } else { + wm8740_write_reg(WM8740_REG3, WM8740_I2S | WM8740_SR0); + } +} diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h index 09001c8045..458fba3412 100644 --- a/firmware/export/audiohw.h +++ b/firmware/export/audiohw.h @@ -165,6 +165,8 @@ struct sound_settings_info #include "uda1380.h" #elif defined(HAVE_UDA1341) #include "uda1341.h" +#elif defined(HAVE_WM8740) +#include "wm8740.h" #elif defined(HAVE_WM8750) || defined(HAVE_WM8751) #include "wm8751.h" #elif defined(HAVE_WM8978) @@ -211,6 +213,8 @@ struct sound_settings_info #include "nwzlinux_codec.h" #elif defined(HAVE_CS4398) #include "cs4398.h" +#elif defined(HAVE_ES9018) +#include "es9018.h" #elif (CONFIG_PLATFORM & (PLATFORM_ANDROID | PLATFORM_MAEMO\ | PLATFORM_PANDORA | PLATFORM_SDL)) #include "hosted_codec.h" @@ -571,7 +575,7 @@ void audiohw_set_depth_3d(int val); #ifdef AUDIOHW_HAVE_FILTER_ROLL_OFF /** * Set DAC's oversampling filter roll-off. - * @param val 0 - sharp roll-off, 1 - slow roll-off. + * @param val 0 - sharp roll-off, 1 - slow roll-off, 2 - short roll-off, 3 - bypass. * NOTE: AUDIOHW_CAPS need to contain * FILTER_ROLL_OFF_CAP */ diff --git a/firmware/export/config.h b/firmware/export/config.h index 8b177963d3..2db12bea4a 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -169,6 +169,8 @@ #define SONY_NWZA860_PAD 64 /* The NWZ-A860 is too different (touchscreen) */ #define AGPTEK_ROCKER_PAD 65 #define XDUOO_X3_PAD 66 +#define IHIFI_770_PAD 67 +#define IHIFI_800_PAD 68 /* CONFIG_REMOTE_KEYPAD */ #define H100_REMOTE 1 @@ -284,6 +286,9 @@ #define LCD_NWZ_LINUX 63 /* as used in the Linux-based NWZ series */ #define LCD_INGENIC_LINUX 64 #define LCD_XDUOOX3 65 /* as used by the xDuoo X3 */ +#define LCD_IHIFI770 66 /* as used by IHIFI 770 */ +#define LCD_IHIFI770C 67 /* as used by IHIFI 770C */ +#define LCD_IHIFI800 68 /* as used by IHIFI 800 */ /* LCD_PIXELFORMAT */ #define HORIZONTAL_PACKING 1 @@ -581,6 +586,12 @@ Lyre prototype 1 */ #include "config/samsungypz5.h" #elif defined(IHIFI760) #include "config/ihifi760.h" +#elif defined(IHIFI770) +#include "config/ihifi770.h" +#elif defined(IHIFI770C) +#include "config/ihifi770c.h" +#elif defined(IHIFI800) +#include "config/ihifi800.h" #elif defined(IHIFI960) #include "config/ihifi960.h" #elif defined(CREATIVE_ZENXFISTYLE) @@ -974,7 +985,6 @@ Lyre prototype 1 */ #define USB_STATUS_BY_EVENT #define USB_DETECT_BY_REQUEST #elif CONFIG_USBOTG == USBOTG_RK27XX -#define USB_STATUS_BY_EVENT #define USB_DETECT_BY_REQUEST #endif /* CONFIG_USB == */ #endif /* HAVE_USBSTACK */ @@ -1193,7 +1203,7 @@ Lyre prototype 1 */ #endif /* HAVE_USB_CHARGING_ENABLE && HAVE_USBSTACK */ #ifndef SIMULATOR -#if defined(HAVE_USBSTACK) || (CONFIG_STORAGE & STORAGE_NAND) +#if defined(HAVE_USBSTACK) || (CONFIG_STORAGE & STORAGE_NAND) || (CONFIG_STORAGE & STORAGE_RAMDISK) #define STORAGE_GET_INFO #endif #endif @@ -1211,7 +1221,8 @@ Lyre prototype 1 */ (CONFIG_USBOTG == USBOTG_JZ4760) || \ (CONFIG_USBOTG == USBOTG_M66591) || \ (CONFIG_USBOTG == USBOTG_DESIGNWARE) || \ - (CONFIG_USBOTG == USBOTG_AS3525) + (CONFIG_USBOTG == USBOTG_AS3525) || \ + (CONFIG_USBOTG == USBOTG_RK27XX) #define USB_HAS_BULK #define USB_HAS_INTERRUPT #elif defined(CPU_TCC780X) || defined(CPU_TCC77X) diff --git a/firmware/export/config/ihifi770.h b/firmware/export/config/ihifi770.h new file mode 100644 index 0000000000..af7acff206 --- /dev/null +++ b/firmware/export/config/ihifi770.h @@ -0,0 +1,197 @@ +/* + * This config file is for IHIFI 770 + */ + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 108 + +#define MODEL_NAME "IHIFI 770" + +/* Define bitmask of input sources - recordable bitmask can be defined + explicitly if different */ +/* #define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FM) */ + +/* define the bitmask of hardware sample rates */ +#define HW_SAMPR_CAPS (SAMPR_CAP_96 | SAMPR_CAP_48 | SAMPR_CAP_44 | \ + SAMPR_CAP_32 | SAMPR_CAP_24 | SAMPR_CAP_22 | \ + SAMPR_CAP_16 | SAMPR_CAP_12 | SAMPR_CAP_11 | SAMPR_CAP_8) + +#define HAVE_WM8740 +#define CODEC_SLAVE + +/* define this if you have a bitmap LCD display */ +#define HAVE_LCD_BITMAP + +/* define this if you can flip your LCD */ +/* #define HAVE_LCD_FLIP */ + +/* define this if you have a colour LCD */ +#define HAVE_LCD_COLOR + +/* define this if you want album art for this target */ +#define HAVE_ALBUMART + +/* define this to enable bitmap scaling */ +#define HAVE_BMP_SCALING + +/* define this to enable JPEG decoding */ +#define HAVE_JPEG + +/* define this if you can invert the colours on your LCD */ +/* #define HAVE_LCD_INVERT */ + +/* define this if you have access to the quickscreen */ +#define HAVE_QUICKSCREEN + +/* define this if you would like tagcache to build on this target */ +#define HAVE_TAGCACHE + +/* define this if you have a flash memory storage */ +#define HAVE_FLASH_STORAGE + +#define CONFIG_STORAGE (STORAGE_SD | STORAGE_NAND) + +#define CONFIG_NAND NAND_RK27XX +#define HAVE_SW_TONE_CONTROLS + +#define HAVE_HOTSWAP + +#define NUM_DRIVES 1 +#define SECTOR_SIZE 512 + +/* for small(ish) SD cards */ +#define HAVE_FAT16SUPPORT + +/* LCD dimensions */ +#define LCD_WIDTH 320 +#define LCD_HEIGHT 240 +/* sqrt(320^2 + 240^2) / 2.4 = 166.7 */ +#define LCD_DPI 167 +#define LCD_DEPTH 16 /* pseudo 262.144 colors */ +#define LCD_PIXELFORMAT RGB565 /* rgb565 */ + +/* Define this if the LCD can shut down */ +/* #define HAVE_LCD_SHUTDOWN */ + +/* Define this if your LCD can be enabled/disabled */ +#define HAVE_LCD_ENABLE + +/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE + should be defined as well. */ +#ifndef BOOTLOADER +/* TODO: #define HAVE_LCD_SLEEP */ +/* TODO: #define HAVE_LCD_SLEEP_SETTING */ +#endif + +#define CONFIG_KEYPAD IHIFI_770_PAD + +/* define this if the target has volume keys which can be used in the lists */ +#define HAVE_VOLUME_IN_LIST + +/* Define this if a programmable hotkey is mapped */ +/* #define HAVE_HOTKEY */ + +/* Define this if you do software codec */ +#define CONFIG_CODEC SWCODEC + +/* define this if you have a real-time clock */ +/* #define CONFIG_RTC RTC_NANO2G */ + +/* Define if the device can wake from an RTC alarm */ +/* #define HAVE_RTC_ALARM */ + +/* Define the type of audio codec */ +/*#define HAVE_RK27XX_CODEC */ + +/* #define HAVE_PCM_DMA_ADDRESS */ + +/* Define this for LCD backlight available */ +#define HAVE_BACKLIGHT +#define HAVE_BACKLIGHT_BRIGHTNESS +#define MIN_BRIGHTNESS_SETTING 0 +#define MAX_BRIGHTNESS_SETTING 31 +#define DEFAULT_BRIGHTNESS_SETTING 31 +#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_HW_REG + +/* Define this if you have a software controlled poweroff */ +#define HAVE_SW_POWEROFF + +/* The number of bytes reserved for loadable codecs */ +#define CODEC_SIZE 0x100000 + +/* The number of bytes reserved for loadable plugins */ +#define PLUGIN_BUFFER_SIZE 0x80000 + +#define BATTERY_CAPACITY_DEFAULT 1050 /* default battery capacity */ +#define BATTERY_CAPACITY_MIN 500 /* min. capacity selectable */ +#define BATTERY_CAPACITY_MAX 1050 /* max. capacity selectable */ +#define BATTERY_CAPACITY_INC 10 /* capacity increment */ +#define BATTERY_TYPES_COUNT 1 /* only one type */ + +#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE + +/* Hardware controlled charging with monitoring */ +#define CONFIG_CHARGING CHARGING_MONITOR + +/* define current usage levels */ +/* TODO: #define CURRENT_NORMAL + * TODO: #define CURRENT_BACKLIGHT 23 + */ + +/* define this if the unit can be powered or charged via USB */ +#define HAVE_USB_POWER + +/* Define this if your LCD can set contrast */ +/* #define HAVE_LCD_CONTRAST */ + +/* Offset ( in the firmware file's header ) to the file CRC */ +#define FIRMWARE_OFFSET_FILE_CRC 0 + +/* Offset ( in the firmware file's header ) to the real data */ +#define FIRMWARE_OFFSET_FILE_DATA 8 + +#define STORAGE_NEEDS_ALIGN + +/* Define this if you have adjustable CPU frequency */ +#define HAVE_ADJUSTABLE_CPU_FREQ + +/* Virtual LED (icon) */ +#define CONFIG_LED LED_VIRTUAL + +/** Non-simulator section **/ +#ifndef SIMULATOR + +/* The exact type of CPU */ +#define CONFIG_CPU RK27XX + +/* Define this to the CPU frequency */ +#define CPU_FREQ 200000000 + +/* I2C interface */ +#define CONFIG_I2C I2C_RK27XX + +/* define this if the hardware can be powered off while charging */ +/* #define HAVE_POWEROFF_WHILE_CHARGING */ + +/* Type of LCD */ +#define CONFIG_LCD LCD_IHIFI770 + +/* USB On-the-go */ +#define CONFIG_USBOTG USBOTG_RK27XX + +/* enable these for the experimental usb stack */ +#define HAVE_USBSTACK + +#define USB_VENDOR_ID 0x071b +#define USB_PRODUCT_ID 0x3202 +#define HAVE_BOOTLOADER_USB_MODE + +#define RKW_FORMAT +#define BOOTFILE_EXT "rkw" +#define BOOTFILE "rockbox." BOOTFILE_EXT +#define BOOTDIR "/.rockbox" + +/* disabled for now */ +#undef HAVE_HOTSWAP + +#endif /* SIMULATOR */ diff --git a/firmware/export/config/ihifi770c.h b/firmware/export/config/ihifi770c.h new file mode 100644 index 0000000000..c4058f337b --- /dev/null +++ b/firmware/export/config/ihifi770c.h @@ -0,0 +1,197 @@ +/* + * This config file is for IHIFI 770C + */ + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 108 + +#define MODEL_NAME "IHIFI 770C" + +/* Define bitmask of input sources - recordable bitmask can be defined + explicitly if different */ +/* #define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FM) */ + +/* define the bitmask of hardware sample rates */ +#define HW_SAMPR_CAPS (SAMPR_CAP_96 | SAMPR_CAP_48 | SAMPR_CAP_44 | \ + SAMPR_CAP_32 | SAMPR_CAP_24 | SAMPR_CAP_22 | \ + SAMPR_CAP_16 | SAMPR_CAP_12 | SAMPR_CAP_11 | SAMPR_CAP_8) + +#define HAVE_WM8740 +#define CODEC_SLAVE + +/* define this if you have a bitmap LCD display */ +#define HAVE_LCD_BITMAP + +/* define this if you can flip your LCD */ +/* #define HAVE_LCD_FLIP */ + +/* define this if you have a colour LCD */ +#define HAVE_LCD_COLOR + +/* define this if you want album art for this target */ +#define HAVE_ALBUMART + +/* define this to enable bitmap scaling */ +#define HAVE_BMP_SCALING + +/* define this to enable JPEG decoding */ +#define HAVE_JPEG + +/* define this if you can invert the colours on your LCD */ +/* #define HAVE_LCD_INVERT */ + +/* define this if you have access to the quickscreen */ +#define HAVE_QUICKSCREEN + +/* define this if you would like tagcache to build on this target */ +#define HAVE_TAGCACHE + +/* define this if you have a flash memory storage */ +#define HAVE_FLASH_STORAGE + +#define CONFIG_STORAGE (STORAGE_SD | STORAGE_NAND) + +#define CONFIG_NAND NAND_RK27XX +#define HAVE_SW_TONE_CONTROLS + +#define HAVE_HOTSWAP + +#define NUM_DRIVES 1 +#define SECTOR_SIZE 512 + +/* for small(ish) SD cards */ +#define HAVE_FAT16SUPPORT + +/* LCD dimensions */ +#define LCD_WIDTH 320 +#define LCD_HEIGHT 240 +/* sqrt(320^2 + 240^2) / 2.4 = 166.7 */ +#define LCD_DPI 167 +#define LCD_DEPTH 16 /* pseudo 262.144 colors */ +#define LCD_PIXELFORMAT RGB565 /* rgb565 */ + +/* Define this if the LCD can shut down */ +/* #define HAVE_LCD_SHUTDOWN */ + +/* Define this if your LCD can be enabled/disabled */ +#define HAVE_LCD_ENABLE + +/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE + should be defined as well. */ +#ifndef BOOTLOADER +/* TODO: #define HAVE_LCD_SLEEP */ +/* TODO: #define HAVE_LCD_SLEEP_SETTING */ +#endif + +#define CONFIG_KEYPAD IHIFI_770_PAD + +/* define this if the target has volume keys which can be used in the lists */ +#define HAVE_VOLUME_IN_LIST + +/* Define this if a programmable hotkey is mapped */ +/* #define HAVE_HOTKEY */ + +/* Define this if you do software codec */ +#define CONFIG_CODEC SWCODEC + +/* define this if you have a real-time clock */ +/* #define CONFIG_RTC RTC_NANO2G */ + +/* Define if the device can wake from an RTC alarm */ +/* #define HAVE_RTC_ALARM */ + +/* Define the type of audio codec */ +/*#define HAVE_RK27XX_CODEC */ + +/* #define HAVE_PCM_DMA_ADDRESS */ + +/* Define this for LCD backlight available */ +#define HAVE_BACKLIGHT +#define HAVE_BACKLIGHT_BRIGHTNESS +#define MIN_BRIGHTNESS_SETTING 0 +#define MAX_BRIGHTNESS_SETTING 31 +#define DEFAULT_BRIGHTNESS_SETTING 31 +#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_HW_REG + +/* Define this if you have a software controlled poweroff */ +#define HAVE_SW_POWEROFF + +/* The number of bytes reserved for loadable codecs */ +#define CODEC_SIZE 0x100000 + +/* The number of bytes reserved for loadable plugins */ +#define PLUGIN_BUFFER_SIZE 0x80000 + +#define BATTERY_CAPACITY_DEFAULT 1050 /* default battery capacity */ +#define BATTERY_CAPACITY_MIN 500 /* min. capacity selectable */ +#define BATTERY_CAPACITY_MAX 1050 /* max. capacity selectable */ +#define BATTERY_CAPACITY_INC 10 /* capacity increment */ +#define BATTERY_TYPES_COUNT 1 /* only one type */ + +#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE + +/* Hardware controlled charging with monitoring */ +#define CONFIG_CHARGING CHARGING_MONITOR + +/* define current usage levels */ +/* TODO: #define CURRENT_NORMAL + * TODO: #define CURRENT_BACKLIGHT 23 + */ + +/* define this if the unit can be powered or charged via USB */ +#define HAVE_USB_POWER + +/* Define this if your LCD can set contrast */ +/* #define HAVE_LCD_CONTRAST */ + +/* Offset ( in the firmware file's header ) to the file CRC */ +#define FIRMWARE_OFFSET_FILE_CRC 0 + +/* Offset ( in the firmware file's header ) to the real data */ +#define FIRMWARE_OFFSET_FILE_DATA 8 + +#define STORAGE_NEEDS_ALIGN + +/* Define this if you have adjustable CPU frequency */ +#define HAVE_ADJUSTABLE_CPU_FREQ + +/* Virtual LED (icon) */ +#define CONFIG_LED LED_VIRTUAL + +/** Non-simulator section **/ +#ifndef SIMULATOR + +/* The exact type of CPU */ +#define CONFIG_CPU RK27XX + +/* Define this to the CPU frequency */ +#define CPU_FREQ 200000000 + +/* I2C interface */ +#define CONFIG_I2C I2C_RK27XX + +/* define this if the hardware can be powered off while charging */ +/* #define HAVE_POWEROFF_WHILE_CHARGING */ + +/* Type of LCD */ +#define CONFIG_LCD LCD_IHIFI770C + +/* USB On-the-go */ +#define CONFIG_USBOTG USBOTG_RK27XX + +/* enable these for the experimental usb stack */ +#define HAVE_USBSTACK + +#define USB_VENDOR_ID 0x071b +#define USB_PRODUCT_ID 0x3202 +#define HAVE_BOOTLOADER_USB_MODE + +#define RKW_FORMAT +#define BOOTFILE_EXT "rkw" +#define BOOTFILE "rockbox." BOOTFILE_EXT +#define BOOTDIR "/.rockbox" + +/* disabled for now */ +#undef HAVE_HOTSWAP + +#endif /* SIMULATOR */ diff --git a/firmware/export/config/ihifi800.h b/firmware/export/config/ihifi800.h new file mode 100644 index 0000000000..eb1c2015ad --- /dev/null +++ b/firmware/export/config/ihifi800.h @@ -0,0 +1,198 @@ +/* + * This config file is for IHIFI 800 + */ + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 109 + +#define MODEL_NAME "IHIFI 800" + +/* Define bitmask of input sources - recordable bitmask can be defined + explicitly if different */ +/* #define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FM) */ + +/* define the bitmask of hardware sample rates */ +#define HW_SAMPR_CAPS (SAMPR_CAP_96 | SAMPR_CAP_48 | SAMPR_CAP_44 | \ + SAMPR_CAP_32 | SAMPR_CAP_24 | SAMPR_CAP_22 | \ + SAMPR_CAP_16 | SAMPR_CAP_12 | SAMPR_CAP_11 | SAMPR_CAP_8) + +#define HAVE_ES9018 +#define CODEC_SLAVE + +/* define this if you have a bitmap LCD display */ +#define HAVE_LCD_BITMAP + +/* define this if you can flip your LCD */ +/* #define HAVE_LCD_FLIP */ + +/* define this if you have a colour LCD */ +#define HAVE_LCD_COLOR + +/* define this if you want album art for this target */ +#define HAVE_ALBUMART + +/* define this to enable bitmap scaling */ +#define HAVE_BMP_SCALING + +/* define this to enable JPEG decoding */ +#define HAVE_JPEG + +/* define this if you can invert the colours on your LCD */ +/* #define HAVE_LCD_INVERT */ + +/* define this if you have access to the quickscreen */ +#define HAVE_QUICKSCREEN + +/* define this if you would like tagcache to build on this target */ +#define HAVE_TAGCACHE + +/* define this if you have a flash memory storage */ +#define HAVE_FLASH_STORAGE + +#define CONFIG_STORAGE (STORAGE_SD | STORAGE_NAND) + +#define CONFIG_NAND NAND_RK27XX +#define HAVE_SW_TONE_CONTROLS + +#define HAVE_HOTSWAP + +#define NUM_DRIVES 1 +#define SECTOR_SIZE 512 + +/* for small(ish) SD cards */ +#define HAVE_FAT16SUPPORT + +/* LCD dimensions */ +#define LCD_WIDTH 240 +#define LCD_HEIGHT 320 +/* sqrt(240^2 + 320^2) / 2.4 = 166.7 */ +#define LCD_DPI 167 +#define LCD_DEPTH 16 /* pseudo 262.144 colors */ +#define LCD_PIXELFORMAT RGB565 /* rgb565 */ + +/* Define this if the LCD can shut down */ +/* #define HAVE_LCD_SHUTDOWN */ + +/* Define this if your LCD can be enabled/disabled */ +#define HAVE_LCD_ENABLE + +/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE + should be defined as well. */ +#ifndef BOOTLOADER +/* TODO: #define HAVE_LCD_SLEEP */ +/* TODO: #define HAVE_LCD_SLEEP_SETTING */ +#endif + +#define CONFIG_KEYPAD IHIFI_800_PAD + +/* define this if the target has volume keys which can be used in the lists */ +#define HAVE_VOLUME_IN_LIST + +/* Define this if a programmable hotkey is mapped */ +/* #define HAVE_HOTKEY */ + +/* Define this if you do software codec */ +#define CONFIG_CODEC SWCODEC + +/* define this if you have a real-time clock */ +/* #define CONFIG_RTC RTC_NANO2G */ + +/* Define if the device can wake from an RTC alarm */ +/* #define HAVE_RTC_ALARM */ + +/* Define the type of audio codec */ +/*#define HAVE_RK27XX_CODEC */ + +/* #define HAVE_PCM_DMA_ADDRESS */ + +/* Define this for LCD backlight available */ +#define HAVE_BACKLIGHT +#define HAVE_BACKLIGHT_BRIGHTNESS +#define MIN_BRIGHTNESS_SETTING 0 +#define MAX_BRIGHTNESS_SETTING 31 +#define DEFAULT_BRIGHTNESS_SETTING 31 +#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_HW_REG + +/* Define this if you have a software controlled poweroff */ +#define HAVE_SW_POWEROFF + +/* The number of bytes reserved for loadable codecs */ +#define CODEC_SIZE 0x100000 + +/* The number of bytes reserved for loadable plugins */ +#define PLUGIN_BUFFER_SIZE 0x80000 + +/* TODO: Figure out real values */ +#define BATTERY_CAPACITY_DEFAULT 1400 /* default battery capacity */ +#define BATTERY_CAPACITY_MIN 700 /* min. capacity selectable */ +#define BATTERY_CAPACITY_MAX 1400 /* max. capacity selectable */ +#define BATTERY_CAPACITY_INC 10 /* capacity increment */ +#define BATTERY_TYPES_COUNT 1 /* only one type */ + +#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE + +/* Hardware controlled charging with monitoring */ +#define CONFIG_CHARGING CHARGING_MONITOR + +/* define current usage levels */ +/* TODO: #define CURRENT_NORMAL + * TODO: #define CURRENT_BACKLIGHT 23 + */ + +/* define this if the unit can be powered or charged via USB */ +#define HAVE_USB_POWER + +/* Define this if your LCD can set contrast */ +/* #define HAVE_LCD_CONTRAST */ + +/* Offset ( in the firmware file's header ) to the file CRC */ +#define FIRMWARE_OFFSET_FILE_CRC 0 + +/* Offset ( in the firmware file's header ) to the real data */ +#define FIRMWARE_OFFSET_FILE_DATA 8 + +#define STORAGE_NEEDS_ALIGN + +/* Define this if you have adjustable CPU frequency */ +#define HAVE_ADJUSTABLE_CPU_FREQ + +/* Virtual LED (icon) */ +#define CONFIG_LED LED_VIRTUAL + +/** Non-simulator section **/ +#ifndef SIMULATOR + +/* The exact type of CPU */ +#define CONFIG_CPU RK27XX + +/* Define this to the CPU frequency */ +#define CPU_FREQ 200000000 + +/* I2C interface */ +#define CONFIG_I2C I2C_RK27XX + +/* define this if the hardware can be powered off while charging */ +/* #define HAVE_POWEROFF_WHILE_CHARGING */ + +/* Type of LCD */ +#define CONFIG_LCD LCD_IHIFI800 + +/* USB On-the-go */ +#define CONFIG_USBOTG USBOTG_RK27XX + +/* enable these for the experimental usb stack */ +#define HAVE_USBSTACK + +#define USB_VENDOR_ID 0x071b +#define USB_PRODUCT_ID 0x3202 +#define HAVE_BOOTLOADER_USB_MODE + +#define RKW_FORMAT +#define BOOTFILE_EXT "rkw" +#define BOOTFILE "rockbox." BOOTFILE_EXT +#define BOOTDIR "/.rockbox" + +/* disabled for now */ +#undef HAVE_HOTSWAP + +#endif /* SIMULATOR */ diff --git a/firmware/export/config/rk27generic.h b/firmware/export/config/rk27generic.h index 503857bd43..69cf9f3758 100644 --- a/firmware/export/config/rk27generic.h +++ b/firmware/export/config/rk27generic.h @@ -63,7 +63,7 @@ /* commented for now */ /* #define HAVE_HOTSWAP */ -#define NUM_DRIVES 2 +#define NUM_DRIVES 1 #define SECTOR_SIZE 512 /* for small(ish) SD cards */ diff --git a/firmware/export/es9018.h b/firmware/export/es9018.h new file mode 100644 index 0000000000..41ea0d0b1c --- /dev/null +++ b/firmware/export/es9018.h @@ -0,0 +1,39 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 _ES9018_H +#define _ES9018_H + +#define ES9018_VOLUME_MIN -1270 +#define ES9018_VOLUME_MAX 0 + +#define AUDIOHW_CAPS (FILTER_ROLL_OFF_CAP) +#define AUDIOHW_HAVE_SHORT_ROLL_OFF +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, ES9018_VOLUME_MIN/10, ES9018_VOLUME_MAX/10, 0) +AUDIOHW_SETTING(FILTER_ROLL_OFF, "", 0, 1, 0, 3, 0) + +void es9018_write_reg(uint8_t reg, uint8_t val); +uint8_t es9018_read_reg(uint8_t reg); + +void audiohw_mute(void); +void audiohw_unmute(void); + +#endif diff --git a/firmware/export/rk27xx.h b/firmware/export/rk27xx.h index 58b3fe8166..dc6bca7cbd 100644 --- a/firmware/export/rk27xx.h +++ b/firmware/export/rk27xx.h @@ -8,7 +8,8 @@ #define FLASH_BANK1 0x11000000 #define USB_NUM_ENDPOINTS 16 -#define USB_DEVBSS_ATTR +/* cache aligned */ +#define USB_DEVBSS_ATTR __attribute__((aligned(CACHEALIGN_SIZE))) /* Timers */ #define APB0_TIMER (ARM_BUS0_BASE + 0x00000000) @@ -811,6 +812,7 @@ #define RXVOIDINTEN (1<<5) #define RXERRINTEN (1<<6) #define RXACKINTEN (1<<7) +#define RXCFINTE (1<<12) /* bits 31:8 reserved for EP0 */ /* bits 31:14 reserved for others */ @@ -833,6 +835,7 @@ #define TXERRINTEN (1<<5) #define TXACKINTEN (1<<6) #define TXDMADNEN (1<<7) /* reserved for EP0 */ +#define TXCFINTE (1<<12) /* bits 31:8 reserved */ /* TXnBUF bits */ diff --git a/firmware/export/wm8740.h b/firmware/export/wm8740.h new file mode 100644 index 0000000000..ff27a7e41e --- /dev/null +++ b/firmware/export/wm8740.h @@ -0,0 +1,83 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 _WM8740_H +#define _WM8740_H + +#define WM8740_VOLUME_MIN -1270 +#define WM8740_VOLUME_MAX 0 + +#define AUDIOHW_CAPS (FILTER_ROLL_OFF_CAP) +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, WM8740_VOLUME_MIN/10, WM8740_VOLUME_MAX/10, 0) +AUDIOHW_SETTING(FILTER_ROLL_OFF, "", 0, 1, 0, 1, 0) + +#define WM8740_REG0 0x0000 +#define WM8740_REG1 0x0200 +#define WM8740_REG2 0x0400 +#define WM8740_REG3 0x0600 +#define WM8740_REG4 0x0C00 + +/** + * Register #0 + */ +#define WM8740_LDL (1<<8) + +/** + * Register #1 + */ +#define WM8740_LDR (1<<8) + +/** + * Register #2 + */ +#define WM8740_MUT (1<<0) +#define WM8740_DEM (1<<1) +#define WM8740_OPE (1<<2) +#define WM8740_IW0 (1<<3) +#define WM8740_IW1 (1<<4) + +/** + * Register #3 + */ +#define WM8740_I2S (1<<0) +#define WM8740_LRP (1<<1) +#define WM8740_ATC (1<<2) +#define WM8740_SR0 (1<<3) +#define WM8740_REV (1<<4) +#define WM8740_SF0 (1<<6) +#define WM8740_SF1 (1<<7) +#define WM8740_IZD (1<<8) + +/** + * Register #4 + */ +#define WM8740_DIFF0 (1<<4) +#define WM8740_DIFF1 (1<<5) +#define WM8740_CDD (1<<6) + +void audiohw_mute(void); +void audiohw_unmute(void); + +void wm8740_set_ml(const int); +void wm8740_set_mc(const int); +void wm8740_set_md(const int); + +#endif diff --git a/firmware/target/arm/rk27xx/backlight-rk27xx.c b/firmware/target/arm/rk27xx/backlight-rk27xx.c index 1756fcdb29..61e887af46 100644 --- a/firmware/target/arm/rk27xx/backlight-rk27xx.c +++ b/firmware/target/arm/rk27xx/backlight-rk27xx.c @@ -75,6 +75,13 @@ static const unsigned short lin_brightness[] = { 759, 768, 778, 788, 800, 812, 826, 841, 856, 873, 891, 910, 931, 952, 975, 1000 }; +#elif defined(IHIFI770) || defined(IHIFI770C) || defined(IHIFI800) +static const unsigned short lin_brightness[] = { + 4096, 4215, 4381, 4603, 4887, 5243, 5679, 6201, + 6818, 7538, 8370, 9320, 10397, 11609, 12963, 14469, + 16133, 17963, 19968, 22156, 24534, 27110, 29893, 32890, + 36109, 39559, 43246, 47180, 51368, 55817, 60537, 65535 +}; #endif bool backlight_hw_init(void) diff --git a/firmware/target/arm/rk27xx/debug-rk27xx.c b/firmware/target/arm/rk27xx/debug-rk27xx.c index 83bc1a5af6..ea0190049f 100644 --- a/firmware/target/arm/rk27xx/debug-rk27xx.c +++ b/firmware/target/arm/rk27xx/debug-rk27xx.c @@ -35,6 +35,8 @@ #elif defined(HM60X) || defined(HM801) || (CONFIG_KEYPAD == MA_PAD) || \ (CONFIG_KEYPAD == IHIFI_PAD) #define DEBUG_CANCEL BUTTON_LEFT +#elif (CONFIG_KEYPAD == IHIFI_770_PAD) || (CONFIG_KEYPAD == IHIFI_800_PAD) +#define DEBUG_CANCEL BUTTON_POWER #endif /* Skeleton for adding target specific debug info to the debug menu diff --git a/firmware/target/arm/rk27xx/ihifi2/audio-ihifi770.c b/firmware/target/arm/rk27xx/ihifi2/audio-ihifi770.c new file mode 100644 index 0000000000..a21ea9cfef --- /dev/null +++ b/firmware/target/arm/rk27xx/ihifi2/audio-ihifi770.c @@ -0,0 +1,88 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 "kernel.h" +#include "audiohw.h" + +void wm8740_hw_init(void) +{ + GPIO_PADR &= ~(1<<0); /* MD */ + GPIO_PACON |= (1<<0); + + GPIO_PADR &= ~(1<<1); /* MC */ + GPIO_PACON |= (1<<1); + + SCU_IOMUXB_CON &= ~(1<<2); + GPIO_PCDR |= (1<<4); /* ML */ + GPIO_PCCON |= (1<<4); +} + +void wm8740_set_md(const int val) +{ + if (val) + GPIO_PADR |= (1<<0); + else + GPIO_PADR &= ~(1<<0); +} + +void wm8740_set_mc(const int val) +{ + if (val) + GPIO_PADR |= (1<<1); + else + GPIO_PADR &= ~(1<<1); +} + +void wm8740_set_ml(const int val) +{ + if (val) + GPIO_PCDR |= (1<<4); + else + GPIO_PCDR &= ~(1<<4); +} + +static void pop_ctrl(const int val) +{ + if (val) + GPIO_PADR |= (1<<7); + else + GPIO_PADR &= ~(1<<7); +} + +void audiohw_postinit(void) +{ + pop_ctrl(0); + sleep(HZ/4); + wm8740_hw_init(); + audiohw_init(); + sleep(HZ/2); + pop_ctrl(1); + sleep(HZ/4); + audiohw_unmute(); +} + +void audiohw_close(void) +{ + audiohw_mute(); + pop_ctrl(0); + sleep(HZ/4); +} diff --git a/firmware/target/arm/rk27xx/ihifi2/audio-ihifi800.c b/firmware/target/arm/rk27xx/ihifi2/audio-ihifi800.c new file mode 100644 index 0000000000..14b126c72a --- /dev/null +++ b/firmware/target/arm/rk27xx/ihifi2/audio-ihifi800.c @@ -0,0 +1,67 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 "kernel.h" +#include "audiohw.h" +#include "i2c-rk27xx.h" + +#define ES9018_I2C_ADDR 0x90 + +static unsigned char buf; + +void es9018_write_reg(uint8_t reg, uint8_t val) +{ + buf = val; + i2c_write(ES9018_I2C_ADDR, reg, sizeof(buf), (void*)&buf); +} + +uint8_t es9018_read_reg(uint8_t reg) +{ + i2c_read(ES9018_I2C_ADDR, reg, sizeof(buf), (void*)&buf); + return buf; +} + +static void pop_ctrl(const int val) +{ + if (val) + GPIO_PADR |= (1<<7); + else + GPIO_PADR &= ~(1<<7); +} + +void audiohw_postinit(void) +{ + pop_ctrl(0); + sleep(HZ/4); + audiohw_init(); + sleep(HZ/2); + pop_ctrl(1); + sleep(HZ/4); + audiohw_unmute(); +} + +void audiohw_close(void) +{ + audiohw_mute(); + pop_ctrl(0); + sleep(HZ/4); +} diff --git a/firmware/target/arm/rk27xx/ihifi2/button-ihifi.c b/firmware/target/arm/rk27xx/ihifi2/button-ihifi.c new file mode 100644 index 0000000000..172853a83a --- /dev/null +++ b/firmware/target/arm/rk27xx/ihifi2/button-ihifi.c @@ -0,0 +1,99 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 "config.h" +#include "system.h" +#include "kernel.h" +#include "button.h" +#include "adc.h" +#include "backlight.h" + +static bool soft_hold = false; +#ifndef BOOTLOADER +static unsigned hold_counter = 0; +#ifndef IHIFI800 +#define HOLDBUTTON gpio_btn +#define HOLDCNTMAX HZ +#else +#define HOLDBUTTON (gpio_btn) && (adc_val > 325) && (adc_val < 480) +#define HOLDCNTMAX (HZ/10) +#endif +#endif + +void button_init_device(void) { + GPIO_PCCON &= ~(1<<1); /* PWR BTN */ + GPIO_PCCON &= ~(1<<7); /* CD */ +} + +bool button_hold(void) +{ + return soft_hold; +} + +int button_read_device(void) { + int adc_val = adc_read(ADC_BUTTONS); + int gpio_btn = GPIO_PCDR & (1<<1); + + int button = BUTTON_NONE; + + if (gpio_btn) + button |= BUTTON_POWER; + +#ifndef BOOTLOADER + if (HOLDBUTTON) { + if (++hold_counter == HOLDCNTMAX) { + soft_hold = !soft_hold; + backlight_hold_changed(soft_hold); + } + } else { + hold_counter = 0; + } + if (soft_hold) { + return (hold_counter <= HOLDCNTMAX) ? BUTTON_NONE : button; + } +#endif + + if (adc_val < 792) { + if (adc_val < 480) { + if (adc_val < 170) { + if (adc_val < 46) { + button |= BUTTON_HOME; // 0-45 + } else { + button |= BUTTON_PLAY; // 46-169 + } + } else { + if (adc_val < 325) { + button |= BUTTON_NEXT; // 170-324 + } else { + button |= BUTTON_VOL_UP;// 325-479 + } + } + } else { + if (adc_val < 636) { + button |= BUTTON_VOL_DOWN;// 480-635 + } else { + button |= BUTTON_PREV; // 636-791 + } + } + } + + return button; +} diff --git a/firmware/target/arm/rk27xx/ihifi2/button-target.h b/firmware/target/arm/rk27xx/ihifi2/button-target.h new file mode 100644 index 0000000000..211e20e1d6 --- /dev/null +++ b/firmware/target/arm/rk27xx/ihifi2/button-target.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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_ + +#define HAS_BUTTON_HOLD + +/* Main unit's buttons */ +#define BUTTON_POWER 0x00000001 +#define BUTTON_HOME 0x00000002 +#define BUTTON_PREV 0x00000004 +#define BUTTON_NEXT 0x00000008 +#define BUTTON_PLAY 0x00000010 +#define BUTTON_VOL_UP 0x00000020 +#define BUTTON_VOL_DOWN 0x00000040 + +#define BUTTON_LEFT 0 +#define BUTTON_RIGHT 0 + +#define BUTTON_MAIN (BUTTON_POWER | BUTTON_HOME | BUTTON_PREV | BUTTON_NEXT | \ + BUTTON_PLAY | BUTTON_VOL_UP | BUTTON_VOL_DOWN) + +/* Software power-off */ +#ifndef IHIFI800 +#define POWEROFF_BUTTON BUTTON_POWER +#else +#define POWEROFF_BUTTON BUTTON_HOME +#endif + +#define POWEROFF_COUNT 30 + +#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/arm/rk27xx/ihifi2/lcd-ihifi770.c b/firmware/target/arm/rk27xx/ihifi2/lcd-ihifi770.c new file mode 100644 index 0000000000..23505d9fa0 --- /dev/null +++ b/firmware/target/arm/rk27xx/ihifi2/lcd-ihifi770.c @@ -0,0 +1,285 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 "config.h" +#include "kernel.h" +#include "lcd.h" +#include "system.h" +#include "cpu.h" +#include "lcdif-rk27xx.h" + +static bool display_on = false; + +void lcd_display_init(void) +{ + unsigned int i, x, y; + + lcd_cmd(0x11); + + lcd_cmd(0x13); + + mdelay(120); + + lcd_cmd(0x29); + + lcd_cmd(0xB0); + lcd_data(0x05); + lcd_data(0x00); + lcd_data(0xF0); + lcd_data(0x0A); + lcd_data(0x41); + lcd_data(0x02); + lcd_data(0x0A); + lcd_data(0x30); + lcd_data(0x31); + lcd_data(0x36); + lcd_data(0x37); + lcd_data(0x40); + lcd_data(0x02); + lcd_data(0x3F); + lcd_data(0x40); + lcd_data(0x02); + lcd_data(0x81); + lcd_data(0x04); + lcd_data(0x05); + lcd_data(0x64); + + lcd_cmd(0xFC); + lcd_data(0x88); + lcd_data(0x00); + lcd_data(0x10); + lcd_data(0x01); + lcd_data(0x01); + lcd_data(0x10); + lcd_data(0x42); + lcd_data(0x42); + lcd_data(0x22); + lcd_data(0x11); + lcd_data(0x11); + lcd_data(0x22); + lcd_data(0x99); + lcd_data(0xAA); + lcd_data(0xAA); + lcd_data(0xAA); + lcd_data(0xBB); + lcd_data(0xBB); + lcd_data(0xAA); + lcd_data(0x33); + lcd_data(0x33); + lcd_data(0x11); + lcd_data(0x01); + lcd_data(0x01); + lcd_data(0x01); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0xC0); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0x00); + + lcd_cmd(0xFD); + lcd_data(0x88); + lcd_data(0x00); + lcd_data(0x10); + lcd_data(0x01); + lcd_data(0x01); + lcd_data(0x10); + lcd_data(0x42); + lcd_data(0x42); + lcd_data(0x22); + lcd_data(0x11); + lcd_data(0x11); + lcd_data(0x22); + lcd_data(0x99); + lcd_data(0xAA); + lcd_data(0xAA); + lcd_data(0xAA); + lcd_data(0xBB); + lcd_data(0xBB); + lcd_data(0xAA); + lcd_data(0x33); + lcd_data(0x33); + lcd_data(0x11); + lcd_data(0x01); + lcd_data(0x01); + lcd_data(0x01); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0x03); + + lcd_cmd(0xBE); + lcd_data(0x00); + lcd_data(0x15); + lcd_data(0x16); + lcd_data(0x08); + lcd_data(0x09); + lcd_data(0x15); + lcd_data(0x10); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0x00); + + lcd_cmd(0xC0); + lcd_data(0x0E); + lcd_data(0x01); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0x00); + + lcd_cmd(0xC1); + lcd_data(0x2F); + lcd_data(0x23); + lcd_data(0xB4); + lcd_data(0xFF); + lcd_data(0x24); + lcd_data(0x03); + lcd_data(0x20); + lcd_data(0x02); + lcd_data(0x02); + lcd_data(0x02); + lcd_data(0x20); + lcd_data(0x20); + lcd_data(0x00); + + lcd_cmd(0xC2); + lcd_data(0x03); + + lcd_cmd(0x26); + lcd_data(0x08); + + lcd_cmd(0x35); + + lcd_cmd(0x36); + lcd_data(0x04); + + lcd_cmd(0x3A); + lcd_data(0x05); + + lcd_cmd(0x2A); + lcd_data(0x013F); + + lcd_cmd(0x2B); + lcd_data(0xEF); + + lcd_cmd(0x2C); + + lcd_cmd(0x2D); + for (i = 0; i < 0x20; i++) { + lcd_data(i << 1); + } + for (i = 0; i < 0x40; i++) { + lcd_data(i); + } + for (i = 0; i < 0x20; i++) { + lcd_data(i << 1); + } + + lcd_cmd(0x2A); + lcd_data(0x00); + + lcd_cmd(0x2B); + lcd_data(0x00); + + lcd_cmd(0x11); + + mdelay(120); + + lcd_cmd(0x29); + + lcd_cmd(0x2C); + + for (x = 0; x < LCD_WIDTH; x++) + for(y=0; y < LCD_HEIGHT; y++) + lcd_data(0x00); + + display_on = true; +} + +void lcd_enable (bool on) +{ + if (on == display_on) + return; + + lcdctrl_bypass(1); + LCDC_CTRL |= RGB24B; + + if (on) { + lcd_cmd(0x11); + mdelay(120); + lcd_cmd(0x29); + lcd_cmd(0x2C); + } else { + lcd_cmd(0x28); + mdelay(120); + lcd_cmd(0x10); + } + + display_on = on; + LCDC_CTRL &= ~RGB24B; +} + +void lcd_set_gram_area(int x_start, int y_start, + int x_end, int y_end) +{ + lcdctrl_bypass(1); + LCDC_CTRL |= RGB24B; + + lcd_cmd(0x2A); + lcd_data((x_start&0xff00)>>8); + lcd_data(x_start&0x00ff); + lcd_data((x_end&0xff00)>>8); + lcd_data(x_end&0x00ff); + + lcd_cmd(0x2B); + lcd_data((y_start&0xff00)>>8); + lcd_data(y_start&0x00ff); + lcd_data((y_end&0xff00)>>8); + lcd_data(y_end&0x00ff); + + lcd_cmd(0x2C); + + LCDC_CTRL &= ~RGB24B; +} + +bool lcd_active() +{ + return display_on; +} + +/* Blit a YUV bitmap directly to the LCD */ +void lcd_blit_yuv(unsigned char * const src[3], + int src_x, int src_y, int stride, + int x, int y, int width, int height) +{ + (void)src; + (void)src_x; + (void)src_y; + (void)stride; + (void)x; + (void)y; + (void)width; + (void)height; +} diff --git a/firmware/target/arm/rk27xx/ihifi2/lcd-ihifi770c.c b/firmware/target/arm/rk27xx/ihifi2/lcd-ihifi770c.c new file mode 100644 index 0000000000..311b8057cb --- /dev/null +++ b/firmware/target/arm/rk27xx/ihifi2/lcd-ihifi770c.c @@ -0,0 +1,248 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 "config.h" +#include "kernel.h" +#include "lcd.h" +#include "system.h" +#include "cpu.h" +#include "lcdif-rk27xx.h" + +static bool display_on = false; + +void lcd_display_init(void) +{ + unsigned int x, y; + + lcd_cmd(0x13); + + mdelay(120); + + lcd_cmd(0x35); + lcd_data(0x00); + + lcd_cmd(0x36); + lcd_data(0x48); + + lcd_cmd(0xD0); + lcd_data(0x00); + lcd_data(0x05); + + lcd_cmd(0xEF); + lcd_data(0x07); + + lcd_cmd(0xF2); + lcd_data(0x1B); + lcd_data(0x16); + lcd_data(0x0F); + lcd_data(0x08); + lcd_data(0x08); + lcd_data(0x08); + lcd_data(0x08); + lcd_data(0x10); + lcd_data(0x00); + lcd_data(0x1C); + lcd_data(0x16); + + lcd_cmd(0xF3); + lcd_data(0x01); + lcd_data(0x41); + lcd_data(0x15); + lcd_data(0x0D); + lcd_data(0x33); + lcd_data(0x63); + lcd_data(0x46); + lcd_data(0x10); + + lcd_cmd(0xF4); + lcd_data(0x5B); + lcd_data(0x5B); + lcd_data(0x55); + lcd_data(0x55); + lcd_data(0x44); + + lcd_cmd(0xF5); + lcd_data(0x12); + lcd_data(0x11); + lcd_data(0x06); + lcd_data(0xF0); + lcd_data(0x00); + lcd_data(0x1F); + + lcd_cmd(0xF6); + lcd_data(0x80); + lcd_data(0x10); + lcd_data(0x00); + + lcd_cmd(0xFD); + lcd_data(0x11); + lcd_data(0x1D); + lcd_data(0x00); + + lcd_cmd(0xF8); + lcd_data(0x00); + lcd_data(0x15); + lcd_data(0x01); + lcd_data(0x08); + lcd_data(0x15); + lcd_data(0x22); + lcd_data(0x25); + lcd_data(0x28); + lcd_data(0x14); + lcd_data(0x13); + lcd_data(0x10); + lcd_data(0x11); + lcd_data(0x09); + lcd_data(0x24); + lcd_data(0x28); + + lcd_cmd(0xF9); + lcd_data(0x00); + lcd_data(0x15); + lcd_data(0x01); + lcd_data(0x08); + lcd_data(0x15); + lcd_data(0x22); + lcd_data(0x25); + lcd_data(0x28); + lcd_data(0x14); + lcd_data(0x13); + lcd_data(0x10); + lcd_data(0x11); + lcd_data(0x09); + lcd_data(0x24); + lcd_data(0x28); + + lcd_cmd(0xFC); + lcd_data(0x00); + lcd_data(0x15); + lcd_data(0x01); + lcd_data(0x08); + lcd_data(0x15); + lcd_data(0x22); + lcd_data(0x25); + lcd_data(0x28); + lcd_data(0x14); + lcd_data(0x13); + lcd_data(0x10); + lcd_data(0x11); + lcd_data(0x09); + lcd_data(0x24); + lcd_data(0x28); + + lcd_cmd(0x36); + lcd_data(0x48); + + lcd_cmd(0x3A); + lcd_data(0x55); + + lcd_cmd(0x2A); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0x01); + lcd_data(0x3F); + + lcd_cmd(0x2B); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0xEF); + + lcd_cmd(0x11); + + mdelay(120); + + lcd_cmd(0x29); + + lcd_cmd(0x2C); + + for (x = 0; x < LCD_WIDTH; x++) + for(y=0; y < LCD_HEIGHT; y++) + lcd_data(0x00); + + display_on = true; +} + +void lcd_enable (bool on) +{ + if (on == display_on) + return; + + lcdctrl_bypass(1); + LCDC_CTRL |= RGB24B; + + if (on) { + lcd_cmd(0x11); + mdelay(120); + lcd_cmd(0x29); + lcd_cmd(0x2C); + } else { + lcd_cmd(0x28); + mdelay(120); + lcd_cmd(0x10); + } + + display_on = on; + LCDC_CTRL &= ~RGB24B; +} + +void lcd_set_gram_area(int x_start, int y_start, + int x_end, int y_end) +{ + lcdctrl_bypass(1); + LCDC_CTRL |= RGB24B; + + lcd_cmd(0x2A); + lcd_data((x_start&0xff00)>>8); + lcd_data(x_start&0x00ff); + lcd_data((x_end&0xff00)>>8); + lcd_data(x_end&0x00ff); + + lcd_cmd(0x2B); + lcd_data((y_start&0xff00)>>8); + lcd_data(y_start&0x00ff); + lcd_data((y_end&0xff00)>>8); + lcd_data(y_end&0x00ff); + + lcd_cmd(0x2C); + + LCDC_CTRL &= ~RGB24B; +} + +bool lcd_active() +{ + return display_on; +} + +/* Blit a YUV bitmap directly to the LCD */ +void lcd_blit_yuv(unsigned char * const src[3], + int src_x, int src_y, int stride, + int x, int y, int width, int height) +{ + (void)src; + (void)src_x; + (void)src_y; + (void)stride; + (void)x; + (void)y; + (void)width; + (void)height; +} diff --git a/firmware/target/arm/rk27xx/ihifi2/lcd-ihifi800.c b/firmware/target/arm/rk27xx/ihifi2/lcd-ihifi800.c new file mode 100644 index 0000000000..821b52dcb6 --- /dev/null +++ b/firmware/target/arm/rk27xx/ihifi2/lcd-ihifi800.c @@ -0,0 +1,228 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 "config.h" +#include "kernel.h" +#include "lcd.h" +#include "system.h" +#include "cpu.h" +#include "lcdif-rk27xx.h" + +static bool display_on = false; + +void lcd_display_init(void) +{ + unsigned int x, y; + + lcd_cmd(0xEF); + lcd_data(0x03); + lcd_data(0x80); + lcd_data(0x02); + + lcd_cmd(0xCF); + lcd_data(0x00); + lcd_data(0xC1); + lcd_data(0x30); + + lcd_cmd(0xED); + lcd_data(0x67); + lcd_data(0x03); + lcd_data(0x12); + lcd_data(0x81); + + lcd_cmd(0xE8); + lcd_data(0x85); + lcd_data(0x11); + lcd_data(0x79); + + lcd_cmd(0xCB); + lcd_data(0x39); + lcd_data(0x2C); + lcd_data(0x00); + lcd_data(0x34); + lcd_data(0x06); + + lcd_cmd(0xF7); + lcd_data(0x20); + + lcd_cmd(0xEA); + lcd_data(0x00); + lcd_data(0x00); + + lcd_cmd(0xC0); + lcd_data(0x1D); + + lcd_cmd(0xC1); + lcd_data(0x12); + + lcd_cmd(0xC5); + lcd_data(0x44); + lcd_data(0x3C); + + lcd_cmd(0xC7); + lcd_data(0x88); + + lcd_cmd(0x3A); + lcd_data(0x55); + + lcd_cmd(0x36); + lcd_data(0x0C); + + lcd_cmd(0xB1); + lcd_data(0x00); + lcd_data(0x17); + + lcd_cmd(0xB6); + lcd_data(0x0A); + lcd_data(0xA2); + + lcd_cmd(0xF2); + lcd_data(0x00); + + lcd_cmd(0x26); + lcd_data(0x01); + + lcd_cmd(0xE0); + lcd_data(0x0F); + lcd_data(0x22); + lcd_data(0x1C); + lcd_data(0x1B); + lcd_data(0x08); + lcd_data(0x0F); + lcd_data(0x48); + lcd_data(0xB8); + lcd_data(0x34); + lcd_data(0x05); + lcd_data(0x0C); + lcd_data(0x09); + lcd_data(0x0F); + lcd_data(0x07); + lcd_data(0x00); + + lcd_cmd(0xE1); + lcd_data(0x00); + lcd_data(0x23); + lcd_data(0x24); + lcd_data(0x07); + lcd_data(0x10); + lcd_data(0x07); + lcd_data(0x38); + lcd_data(0x47); + lcd_data(0x4B); + lcd_data(0x0A); + lcd_data(0x13); + lcd_data(0x06); + lcd_data(0x30); + lcd_data(0x38); + lcd_data(0x0F); + + lcd_cmd(0x2A); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0xEF); + + lcd_cmd(0x2B); + lcd_data(0x00); + lcd_data(0x00); + lcd_data(0x01); + lcd_data(0x3F); + + lcd_cmd(0x11); + + mdelay(120); + + lcd_cmd(0x29); + + lcd_cmd(0x2C); + + for (x = 0; x < LCD_WIDTH; x++) + for(y=0; y < LCD_HEIGHT; y++) + lcd_data(0x00); + + display_on = true; +} + +void lcd_enable (bool on) +{ + if (on == display_on) + return; + + lcdctrl_bypass(1); + LCDC_CTRL |= RGB24B; + + if (on) { + lcd_cmd(0x11); + mdelay(120); + lcd_cmd(0x29); + lcd_cmd(0x2C); + } else { + lcd_cmd(0x28); + mdelay(120); + lcd_cmd(0x10); + } + + display_on = on; + LCDC_CTRL &= ~RGB24B; +} + +void lcd_set_gram_area(int x_start, int y_start, + int x_end, int y_end) +{ + lcdctrl_bypass(1); + LCDC_CTRL |= RGB24B; + + lcd_cmd(0x2A); + lcd_data((x_start&0xff00)>>8); + lcd_data(x_start&0x00ff); + lcd_data((x_end&0xff00)>>8); + lcd_data(x_end&0x00ff); + + lcd_cmd(0x2B); + lcd_data((y_start&0xff00)>>8); + lcd_data(y_start&0x00ff); + lcd_data((y_end&0xff00)>>8); + lcd_data(y_end&0x00ff); + + lcd_cmd(0x2C); + + LCDC_CTRL &= ~RGB24B; +} + +bool lcd_active() +{ + return display_on; +} + +/* Blit a YUV bitmap directly to the LCD */ +void lcd_blit_yuv(unsigned char * const src[3], + int src_x, int src_y, int stride, + int x, int y, int width, int height) +{ + (void)src; + (void)src_x; + (void)src_y; + (void)stride; + (void)x; + (void)y; + (void)width; + (void)height; +} diff --git a/firmware/target/arm/rk27xx/ihifi2/lcd-target.h b/firmware/target/arm/rk27xx/ihifi2/lcd-target.h new file mode 100644 index 0000000000..6b2aa5d8a5 --- /dev/null +++ b/firmware/target/arm/rk27xx/ihifi2/lcd-target.h @@ -0,0 +1,26 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * + * 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 LCD_TARGET_H +#define LCD_TARGET_H + +#define LCD_DATABUS_WIDTH LCDIF_16BIT +#endif diff --git a/firmware/target/arm/rk27xx/ihifi2/power-ihifi.c b/firmware/target/arm/rk27xx/ihifi2/power-ihifi.c new file mode 100644 index 0000000000..cc489eacfe --- /dev/null +++ b/firmware/target/arm/rk27xx/ihifi2/power-ihifi.c @@ -0,0 +1,53 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 +#include "config.h" +#include "inttypes.h" +#include "power.h" +#include "panic.h" +#include "system.h" +#include "usb_core.h" /* for usb_charging_maxcurrent_change */ +#include "adc.h" + +void power_off(void) +{ + GPIO_PCCON &= ~(1<<0); + while(1); +} + +void power_init(void) +{ + GPIO_PCDR |= (1<<0); + GPIO_PCCON |= (1<<0); + + GPIO_PADR &= ~(1<<7); /* MUTE */ + GPIO_PACON |= (1<<7); +} + +unsigned int power_input_status(void) +{ + return (usb_detect() == USB_INSERTED) ? POWER_INPUT_MAIN_CHARGER : POWER_INPUT_NONE; +} + +bool charging_state(void) +{ + return (adc_read(ADC_EXTRA) < 512); +} diff --git a/firmware/target/arm/rk27xx/ihifi2/powermgmt-ihifi770.c b/firmware/target/arm/rk27xx/ihifi2/powermgmt-ihifi770.c new file mode 100644 index 0000000000..b0ff4f5a7b --- /dev/null +++ b/firmware/target/arm/rk27xx/ihifi2/powermgmt-ihifi770.c @@ -0,0 +1,64 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 "config.h" +#include "adc.h" +#include "adc-target.h" +#include "powermgmt.h" + +/* Battery voltage calculation and discharge/charge curves for the iHiFi 770 + + Battery voltage is calculated under the assumption that the adc full-scale + readout represents 3.00V and that the battery ADC channel is fed with + exactly half of the battery voltage (through a resistive divider). + Charge curve have not been calibrated yet. +*/ + +const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = +{ + /* 5% */ + 3500, +}; + +const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = +{ + /* 0% */ + 3300, +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ +const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +{ + { 3300, 3570, 3660, 3696, 3712, 3742, 3798, 3865, 3935, 4020, 4130 } +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ +const unsigned short percent_to_volt_charge[11] = + { 3300, 3570, 3660, 3696, 3712, 3742, 3798, 3865, 3935, 4020, 4130 }; + +/* full-scale ADC readout (2^10) in millivolt */ +#define BATTERY_SCALE_FACTOR 6296 + +/* Returns battery voltage from ADC [millivolts] */ +int _battery_voltage(void) +{ + return (adc_read(ADC_BATTERY) * BATTERY_SCALE_FACTOR) >> 10; +} diff --git a/firmware/target/arm/rk27xx/ihifi2/powermgmt-ihifi770c.c b/firmware/target/arm/rk27xx/ihifi2/powermgmt-ihifi770c.c new file mode 100644 index 0000000000..613553010b --- /dev/null +++ b/firmware/target/arm/rk27xx/ihifi2/powermgmt-ihifi770c.c @@ -0,0 +1,64 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 "config.h" +#include "adc.h" +#include "adc-target.h" +#include "powermgmt.h" + +/* Battery voltage calculation and discharge/charge curves for the iHiFi 770C + + Battery voltage is calculated under the assumption that the adc full-scale + readout represents 3.00V and that the battery ADC channel is fed with + exactly half of the battery voltage (through a resistive divider). + Charge curve have not been calibrated yet. +*/ + +const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = +{ + /* 5% */ + 3500, +}; + +const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = +{ + /* 0% */ + 3300, +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ +const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +{ + { 3300, 3570, 3660, 3696, 3712, 3742, 3798, 3865, 3935, 4020, 4130 } +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ +const unsigned short percent_to_volt_charge[11] = + { 3300, 3570, 3660, 3696, 3712, 3742, 3798, 3865, 3935, 4020, 4130 }; + +/* full-scale ADC readout (2^10) in millivolt */ +#define BATTERY_SCALE_FACTOR 6296 + +/* Returns battery voltage from ADC [millivolts] */ +int _battery_voltage(void) +{ + return (adc_read(ADC_BATTERY) * BATTERY_SCALE_FACTOR) >> 10; +} diff --git a/firmware/target/arm/rk27xx/ihifi2/powermgmt-ihifi800.c b/firmware/target/arm/rk27xx/ihifi2/powermgmt-ihifi800.c new file mode 100644 index 0000000000..26f4e47b93 --- /dev/null +++ b/firmware/target/arm/rk27xx/ihifi2/powermgmt-ihifi800.c @@ -0,0 +1,64 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Roman Stolyarov + * + * 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 "config.h" +#include "adc.h" +#include "adc-target.h" +#include "powermgmt.h" + +/* Battery voltage calculation and discharge/charge curves for the iHiFi 800 + + Battery voltage is calculated under the assumption that the adc full-scale + readout represents 3.00V and that the battery ADC channel is fed with + exactly half of the battery voltage (through a resistive divider). + Charge curve have not been calibrated yet. +*/ + +const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = +{ + /* 5% */ + 3628, +}; + +const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = +{ + /* 0% */ + 3300, +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ +const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +{ + { 3300, 3649, 3701, 3726, 3745, 3778, 3831, 3904, 3965, 4056, 4160 } +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ +const unsigned short percent_to_volt_charge[11] = + { 3300, 3649, 3701, 3726, 3745, 3778, 3831, 3904, 3965, 4056, 4160 }; + +/* full-scale ADC readout (2^10) in millivolt */ +#define BATTERY_SCALE_FACTOR 6296 + +/* Returns battery voltage from ADC [millivolts] */ +int _battery_voltage(void) +{ + return (adc_read(ADC_BATTERY) * BATTERY_SCALE_FACTOR) >> 10; +} diff --git a/firmware/target/arm/rk27xx/sd-rk27xx.c b/firmware/target/arm/rk27xx/sd-rk27xx.c index 2ddfd0cf0a..e5467058de 100644 --- a/firmware/target/arm/rk27xx/sd-rk27xx.c +++ b/firmware/target/arm/rk27xx/sd-rk27xx.c @@ -97,7 +97,7 @@ void INT_SD(void) /* get the status */ cmd_error = SD_CMDRES; semaphore_release(&command_completion_signal); - } + } /* data transfer status pending */ if(status & DATA_XFER_STAT) @@ -140,13 +140,15 @@ static void mmu_buff_reset(void) static inline bool card_detect_target(void) { -#if defined(RK27_GENERIC) -/* My generic device uses PC7 pin, active low */ +#if defined(RK27_GENERIC) || defined(IHIFI770) || defined(IHIFI770C) || defined(IHIFI800) + /* PC7, active low */ return !(GPIO_PCDR & 0x80); #elif defined(HM60X) || defined(HM801) + /* PF2, active low */ return !(GPIO_PFDR & (1<<2)); #elif defined(MA9) || defined(MA9C) || defined(MA8) || defined(MA8C) - return (GPIO_PCDR & 0x80); + /* PC7, active high */ + return (GPIO_PCDR & (1<<7)); #elif defined(IHIFI760) || defined(IHIFI960) /* TODO: find out pin */ return true; @@ -190,7 +192,7 @@ static bool send_cmd(const int cmd, const int arg, const int res, #if 0 /* for some misterious reason the card does not report itself as being in TRAN * but transfers are successful. Rockchip OF does not check the card state - * after SELECT. I checked two different cards. + * after SELECT. I checked two different cards. */ static void print_card_status(void) { @@ -224,7 +226,7 @@ static int sd_wait_for_tran_state(void) { return 0; } - + if(TIME_AFTER(current_tick, timeout)) { return -10 * ((response >> 9) & 0xf); @@ -265,7 +267,7 @@ static int sd_init_card(void) /* CMD0 Go Idle */ if(!send_cmd(SD_GO_IDLE_STATE, 0, RES_NO, NULL)) return -1; - + sleep(1); /* CMD8 Check for v2 sd card. Must be sent before using ACMD41 @@ -671,7 +673,7 @@ int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count, #endif return ret; - + #endif /* defined(BOOTLOADER) */ } diff --git a/firmware/target/arm/rk27xx/usb-drv-rk27xx.c b/firmware/target/arm/rk27xx/usb-drv-rk27xx.c index badc3ab5ed..057ecf6ebc 100644 --- a/firmware/target/arm/rk27xx/usb-drv-rk27xx.c +++ b/firmware/target/arm/rk27xx/usb-drv-rk27xx.c @@ -28,37 +28,16 @@ #include "kernel.h" #include "panic.h" -//#include "usb-s3c6400x.h" - #include "usb_ch9.h" #include "usb_core.h" #include #include "power.h" +#define LOGF_ENABLE #include "logf.h" typedef volatile uint32_t reg32; -/* Bulk OUT: ep1, ep4, ep7, ep10, ep13 */ -#define BOUT_RXSTAT(ep_num) (*(reg32*)(AHB0_UDC+0x54+0x38*(ep_num/3))) -#define BOUT_RXCON(ep_num) (*(reg32*)(AHB0_UDC+0x58+0x38*(ep_num/3))) -#define BOUT_DMAOUTCTL(ep_num) (*(reg32*)(AHB0_UDC+0x5C+0x38*(ep_num/3))) -#define BOUT_DMAOUTLMADDR(ep_num) (*(reg32*)(AHB0_UDC+0x60+0x38*(ep_num/3))) - -/* Bulk IN: ep2, ep5, ep8, ep11, ep4 */ -#define BIN_TXSTAT(ep_num) (*(reg32*)(AHB0_UDC+0x64+0x38*(ep_num/3))) -#define BIN_TXCON(ep_num) (*(reg32*)(AHB0_UDC+0x68+0x38*(ep_num/3))) -#define BIN_TXBUF(ep_num) (*(reg32*)(AHB0_UDC+0x6C+0x38*(ep_num/3))) -#define BIN_DMAINCTL(ep_num) (*(reg32*)(AHB0_UDC+0x70+0x38*(ep_num/3))) -#define BIN_DMAINLMADDR(ep_num) (*(reg32*)(AHB0_UDC+0x74+0x38*(ep_num/3))) - -/* INTERRUPT IN: ep3, ep6, ep9, ep12, ep15 */ -#define IIN_TXSTAT(ep_num) (*(reg32*)(AHB0_UDC+0x78+0x38*((ep_num/3)-1))) -#define IIN_TXCON(ep_num) (*(reg32*)(AHB0_UDC+0x7C+0x38*((ep_num/3)-1))) -#define IIN_TXBUF(ep_num) (*(reg32*)(AHB0_UDC+0x80+0x38*((ep_num/3)-1))) -#define IIN_DMAINCTL(ep_num) (*(reg32*)(AHB0_UDC+0x84+0x38*((ep_num/3)-1))) -#define IIN_DMAINLMADDR(ep_num) (*(reg32*)(AHB0_UDC+0x88+0x38*((ep_num/3)-1))) - #ifdef LOGF_ENABLE #define XFER_DIR_STR(dir) ((dir) ? "IN" : "OUT") #define XFER_TYPE_STR(type) \ @@ -68,9 +47,12 @@ typedef volatile uint32_t reg32; ((type) == USB_ENDPOINT_XFER_INT ? "INTR" : "INVL")))) #endif -struct endpoint_t { +struct endpoint_t +{ + const int ep_num; /* EP number */ const int type; /* EP type */ const int dir; /* DIR_IN/DIR_OUT */ + volatile unsigned long *stat; /* RXSTAT/TXSTAT register */ bool allocated; /* flag to mark EPs taken */ volatile void *buf; /* tx/rx buffer address */ volatile int len; /* size of the transfer (bytes) */ @@ -79,110 +61,91 @@ struct endpoint_t { struct semaphore complete; /* semaphore for blocking transfers */ }; -#define EP_INIT(_type, _dir, _alloced, _buf, _len, _cnt, _block) \ - { .type = (_type), .dir = (_dir), .allocated = (_alloced), .buf = (_buf), \ - .len = (_len), .cnt = (_cnt), .block = (_block) } - -static struct endpoint_t ctrlep[2] = { - EP_INIT(USB_ENDPOINT_XFER_CONTROL, DIR_OUT, true, NULL, 0, 0, true), - EP_INIT(USB_ENDPOINT_XFER_CONTROL, DIR_IN, true, NULL, 0, 0, true), +/* compute RXCON address from RXSTAT, and so on */ +#define RXSTAT(endp) *((endp)->stat) +#define RXCON(endp) *(1 + (endp)->stat) +#define DMAOUTCTL(endp) *(2 + (endp)->stat) +#define DMAOUTLMADDR(endp) *(3 + (endp)->stat) +/* compute TXCON address from TXSTAT, and so on */ +#define TXSTAT(endp) *((endp)->stat) +#define TXCON(endp) *(1 + (endp)->stat) +#define TXBUF(endp) *(2 + (endp)->stat) +#define DMAINCTL(endp) *(3 + (endp)->stat) +#define DMAINLMADDR(endp) *(4 + (endp)->stat) + +#define ENDPOINT(num, type, dir, reg) \ + {num, USB_ENDPOINT_XFER_##type, USB_DIR_##dir, reg, false, NULL, 0, 0, true, {{0, 0}, 0, 0}} + +static struct endpoint_t ctrlep[2] = +{ + ENDPOINT(0, CONTROL, OUT, &RX0STAT), + ENDPOINT(0, CONTROL, IN, &TX0STAT), }; -static struct endpoint_t endpoints[16] = { - EP_INIT(USB_ENDPOINT_XFER_CONTROL, 3, true, NULL, 0, 0, true ), /* stub */ - EP_INIT(USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false ), /* BOUT1 */ - EP_INIT(USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false ), /* BIN2 */ - EP_INIT(USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false ), /* IIN3 */ - EP_INIT(USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false ), /* BOUT4 */ - EP_INIT(USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false ), /* BIN5 */ - EP_INIT(USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false ), /* IIN6 */ - EP_INIT(USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false ), /* BOUT7 */ - EP_INIT(USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false ), /* BIN8 */ - EP_INIT(USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false ), /* IIN9 */ - EP_INIT(USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false ), /* BOUT10 */ - EP_INIT(USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false ), /* BIN11 */ - EP_INIT(USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false ), /* IIN12 */ - EP_INIT(USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false ), /* BOUT13 */ - EP_INIT(USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false ), /* BIN14 */ - EP_INIT(USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false ), /* IIN15 */ +static struct endpoint_t endpoints[16] = +{ + ENDPOINT(0, CONTROL, OUT, NULL), /* stub */ + ENDPOINT(1, BULK, OUT, &RX1STAT), /* BOUT1 */ + ENDPOINT(2, BULK, IN, &TX2STAT), /* BIN2 */ + ENDPOINT(3, INT, IN, &TX3STAT), /* IIN3 */ + ENDPOINT(4, BULK, OUT, &RX4STAT), /* BOUT4 */ + ENDPOINT(5, BULK, IN, &TX5STAT), /* BIN5 */ + ENDPOINT(6, INT, IN, &TX6STAT), /* IIN6 */ + ENDPOINT(7, BULK, OUT, &RX7STAT), /* BOUT7 */ + ENDPOINT(8, BULK, IN, &TX8STAT), /* BIN8 */ + ENDPOINT(9, INT, IN, &TX9STAT), /* IIN9 */ + ENDPOINT(10, BULK, OUT, &RX10STAT), /* BOUT10 */ + ENDPOINT(11, BULK, IN, &TX11STAT), /* BIN11 */ + ENDPOINT(12, INT, IN, &TX12STAT), /* IIN12 */ + ENDPOINT(13, BULK, OUT, &RX13STAT), /* BOUT13 */ + ENDPOINT(14, BULK, IN, &TX14STAT), /* BIN14 */ + ENDPOINT(15, INT, IN, &TX15STAT), /* IIN15 */ }; +static volatile bool set_address = false; +static volatile bool set_configuration = false; + +#undef ENDPOINT + static void setup_received(void) { static uint32_t setup_data[2]; - + logf("udc: setup"); + /* copy setup data from packet */ setup_data[0] = SETUP1; setup_data[1] = SETUP2; - /* clear all pending control transfers - * do we need this here? - */ - /* pass setup data to the upper layer */ usb_core_control_request((struct usb_ctrlrequest*)setup_data); } -/* service ep0 IN transaction */ -static void ctr_write(void) +static int max_pkt_size(struct endpoint_t *endp) { - int xfer_size = (ctrlep[DIR_IN].cnt > 64) ? 64 : ctrlep[DIR_IN].cnt; - unsigned int timeout = current_tick + HZ/10; - - while (TX0BUF & TXFULL) /* TX0FULL flag */ + switch(endp->type) { - if(TIME_AFTER(current_tick, timeout)) - break; + case USB_ENDPOINT_XFER_CONTROL: return 64; + case USB_ENDPOINT_XFER_BULK: return usb_drv_port_speed() ? 512 : 64; + case USB_ENDPOINT_XFER_INT: return usb_drv_port_speed() ? 1024 : 64; + default: panicf("die"); return 0; } - - TX0STAT = xfer_size; /* size of the transfer */ - TX0DMALM_IADDR = (uint32_t)ctrlep[DIR_IN].buf; /* local buffer address */ - TX0DMAINCTL = DMA_START; /* start DMA */ - TX0CON &= ~TXNAK; /* clear NAK */ - - /* Decrement by max packet size is intentional. - * This way if we have final packet short one we will get negative len - * after transfer, which in turn indicates we *don't* need to send - * zero length packet. If the final packet is max sized packet we will - * get zero len after transfer which indicates we need to send - * zero length packet to signal host end of the transfer. - */ - ctrlep[DIR_IN].cnt -= 64; - ctrlep[DIR_IN].buf += xfer_size; -} - -static void ctr_read(void) -{ - int xfer_size = RX0STAT & 0xffff; - - /* clear NAK bit */ - RX0CON &= ~RXNAK; - - ctrlep[DIR_OUT].cnt -= xfer_size; - ctrlep[DIR_OUT].buf += xfer_size; - - RX0DMAOUTLMADDR = (uint32_t)ctrlep[DIR_OUT].buf; /* buffer address */ - RX0DMACTLO = DMA_START; /* start DMA */ } -static void blk_write(int ep) +static void ep_write(struct endpoint_t *endp) { - int ep_num = EP_NUM(ep); - int max = usb_drv_port_speed() ? 512 : 64; - int xfer_size = (endpoints[ep_num].cnt > max) ? max : endpoints[ep_num].cnt; + int xfer_size = MIN(max_pkt_size(endp), endp->cnt); unsigned int timeout = current_tick + HZ/10; - - while (BIN_TXBUF(ep_num) & TXFULL) /* TXFULL flag */ + + while(TXBUF(endp) & TXFULL) /* TXFULL flag */ { if(TIME_AFTER(current_tick, timeout)) break; } - - BIN_TXSTAT(ep_num) = xfer_size; /* size */ - BIN_DMAINLMADDR(ep_num) = (uint32_t)endpoints[ep_num].buf; /* buf address */ - BIN_DMAINCTL(ep_num) = DMA_START; /* start DMA */ - BIN_TXCON(ep_num) &= ~TXNAK; /* clear NAK */ - + + /* setup transfer size and DMA */ + TXSTAT(endp) = xfer_size; + DMAINLMADDR(endp) = (uint32_t)endp->buf; /* local buffer address */ + DMAINCTL(endp) = DMA_START; /* Decrement by max packet size is intentional. * This way if we have final packet short one we will get negative len * after transfer, which in turn indicates we *don't* need to send @@ -190,247 +153,141 @@ static void blk_write(int ep) * get zero len after transfer which indicates we need to send * zero length packet to signal host end of the transfer. */ - endpoints[ep_num].cnt -= max; - endpoints[ep_num].buf += xfer_size; + endp->cnt -= max_pkt_size(endp); + endp->buf += xfer_size; + /* clear NAK */ + TXCON(endp) &= ~TXNAK; } -static void blk_read(int ep) +static void ep_read(struct endpoint_t *endp) { - int ep_num = EP_NUM(ep); - int xfer_size = BOUT_RXSTAT(ep_num) & 0xffff; - - /* clear NAK bit */ - BOUT_RXCON(ep_num) &= ~RXNAK; - - endpoints[ep_num].cnt -= xfer_size; - endpoints[ep_num].buf += xfer_size; - - BOUT_DMAOUTLMADDR(ep_num) = (uint32_t)endpoints[ep_num].buf; - BOUT_DMAOUTCTL(ep_num) = DMA_START; -} - -static void int_write(int ep) -{ - int ep_num = EP_NUM(ep); - int max = usb_drv_port_speed() ? 1024 : 64; - int xfer_size = (endpoints[ep_num].cnt > max) ? max : endpoints[ep_num].cnt; - unsigned int timeout = current_tick + HZ/10; - - while (IIN_TXBUF(ep_num) & TXFULL) /* TXFULL flag */ - { - if(TIME_AFTER(current_tick, timeout)) - break; - } - - IIN_TXSTAT(ep_num) = xfer_size; /* size */ - IIN_DMAINLMADDR(ep_num) = (uint32_t)endpoints[ep_num].buf; /* buf address */ - IIN_DMAINCTL(ep_num) = DMA_START; /* start DMA */ - IIN_TXCON(ep_num) &= ~TXNAK; /* clear NAK */ - - /* Decrement by max packet size is intentional. - * This way if we have final packet short one we will get negative len - * after transfer, which in turn indicates we *don't* need to send - * zero length packet. If the final packet is max sized packet we will - * get zero len after transfer which indicates we need to send - * zero length packet to signal host end of the transfer. - */ - endpoints[ep_num].cnt -= max; - endpoints[ep_num].buf += xfer_size; + /* setup DMA */ + DMAOUTLMADDR(endp) = (uint32_t)endp->buf; /* local buffer address */ + DMAOUTCTL(endp) = DMA_START; + /* clear NAK */ + RXCON(endp) &= ~RXNAK; } -/* UDC ISR function */ -void INT_UDC(void) +static void in_intr(struct endpoint_t *endp) { - uint32_t txstat, rxstat; - int tmp, ep_num; - - /* read what caused UDC irq */ - uint32_t intsrc = INT2FLAG & 0x7fffff; - - if (intsrc & SETUP_INTR) /* setup interrupt */ + uint32_t txstat = TXSTAT(endp); + /* check if clear feature was sent by host */ + if(txstat & TXCFINT) { - setup_received(); + logf("clear_stall: %d", endp->ep_num); + usb_drv_stall(endp->ep_num, false, true); } - else if (intsrc & IN0_INTR) /* ep0 in interrupt */ + /* check if a transfer has finished */ + if(txstat & TXACK) { - txstat = TX0STAT; /* read clears flags */ - - /* TODO handle errors */ - if (txstat & TXACK) /* check TxACK flag */ + logf("udc: ack(%d)", endp->ep_num); + /* finished ? */ + if(endp->cnt <= 0) { - if (ctrlep[DIR_IN].cnt >= 0) - { - /* we still have data to send (or ZLP) */ - ctr_write(); - } - else - { - /* final ack received */ - usb_core_transfer_complete(0, /* ep */ - USB_DIR_IN, /* dir */ - 0, /* status */ - ctrlep[DIR_IN].len); /* length */ - - /* release semaphore for blocking transfer */ - if (ctrlep[DIR_IN].block) - semaphore_release(&ctrlep[DIR_IN].complete); - } + usb_core_transfer_complete(endp->ep_num, endp->dir, 0, endp->len); + /* release semaphore for blocking transfer */ + if(endp->block) + semaphore_release(&endp->complete); } + else /* more data to send */ + ep_write(endp); } - else if (intsrc & OUT0_INTR) /* ep0 out interrupt */ - { - rxstat = RX0STAT; +} - /* TODO handle errors */ - if (rxstat & RXACK) /* RxACK */ - { - if (ctrlep[DIR_OUT].cnt > 0) - ctr_read(); - else - usb_core_transfer_complete(0, /* ep */ - USB_DIR_OUT, /* dir */ - 0, /* status */ - ctrlep[DIR_OUT].len); /* length */ - } - } - else if (intsrc & USBRST_INTR) /* usb reset */ - { - usb_drv_init(); - } - else if (intsrc & RESUME_INTR) /* usb resume */ - { - TX0CON |= TXCLR; /* TxClr */ - TX0CON &= ~TXCLR; - RX0CON |= RXCLR; /* RxClr */ - RX0CON &= ~RXCLR; - } - else if (intsrc & SUSP_INTR) /* usb suspend */ +static void out_intr(struct endpoint_t *endp) +{ + uint32_t rxstat = RXSTAT(endp); + logf("udc: out intr(%d)", endp->ep_num); + /* check if clear feature was sent by host */ + if(rxstat & RXCFINT) { + logf("clear_stall: %d", endp->ep_num); + usb_drv_stall(endp->ep_num, false, false); } - else if (intsrc & CONN_INTR) /* usb connect */ + /* check if a transfer has finished */ + if(rxstat & RXACK) { + int xfer_size = rxstat & 0xffff; + endp->cnt -= xfer_size; + endp->buf += xfer_size; + logf("udc: ack(%d) -> %d/%d", endp->ep_num, xfer_size, endp->cnt); + /* finished ? */ + if(endp->cnt <= 0 || xfer_size < max_pkt_size(endp)) + usb_core_transfer_complete(endp->ep_num, endp->dir, 0, endp->len); + else + ep_read(endp); } - else - { - /* lets figure out which ep generated irq */ - tmp = intsrc >> 7; - for (ep_num=1; ep_num < 15; ep_num++) - { - tmp >>= ep_num; - if (tmp & 0x01) - break; - } - - if (intsrc & ((1<<8)|(1<<11)|(1<<14)|(1<<17)|(1<<20))) - { - /* bulk out */ - rxstat = BOUT_RXSTAT(ep_num); - - /* TODO handle errors */ - if (rxstat & (1<<18)) /* RxACK */ - { - if (endpoints[ep_num].cnt > 0) - blk_read(ep_num); - else - usb_core_transfer_complete(ep_num, /* ep */ - USB_DIR_OUT, /* dir */ - 0, /* status */ - endpoints[ep_num].len); /* length */ - } - } - else if (intsrc & ((1<<9)|(1<<12)|(1<<15)|(1<<18)|(1<<21))) +} + +static void udc_phy_reset(void) +{ + DEV_CTL |= SOFT_POR; + udelay(10000); /* min 10ms */ + DEV_CTL &= ~SOFT_POR; +} + +static void udc_soft_connect(void) +{ + DEV_CTL |= CSR_DONE | + DEV_SOFT_CN | + DEV_SELF_PWR; +} + +static void udc_helper(void) +{ + uint32_t dev_info = DEV_INFO; + + /* This polls for DEV_EN bit set in DEV_INFO register + * as well as tracks current requested configuration + * (DEV_INFO [11:8]). On state change it notifies usb stack + * about it. + */ + + /* SET ADDRESS request */ + if(!set_address) + if(dev_info & 0x7f) { - /* bulk in */ - txstat = BIN_TXSTAT(ep_num); - - /* TODO handle errors */ - if (txstat & (1<<18)) /* check TxACK flag */ - { - if (endpoints[ep_num].cnt >= 0) - { - /* we still have data to send (or ZLP) */ - blk_write(ep_num); - } - else - { - /* final ack received */ - usb_core_transfer_complete(ep_num, /* ep */ - USB_DIR_IN, /* dir */ - 0, /* status */ - endpoints[ep_num].len); /* length */ - - /* release semaphore for blocking transfer */ - if (endpoints[ep_num].block) - semaphore_release(&endpoints[ep_num].complete); - } - } + set_address = true; + usb_core_notify_set_address(dev_info & 0x7f); } - else if (intsrc & ((1<<10)|(1<13)|(1<<16)|(1<<19)|(1<<22))) + + /* SET CONFIGURATION request */ + if(!set_configuration) + if(dev_info & DEV_EN) { - /* int in */ - txstat = IIN_TXSTAT(ep_num); - - /* TODO handle errors */ - if (txstat & TXACK) /* check TxACK flag */ - { - if (endpoints[ep_num].cnt >= 0) - { - /* we still have data to send (or ZLP) */ - int_write(ep_num); - } - else - { - /* final ack received */ - usb_core_transfer_complete(ep_num, /* ep */ - USB_DIR_IN, /* dir */ - 0, /* status */ - endpoints[ep_num].len); /* length */ - - /* release semaphore for blocking transfer */ - if (endpoints[ep_num].block) - semaphore_release(&endpoints[ep_num].complete); - } - } + set_configuration = true; + usb_core_notify_set_config(((dev_info >> 7) & 0xf) + 1); } - } } /* return port speed FS=0, HS=1 */ int usb_drv_port_speed(void) { - return ((DEV_INFO & DEV_SPEED) == 0) ? 0 : 1; + return (DEV_INFO & DEV_SPEED) ? 0 : 1; } /* Reserve endpoint */ int usb_drv_request_endpoint(int type, int dir) { - int ep_num, ep_dir; - int ep_type; - - /* Safety */ - ep_dir = EP_DIR(dir); - ep_type = type & USB_ENDPOINT_XFERTYPE_MASK; + logf("req: %s %s", XFER_DIR_STR(dir), XFER_TYPE_STR(type)); - logf("req: %s %s", XFER_DIR_STR(ep_dir), XFER_TYPE_STR(ep_type)); - /* Find an available ep/dir pair */ - for (ep_num=1;ep_numtype == ep_type && - endpoint->dir == ep_dir && - !endpoint->allocated) - { - /* mark endpoint as taken */ - endpoint->allocated = true; - - /* enable interrupt from this endpoint */ - EN_INT |= (1<<(ep_num+7)); - - logf("add: ep%d %s", ep_num, XFER_DIR_STR(ep_dir)); - return (ep_num | (dir & USB_ENDPOINT_DIR_MASK)); - } + struct endpoint_t *endp = &endpoints[ep_num]; + + if(endp->allocated || endp->type != type || endp->dir != dir) + continue; + /* allocate endpoint and enable interrupt */ + endp->allocated = true; + if(dir == USB_DIR_IN) + TXCON(endp) = (ep_num << 8) | TXEPEN | TXNAK | TXACKINTEN | TXCFINTE; + else + RXCON(endp) = (ep_num << 8) | RXEPEN | RXNAK | RXACKINTEN | RXCFINTE | RXERRINTEN; + EN_INT |= 1 << (ep_num + 7); + + logf("add: ep%d %s", ep_num, XFER_DIR_STR(dir)); + return ep_num | dir; } return -1; } @@ -439,14 +296,12 @@ int usb_drv_request_endpoint(int type, int dir) void usb_drv_release_endpoint(int ep) { int ep_num = EP_NUM(ep); - int ep_dir = EP_DIR(ep); - (void) ep_dir; - logf("rel: ep%d %s", ep_num, XFER_DIR_STR(ep_dir)); + logf("rel: ep%d", ep_num); endpoints[ep_num].allocated = false; - + /* disable interrupt from this endpoint */ - EN_INT &= ~(1<<(ep_num+7)); + EN_INT &= ~(1 << (ep_num + 7)); } /* Set the address (usually it's in a register). @@ -463,39 +318,25 @@ void usb_drv_set_address(int address) static int _usb_drv_send(int endpoint, void *ptr, int length, bool block) { + logf("udc: send(%x)", endpoint); struct endpoint_t *ep; int ep_num = EP_NUM(endpoint); - + if (ep_num == 0) ep = &ctrlep[DIR_IN]; else ep = &endpoints[ep_num]; + /* for send transfers, make sure the data is committed */ + commit_discard_dcache_range(ptr, length); ep->buf = ptr; ep->len = ep->cnt = length; - - if (block) - ep->block = true; - else - ep->block = false; - - switch (ep->type) - { - case USB_ENDPOINT_XFER_CONTROL: - ctr_write(); - break; - - case USB_ENDPOINT_XFER_BULK: - blk_write(ep_num); - break; - - case USB_ENDPOINT_XFER_INT: - int_write(ep_num); - break; - } - - if (block) - /* wait for transfer to end */ + ep->block = block; + + ep_write(ep); + + /* wait for transfer to end */ + if(block) semaphore_wait(&ep->complete, TIMEOUT_BLOCK); return 0; @@ -516,28 +357,20 @@ int usb_drv_send_nonblocking(int endpoint, void *ptr, int length) /* Setup a receive transfer. (non blocking) */ int usb_drv_recv(int endpoint, void* ptr, int length) { + logf("udc: recv(%x)", endpoint); struct endpoint_t *ep; int ep_num = EP_NUM(endpoint); - - if (ep_num == 0) - { + + if(ep_num == 0) ep = &ctrlep[DIR_OUT]; - - ctr_read(); - } else - { ep = &endpoints[ep_num]; - - /* clear NAK bit */ - BOUT_RXCON(ep_num) &= ~RXNAK; - BOUT_DMAOUTLMADDR(ep_num) = (uint32_t)ptr; - BOUT_DMAOUTCTL(ep_num) = DMA_START; - } - + + /* for recv, discard the cache lines related to the buffer */ + commit_discard_dcache_range(ptr, length); ep->buf = ptr; ep->len = ep->cnt = length; - + ep_read(ep); return 0; } @@ -560,173 +393,54 @@ void usb_drv_set_test_mode(int mode) /* Check if endpoint is in stall state */ bool usb_drv_stalled(int endpoint, bool in) { - int ep_num = EP_NUM(endpoint); - - switch (endpoints[ep_num].type) - { - case USB_ENDPOINT_XFER_CONTROL: - if (in) - return (TX0CON & TXSTALL) ? true : false; - else - return (RX0CON & RXSTALL) ? true : false; - - break; + struct endpoint_t *endp = &endpoints[EP_NUM(endpoint)]; - case USB_ENDPOINT_XFER_BULK: - if (in) - return (BIN_TXCON(ep_num) & TXSTALL) ? true : false; - else - return (BOUT_RXCON(ep_num) & RXSTALL) ? true : false; - - break; - - case USB_ENDPOINT_XFER_INT: - if (in) - return (IIN_TXCON(ep_num) & TXSTALL) ? true : false; - else - return false; /* we don't have such endpoint anyway */ - - break; - } - - return false; + if(in) + return !!(TXCON(endp) & TXSTALL); + else + return !!(RXCON(endp) & RXSTALL); } /* Stall the endpoint. Usually set a flag in the controller */ void usb_drv_stall(int endpoint, bool stall, bool in) { - int ep_num = EP_NUM(endpoint); - - switch (endpoints[ep_num].type) + struct endpoint_t *endp = &endpoints[EP_NUM(endpoint)]; + if(in) { - case USB_ENDPOINT_XFER_CONTROL: - if (in) - { - if (stall) - TX0CON |= TXSTALL; - else - TX0CON &= ~TXSTALL; - } - else - { - if (stall) - RX0CON |= RXSTALL; - else - RX0CON &= ~RXSTALL; /* doc says Auto clear by UDC 2.0 */ - } - break; - - case USB_ENDPOINT_XFER_BULK: - if (in) - { - if (stall) - BIN_TXCON(ep_num) |= TXSTALL; - else - BIN_TXCON(ep_num) &= ~TXSTALL; - } - else - { - if (stall) - BOUT_RXCON(ep_num) |= RXSTALL; - else - BOUT_RXCON(ep_num) &= ~RXSTALL; - } - break; - - case USB_ENDPOINT_XFER_INT: - if (in) - { - if (stall) - IIN_TXCON(ep_num) |= TXSTALL; - else - IIN_TXCON(ep_num) &= ~TXSTALL; - } - break; + if(stall) + TXCON(endp) |= TXSTALL; + else + TXCON(endp) &= ~TXSTALL; + } + else + { + if(stall) + RXCON(endp) |= RXSTALL; + else + RXCON(endp) &= ~RXSTALL; } } /* one time init (once per connection) - basicaly enable usb core */ void usb_drv_init(void) { - int ep_num; - - /* enable USB clock */ - SCU_CLKCFG &= ~CLKCFG_UDC; - - /* 1. do soft disconnect */ - DEV_CTL = DEV_SELF_PWR; - - /* 2. do power on reset to PHY */ - DEV_CTL = DEV_SELF_PWR | - SOFT_POR; - - /* 3. wait more than 10ms */ - udelay(20000); - - /* 4. clear SOFT_POR bit */ - DEV_CTL &= ~SOFT_POR; - - /* 5. configure minimal EN_INT */ - EN_INT = EN_SUSP_INTR | /* Enable Suspend Interrupt */ - EN_RESUME_INTR | /* Enable Resume Interrupt */ - EN_USBRST_INTR | /* Enable USB Reset Interrupt */ - EN_OUT0_INTR | /* Enable OUT Token receive Interrupt EP0 */ - EN_IN0_INTR | /* Enable IN Token transmits Interrupt EP0 */ - EN_SETUP_INTR; /* Enable SETUP Packet Receive Interrupt */ - - /* 6. configure INTCON */ - INTCON = UDC_INTHIGH_ACT | /* interrupt high active */ - UDC_INTEN; /* enable EP0 interrupts */ - - /* 7. configure EP0 control registers */ - TX0CON = TXACKINTEN | /* Set as one to enable the EP0 tx irq */ - TXNAK; /* Set as one to response NAK handshake */ - - RX0CON = RXACKINTEN | - RXEPEN | /* Endpoint 0 Enable. When cleared the endpoint does - * not respond to an SETUP or OUT token - */ - - RXNAK; /* Set as one to response NAK handshake */ - - /* 8. write final bits to DEV_CTL */ - DEV_CTL = CSR_DONE | /* Configure CSR done */ - DEV_PHY16BIT | /* 16-bit data path enabled. udc_clk = 30MHz */ - DEV_SOFT_CN | /* Device soft connect */ - DEV_SELF_PWR; /* Device self power */ - /* init semaphore of ep0 */ semaphore_init(&ctrlep[DIR_OUT].complete, 1, 0); semaphore_init(&ctrlep[DIR_IN].complete, 1, 0); - - for (ep_num = 1; ep_num < USB_NUM_ENDPOINTS; ep_num++) - { + + for(int ep_num = 1; ep_num < USB_NUM_ENDPOINTS; ep_num++) semaphore_init(&endpoints[ep_num].complete, 1, 0); - - if (ep_num%3 == 0) /* IIN 3, 6, 9, 12, 15 */ - { - IIN_TXCON(ep_num) |= (ep_num<<8)|TXEPEN|TXNAK; /* ep_num, enable, NAK */ - } - else if (ep_num%3 == 1) /* BOUT 1, 4, 7, 10, 13 */ - { - BOUT_RXCON(ep_num) |= (ep_num<<8)|RXEPEN|RXNAK; /* ep_num, NAK, enable */ - } - else if (ep_num%3 == 2) /* BIN 2, 5, 8, 11, 14 */ - { - BIN_TXCON(ep_num) |= (ep_num<<8)|TXEPEN|TXNAK; /* ep_num, enable, NAK */ - } - } } /* turn off usb core */ void usb_drv_exit(void) { DEV_CTL = DEV_SELF_PWR; - + /* disable USB interrupts in interrupt controller */ INTC_IMR &= ~IRQ_ARM_UDC; INTC_IECR &= ~IRQ_ARM_UDC; - + /* we cannot disable UDC clock since this causes data abort * when reading DEV_INFO in order to check usb connect event */ @@ -734,9 +448,94 @@ void usb_drv_exit(void) int usb_detect(void) { - if (DEV_INFO & VBUS_STS) + if(DEV_INFO & VBUS_STS) return USB_INSERTED; else return USB_EXTRACTED; } +/* UDC ISR function */ +void INT_UDC(void) +{ + /* read what caused UDC irq */ + uint32_t intsrc = INT2FLAG & 0x7fffff; + + if(intsrc & USBRST_INTR) /* usb reset */ + { + logf("udc_int: reset, %ld", current_tick); + + EN_INT = EN_SUSP_INTR | /* Enable Suspend Irq */ + EN_RESUME_INTR | /* Enable Resume Irq */ + EN_USBRST_INTR | /* Enable USB Reset Irq */ + EN_OUT0_INTR | /* Enable OUT Token receive Irq EP0 */ + EN_IN0_INTR | /* Enable IN Token transmit Irq EP0 */ + EN_SETUP_INTR; /* Enable SETUP Packet Receive Irq */ + + INTCON = UDC_INTHIGH_ACT | /* interrupt high active */ + UDC_INTEN; /* enable EP0 irqs */ + + TX0CON = TXACKINTEN | /* Set as one to enable the EP0 tx irq */ + TXNAK; /* Set as one to response NAK handshake */ + + RX0CON = RXACKINTEN | + RXEPEN | /* Endpoint 0 Enable. When cleared the + * endpoint does not respond to an SETUP + * or OUT token */ + RXNAK; /* Set as one to response NAK handshake */ + + set_address = false; + set_configuration = false; + } + /* This needs to be processed AFTER usb reset */ + udc_helper(); + + if(intsrc & SETUP_INTR) /* setup interrupt */ + { + setup_received(); + } + if(intsrc & IN0_INTR) + { + /* EP0 IN done */ + in_intr(&ctrlep[DIR_IN]); + } + if(intsrc & OUT0_INTR) + { + /* EP0 OUT done */ + out_intr(&ctrlep[DIR_OUT]); + } + if(intsrc & USBRST_INTR) + { + /* usb reset */ + usb_drv_init(); + } + if(intsrc & RESUME_INTR) + { + /* usb resume */ + TX0CON |= TXCLR; /* TxClr */ + TX0CON &= ~TXCLR; + RX0CON |= RXCLR; /* RxClr */ + RX0CON &= ~RXCLR; + } + if(intsrc & SUSP_INTR) + { + /* usb suspend */ + } + if(intsrc & CONN_INTR) + { + /* usb connect */ + udc_phy_reset(); + udelay(10000); /* wait at least 10ms */ + udc_soft_connect(); + } + /* other endpoints */ + for(int ep_num = 1; ep_num < 16; ep_num++) + { + if(!(intsrc & (1 << (ep_num + 7)))) + continue; + struct endpoint_t *endp = &endpoints[ep_num]; + if(endp->dir == USB_DIR_IN) + in_intr(endp); + else + out_intr(endp); + } +} diff --git a/firmware/target/arm/rk27xx/usb-rk27xx.c b/firmware/target/arm/rk27xx/usb-rk27xx.c index 20bf867c8d..09c9090a3b 100644 --- a/firmware/target/arm/rk27xx/usb-rk27xx.c +++ b/firmware/target/arm/rk27xx/usb-rk27xx.c @@ -32,6 +32,20 @@ int usb_status = USB_EXTRACTED; void usb_init_device(void) { + /* enable UDC interrupt */ + INTC_IMR |= (1<<16); + INTC_IECR |= (1<<16); + + EN_INT = EN_SUSP_INTR | /* Enable Suspend Interrupt */ + EN_RESUME_INTR | /* Enable Resume Interrupt */ + EN_USBRST_INTR | /* Enable USB Reset Interrupt */ + EN_OUT0_INTR | /* Enable OUT Token receive Interrupt EP0 */ + EN_IN0_INTR | /* Enable IN Token transmits Interrupt EP0 */ + EN_SETUP_INTR; /* Enable SETUP Packet Receive Interrupt */ + + /* configure INTCON */ + INTCON = UDC_INTHIGH_ACT | /* interrupt high active */ + UDC_INTEN; /* enable EP0 interrupts */ } void usb_attach(void) diff --git a/firmware/target/hosted/sdl/sim-ui-defines.h b/firmware/target/hosted/sdl/sim-ui-defines.h index 0303ac8ca2..99ae062595 100644 --- a/firmware/target/hosted/sdl/sim-ui-defines.h +++ b/firmware/target/hosted/sdl/sim-ui-defines.h @@ -527,6 +527,28 @@ #define UI_HEIGHT 457 /* height of GUI window */ #define UI_LCD_POSX 34 #define UI_LCD_POSY 73 + +#elif defined(IHIFI770) +#define UI_TITLE "iHiFi 770" +#define UI_WIDTH 382 /* width of GUI window */ +#define UI_HEIGHT 690 /* height of GUI window */ +#define UI_LCD_POSX 32 +#define UI_LCD_POSY 86 + +#elif defined(IHIFI770C) +#define UI_TITLE "iHiFi 770C" +#define UI_WIDTH 382 /* width of GUI window */ +#define UI_HEIGHT 690 /* height of GUI window */ +#define UI_LCD_POSX 32 +#define UI_LCD_POSY 86 + +#elif defined(IHIFI800) +#define UI_TITLE "iHiFi 800" +#define UI_WIDTH 300 /* width of GUI window */ +#define UI_HEIGHT 670 /* height of GUI window */ +#define UI_LCD_POSX 26 +#define UI_LCD_POSY 40 + #elif defined(SIMULATOR) #error no UI defines #endif -- cgit v1.2.3