From 32f763c39a797221a6e850704feb3743bc104d8c Mon Sep 17 00:00:00 2001 From: Marcin Bukat Date: Mon, 17 Oct 2011 10:32:19 +0000 Subject: Add HiFiMAN HM-60x target(s). FS#12319 by Andrew Ryabinin with some (small) modification by me. This also splits rk27xx lcd driver into lcdif-rk27xx and lcd controller specific part. Some modifications to the pcm driver have been made to allow using codecs in slave mode (as TDA1543 used in hifiman is slave only i2s codec). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30765 a1c6a512-1295-4272-9138-f99709370657 --- apps/SOURCES | 4 +- apps/keymaps/keymap-hm60x.c | 88 ++++++ bootloader/SOURCES | 2 +- firmware/SOURCES | 14 +- firmware/drivers/audio/tda1543.c | 46 +++ firmware/export/audiohw.h | 2 + firmware/export/config.h | 4 + firmware/export/config/hifimanhm60x.h | 183 ++++++++++++ firmware/export/tda1543.h | 29 ++ firmware/target/arm/rk27xx/adc-target.h | 4 +- firmware/target/arm/rk27xx/debug-target.h | 4 + firmware/target/arm/rk27xx/hm60x/button-hm60x.c | 46 +++ firmware/target/arm/rk27xx/hm60x/button-target.h | 44 +++ firmware/target/arm/rk27xx/hm60x/lcd-hm60x.c | 148 ++++++++++ firmware/target/arm/rk27xx/hm60x/power-hm60x.c | 48 +++ firmware/target/arm/rk27xx/hm60x/powermgmt-hm60x.c | 66 +++++ firmware/target/arm/rk27xx/lcd-rk27xx.c | 328 --------------------- firmware/target/arm/rk27xx/lcdif-rk27xx.c | 161 ++++++++++ firmware/target/arm/rk27xx/lcdif-rk27xx.h | 11 + firmware/target/arm/rk27xx/pcm-rk27xx.c | 62 +++- .../arm/rk27xx/rk27generic/lcd-rk27generic.c | 211 +++++++++++++ tools/configure | 27 +- 22 files changed, 1194 insertions(+), 338 deletions(-) create mode 100644 apps/keymaps/keymap-hm60x.c create mode 100644 firmware/drivers/audio/tda1543.c create mode 100644 firmware/export/config/hifimanhm60x.h create mode 100644 firmware/export/tda1543.h create mode 100644 firmware/target/arm/rk27xx/hm60x/button-hm60x.c create mode 100644 firmware/target/arm/rk27xx/hm60x/button-target.h create mode 100644 firmware/target/arm/rk27xx/hm60x/lcd-hm60x.c create mode 100644 firmware/target/arm/rk27xx/hm60x/power-hm60x.c create mode 100644 firmware/target/arm/rk27xx/hm60x/powermgmt-hm60x.c delete mode 100644 firmware/target/arm/rk27xx/lcd-rk27xx.c create mode 100644 firmware/target/arm/rk27xx/lcdif-rk27xx.c create mode 100644 firmware/target/arm/rk27xx/lcdif-rk27xx.h create mode 100644 firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c diff --git a/apps/SOURCES b/apps/SOURCES index 443b42fedc..a08dc046c2 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -325,4 +325,6 @@ keymaps/keymap-sdl.c keymaps/keymap-fuzeplus.c #elif CONFIG_KEYPAD == RK27XX_GENERIC_PAD keymaps/keymap-rk27xx-generic.c -#endif +#elif CONFIG_KEYPAD == HM60X_PAD +keymaps/keymap-hm60x.c +#endif \ No newline at end of file diff --git a/apps/keymaps/keymap-hm60x.c b/apps/keymaps/keymap-hm60x.c new file mode 100644 index 0000000000..3f75ac82d4 --- /dev/null +++ b/apps/keymaps/keymap-hm60x.c @@ -0,0 +1,88 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 Andrew Ryabinin + * + * 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. + * + ****************************************************************************/ + +/* Button Code Definitions for HiFiMAN HM-601 reference design target */ + +#include "config.h" +#include "action.h" +#include "button.h" + +/* + * The format of the list is as follows + * { Action Code, Button code, Prereq button code } + * if there's no need to check the previous button's value, use BUTTON_NONE + * Insert LAST_ITEM_IN_LIST at the end of each mapping + */ +static const struct button_mapping button_context_standard[] = { + { ACTION_STD_PREV, BUTTON_UP, BUTTON_NONE }, + { ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_NEXT, BUTTON_DOWN, BUTTON_NONE }, + { ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + + { ACTION_STD_CONTEXT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY }, + { ACTION_STD_CANCEL, BUTTON_LEFT, BUTTON_NONE }, + { ACTION_STD_OK, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, + { ACTION_STD_MENU, BUTTON_RIGHT, BUTTON_NONE }, + + LAST_ITEM_IN_LIST +}; /* button_context_standard */ + +static const struct button_mapping button_context_wps[] = { + { ACTION_WPS_PLAY, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, + { ACTION_WPS_STOP, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY }, + { ACTION_WPS_SKIPPREV, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT }, + { ACTION_WPS_SEEKBACK, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_WPS_STOPSEEK, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT|BUTTON_REPEAT }, + { ACTION_WPS_SKIPNEXT, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT}, + { ACTION_WPS_SEEKFWD, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_WPS_STOPSEEK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT|BUTTON_REPEAT }, + + { ACTION_WPS_BROWSE, BUTTON_UP|BUTTON_REL, BUTTON_UP }, + { ACTION_WPS_CONTEXT, BUTTON_UP|BUTTON_REPEAT, BUTTON_UP }, + { ACTION_WPS_MENU, BUTTON_DOWN|BUTTON_REL, BUTTON_DOWN }, + { ACTION_WPS_QUICKSCREEN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_DOWN }, + + LAST_ITEM_IN_LIST +}; /* button_context_wps */ + + + +/* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */ +const struct button_mapping* get_context_mapping(int context) +{ + switch (context) + { + case CONTEXT_STD: + return button_context_standard; + case CONTEXT_WPS: + return button_context_wps; + + case CONTEXT_TREE: + case CONTEXT_LIST: + case CONTEXT_MAINMENU: + + case CONTEXT_SETTINGS: + case CONTEXT_SETTINGS|CONTEXT_REMOTE: + default: + return button_context_standard; + } + return button_context_standard; +} diff --git a/bootloader/SOURCES b/bootloader/SOURCES index bc9dc855b1..d1d659837d 100644 --- a/bootloader/SOURCES +++ b/bootloader/SOURCES @@ -67,7 +67,7 @@ main-pp.c show_logo.c #elif defined(MPIO_HD200) || defined(MPIO_HD300) mpio_hd200_hd300.c -#elif defined(RK27_GENERIC) +#elif defined(RK27_GENERIC) || defined(HM60X) rk27xx.c show_logo.c #endif diff --git a/firmware/SOURCES b/firmware/SOURCES index 367241db08..739f8e63db 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -355,6 +355,8 @@ drivers/audio/uda1341.c drivers/audio/cs42l55.c #elif defined (HAVE_RK27XX_CODEC) drivers/audio/rk27xx_codec.c +#elif defined (HAVE_TDA1543) +drivers/audio/tda1543.c #endif /* defined(HAVE_*) */ #elif defined(HAVE_SDL_AUDIO) drivers/audio/sdl.c @@ -1671,12 +1673,12 @@ target/arm/rk27xx/kernel-rk27xx.c target/arm/rk27xx/system-rk27xx.c target/arm/rk27xx/timer-rk27xx.c target/arm/rk27xx/backlight-rk27xx.c -target/arm/rk27xx/lcd-rk27xx.c target/arm/rk27xx/adc-rk27xx.c target/arm/rk27xx/sd-rk27xx.c target/arm/rk27xx/ftl-rk27xx.c target/arm/rk27xx/nand-rk27xx.c target/arm/rk27xx/usb-rk27xx.c +target/arm/rk27xx/lcdif-rk27xx.c #ifndef BOOTLOADER target/arm/rk27xx/pcm-rk27xx.c target/arm/rk27xx/debug-rk27xx.c @@ -1687,6 +1689,7 @@ target/arm/rk27xx/debug-rk27xx.c target/arm/rk27xx/rk27generic/button-rk27generic.c target/arm/rk27xx/rk27generic/powermgmt-rk27generic.c target/arm/rk27xx/rk27generic/power-rk27generic.c +target/arm/rk27xx/rk27generic/lcd-rk27generic.c #endif #endif @@ -1914,3 +1917,12 @@ target/hosted/android/app/button-application.c drivers/audio/android.c thread.c #endif + +#ifndef SIMULATOR +#if defined(HM60X) +target/arm/rk27xx/hm60x/button-hm60x.c +target/arm/rk27xx/hm60x/powermgmt-hm60x.c +target/arm/rk27xx/hm60x/power-hm60x.c +target/arm/rk27xx/hm60x/lcd-hm60x.c +#endif +#endif diff --git a/firmware/drivers/audio/tda1543.c b/firmware/drivers/audio/tda1543.c new file mode 100644 index 0000000000..ca51d95265 --- /dev/null +++ b/firmware/drivers/audio/tda1543.c @@ -0,0 +1,46 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * + * Copyright (c) 2011 Andrew Ryabinin + * + * 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 "audio.h" +#include "audiohw.h" + +const struct sound_settings_info audiohw_settings[] = { + [SOUND_VOLUME] = {"dB", 0, 1, -1, 0, 0}, + /* HAVE_SW_TONE_CONTROLS */ + [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0}, + [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0}, + [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, + [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, + [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, +}; + +void audiohw_preinit(void) { } + +void audiohw_postinit(void) { } + +void audiohw_close(void) { } + +void audiohw_set_frequency(int fsel) +{ + (void)fsel; +} diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h index 9956909b5d..e40ee6ee79 100644 --- a/firmware/export/audiohw.h +++ b/firmware/export/audiohw.h @@ -74,6 +74,8 @@ #include "cs42l55.h" #elif defined(HAVE_IMX233_CODEC) #include "imx233-codec.h" +#elif defined(HAVE_TDA1543) +#include "tda1543.h" #endif #if (CONFIG_PLATFORM & PLATFORM_HOSTED) /* #include gives errors in other code areas, diff --git a/firmware/export/config.h b/firmware/export/config.h index 1c55d232ef..0d0617bb13 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -140,6 +140,7 @@ #define MPIO_HD300_PAD 47 #define SANSA_FUZEPLUS_PAD 48 #define RK27XX_GENERIC_PAD 49 +#define HM60X_PAD 50 /* CONFIG_REMOTE_KEYPAD */ #define H100_REMOTE 1 @@ -226,6 +227,7 @@ #define LCD_FUZEPLUS 41 #define LCD_SPFD5420A 42 /* rk27xx */ #define LCD_CLIPZIP 43 /* as used by the Sandisk Sansa Clip Zip */ +#define LCD_HX8340B 44 /* as used by the HiFiMAN HM-601/HM-602/HM-801 */ /* LCD_PIXELFORMAT */ #define HORIZONTAL_PACKING 1 @@ -459,6 +461,8 @@ Lyre prototype 1 */ #include "config/mpiohd300.h" #elif defined(RK27_GENERIC) #include "config/rk27generic.h" +#elif defined(HM60X) +#include "config/hifimanhm60x.h" #elif defined(SDLAPP) #include "config/sdlapp.h" #elif defined(ANDROID) diff --git a/firmware/export/config/hifimanhm60x.h b/firmware/export/config/hifimanhm60x.h new file mode 100644 index 0000000000..88af364bc9 --- /dev/null +++ b/firmware/export/config/hifimanhm60x.h @@ -0,0 +1,183 @@ +/* + * This config file is for HiFiMAN HM-60x reference design + */ +#define TARGET_TREE /* this target is using the target tree system */ + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 79 + +#define MODEL_NAME "HiFiMAN HM-60x" + +/* 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_TDA1543 +#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 have access to the pitchscreen */ +#define HAVE_PITCHSCREEN + +/* 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 + +/* commented for now */ +/* #define HAVE_HOTSWAP */ + +#define NUM_DRIVES 2 +#define SECTOR_SIZE 512 + +/* for small(ish) SD cards */ +#define HAVE_FAT16SUPPORT + +/* LCD dimensions */ +#define LCD_WIDTH 220 +#define LCD_HEIGHT 176 +#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 HM60X_PAD + +/* Define this to enable morse code input */ +#define HAVE_MORSE_INPUT + +/* 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 CONFIG_LCD LCD_HX8340B + +/* 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 20 +#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 600 /* default battery capacity */ +#define BATTERY_CAPACITY_MIN 300 /* min. capacity selectable */ +#define BATTERY_CAPACITY_MAX 600 /* max. capacity selectable */ +#define BATTERY_CAPACITY_INC 10 /* capacity increment */ +#define BATTERY_TYPES_COUNT 1 /* only one type */ + +/* 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 + +/* USB On-the-go */ +#define CONFIG_USBOTG USBOTG_RK27XX + +/* enable these for the experimental usb stack */ +#define HAVE_USBSTACK + +#define USE_ROCKBOX_USB +#define USB_VENDOR_ID 0x071b +#define USB_PRODUCT_ID 0x3202 +#define HAVE_BOOTLOADER_USB_MODE + +/* Define this if your LCD can set contrast */ +/* #define HAVE_LCD_CONTRAST */ + +/* The exact type of CPU */ +#define CONFIG_CPU RK27XX + +/* I2C interface */ +#define CONFIG_I2C I2C_RK27XX + +/* Define this to the CPU frequency */ +#define CPU_FREQ 200000000 + +/* define this if the hardware can be powered off while charging */ +/* #define HAVE_POWEROFF_WHILE_CHARGING */ + +/* 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 */ + +#define BOOTFILE_EXT "rk27" +#define BOOTFILE "rockbox." BOOTFILE_EXT +#define BOOTDIR "/.rockbox" diff --git a/firmware/export/tda1543.h b/firmware/export/tda1543.h new file mode 100644 index 0000000000..6561f0823a --- /dev/null +++ b/firmware/export/tda1543.h @@ -0,0 +1,29 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * + * Copyright (c) 2011 Andrew Ryabinin + * + * 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 __TDA1543_H_ +#define __TDA1543_H_ + +#define VOLUME_MIN -1 +#define VOLUME_MAX 0 + + +#endif /* __TDA1543_H_ */ diff --git a/firmware/target/arm/rk27xx/adc-target.h b/firmware/target/arm/rk27xx/adc-target.h index f6b8c98bb9..c359f3d7df 100644 --- a/firmware/target/arm/rk27xx/adc-target.h +++ b/firmware/target/arm/rk27xx/adc-target.h @@ -24,8 +24,8 @@ #define NUM_ADC_CHANNELS 4 #define ADC_BATTERY 0 -#define ADC_UNKNOWN_1 1 -#define ADC_UNKNOWN_2 2 +#define ADC_BUTTONS 1 +#define ADC_UNKNOWN 2 #define ADC_VREF 3 /* that is what datasheet says */ #define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */ diff --git a/firmware/target/arm/rk27xx/debug-target.h b/firmware/target/arm/rk27xx/debug-target.h index a507e96fdc..c083b9282a 100644 --- a/firmware/target/arm/rk27xx/debug-target.h +++ b/firmware/target/arm/rk27xx/debug-target.h @@ -24,7 +24,11 @@ #include +#ifdef RK27_GENERIC #define DEBUG_CANCEL BUTTON_VOL +#elif defined(HM60X) +#define DEBUG_CANCEL BUTTON_LEFT +#endif bool dbg_hw_info(void); bool dbg_ports(void); diff --git a/firmware/target/arm/rk27xx/hm60x/button-hm60x.c b/firmware/target/arm/rk27xx/hm60x/button-hm60x.c new file mode 100644 index 0000000000..eaadaa131c --- /dev/null +++ b/firmware/target/arm/rk27xx/hm60x/button-hm60x.c @@ -0,0 +1,46 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 Andrew Ryabinin + * + * 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 "button.h" +#include "adc.h" + +void button_init_device(void) { + /* setup button gpio as input */ + GPIO_PCCON &= ~(POWEROFF_BUTTON); +} + +int button_read_device(void) { + int adc_val = adc_read(ADC_BUTTONS); + if (adc_val < 30) { + return BUTTON_UP | (GPIO_PCDR & POWEROFF_BUTTON); + } else if (adc_val < 250) { + return BUTTON_RIGHT | (GPIO_PCDR & POWEROFF_BUTTON); + } else if (adc_val < 380) { + return BUTTON_LEFT | (GPIO_PCDR & POWEROFF_BUTTON); + } else if (adc_val < 450) { + return BUTTON_DOWN | (GPIO_PCDR & POWEROFF_BUTTON); + } else if (adc_val < 560) { + return BUTTON_PLAY | (GPIO_PCDR & POWEROFF_BUTTON); + } + return (GPIO_PCDR & POWEROFF_BUTTON); +} diff --git a/firmware/target/arm/rk27xx/hm60x/button-target.h b/firmware/target/arm/rk27xx/hm60x/button-target.h new file mode 100644 index 0000000000..0209e0637d --- /dev/null +++ b/firmware/target/arm/rk27xx/hm60x/button-target.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 Andrew Ryabinin + * + * 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_ + +#include +#include "config.h" + +void button_init_device(void); +int button_read_device(void); + + +#define BUTTON_UP 0x00000001 +#define BUTTON_DOWN 0x00000004 +#define BUTTON_LEFT 0x00000008 +#define BUTTON_RIGHT 0x00000010 +#define BUTTON_PLAY 0x00000020 + + +#define BUTTON_REMOTE 0 + + +#define POWEROFF_BUTTON 0x02 +#define POWEROFF_COUNT 30 + +#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/arm/rk27xx/hm60x/lcd-hm60x.c b/firmware/target/arm/rk27xx/hm60x/lcd-hm60x.c new file mode 100644 index 0000000000..932154da8d --- /dev/null +++ b/firmware/target/arm/rk27xx/hm60x/lcd-hm60x.c @@ -0,0 +1,148 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 Andrew Ryabinin + * + * + * 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" + + +/* TODO */ +static void lcd_sleep(unsigned int sleep) +{ + (void)sleep; +} + +void lcd_display_init() +{ + unsigned int x, y; + + /* Driving ability setting */ + lcd_write_reg(0x60, 0x00); + lcd_write_reg(0x61, 0x06); + lcd_write_reg(0x62, 0x00); + lcd_write_reg(0x63, 0xC8); + + /* Gamma 2.2 Setting */ + lcd_write_reg(0x40, 0x00); + lcd_write_reg(0x41, 0x40); + lcd_write_reg(0x42, 0x45); + lcd_write_reg(0x43, 0x01); + lcd_write_reg(0x44, 0x60); + lcd_write_reg(0x45, 0x05); + lcd_write_reg(0x46, 0x0C); + lcd_write_reg(0x47, 0xD1); + lcd_write_reg(0x48, 0x05); + + lcd_write_reg(0x50, 0x75); + lcd_write_reg(0x51, 0x01); + lcd_write_reg(0x52, 0x67); + lcd_write_reg(0x53, 0x14); + lcd_write_reg(0x54, 0xF2); + lcd_write_reg(0x55, 0x07); + lcd_write_reg(0x56, 0x03); + lcd_write_reg(0x57, 0x49); + + /* Power voltage setting */ + lcd_write_reg(0x1F, 0x03); + lcd_write_reg(0x20, 0x00); + lcd_write_reg(0x24, 0x28); + lcd_write_reg(0x25, 0x45); + + lcd_write_reg(0x23, 0x2F); + + /* Power on setting */ + lcd_write_reg(0x18, 0x44); + lcd_write_reg(0x21, 0x01); + lcd_write_reg(0x01, 0x00); + lcd_write_reg(0x1C, 0x03); + lcd_write_reg(0x19, 0x06); + udelay(5); + + /* Display on setting */ + lcd_write_reg(0x26, 0x84); + udelay(40); + lcd_write_reg(0x26, 0xB8); + udelay(40); + lcd_write_reg(0x26, 0xBC); + udelay(40); + + /* Memmory access setting */ + lcd_write_reg(0x16, 0x48); + /* Setup 16bit mode */ + lcd_write_reg(0x17, 0x05); + + /* Set GRAM area */ + lcd_write_reg(0x02, 0x00); + lcd_write_reg(0x03, 0x00); + lcd_write_reg(0x04, 0x00); + lcd_write_reg(0x05, LCD_HEIGHT - 1); + lcd_write_reg(0x06, 0x00); + lcd_write_reg(0x07, 0x00); + lcd_write_reg(0x08, 0x00); + lcd_write_reg(0x09, LCD_WIDTH - 1); + + /* Start GRAM write */ + lcd_cmd(0x22); + + for (x=0; x ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright © 2009 Bertrik Sikken + * + * 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 */ + +void power_off(void) +{ + +} + +void power_init(void) +{ + GPIO_PCDR |= (1<<0); + GPIO_PCCON |= (1<<0); +} + +unsigned int power_input_status(void) +{ + return (usb_detect() == USB_INSERTED) ? POWER_INPUT_MAIN_CHARGER : POWER_INPUT_NONE; +} + +bool charging_state(void) +{ + return true; +} diff --git a/firmware/target/arm/rk27xx/hm60x/powermgmt-hm60x.c b/firmware/target/arm/rk27xx/hm60x/powermgmt-hm60x.c new file mode 100644 index 0000000000..7b5b171ccb --- /dev/null +++ b/firmware/target/arm/rk27xx/hm60x/powermgmt-hm60x.c @@ -0,0 +1,66 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright © 2009 Bertrik Sikken + * + * 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 Meizu M3. + + 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). + Discharge and charge curves have not been calibrated yet. +*/ + +const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = +{ + /* TODO: this is just an initial guess */ + 3400 +}; + +const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = +{ + /* TODO: this is just an initial guess */ + 3300 +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ +const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +{ + /* TODO: simple uncalibrated curve, linear except for first 10% */ + { 3300, 3600, 3665, 3730, 3795, 3860, 3925, 3990, 4055, 4120, 4185 } +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ +const unsigned short percent_to_volt_charge[11] = + /* TODO: simple uncalibrated curve, linear except for first 10% */ + { 3300, 3600, 3665, 3730, 3795, 3860, 3925, 3990, 4055, 4120, 4185 }; + +/* full-scale ADC readout (2^10) in millivolt */ +#define BATTERY_SCALE_FACTOR 6000 + +/* Returns battery voltage from ADC [millivolts] */ +unsigned int battery_adc_voltage(void) +{ + return (adc_read(ADC_BATTERY) * BATTERY_SCALE_FACTOR) >> 10; +} diff --git a/firmware/target/arm/rk27xx/lcd-rk27xx.c b/firmware/target/arm/rk27xx/lcd-rk27xx.c deleted file mode 100644 index fda95e3174..0000000000 --- a/firmware/target/arm/rk27xx/lcd-rk27xx.c +++ /dev/null @@ -1,328 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2011 Marcin Bukat - * - * 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 "spfd5420a.h" - -static inline void delay_nop(int cycles) -{ - asm volatile ("1: subs %[n], %[n], #1 \n\t" - " bne 1b" - : - : [n] "r" (cycles)); -} - -static unsigned int lcd_data_transform(unsigned int data) -{ - /* 18 bit interface */ - unsigned int r, g, b; - r = (data & 0x0000fc00)<<8; - /* g = ((data & 0x00000300) >> 2) | ((data & 0x000000e0) >> 3); */ - g = ((data & 0x00000300) << 6) | ((data & 0x000000e0) << 5); - b = (data & 0x00000001f) << 3; - - return (r | g | b); -} - -/* converts RGB565 pixel into internal lcd bus format */ -static unsigned int lcd_pixel_transform(unsigned short rgb565) -{ - unsigned int r, g, b; - b = rgb565 & 0x1f; - g = (rgb565 >> 5) & 0x3f; - r = (rgb565 >> 11) & 0x1f; - - return r<<19 | g<<10 | b<<3; -} - -static void lcd_cmd(unsigned int cmd) -{ - LCD_COMMAND = lcd_data_transform(cmd); -} - -static void lcd_data(unsigned int data) -{ - LCD_DATA = lcd_data_transform(data); -} - -static void lcd_write_reg(unsigned int reg, unsigned int val) -{ - lcd_cmd(reg); - lcd_data(val); -} - -static void lcdctrl_bypass(unsigned int on_off) -{ - while (!(LCDC_STA & LCDC_MCU_IDLE)); - - if (on_off) - MCU_CTRL |= MCU_CTRL_BYPASS; - else - MCU_CTRL &= ~MCU_CTRL_BYPASS; -} - -/* This part is unclear. I am unable to use buffered/FIFO based writes - * to lcd. Depending on settings of IF I get various patterns on display - * but not what I want to display apparently. - */ -static void lcdctrl_init(void) -{ - /* alpha b111 - * stop at current frame complete - * MCU mode - * 24b RGB - */ - LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B; - MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS; - - HOR_ACT = 400 + 3; /* define horizonatal active region */ - VERT_ACT = 240; /* define vertical active region */ - VERT_PERIOD = 0xfff; /* CSn/WEn/RDn signal timings */ - - LINE0_YADDR = LINE_ALPHA_EN | 0x7fe; - LINE1_YADDR = LINE_ALPHA_EN | ((1 * 400) - 2); - LINE2_YADDR = LINE_ALPHA_EN | ((2 * 400) - 2); - LINE3_YADDR = LINE_ALPHA_EN | ((3 * 400) - 2); - - LINE0_UVADDR = 0x7fe + 1; - LINE1_UVADDR = ((1 * 400) - 2 + 1); - LINE2_UVADDR = ((2 * 400) - 2 + 1); - LINE3_UVADDR = ((3 * 400) - 2 + 1); - -#if 0 - LINE0_YADDR = 0; - LINE1_YADDR = (1 * 400); - LINE2_YADDR = (2 * 400); - LINE3_YADDR = (3 * 400); - - LINE0_UVADDR = 1; - LINE1_UVADDR = (1 * 400) + 1; - LINE2_UVADDR = (2 * 400) + 1; - LINE3_UVADDR = (3 * 400) + 1; - - START_X = 0; - START_Y = 0; - DELTA_X = 0x200; /* no scaling */ - DELTA_Y = 0x200; /* no scaling */ -#endif - LCDC_INTR_MASK = INTR_MASK_LINE; /* INTR_MASK_EVENLINE; */ -} - -/* configure pins to drive lcd in 18bit mode */ -static void iomux_lcd(void) -{ - unsigned long muxa; - - muxa = SCU_IOMUXA_CON & ~(IOMUX_LCD_VSYNC|IOMUX_LCD_DEN|0xff); - muxa |= IOMUX_LCD_D18|IOMUX_LCD_D20|IOMUX_LCD_D22|IOMUX_LCD_D17|IOMUX_LCD_D16; - - SCU_IOMUXA_CON = muxa; - SCU_IOMUXB_CON |= IOMUX_LCD_D815; -} - -/* not tested */ -static void lcd_sleep(unsigned int sleep) -{ - if (sleep) - { - /* enter sleep mode */ - lcd_write_reg(DISPLAY_CTRL1, 0x0170); - delay_nop(50); - lcd_write_reg(DISPLAY_CTRL1, 0x0000); - delay_nop(50); - lcd_write_reg(PWR_CTRL1, 0x14B4); - } - else - { - /* return to normal operation */ - lcd_write_reg(PWR_CTRL1, 0x14B0); - delay_nop(50); - lcd_write_reg(DISPLAY_CTRL1, 0x0173); - } - - lcd_cmd(GRAM_WRITE); -} - -void lcd_init_device() -{ - unsigned int x, y; - - iomux_lcd(); /* setup pins for 18bit lcd interface */ - lcdctrl_init(); /* basic lcdc module configuration */ - - lcdctrl_bypass(1); /* run in bypass mode - all writes goes directly to lcd controller */ - - lcd_write_reg(RESET, 0x0001); - delay_nop(10000); - lcd_write_reg(RESET, 0x0000); - delay_nop(10000); - lcd_write_reg(IF_ENDIAN, 0x0000); /* order of receiving data */ - lcd_write_reg(DRIVER_OUT_CTRL, 0x0000); - lcd_write_reg(ENTRY_MODE, 0x1038); - lcd_write_reg(WAVEFORM_CTRL, 0x0100); - lcd_write_reg(SHAPENING_CTRL, 0x0000); - lcd_write_reg(DISPLAY_CTRL2, 0x0808); - lcd_write_reg(LOW_PWR_CTRL1, 0x0001); - lcd_write_reg(LOW_PWR_CTRL2, 0x0010); - lcd_write_reg(EXT_DISP_CTRL1, 0x0000); - lcd_write_reg(EXT_DISP_CTRL2, 0x0000); - lcd_write_reg(BASE_IMG_SIZE, 0x3100); - lcd_write_reg(BASE_IMG_CTRL, 0x0001); - lcd_write_reg(VSCROLL_CTRL, 0x0000); - lcd_write_reg(PART1_POS, 0x0000); - lcd_write_reg(PART1_START, 0x0000); - lcd_write_reg(PART1_END, 0x018F); - lcd_write_reg(PART2_POS, 0x0000); - lcd_write_reg(PART2_START, 0x0000); - lcd_write_reg(PART2_END, 0x0000); - - lcd_write_reg(PANEL_IF_CTRL1, 0x0011); - delay_nop(10000); - lcd_write_reg(PANEL_IF_CTRL2, 0x0202); - lcd_write_reg(PANEL_IF_CTRL3, 0x0300); - delay_nop(10000); - lcd_write_reg(PANEL_IF_CTRL4, 0x021E); - lcd_write_reg(PANEL_IF_CTRL5, 0x0202); - lcd_write_reg(PANEL_IF_CTRL6, 0x0100); - lcd_write_reg(FRAME_MKR_CTRL, 0x0000); - lcd_write_reg(MDDI_CTRL, 0x0000); - - lcd_write_reg(GAMMA_CTRL1, 0x0101); - lcd_write_reg(GAMMA_CTRL2, 0x0000); - lcd_write_reg(GAMMA_CTRL3, 0x0016); - lcd_write_reg(GAMMA_CTRL4, 0x2913); - lcd_write_reg(GAMMA_CTRL5, 0x260B); - lcd_write_reg(GAMMA_CTRL6, 0x0101); - lcd_write_reg(GAMMA_CTRL7, 0x1204); - lcd_write_reg(GAMMA_CTRL8, 0x0415); - lcd_write_reg(GAMMA_CTRL9, 0x0205); - lcd_write_reg(GAMMA_CTRL10, 0x0303); - lcd_write_reg(GAMMA_CTRL11, 0x0E05); - lcd_write_reg(GAMMA_CTRL12, 0x0D01); - lcd_write_reg(GAMMA_CTRL13, 0x010D); - lcd_write_reg(GAMMA_CTRL14, 0x050E); - lcd_write_reg(GAMMA_CTRL15, 0x0303); - lcd_write_reg(GAMMA_CTRL16, 0x0502); - - /* power on */ - lcd_write_reg(DISPLAY_CTRL1, 0x0001); - lcd_write_reg(PWR_CTRL6, 0x0001); - lcd_write_reg(PWR_CTRL7, 0x0060); - delay_nop(50000); - lcd_write_reg(PWR_CTRL1, 0x16B0); - delay_nop(10000); - lcd_write_reg(PWR_CTRL2, 0x0147); - delay_nop(10000); - lcd_write_reg(PWR_CTRL3, 0x0117); - delay_nop(10000); - lcd_write_reg(PWR_CTRL4, 0x2F00); - delay_nop(50000); - lcd_write_reg(VCOM_HV2, 0x0000); /* src 0x0090 */ - delay_nop(10000); - lcd_write_reg(VCOM_HV1, 0x0008); /* src 0x000A */ - lcd_write_reg(PWR_CTRL3, 0x01BE); - delay_nop(10000); - - /* addresses setup */ - lcd_write_reg(WINDOW_H_START, 0x0000); - lcd_write_reg(WINDOW_H_END, 0x00EF); /* 239 */ - lcd_write_reg(WINDOW_V_START, 0x0000); - lcd_write_reg(WINDOW_V_END, 0x018F); /* 399 */ - lcd_write_reg(GRAM_H_ADDR, 0x0000); - lcd_write_reg(GRAM_V_ADDR, 0x0000); - - /* display on */ - lcd_write_reg(DISPLAY_CTRL1, 0x0021); - delay_nop(40000); - lcd_write_reg(DISPLAY_CTRL1, 0x0061); - delay_nop(100000); - lcd_write_reg(DISPLAY_CTRL1, 0x0173); - delay_nop(300000); - - - /* clear screen */ - lcd_cmd(GRAM_WRITE); - - for (x=0; x<400; x++) - for(y=0; y<240; y++) - lcd_data(0x000000); - - lcd_sleep(0); -} - -/* This is ugly hack. We drive lcd in bypass mode - * where all writes goes directly to lcd controller. - * This is suboptimal at best. IF module povides - * FIFO, internal sram buffer, hardware scaller, - * DMA signals, hardware alpha blending and more. - * BUT the fact is that I have no idea how to use - * this modes. Datasheet floating around is very - * unclean in this regard and OF uses ackward - * lcd update routines which are hard to understand. - * Moreover OF sets some bits in IF module registers - * which are referred as reseved in datasheet. - */ -void lcd_update() -{ - lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); -} - - -void lcd_update_rect(int x, int y, int width, int height) -{ - int px = x, py = y; - int pxmax = x + width, pymax = y + height; - - /* addresses setup */ - lcd_write_reg(WINDOW_H_START, y); - lcd_write_reg(WINDOW_H_END, pymax-1); - lcd_write_reg(WINDOW_V_START, x); - lcd_write_reg(WINDOW_V_END, pxmax-1); - lcd_write_reg(GRAM_H_ADDR, y); - lcd_write_reg(GRAM_V_ADDR, x); - - lcd_cmd(GRAM_WRITE); - - for (py=y; py ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 Marcin Bukat + * + * 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" + + +unsigned int lcd_data_transform(unsigned int data) +{ + unsigned int r, g, b; + +#if defined(RK27_GENERIC) + /* 18 bit interface */ + r = (data & 0x0000fc00)<<8; + /* g = ((data & 0x00000300) >> 2) | ((data & 0x000000e0) >> 3); */ + g = ((data & 0x00000300) << 6) | ((data & 0x000000e0) << 5); + b = (data & 0x00000001f) << 3; +#elif defined(HM60X) + /* 16 bit interface */ + r = (data & 0x0000f800) << 8; + g = (data & 0x000007e0) << 5; + b = (data & 0x0000001f) << 3; +#else +#error "Unknown target" +#endif + + return (r | g | b); +} + +void lcd_cmd(unsigned int cmd) +{ + LCD_COMMAND = lcd_data_transform(cmd); +} + +void lcd_data(unsigned int data) +{ + LCD_DATA = lcd_data_transform(data); +} + +void lcd_write_reg(unsigned int reg, unsigned int val) +{ + lcd_cmd(reg); + lcd_data(val); +} + +static void lcdctrl_bypass(unsigned int on_off) +{ + while (!(LCDC_STA & LCDC_MCU_IDLE)); + + if (on_off) + MCU_CTRL |= MCU_CTRL_BYPASS; + else + MCU_CTRL &= ~MCU_CTRL_BYPASS; +} + +/* This part is unclear. I am unable to use buffered/FIFO based writes + * to lcd. Depending on settings of IF I get various patterns on display + * but not what I want to display apparently. + */ +static void lcdctrl_init(void) +{ + /* alpha b111 + * stop at current frame complete + * MCU mode + * 24b RGB + */ + LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B; + MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS; + + HOR_ACT = LCD_WIDTH + 3; /* define horizonatal active region */ + VERT_ACT = LCD_HEIGHT; /* define vertical active region */ + VERT_PERIOD = 0xfff; /* CSn/WEn/RDn signal timings */ + + LINE0_YADDR = LINE_ALPHA_EN | 0x7fe; + LINE1_YADDR = LINE_ALPHA_EN | ((1 * LCD_WIDTH) - 2); + LINE2_YADDR = LINE_ALPHA_EN | ((2 * LCD_WIDTH) - 2); + LINE3_YADDR = LINE_ALPHA_EN | ((3 * LCD_WIDTH) - 2); + + LINE0_UVADDR = 0x7fe + 1; + LINE1_UVADDR = ((1 * LCD_WIDTH) - 2 + 1); + LINE2_UVADDR = ((2 * LCD_WIDTH) - 2 + 1); + LINE3_UVADDR = ((3 * LCD_WIDTH) - 2 + 1); + +#if 0 + LINE0_YADDR = 0; + LINE1_YADDR = (1 * LCD_WIDTH); + LINE2_YADDR = (2 * LCD_WIDTH); + LINE3_YADDR = (3 * LCD_WIDTH); + + LINE0_UVADDR = 1; + LINE1_UVADDR = (1 * LCD_WIDTH) + 1; + LINE2_UVADDR = (2 * LCD_WIDTH) + 1; + LINE3_UVADDR = (3 * LCD_WIDTH) + 1; + + START_X = 0; + START_Y = 0; + DELTA_X = 0x200; /* no scaling */ + DELTA_Y = 0x200; /* no scaling */ +#endif + LCDC_INTR_MASK = INTR_MASK_LINE; /* INTR_MASK_EVENLINE; */ +} + +/* configure pins to drive lcd in 18bit mode */ +static void iomux_lcd(void) +{ + unsigned long muxa; + + muxa = SCU_IOMUXA_CON & ~(IOMUX_LCD_VSYNC|IOMUX_LCD_DEN|0xff); + muxa |= IOMUX_LCD_D18|IOMUX_LCD_D20|IOMUX_LCD_D22|IOMUX_LCD_D17|IOMUX_LCD_D16; + + SCU_IOMUXA_CON = muxa; + SCU_IOMUXB_CON |= IOMUX_LCD_D815; +} + +void lcd_init_device() +{ + iomux_lcd(); /* setup pins for 16bit lcd interface */ + lcdctrl_init(); /* basic lcdc module configuration */ + + lcdctrl_bypass(1); /* run in bypass mode - all writes goes directly to lcd controller */ + lcd_display_init(); +} + +/* This is ugly hack. We drive lcd in bypass mode + * where all writes goes directly to lcd controller. + * This is suboptimal at best. IF module povides + * FIFO, internal sram buffer, hardware scaller, + * DMA signals, hardware alpha blending and more. + * BUT the fact is that I have no idea how to use + * this modes. Datasheet floating around is very + * unclean in this regard and OF uses ackward + * lcd update routines which are hard to understand. + * Moreover OF sets some bits in IF module registers + * which are referred as reseved in datasheet. + */ +void lcd_update() +{ + lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); +} diff --git a/firmware/target/arm/rk27xx/lcdif-rk27xx.h b/firmware/target/arm/rk27xx/lcdif-rk27xx.h new file mode 100644 index 0000000000..caf97c8e94 --- /dev/null +++ b/firmware/target/arm/rk27xx/lcdif-rk27xx.h @@ -0,0 +1,11 @@ +#ifndef _LCDIF_RK27XX_H +#define _LCDIF_RK27XX_H + +unsigned int lcd_data_transform(unsigned int data); + +void lcd_cmd(unsigned int cmd); +void lcd_data(unsigned int data); +void lcd_write_reg(unsigned int reg, unsigned int val); +void lcd_display_init(void); + +#endif /* _LCDIF_RK27XX_H */ diff --git a/firmware/target/arm/rk27xx/pcm-rk27xx.c b/firmware/target/arm/rk27xx/pcm-rk27xx.c index b8ae56adaf..80a8d462ea 100644 --- a/firmware/target/arm/rk27xx/pcm-rk27xx.c +++ b/firmware/target/arm/rk27xx/pcm-rk27xx.c @@ -8,6 +8,7 @@ * $Id$ * * Copyright (C) 2011 Marcin Bukat + * Copyright (C) 2011 Andrew Ryabinin * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -179,13 +180,65 @@ static void i2s_init(void) (0<<2) | /* normal operation */ #ifdef CODEC_SLAVE (1<<1) | /* start Tx (master mode) */ - (1<<0); /* start Rx (master mode) */ + (0<<0); /* do not start Rx (master mode) */ + /* setting Rx bit to 1 result in choppy audio */ #else (0<<1) | /* not used in slave mode */ (0<<0); /* not used in slave mode */ #endif } +#ifdef CODEC_SLAVE +/* When codec is slave we need to setup i2s MCLK clock using codec pll. + * The MCLK frequency is 256*codec frequency as i2s setup is: + * LRCK/SCLK = 64 and MCLK/SCLK = 4 (see i2s_init() for reference) + * + * PLL output frequency: + * Fout = ((Fref / (CLKR+1)) * (CLKF+1)) / (CLKOD+1) + * Fref = 24 MHz + */ +static void set_codec_freq(unsigned int freq) +{ + long timeout; + + /* {CLKR, CLKF, CLKOD, CODECPLL_DIV} */ + static const unsigned int pcm_freq_params[HW_NUM_FREQ][4] = + { + [HW_FREQ_96] = {24, 255, 4, 1}, + [HW_FREQ_48] = {24, 127, 4, 1}, + [HW_FREQ_44] = {24, 293, 4, 4}, + [HW_FREQ_32] = {24, 127, 4, 2}, + [HW_FREQ_24] = {24, 127, 4, 3}, + [HW_FREQ_22] = {24, 146, 4, 4}, + [HW_FREQ_16] = {24, 127, 5, 4}, + [HW_FREQ_12] = {24, 127, 4, 7}, + [HW_FREQ_11] = {24, 146, 4, 9}, + [HW_FREQ_8] = {24, 127, 5, 9}, + }; + /* select divider output from codec pll */ + SCU_DIVCON1 &= ~((1<<9) | (0xF<<5)); + SCU_DIVCON1 |= (pcm_freq_params[freq][3]<<5); + + /* Codec PLL power up */ + SCU_PLLCON3 &= ~(1<<22); + + SCU_PLLCON3 = (1<<24) | /* Saturation behavior enable */ + (1<<23) | /* Enable fast locking circuit */ + (pcm_freq_params[freq][0]<<16) | /* CLKR factor */ + (pcm_freq_params[freq][1]<<4) | /* CLKF factor */ + (pcm_freq_params[freq][2]<<1) ; /* CLKOD factor */ + +/* wait for CODEC PLL lock with 10 ms timeout + * datasheet states that pll lock should take approx. 0.3 ms + */ + timeout = current_tick + (HZ/100); + while (!(SCU_STATUS & (1<<2))) + if (TIME_AFTER(current_tick, timeout)) + break; + +} +#endif + void pcm_play_dma_init(void) { /* unmask HDMA interrupt in INTC */ @@ -204,8 +257,11 @@ void pcm_play_dma_postinit(void) void pcm_dma_apply_settings(void) { - /* I2S module runs in slave mode */ - return; +#ifdef CODEC_SLAVE + set_codec_freq(pcm_fsel); +#endif + + audiohw_set_frequency(pcm_fsel); } size_t pcm_get_bytes_waiting(void) diff --git a/firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c b/firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c new file mode 100644 index 0000000000..b184630ebe --- /dev/null +++ b/firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c @@ -0,0 +1,211 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 Marcin Bukat + * + * 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 "spfd5420a.h" +#include "lcdif-rk27xx.h" + +/* TODO: convert to udelay() */ +static inline void delay_nop(int cycles) +{ + asm volatile ("1: subs %[n], %[n], #1 \n\t" + " bne 1b" + : + : [n] "r" (cycles)); +} + + +/* converts RGB565 pixel into internal lcd bus format */ +static unsigned int lcd_pixel_transform(unsigned short rgb565) +{ + unsigned int r, g, b; + b = rgb565 & 0x1f; + g = (rgb565 >> 5) & 0x3f; + r = (rgb565 >> 11) & 0x1f; + + return r<<19 | g<<10 | b<<3; +} + +/* not tested */ +static void lcd_sleep(bool sleep) +{ + if (sleep) + { + /* enter sleep mode */ + lcd_write_reg(DISPLAY_CTRL1, 0x0170); + delay_nop(50); + lcd_write_reg(DISPLAY_CTRL1, 0x0000); + delay_nop(50); + lcd_write_reg(PWR_CTRL1, 0x14B4); + } + else + { + /* return to normal operation */ + lcd_write_reg(PWR_CTRL1, 0x14B0); + delay_nop(50); + lcd_write_reg(DISPLAY_CTRL1, 0x0173); + } + + lcd_cmd(GRAM_WRITE); +} + +void lcd_display_init() +{ + unsigned int x, y; + + lcd_write_reg(RESET, 0x0001); + delay_nop(10000); + lcd_write_reg(RESET, 0x0000); + delay_nop(10000); + lcd_write_reg(IF_ENDIAN, 0x0000); /* order of receiving data */ + lcd_write_reg(DRIVER_OUT_CTRL, 0x0000); + lcd_write_reg(ENTRY_MODE, 0x1038); + lcd_write_reg(WAVEFORM_CTRL, 0x0100); + lcd_write_reg(SHAPENING_CTRL, 0x0000); + lcd_write_reg(DISPLAY_CTRL2, 0x0808); + lcd_write_reg(LOW_PWR_CTRL1, 0x0001); + lcd_write_reg(LOW_PWR_CTRL2, 0x0010); + lcd_write_reg(EXT_DISP_CTRL1, 0x0000); + lcd_write_reg(EXT_DISP_CTRL2, 0x0000); + lcd_write_reg(BASE_IMG_SIZE, 0x3100); + lcd_write_reg(BASE_IMG_CTRL, 0x0001); + lcd_write_reg(VSCROLL_CTRL, 0x0000); + lcd_write_reg(PART1_POS, 0x0000); + lcd_write_reg(PART1_START, 0x0000); + lcd_write_reg(PART1_END, 0x018F); + lcd_write_reg(PART2_POS, 0x0000); + lcd_write_reg(PART2_START, 0x0000); + lcd_write_reg(PART2_END, 0x0000); + + lcd_write_reg(PANEL_IF_CTRL1, 0x0011); + delay_nop(10000); + lcd_write_reg(PANEL_IF_CTRL2, 0x0202); + lcd_write_reg(PANEL_IF_CTRL3, 0x0300); + delay_nop(10000); + lcd_write_reg(PANEL_IF_CTRL4, 0x021E); + lcd_write_reg(PANEL_IF_CTRL5, 0x0202); + lcd_write_reg(PANEL_IF_CTRL6, 0x0100); + lcd_write_reg(FRAME_MKR_CTRL, 0x0000); + lcd_write_reg(MDDI_CTRL, 0x0000); + + lcd_write_reg(GAMMA_CTRL1, 0x0101); + lcd_write_reg(GAMMA_CTRL2, 0x0000); + lcd_write_reg(GAMMA_CTRL3, 0x0016); + lcd_write_reg(GAMMA_CTRL4, 0x2913); + lcd_write_reg(GAMMA_CTRL5, 0x260B); + lcd_write_reg(GAMMA_CTRL6, 0x0101); + lcd_write_reg(GAMMA_CTRL7, 0x1204); + lcd_write_reg(GAMMA_CTRL8, 0x0415); + lcd_write_reg(GAMMA_CTRL9, 0x0205); + lcd_write_reg(GAMMA_CTRL10, 0x0303); + lcd_write_reg(GAMMA_CTRL11, 0x0E05); + lcd_write_reg(GAMMA_CTRL12, 0x0D01); + lcd_write_reg(GAMMA_CTRL13, 0x010D); + lcd_write_reg(GAMMA_CTRL14, 0x050E); + lcd_write_reg(GAMMA_CTRL15, 0x0303); + lcd_write_reg(GAMMA_CTRL16, 0x0502); + + /* power on */ + lcd_write_reg(DISPLAY_CTRL1, 0x0001); + lcd_write_reg(PWR_CTRL6, 0x0001); + lcd_write_reg(PWR_CTRL7, 0x0060); + delay_nop(50000); + lcd_write_reg(PWR_CTRL1, 0x16B0); + delay_nop(10000); + lcd_write_reg(PWR_CTRL2, 0x0147); + delay_nop(10000); + lcd_write_reg(PWR_CTRL3, 0x0117); + delay_nop(10000); + lcd_write_reg(PWR_CTRL4, 0x2F00); + delay_nop(50000); + lcd_write_reg(VCOM_HV2, 0x0000); /* src 0x0090 */ + delay_nop(10000); + lcd_write_reg(VCOM_HV1, 0x0008); /* src 0x000A */ + lcd_write_reg(PWR_CTRL3, 0x01BE); + delay_nop(10000); + + /* addresses setup */ + lcd_write_reg(WINDOW_H_START, 0x0000); + lcd_write_reg(WINDOW_H_END, 0x00EF); /* 239 */ + lcd_write_reg(WINDOW_V_START, 0x0000); + lcd_write_reg(WINDOW_V_END, 0x018F); /* 399 */ + lcd_write_reg(GRAM_H_ADDR, 0x0000); + lcd_write_reg(GRAM_V_ADDR, 0x0000); + + /* display on */ + lcd_write_reg(DISPLAY_CTRL1, 0x0021); + delay_nop(40000); + lcd_write_reg(DISPLAY_CTRL1, 0x0061); + delay_nop(100000); + lcd_write_reg(DISPLAY_CTRL1, 0x0173); + delay_nop(300000); + + + /* clear screen */ + lcd_cmd(GRAM_WRITE); + + for (x=0; x