summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/rk27xx
diff options
context:
space:
mode:
authorAndrew Ryabinin <ryabinin.a.a@gmail.com>2013-04-15 09:51:22 +0400
committerAndrew Ryabinin <ryabinin.a.a@gmail.com>2013-05-06 14:09:24 +0400
commitfa4e1baa83a5f3f28f98b5b744b7692be9fb4fca (patch)
treedbb558d0e36b25031131d0c1e62f8c1ff8238470 /firmware/target/arm/rk27xx
parent3fd25dcbed6ef964b828698facf6cc15189441ca (diff)
downloadrockbox-fa4e1baa83a5f3f28f98b5b744b7692be9fb4fca.tar.gz
rockbox-fa4e1baa83a5f3f28f98b5b744b7692be9fb4fca.zip
Introduce HiFi E.T MA9 port.
Change-Id: I79aadc958fd5222f26f91ed127f8c6fb2c465dc2
Diffstat (limited to 'firmware/target/arm/rk27xx')
-rw-r--r--firmware/target/arm/rk27xx/backlight-rk27xx.c7
-rw-r--r--firmware/target/arm/rk27xx/debug-rk27xx.c2
-rw-r--r--firmware/target/arm/rk27xx/lcdif-rk27xx.c2
-rw-r--r--firmware/target/arm/rk27xx/ma/audio-ma.c85
-rw-r--r--firmware/target/arm/rk27xx/ma/button-ma.c74
-rw-r--r--firmware/target/arm/rk27xx/ma/button-target.h40
-rw-r--r--firmware/target/arm/rk27xx/ma/lcd-ma.c206
-rw-r--r--firmware/target/arm/rk27xx/ma/lcd-target.h27
-rw-r--r--firmware/target/arm/rk27xx/ma/pca9555-ma.c93
-rw-r--r--firmware/target/arm/rk27xx/ma/pca9555-target.h27
-rw-r--r--firmware/target/arm/rk27xx/ma/power-ma.c58
-rw-r--r--firmware/target/arm/rk27xx/ma/powermgmt-ma.c61
-rw-r--r--firmware/target/arm/rk27xx/sd-rk27xx.c2
13 files changed, 682 insertions, 2 deletions
diff --git a/firmware/target/arm/rk27xx/backlight-rk27xx.c b/firmware/target/arm/rk27xx/backlight-rk27xx.c
index f95a63ecde..9ea9c9984e 100644
--- a/firmware/target/arm/rk27xx/backlight-rk27xx.c
+++ b/firmware/target/arm/rk27xx/backlight-rk27xx.c
@@ -61,6 +61,13 @@ static const unsigned short lin_brightness[] = {
562, 579, 596, 616, 637, 660, 684, 711,
739, 770, 802, 837, 874, 914, 955, 1000
};
+#elif defined(MA9)
+static const unsigned short lin_brightness[] = {
+ 2, 4, 7, 10, 15, 21, 28, 36,
+ 46, 58, 72, 87, 104, 124, 146, 171,
+ 198, 227, 260, 295, 334, 376, 421, 470,
+ 522, 578, 638, 702, 770, 842, 918, 1000
+};
#endif
bool _backlight_init(void)
diff --git a/firmware/target/arm/rk27xx/debug-rk27xx.c b/firmware/target/arm/rk27xx/debug-rk27xx.c
index 98ceaf634a..a73ca05c77 100644
--- a/firmware/target/arm/rk27xx/debug-rk27xx.c
+++ b/firmware/target/arm/rk27xx/debug-rk27xx.c
@@ -32,7 +32,7 @@
#ifdef RK27_GENERIC
#define DEBUG_CANCEL BUTTON_VOL
-#elif defined(HM60X) || defined(HM801)
+#elif defined(HM60X) || defined(HM801) || defined(MA9)
#define DEBUG_CANCEL BUTTON_LEFT
#endif
diff --git a/firmware/target/arm/rk27xx/lcdif-rk27xx.c b/firmware/target/arm/rk27xx/lcdif-rk27xx.c
index d5847392a3..3f22057f2f 100644
--- a/firmware/target/arm/rk27xx/lcdif-rk27xx.c
+++ b/firmware/target/arm/rk27xx/lcdif-rk27xx.c
@@ -56,7 +56,7 @@ static uint32_t lcd_data_transform(uint32_t data)
/* g = ((data & 0x00000300) >> 2) | ((data & 0x000000e0) >> 3); */
g = ((data & 0x00000300) << 6) | ((data & 0x000000e0) << 5);
b = (data & 0x00000001f) << 3;
-#elif defined(HM60X) || defined(HM801)
+#elif defined(HM60X) || defined(HM801) || defined(MA9)
/* 16 bit interface */
r = (data & 0x0000f800) << 8;
g = (data & 0x000007e0) << 5;
diff --git a/firmware/target/arm/rk27xx/ma/audio-ma.c b/firmware/target/arm/rk27xx/ma/audio-ma.c
new file mode 100644
index 0000000000..c870ca09b8
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ma/audio-ma.c
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2013 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 "audiohw.h"
+#include "df1704.h"
+#include "pca9555.h"
+#include "i2c-rk27xx.h"
+#include "system.h"
+
+void df1704_set_ml_dir(const int dir)
+{
+ pca9555_write_config(dir<<8, (1<<8));
+}
+
+void df1704_set_ml(const int val)
+{
+ pca9555_write_output(val<<8, 1<<8);
+}
+
+void df1704_set_mc(const int val)
+{
+ pca9555_write_output(val<<1, 1<<1);
+}
+
+void df1704_set_md(const int val)
+{
+ pca9555_write_output(val<<0, 1<<0);
+}
+
+static void pop_ctrl(const int val)
+{
+ pca9555_write_output(val<<5, 1<<5);
+}
+
+static void amp_enable(const int val)
+{
+ pca9555_write_output(val<<3, 1<<3);
+}
+
+static void df1704_enable(const int val)
+{
+ pca9555_write_output(val<<4, 1<<4);
+}
+
+
+void audiohw_postinit(void)
+{
+ pop_ctrl(0);
+ sleep(HZ/4);
+ df1704_enable(1);
+ amp_enable(1);
+ sleep(HZ/100);
+ df1704_init();
+ sleep(HZ/4);
+ pop_ctrl(1);
+}
+
+void audiohw_close(void)
+{
+ df1704_mute();
+ pop_ctrl(0);
+ sleep(HZ/5);
+ amp_enable(0);
+ df1704_enable(0);
+ sleep(HZ/5);
+ pop_ctrl(1);
+}
diff --git a/firmware/target/arm/rk27xx/ma/button-ma.c b/firmware/target/arm/rk27xx/ma/button-ma.c
new file mode 100644
index 0000000000..f8da786e4f
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ma/button-ma.c
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2013 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"
+#include "backlight.h"
+#include "pca9555.h"
+
+extern unsigned short pca9555_in_ports;
+
+/* upper bounds of key's voltage values */
+#define ADV_KEYUP 0x05B + 0x10
+#define ADV_KEYDOWN 0x0F3 + 0x10
+#define ADV_KEYLEFT 0x190 + 0x10
+#define ADV_KEYRIGHT 0x22C + 0x10
+#define ADV_KEYMENU 0x2CA + 0x10
+
+
+void button_init_device(void) {
+ GPIO_PCCON &= ~(1<<1);
+ pca9555_init();
+}
+
+int button_read_device(void) {
+ int adc_val = adc_read(ADC_BUTTONS);
+ int button = 0;
+
+ if (adc_val < ADV_KEYLEFT) {
+ if (adc_val < ADV_KEYDOWN) {
+ if (adc_val < ADV_KEYUP) {
+ button = BUTTON_UP;
+ } else {
+ button = BUTTON_DOWN;
+ }
+ } else {
+ button = BUTTON_LEFT;
+ }
+ } else {
+ if (adc_val < ADV_KEYRIGHT) {
+ button = BUTTON_RIGHT;
+ } else if (adc_val < ADV_KEYMENU) {
+ button = BUTTON_MENU;
+ }
+ }
+
+ if (GPIO_PCDR & (1<<1)) {
+ button |= BUTTON_PLAY;
+ }
+ if (((GPIO_PFDR&(1<<2)) == 0) &&
+ ((pca9555_in_ports & (1<<15)) == 0)) {
+ button |= BUTTON_BACK;
+ }
+ return button;
+}
diff --git a/firmware/target/arm/rk27xx/ma/button-target.h b/firmware/target/arm/rk27xx/ma/button-target.h
new file mode 100644
index 0000000000..56e8e903b0
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ma/button-target.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2013 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_
+
+#define BUTTON_UP 0x00000001
+#define BUTTON_DOWN 0x00000002
+#define BUTTON_LEFT 0x00000004
+#define BUTTON_RIGHT 0x00000008
+#define BUTTON_PLAY 0x00000010
+#define BUTTON_MENU 0x00000020
+#define BUTTON_BACK 0x00000040
+
+#define BUTTON_MAIN (BUTTON_UP|BUTTON_DOWN| \
+ BUTTON_RIGHT|BUTTON_LEFT| \
+ BUTTON_PLAY|BUTTON_MENU|BUTTON_BACK)
+
+#define POWEROFF_BUTTON BUTTON_PLAY
+#define POWEROFF_COUNT 30
+
+#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/arm/rk27xx/ma/lcd-ma.c b/firmware/target/arm/rk27xx/ma/lcd-ma.c
new file mode 100644
index 0000000000..ad67352eb7
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ma/lcd-ma.c
@@ -0,0 +1,206 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2013 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"
+
+static bool display_on = false;
+
+
+void lcd_display_init(void)
+{
+ int i;
+ unsigned int x, y;
+
+ lcd_cmd(0x00B9);
+ lcd_data(0x00FF);
+ lcd_data(0x0093);
+ lcd_data(0x0042);
+
+ lcd_cmd(0x0021); /* display inversion on ??? */
+
+ /* memory access control */
+ lcd_cmd(0x0036);
+ lcd_data(0x00C9);
+
+ /* set 16-bit pixel format */
+ lcd_cmd(0x003A);
+ lcd_data(0x0005);
+
+ /* Setup color depth conversion lookup table */
+ lcd_cmd(0x002D);
+ /* red */
+ for(i = 0; i < 32; i++)
+ lcd_data(2*i);
+ /* green */
+ for(i = 0; i < 64; i++)
+ lcd_data(1*i);
+ /* blue */
+ for(i = 0; i < 32; i++)
+ lcd_data(2*i);
+
+ /* power control settings */
+ lcd_cmd(0x00C0);
+ lcd_data(0x0025); /* VREG1OUT 4.70V */
+ lcd_data(0x000A); /* VCOM 2.8V */
+
+ lcd_cmd(0x00C1);
+ lcd_data(0x0001);
+
+ lcd_cmd(0x00C5);
+ lcd_data(0x002F);
+ lcd_data(0x0027);
+
+ lcd_cmd(0x00C7);
+ lcd_data(0x00D3);
+
+ lcd_cmd(0x00B8);
+ lcd_data(0x000B);
+
+ /* Positive gamma correction */
+ lcd_cmd(0x00E0);
+ lcd_data(0x000F);
+ lcd_data(0x0022);
+ lcd_data(0x001D);
+ lcd_data(0x000B);
+ lcd_data(0x000F);
+ lcd_data(0x0007);
+ lcd_data(0x004C);
+ lcd_data(0x0076);
+ lcd_data(0x003C);
+ lcd_data(0x0009);
+ lcd_data(0x0016);
+ lcd_data(0x0007);
+ lcd_data(0x0012);
+ lcd_data(0x000B);
+ lcd_data(0x0008);
+
+ /* Negative Gamma Correction */
+ lcd_cmd(0x00E1);
+ lcd_data(0x0008);
+ lcd_data(0x001F);
+ lcd_data(0x0024);
+ lcd_data(0x0003);
+ lcd_data(0x000E);
+ lcd_data(0x0003);
+ lcd_data(0x0035);
+ lcd_data(0x0023);
+ lcd_data(0x0045);
+ lcd_data(0x0001);
+ lcd_data(0x000B);
+ lcd_data(0x0007);
+ lcd_data(0x002F);
+ lcd_data(0x0036);
+ lcd_data(0x000F);
+
+ lcd_cmd(0x00F2);
+ lcd_data(0x0000);
+
+ /* exit sleep */
+ lcd_cmd(0x0011);
+ udelay(5000);
+ lcd_cmd(0x0029);
+
+ lcd_cmd(0x002C);
+ 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);
+ } else {
+ lcd_cmd(0x10);
+ }
+ udelay(5000);
+
+ display_on = on;
+ LCDC_CTRL &= ~RGB24B;
+}
+
+void lcd_set_gram_area(int x, int y, int width, int height)
+{
+ lcdctrl_bypass(1);
+ LCDC_CTRL |= RGB24B;
+
+ lcd_cmd(0x002A);
+ lcd_data((x&0xff00)>>8);
+ lcd_data(x&0x00ff);
+ lcd_data(((width-1)&0xff00)>>8);
+ lcd_data((width-1)&0x00ff);
+ lcd_cmd(0x002B);
+ lcd_data((y&0xff00)>>8);
+ lcd_data(y&0x00ff);
+ lcd_data(((height-1)&0xff00)>>8);
+ lcd_data((height-1)&0x00ff);
+
+ lcd_cmd(0x2c);
+ LCDC_CTRL &= ~RGB24B;
+}
+
+void lcd_update_rect(int x, int y, int width, int height)
+{
+ int px = x, py = y;
+ int pxmax = x + width, pymax = y + height;
+
+ lcd_set_gram_area(x, y, pxmax, pymax);
+
+ for (py = y; py < pymax; py++)
+ for (px = x; px < pxmax; px++)
+ LCD_DATA = (*FBADDR(px, py));
+
+}
+
+
+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/ma/lcd-target.h b/firmware/target/arm/rk27xx/ma/lcd-target.h
new file mode 100644
index 0000000000..f411a53de2
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ma/lcd-target.h
@@ -0,0 +1,27 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2013 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 LCD_TARGET_H
+#define LCD_TARGET_H
+
+#define LCD_DATABUS_WIDTH LCDIF_16BIT
+
+#endif
diff --git a/firmware/target/arm/rk27xx/ma/pca9555-ma.c b/firmware/target/arm/rk27xx/ma/pca9555-ma.c
new file mode 100644
index 0000000000..9611d84590
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ma/pca9555-ma.c
@@ -0,0 +1,93 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2013 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 "system.h"
+#include "i2c-rk27xx.h"
+#include "pca9555.h"
+
+static struct semaphore pca9555_sem;
+static char pca9555_thread_stack[DEFAULT_STACK_SIZE];
+volatile unsigned short pca9555_in_ports;
+
+void INT_GPIO1(void)
+{
+ if (GPIO1_ISR & (1<<10)) { /* GPIO F2 pin */
+ GPIO_IEF &= ~(1<<2);
+ GPIO_ICF |= (1<<2);
+ semaphore_release(&pca9555_sem);
+ }
+}
+
+static void pca9555_read_thread(void)
+{
+ while(1) {
+ if ((GPIO_PFDR&(1<<2)) == 0) {
+ pca9555_in_ports = pca9555_read_input();
+ } else {
+ pca9555_in_ports = (1<<15)|(1<<11); /* restore defaults */
+ }
+ sleep(HZ/20);
+ GPIO_IEF |= (1<<2);
+ semaphore_wait(&pca9555_sem, TIMEOUT_BLOCK);
+ }
+}
+
+static void pca9555_ports_init(void)
+{
+ unsigned short data = 0;
+
+ data = 0xf800; /* port0 - pins 0-7 output, port1 - pins 0-2 output, pins 3-7 input */
+ pca9555_write_config(data, 0xffff);
+
+ /*
+ * IO0-7 IO0-6 IO0-5 IO0_4 IO0_3 IO0_2 IO0_1 IO0_0
+ * USB_SEL KP_LED POP DAC_EN AMP_EN SPI_CS SPI_CLK SPI_DATA
+ * 1:MSD 1:OFF 1 0 0 1 1 1
+ */
+ data = ((1<<7)|(1<<6)|(1<<5)|(0<<4)|(0<<3)|(1<<2)|(1<<1)|(1<<0));
+
+ /*
+ * IO1-2 IO1_1 IO1_0
+ * CHG_EN DAC_EN DF1704_CS
+ * 1 0 1
+ */
+ data |= ((1<<10)|(0<<9)|(1<<8));
+ pca9555_write_output(data, 0xffff);
+}
+
+void pca9555_target_init(void)
+{
+ GPIO_PFCON &= ~(1<<2); /* PF2 for PCA9555 input INT */
+
+ pca9555_ports_init();
+ semaphore_init(&pca9555_sem, 1, 0);
+
+ INTC_IMR |= IRQ_ARM_GPIO1;
+ INTC_IECR |= IRQ_ARM_GPIO1;
+ GPIO_ISF |= (1<<2);
+
+ create_thread(pca9555_read_thread,
+ pca9555_thread_stack,
+ sizeof(pca9555_thread_stack),
+ 0,
+ "pca9555_read" IF_PRIO(, PRIORITY_SYSTEM)
+ IF_COP(, CPU));
+}
diff --git a/firmware/target/arm/rk27xx/ma/pca9555-target.h b/firmware/target/arm/rk27xx/ma/pca9555-target.h
new file mode 100644
index 0000000000..25cb1dac84
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ma/pca9555-target.h
@@ -0,0 +1,27 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2013 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 _PCA9555_TARGET_H
+#define _PCA9555_TARGET_H
+
+#define PCA9555_I2C_ADDR 0x40
+
+#endif
diff --git a/firmware/target/arm/rk27xx/ma/power-ma.c b/firmware/target/arm/rk27xx/ma/power-ma.c
new file mode 100644
index 0000000000..fb7c23251a
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ma/power-ma.c
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright © 2013 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 <stdbool.h>
+#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)
+{
+ GPIO_PCDR |= (1<<0);
+ GPIO_PCCON &= ~(1<<0);
+ while(1);
+}
+
+void power_init(void)
+{
+ GPIO_PCDR |= (1<<0);
+ GPIO_PCCON |= (1<<0);
+}
+
+unsigned int power_input_status(void)
+{
+ unsigned int status = POWER_INPUT_NONE;
+
+ if (charging_state())
+ status |= POWER_INPUT_MAIN_CHARGER;
+ return status;
+}
+
+extern unsigned short pca9555_in_ports;
+
+bool charging_state(void)
+{
+ return (((GPIO_PFDR&(1<<2)) == 0) && ((pca9555_in_ports&(1<<11)) == 0));
+}
+
diff --git a/firmware/target/arm/rk27xx/ma/powermgmt-ma.c b/firmware/target/arm/rk27xx/ma/powermgmt-ma.c
new file mode 100644
index 0000000000..23196d1591
--- /dev/null
+++ b/firmware/target/arm/rk27xx/ma/powermgmt-ma.c
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright © 2013 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 "adc.h"
+#include "adc-target.h"
+#include "powermgmt.h"
+
+/**
+ * Battery voltage calculation and discharge/charge curves for the HiFi E.T MA9.
+ */
+
+const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
+{
+ /* TODO: this is just an initial guess */
+ 6700
+};
+
+const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
+{
+ 6600
+};
+
+/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
+const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
+{
+ /* Uncalibrated curve */
+ { 6600, 6936, 7042, 7124, 7218, 7288, 7382, 7534, 7674, 7838, 8200 }
+};
+
+/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
+const unsigned short percent_to_volt_charge[11] =
+ /* TODO: simple copy of discharge curve */
+ { 6600, 6936, 7042, 7124, 7218, 7288, 7382, 7534, 7674, 7838, 8200 };
+
+/* full-scale ADC readout (2^10) in millivolt */
+#define BATTERY_SCALE_FACTOR 9170
+
+/* 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 a3ff344d78..cb870c9e38 100644
--- a/firmware/target/arm/rk27xx/sd-rk27xx.c
+++ b/firmware/target/arm/rk27xx/sd-rk27xx.c
@@ -132,6 +132,8 @@ static inline bool card_detect_target(void)
return !(GPIO_PCDR & 0x80);
#elif defined(HM60X) || defined(HM801)
return !(GPIO_PFDR & (1<<2));
+#elif defined(MA9)
+ return (GPIO_PCDR & 0x80);
#else
#error "Unknown target"
#endif