summaryrefslogtreecommitdiff
path: root/firmware/target/arm/rk27xx
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2011-10-17 10:32:19 +0000
committerMarcin Bukat <marcin.bukat@gmail.com>2011-10-17 10:32:19 +0000
commit32f763c39a797221a6e850704feb3743bc104d8c (patch)
treec509c38423f2efb76a13119f92c21e5e82476a42 /firmware/target/arm/rk27xx
parentf0311d3310e84906a6c1afaf941f2f58e2063c30 (diff)
downloadrockbox-32f763c39a797221a6e850704feb3743bc104d8c.tar.gz
rockbox-32f763c39a797221a6e850704feb3743bc104d8c.zip
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
Diffstat (limited to 'firmware/target/arm/rk27xx')
-rw-r--r--firmware/target/arm/rk27xx/adc-target.h4
-rw-r--r--firmware/target/arm/rk27xx/debug-target.h4
-rw-r--r--firmware/target/arm/rk27xx/hm60x/button-hm60x.c46
-rw-r--r--firmware/target/arm/rk27xx/hm60x/button-target.h44
-rw-r--r--firmware/target/arm/rk27xx/hm60x/lcd-hm60x.c148
-rw-r--r--firmware/target/arm/rk27xx/hm60x/power-hm60x.c48
-rw-r--r--firmware/target/arm/rk27xx/hm60x/powermgmt-hm60x.c66
-rw-r--r--firmware/target/arm/rk27xx/lcdif-rk27xx.c161
-rw-r--r--firmware/target/arm/rk27xx/lcdif-rk27xx.h11
-rw-r--r--firmware/target/arm/rk27xx/pcm-rk27xx.c62
-rw-r--r--firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c (renamed from firmware/target/arm/rk27xx/lcd-rk27xx.c)131
11 files changed, 596 insertions, 129 deletions
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 @@
24#define NUM_ADC_CHANNELS 4 24#define NUM_ADC_CHANNELS 4
25 25
26#define ADC_BATTERY 0 26#define ADC_BATTERY 0
27#define ADC_UNKNOWN_1 1 27#define ADC_BUTTONS 1
28#define ADC_UNKNOWN_2 2 28#define ADC_UNKNOWN 2
29#define ADC_VREF 3 /* that is what datasheet says */ 29#define ADC_VREF 3 /* that is what datasheet says */
30 30
31#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */ 31#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 @@
24 24
25#include <stdbool.h> 25#include <stdbool.h>
26 26
27#ifdef RK27_GENERIC
27#define DEBUG_CANCEL BUTTON_VOL 28#define DEBUG_CANCEL BUTTON_VOL
29#elif defined(HM60X)
30#define DEBUG_CANCEL BUTTON_LEFT
31#endif
28 32
29bool dbg_hw_info(void); 33bool dbg_hw_info(void);
30bool dbg_ports(void); 34bool 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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 Andrew Ryabinin
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "system.h"
24#include "button.h"
25#include "adc.h"
26
27void button_init_device(void) {
28 /* setup button gpio as input */
29 GPIO_PCCON &= ~(POWEROFF_BUTTON);
30}
31
32int button_read_device(void) {
33 int adc_val = adc_read(ADC_BUTTONS);
34 if (adc_val < 30) {
35 return BUTTON_UP | (GPIO_PCDR & POWEROFF_BUTTON);
36 } else if (adc_val < 250) {
37 return BUTTON_RIGHT | (GPIO_PCDR & POWEROFF_BUTTON);
38 } else if (adc_val < 380) {
39 return BUTTON_LEFT | (GPIO_PCDR & POWEROFF_BUTTON);
40 } else if (adc_val < 450) {
41 return BUTTON_DOWN | (GPIO_PCDR & POWEROFF_BUTTON);
42 } else if (adc_val < 560) {
43 return BUTTON_PLAY | (GPIO_PCDR & POWEROFF_BUTTON);
44 }
45 return (GPIO_PCDR & POWEROFF_BUTTON);
46}
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 Andrew Ryabinin
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _BUTTON_TARGET_H_
22#define _BUTTON_TARGET_H_
23
24#include <stdbool.h>
25#include "config.h"
26
27void button_init_device(void);
28int button_read_device(void);
29
30
31#define BUTTON_UP 0x00000001
32#define BUTTON_DOWN 0x00000004
33#define BUTTON_LEFT 0x00000008
34#define BUTTON_RIGHT 0x00000010
35#define BUTTON_PLAY 0x00000020
36
37
38#define BUTTON_REMOTE 0
39
40
41#define POWEROFF_BUTTON 0x02
42#define POWEROFF_COUNT 30
43
44#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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 Andrew Ryabinin
11 *
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "config.h"
24#include "kernel.h"
25#include "lcd.h"
26#include "system.h"
27#include "cpu.h"
28#include "lcdif-rk27xx.h"
29
30
31/* TODO */
32static void lcd_sleep(unsigned int sleep)
33{
34 (void)sleep;
35}
36
37void lcd_display_init()
38{
39 unsigned int x, y;
40
41 /* Driving ability setting */
42 lcd_write_reg(0x60, 0x00);
43 lcd_write_reg(0x61, 0x06);
44 lcd_write_reg(0x62, 0x00);
45 lcd_write_reg(0x63, 0xC8);
46
47 /* Gamma 2.2 Setting */
48 lcd_write_reg(0x40, 0x00);
49 lcd_write_reg(0x41, 0x40);
50 lcd_write_reg(0x42, 0x45);
51 lcd_write_reg(0x43, 0x01);
52 lcd_write_reg(0x44, 0x60);
53 lcd_write_reg(0x45, 0x05);
54 lcd_write_reg(0x46, 0x0C);
55 lcd_write_reg(0x47, 0xD1);
56 lcd_write_reg(0x48, 0x05);
57
58 lcd_write_reg(0x50, 0x75);
59 lcd_write_reg(0x51, 0x01);
60 lcd_write_reg(0x52, 0x67);
61 lcd_write_reg(0x53, 0x14);
62 lcd_write_reg(0x54, 0xF2);
63 lcd_write_reg(0x55, 0x07);
64 lcd_write_reg(0x56, 0x03);
65 lcd_write_reg(0x57, 0x49);
66
67 /* Power voltage setting */
68 lcd_write_reg(0x1F, 0x03);
69 lcd_write_reg(0x20, 0x00);
70 lcd_write_reg(0x24, 0x28);
71 lcd_write_reg(0x25, 0x45);
72
73 lcd_write_reg(0x23, 0x2F);
74
75 /* Power on setting */
76 lcd_write_reg(0x18, 0x44);
77 lcd_write_reg(0x21, 0x01);
78 lcd_write_reg(0x01, 0x00);
79 lcd_write_reg(0x1C, 0x03);
80 lcd_write_reg(0x19, 0x06);
81 udelay(5);
82
83 /* Display on setting */
84 lcd_write_reg(0x26, 0x84);
85 udelay(40);
86 lcd_write_reg(0x26, 0xB8);
87 udelay(40);
88 lcd_write_reg(0x26, 0xBC);
89 udelay(40);
90
91 /* Memmory access setting */
92 lcd_write_reg(0x16, 0x48);
93 /* Setup 16bit mode */
94 lcd_write_reg(0x17, 0x05);
95
96 /* Set GRAM area */
97 lcd_write_reg(0x02, 0x00);
98 lcd_write_reg(0x03, 0x00);
99 lcd_write_reg(0x04, 0x00);
100 lcd_write_reg(0x05, LCD_HEIGHT - 1);
101 lcd_write_reg(0x06, 0x00);
102 lcd_write_reg(0x07, 0x00);
103 lcd_write_reg(0x08, 0x00);
104 lcd_write_reg(0x09, LCD_WIDTH - 1);
105
106 /* Start GRAM write */
107 lcd_cmd(0x22);
108
109 for (x=0; x<LCD_WIDTH; x++)
110 for(y=0; y<LCD_HEIGHT; y++)
111 lcd_data(0x00);
112
113 lcd_sleep(0);
114}
115
116
117
118void lcd_update_rect(int x, int y, int width, int height)
119{
120 int px = x, py = y;
121 int pxmax = x + width, pymax = y + height;
122
123 lcd_write_reg(0x03, y);
124 lcd_write_reg(0x05, pymax-1);
125 lcd_write_reg(0x07, x);
126 lcd_write_reg(0x09, pxmax-1);
127
128 lcd_cmd(0x22);
129
130 for (px=x; px<pxmax; px++)
131 for (py=y; py<pymax; py++)
132 lcd_data(lcd_framebuffer[py][px]);
133}
134
135/* Blit a YUV bitmap directly to the LCD */
136void lcd_blit_yuv(unsigned char * const src[3],
137 int src_x, int src_y, int stride,
138 int x, int y, int width, int height)
139{
140 (void)src;
141 (void)src_x;
142 (void)src_y;
143 (void)stride;
144 (void)x;
145 (void)y;
146 (void)width;
147 (void)height;
148}
diff --git a/firmware/target/arm/rk27xx/hm60x/power-hm60x.c b/firmware/target/arm/rk27xx/hm60x/power-hm60x.c
new file mode 100644
index 0000000000..5c2abeb121
--- /dev/null
+++ b/firmware/target/arm/rk27xx/hm60x/power-hm60x.c
@@ -0,0 +1,48 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright © 2009 Bertrik Sikken
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <stdbool.h>
22#include "config.h"
23#include "inttypes.h"
24#include "power.h"
25#include "panic.h"
26#include "system.h"
27#include "usb_core.h" /* for usb_charging_maxcurrent_change */
28
29void power_off(void)
30{
31
32}
33
34void power_init(void)
35{
36 GPIO_PCDR |= (1<<0);
37 GPIO_PCCON |= (1<<0);
38}
39
40unsigned int power_input_status(void)
41{
42 return (usb_detect() == USB_INSERTED) ? POWER_INPUT_MAIN_CHARGER : POWER_INPUT_NONE;
43}
44
45bool charging_state(void)
46{
47 return true;
48}
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright © 2009 Bertrik Sikken
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "adc.h"
24#include "adc-target.h"
25#include "powermgmt.h"
26
27/* Battery voltage calculation and discharge/charge curves for the Meizu M3.
28
29 Battery voltage is calculated under the assumption that the adc full-scale
30 readout represents 3.00V and that the battery ADC channel is fed with
31 exactly half of the battery voltage (through a resistive divider).
32 Discharge and charge curves have not been calibrated yet.
33*/
34
35const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
36{
37 /* TODO: this is just an initial guess */
38 3400
39};
40
41const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
42{
43 /* TODO: this is just an initial guess */
44 3300
45};
46
47/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
48const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
49{
50 /* TODO: simple uncalibrated curve, linear except for first 10% */
51 { 3300, 3600, 3665, 3730, 3795, 3860, 3925, 3990, 4055, 4120, 4185 }
52};
53
54/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
55const unsigned short percent_to_volt_charge[11] =
56 /* TODO: simple uncalibrated curve, linear except for first 10% */
57 { 3300, 3600, 3665, 3730, 3795, 3860, 3925, 3990, 4055, 4120, 4185 };
58
59/* full-scale ADC readout (2^10) in millivolt */
60#define BATTERY_SCALE_FACTOR 6000
61
62/* Returns battery voltage from ADC [millivolts] */
63unsigned int battery_adc_voltage(void)
64{
65 return (adc_read(ADC_BATTERY) * BATTERY_SCALE_FACTOR) >> 10;
66}
diff --git a/firmware/target/arm/rk27xx/lcdif-rk27xx.c b/firmware/target/arm/rk27xx/lcdif-rk27xx.c
new file mode 100644
index 0000000000..aeee63ee7e
--- /dev/null
+++ b/firmware/target/arm/rk27xx/lcdif-rk27xx.c
@@ -0,0 +1,161 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 Marcin Bukat
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "kernel.h"
24#include "lcd.h"
25#include "system.h"
26#include "cpu.h"
27#include "lcdif-rk27xx.h"
28
29
30unsigned int lcd_data_transform(unsigned int data)
31{
32 unsigned int r, g, b;
33
34#if defined(RK27_GENERIC)
35 /* 18 bit interface */
36 r = (data & 0x0000fc00)<<8;
37 /* g = ((data & 0x00000300) >> 2) | ((data & 0x000000e0) >> 3); */
38 g = ((data & 0x00000300) << 6) | ((data & 0x000000e0) << 5);
39 b = (data & 0x00000001f) << 3;
40#elif defined(HM60X)
41 /* 16 bit interface */
42 r = (data & 0x0000f800) << 8;
43 g = (data & 0x000007e0) << 5;
44 b = (data & 0x0000001f) << 3;
45#else
46#error "Unknown target"
47#endif
48
49 return (r | g | b);
50}
51
52void lcd_cmd(unsigned int cmd)
53{
54 LCD_COMMAND = lcd_data_transform(cmd);
55}
56
57void lcd_data(unsigned int data)
58{
59 LCD_DATA = lcd_data_transform(data);
60}
61
62void lcd_write_reg(unsigned int reg, unsigned int val)
63{
64 lcd_cmd(reg);
65 lcd_data(val);
66}
67
68static void lcdctrl_bypass(unsigned int on_off)
69{
70 while (!(LCDC_STA & LCDC_MCU_IDLE));
71
72 if (on_off)
73 MCU_CTRL |= MCU_CTRL_BYPASS;
74 else
75 MCU_CTRL &= ~MCU_CTRL_BYPASS;
76}
77
78/* This part is unclear. I am unable to use buffered/FIFO based writes
79 * to lcd. Depending on settings of IF I get various patterns on display
80 * but not what I want to display apparently.
81 */
82static void lcdctrl_init(void)
83{
84 /* alpha b111
85 * stop at current frame complete
86 * MCU mode
87 * 24b RGB
88 */
89 LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B;
90 MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS;
91
92 HOR_ACT = LCD_WIDTH + 3; /* define horizonatal active region */
93 VERT_ACT = LCD_HEIGHT; /* define vertical active region */
94 VERT_PERIOD = 0xfff; /* CSn/WEn/RDn signal timings */
95
96 LINE0_YADDR = LINE_ALPHA_EN | 0x7fe;
97 LINE1_YADDR = LINE_ALPHA_EN | ((1 * LCD_WIDTH) - 2);
98 LINE2_YADDR = LINE_ALPHA_EN | ((2 * LCD_WIDTH) - 2);
99 LINE3_YADDR = LINE_ALPHA_EN | ((3 * LCD_WIDTH) - 2);
100
101 LINE0_UVADDR = 0x7fe + 1;
102 LINE1_UVADDR = ((1 * LCD_WIDTH) - 2 + 1);
103 LINE2_UVADDR = ((2 * LCD_WIDTH) - 2 + 1);
104 LINE3_UVADDR = ((3 * LCD_WIDTH) - 2 + 1);
105
106#if 0
107 LINE0_YADDR = 0;
108 LINE1_YADDR = (1 * LCD_WIDTH);
109 LINE2_YADDR = (2 * LCD_WIDTH);
110 LINE3_YADDR = (3 * LCD_WIDTH);
111
112 LINE0_UVADDR = 1;
113 LINE1_UVADDR = (1 * LCD_WIDTH) + 1;
114 LINE2_UVADDR = (2 * LCD_WIDTH) + 1;
115 LINE3_UVADDR = (3 * LCD_WIDTH) + 1;
116
117 START_X = 0;
118 START_Y = 0;
119 DELTA_X = 0x200; /* no scaling */
120 DELTA_Y = 0x200; /* no scaling */
121#endif
122 LCDC_INTR_MASK = INTR_MASK_LINE; /* INTR_MASK_EVENLINE; */
123}
124
125/* configure pins to drive lcd in 18bit mode */
126static void iomux_lcd(void)
127{
128 unsigned long muxa;
129
130 muxa = SCU_IOMUXA_CON & ~(IOMUX_LCD_VSYNC|IOMUX_LCD_DEN|0xff);
131 muxa |= IOMUX_LCD_D18|IOMUX_LCD_D20|IOMUX_LCD_D22|IOMUX_LCD_D17|IOMUX_LCD_D16;
132
133 SCU_IOMUXA_CON = muxa;
134 SCU_IOMUXB_CON |= IOMUX_LCD_D815;
135}
136
137void lcd_init_device()
138{
139 iomux_lcd(); /* setup pins for 16bit lcd interface */
140 lcdctrl_init(); /* basic lcdc module configuration */
141
142 lcdctrl_bypass(1); /* run in bypass mode - all writes goes directly to lcd controller */
143 lcd_display_init();
144}
145
146/* This is ugly hack. We drive lcd in bypass mode
147 * where all writes goes directly to lcd controller.
148 * This is suboptimal at best. IF module povides
149 * FIFO, internal sram buffer, hardware scaller,
150 * DMA signals, hardware alpha blending and more.
151 * BUT the fact is that I have no idea how to use
152 * this modes. Datasheet floating around is very
153 * unclean in this regard and OF uses ackward
154 * lcd update routines which are hard to understand.
155 * Moreover OF sets some bits in IF module registers
156 * which are referred as reseved in datasheet.
157 */
158void lcd_update()
159{
160 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
161}
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 @@
1#ifndef _LCDIF_RK27XX_H
2#define _LCDIF_RK27XX_H
3
4unsigned int lcd_data_transform(unsigned int data);
5
6void lcd_cmd(unsigned int cmd);
7void lcd_data(unsigned int data);
8void lcd_write_reg(unsigned int reg, unsigned int val);
9void lcd_display_init(void);
10
11#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 @@
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2011 Marcin Bukat 10 * Copyright (C) 2011 Marcin Bukat
11 * Copyright (C) 2011 Andrew Ryabinin
11 * 12 *
12 * This program is free software; you can redistribute it and/or 13 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License 14 * modify it under the terms of the GNU General Public License
@@ -179,13 +180,65 @@ static void i2s_init(void)
179 (0<<2) | /* normal operation */ 180 (0<<2) | /* normal operation */
180#ifdef CODEC_SLAVE 181#ifdef CODEC_SLAVE
181 (1<<1) | /* start Tx (master mode) */ 182 (1<<1) | /* start Tx (master mode) */
182 (1<<0); /* start Rx (master mode) */ 183 (0<<0); /* do not start Rx (master mode) */
184 /* setting Rx bit to 1 result in choppy audio */
183#else 185#else
184 (0<<1) | /* not used in slave mode */ 186 (0<<1) | /* not used in slave mode */
185 (0<<0); /* not used in slave mode */ 187 (0<<0); /* not used in slave mode */
186#endif 188#endif
187} 189}
188 190
191#ifdef CODEC_SLAVE
192/* When codec is slave we need to setup i2s MCLK clock using codec pll.
193 * The MCLK frequency is 256*codec frequency as i2s setup is:
194 * LRCK/SCLK = 64 and MCLK/SCLK = 4 (see i2s_init() for reference)
195 *
196 * PLL output frequency:
197 * Fout = ((Fref / (CLKR+1)) * (CLKF+1)) / (CLKOD+1)
198 * Fref = 24 MHz
199 */
200static void set_codec_freq(unsigned int freq)
201{
202 long timeout;
203
204 /* {CLKR, CLKF, CLKOD, CODECPLL_DIV} */
205 static const unsigned int pcm_freq_params[HW_NUM_FREQ][4] =
206 {
207 [HW_FREQ_96] = {24, 255, 4, 1},
208 [HW_FREQ_48] = {24, 127, 4, 1},
209 [HW_FREQ_44] = {24, 293, 4, 4},
210 [HW_FREQ_32] = {24, 127, 4, 2},
211 [HW_FREQ_24] = {24, 127, 4, 3},
212 [HW_FREQ_22] = {24, 146, 4, 4},
213 [HW_FREQ_16] = {24, 127, 5, 4},
214 [HW_FREQ_12] = {24, 127, 4, 7},
215 [HW_FREQ_11] = {24, 146, 4, 9},
216 [HW_FREQ_8] = {24, 127, 5, 9},
217 };
218 /* select divider output from codec pll */
219 SCU_DIVCON1 &= ~((1<<9) | (0xF<<5));
220 SCU_DIVCON1 |= (pcm_freq_params[freq][3]<<5);
221
222 /* Codec PLL power up */
223 SCU_PLLCON3 &= ~(1<<22);
224
225 SCU_PLLCON3 = (1<<24) | /* Saturation behavior enable */
226 (1<<23) | /* Enable fast locking circuit */
227 (pcm_freq_params[freq][0]<<16) | /* CLKR factor */
228 (pcm_freq_params[freq][1]<<4) | /* CLKF factor */
229 (pcm_freq_params[freq][2]<<1) ; /* CLKOD factor */
230
231/* wait for CODEC PLL lock with 10 ms timeout
232 * datasheet states that pll lock should take approx. 0.3 ms
233 */
234 timeout = current_tick + (HZ/100);
235 while (!(SCU_STATUS & (1<<2)))
236 if (TIME_AFTER(current_tick, timeout))
237 break;
238
239}
240#endif
241
189void pcm_play_dma_init(void) 242void pcm_play_dma_init(void)
190{ 243{
191 /* unmask HDMA interrupt in INTC */ 244 /* unmask HDMA interrupt in INTC */
@@ -204,8 +257,11 @@ void pcm_play_dma_postinit(void)
204 257
205void pcm_dma_apply_settings(void) 258void pcm_dma_apply_settings(void)
206{ 259{
207 /* I2S module runs in slave mode */ 260#ifdef CODEC_SLAVE
208 return; 261 set_codec_freq(pcm_fsel);
262#endif
263
264 audiohw_set_frequency(pcm_fsel);
209} 265}
210 266
211size_t pcm_get_bytes_waiting(void) 267size_t pcm_get_bytes_waiting(void)
diff --git a/firmware/target/arm/rk27xx/lcd-rk27xx.c b/firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c
index fda95e3174..b184630ebe 100644
--- a/firmware/target/arm/rk27xx/lcd-rk27xx.c
+++ b/firmware/target/arm/rk27xx/rk27generic/lcd-rk27generic.c
@@ -25,7 +25,9 @@
25#include "system.h" 25#include "system.h"
26#include "cpu.h" 26#include "cpu.h"
27#include "spfd5420a.h" 27#include "spfd5420a.h"
28#include "lcdif-rk27xx.h"
28 29
30/* TODO: convert to udelay() */
29static inline void delay_nop(int cycles) 31static inline void delay_nop(int cycles)
30{ 32{
31 asm volatile ("1: subs %[n], %[n], #1 \n\t" 33 asm volatile ("1: subs %[n], %[n], #1 \n\t"
@@ -34,17 +36,6 @@ static inline void delay_nop(int cycles)
34 : [n] "r" (cycles)); 36 : [n] "r" (cycles));
35} 37}
36 38
37static unsigned int lcd_data_transform(unsigned int data)
38{
39 /* 18 bit interface */
40 unsigned int r, g, b;
41 r = (data & 0x0000fc00)<<8;
42 /* g = ((data & 0x00000300) >> 2) | ((data & 0x000000e0) >> 3); */
43 g = ((data & 0x00000300) << 6) | ((data & 0x000000e0) << 5);
44 b = (data & 0x00000001f) << 3;
45
46 return (r | g | b);
47}
48 39
49/* converts RGB565 pixel into internal lcd bus format */ 40/* converts RGB565 pixel into internal lcd bus format */
50static unsigned int lcd_pixel_transform(unsigned short rgb565) 41static unsigned int lcd_pixel_transform(unsigned short rgb565)
@@ -57,93 +48,8 @@ static unsigned int lcd_pixel_transform(unsigned short rgb565)
57 return r<<19 | g<<10 | b<<3; 48 return r<<19 | g<<10 | b<<3;
58} 49}
59 50
60static void lcd_cmd(unsigned int cmd)
61{
62 LCD_COMMAND = lcd_data_transform(cmd);
63}
64
65static void lcd_data(unsigned int data)
66{
67 LCD_DATA = lcd_data_transform(data);
68}
69
70static void lcd_write_reg(unsigned int reg, unsigned int val)
71{
72 lcd_cmd(reg);
73 lcd_data(val);
74}
75
76static void lcdctrl_bypass(unsigned int on_off)
77{
78 while (!(LCDC_STA & LCDC_MCU_IDLE));
79
80 if (on_off)
81 MCU_CTRL |= MCU_CTRL_BYPASS;
82 else
83 MCU_CTRL &= ~MCU_CTRL_BYPASS;
84}
85
86/* This part is unclear. I am unable to use buffered/FIFO based writes
87 * to lcd. Depending on settings of IF I get various patterns on display
88 * but not what I want to display apparently.
89 */
90static void lcdctrl_init(void)
91{
92 /* alpha b111
93 * stop at current frame complete
94 * MCU mode
95 * 24b RGB
96 */
97 LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B;
98 MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS;
99
100 HOR_ACT = 400 + 3; /* define horizonatal active region */
101 VERT_ACT = 240; /* define vertical active region */
102 VERT_PERIOD = 0xfff; /* CSn/WEn/RDn signal timings */
103
104 LINE0_YADDR = LINE_ALPHA_EN | 0x7fe;
105 LINE1_YADDR = LINE_ALPHA_EN | ((1 * 400) - 2);
106 LINE2_YADDR = LINE_ALPHA_EN | ((2 * 400) - 2);
107 LINE3_YADDR = LINE_ALPHA_EN | ((3 * 400) - 2);
108
109 LINE0_UVADDR = 0x7fe + 1;
110 LINE1_UVADDR = ((1 * 400) - 2 + 1);
111 LINE2_UVADDR = ((2 * 400) - 2 + 1);
112 LINE3_UVADDR = ((3 * 400) - 2 + 1);
113
114#if 0
115 LINE0_YADDR = 0;
116 LINE1_YADDR = (1 * 400);
117 LINE2_YADDR = (2 * 400);
118 LINE3_YADDR = (3 * 400);
119
120 LINE0_UVADDR = 1;
121 LINE1_UVADDR = (1 * 400) + 1;
122 LINE2_UVADDR = (2 * 400) + 1;
123 LINE3_UVADDR = (3 * 400) + 1;
124
125 START_X = 0;
126 START_Y = 0;
127 DELTA_X = 0x200; /* no scaling */
128 DELTA_Y = 0x200; /* no scaling */
129#endif
130 LCDC_INTR_MASK = INTR_MASK_LINE; /* INTR_MASK_EVENLINE; */
131}
132
133/* configure pins to drive lcd in 18bit mode */
134static void iomux_lcd(void)
135{
136 unsigned long muxa;
137
138 muxa = SCU_IOMUXA_CON & ~(IOMUX_LCD_VSYNC|IOMUX_LCD_DEN|0xff);
139 muxa |= IOMUX_LCD_D18|IOMUX_LCD_D20|IOMUX_LCD_D22|IOMUX_LCD_D17|IOMUX_LCD_D16;
140
141 SCU_IOMUXA_CON = muxa;
142 SCU_IOMUXB_CON |= IOMUX_LCD_D815;
143}
144
145/* not tested */ 51/* not tested */
146static void lcd_sleep(unsigned int sleep) 52static void lcd_sleep(bool sleep)
147{ 53{
148 if (sleep) 54 if (sleep)
149 { 55 {
@@ -165,15 +71,10 @@ static void lcd_sleep(unsigned int sleep)
165 lcd_cmd(GRAM_WRITE); 71 lcd_cmd(GRAM_WRITE);
166} 72}
167 73
168void lcd_init_device() 74void lcd_display_init()
169{ 75{
170 unsigned int x, y; 76 unsigned int x, y;
171 77
172 iomux_lcd(); /* setup pins for 18bit lcd interface */
173 lcdctrl_init(); /* basic lcdc module configuration */
174
175 lcdctrl_bypass(1); /* run in bypass mode - all writes goes directly to lcd controller */
176
177 lcd_write_reg(RESET, 0x0001); 78 lcd_write_reg(RESET, 0x0001);
178 delay_nop(10000); 79 delay_nop(10000);
179 lcd_write_reg(RESET, 0x0000); 80 lcd_write_reg(RESET, 0x0000);
@@ -265,31 +166,13 @@ void lcd_init_device()
265 /* clear screen */ 166 /* clear screen */
266 lcd_cmd(GRAM_WRITE); 167 lcd_cmd(GRAM_WRITE);
267 168
268 for (x=0; x<400; x++) 169 for (x=0; x<LCD_WIDTH; x++)
269 for(y=0; y<240; y++) 170 for(y=0; y<LCD_HEIGHT; y++)
270 lcd_data(0x000000); 171 lcd_data(0x000000);
271 172
272 lcd_sleep(0); 173 lcd_sleep(false);
273} 174}
274 175
275/* This is ugly hack. We drive lcd in bypass mode
276 * where all writes goes directly to lcd controller.
277 * This is suboptimal at best. IF module povides
278 * FIFO, internal sram buffer, hardware scaller,
279 * DMA signals, hardware alpha blending and more.
280 * BUT the fact is that I have no idea how to use
281 * this modes. Datasheet floating around is very
282 * unclean in this regard and OF uses ackward
283 * lcd update routines which are hard to understand.
284 * Moreover OF sets some bits in IF module registers
285 * which are referred as reseved in datasheet.
286 */
287void lcd_update()
288{
289 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
290}
291
292
293void lcd_update_rect(int x, int y, int width, int height) 176void lcd_update_rect(int x, int y, int width, int height)
294{ 177{
295 int px = x, py = y; 178 int px = x, py = y;