diff options
Diffstat (limited to 'firmware/target/arm/rk27xx')
-rw-r--r-- | firmware/target/arm/rk27xx/adc-target.h | 4 | ||||
-rw-r--r-- | firmware/target/arm/rk27xx/debug-target.h | 4 | ||||
-rw-r--r-- | firmware/target/arm/rk27xx/hm60x/button-hm60x.c | 46 | ||||
-rw-r--r-- | firmware/target/arm/rk27xx/hm60x/button-target.h | 44 | ||||
-rw-r--r-- | firmware/target/arm/rk27xx/hm60x/lcd-hm60x.c | 148 | ||||
-rw-r--r-- | firmware/target/arm/rk27xx/hm60x/power-hm60x.c | 48 | ||||
-rw-r--r-- | firmware/target/arm/rk27xx/hm60x/powermgmt-hm60x.c | 66 | ||||
-rw-r--r-- | firmware/target/arm/rk27xx/lcdif-rk27xx.c | 161 | ||||
-rw-r--r-- | firmware/target/arm/rk27xx/lcdif-rk27xx.h | 11 | ||||
-rw-r--r-- | firmware/target/arm/rk27xx/pcm-rk27xx.c | 62 | ||||
-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 @@ #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 <stdbool.h> +#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 <stdbool.h> +#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<LCD_WIDTH; x++) + for(y=0; y<LCD_HEIGHT; y++) + lcd_data(0x00); + + lcd_sleep(0); +} + + + +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_write_reg(0x03, y); + lcd_write_reg(0x05, pymax-1); + lcd_write_reg(0x07, x); + lcd_write_reg(0x09, pxmax-1); + + lcd_cmd(0x22); + + for (px=x; px<pxmax; px++) + for (py=y; py<pymax; py++) + lcd_data(lcd_framebuffer[py][px]); +} + +/* 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/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 @@ +/*************************************************************************** + * __________ __ ___. + * 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 <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) +{ + +} + +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/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 @@ +/*************************************************************************** + * __________ __ ___. + * 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 "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/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 @@ #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" @@ -34,17 +36,6 @@ static inline void delay_nop(int cycles) : [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) @@ -57,93 +48,8 @@ static unsigned int lcd_pixel_transform(unsigned short rgb565) 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) +static void lcd_sleep(bool sleep) { if (sleep) { @@ -165,15 +71,10 @@ static void lcd_sleep(unsigned int sleep) lcd_cmd(GRAM_WRITE); } -void lcd_init_device() +void lcd_display_init() { 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); @@ -265,31 +166,13 @@ void lcd_init_device() /* clear screen */ lcd_cmd(GRAM_WRITE); - for (x=0; x<400; x++) - for(y=0; y<240; y++) + for (x=0; x<LCD_WIDTH; x++) + for(y=0; y<LCD_HEIGHT; y++) lcd_data(0x000000); - lcd_sleep(0); + lcd_sleep(false); } -/* 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; |