summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/imx233/creative-zenxfi3
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-06-17 00:06:24 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-06-17 00:29:25 +0200
commit069a0269a922ad466d35611d128dda377ef305c1 (patch)
tree2873857099d2f7f5ee2bf16c73b245fa821c8597 /firmware/target/arm/imx233/creative-zenxfi3
parent52426d08918eadfba178f74e1bd5d1663f9c73e0 (diff)
downloadrockbox-069a0269a922ad466d35611d128dda377ef305c1.tar.gz
rockbox-069a0269a922ad466d35611d128dda377ef305c1.tar.bz2
rockbox-069a0269a922ad466d35611d128dda377ef305c1.zip
imx233: fix/improve lcdif for stmp3600 and stmp4700, fix drivers
Factorise pin setup, rewrite PIO code, add support for lcdif irq, handle all the various differences between the stmps, drop yuv blitting code since it already exists in the common lcd drivers. Change-Id: Ifc40aed9b3b12f16611ce960602e46a5bc87ae53
Diffstat (limited to 'firmware/target/arm/imx233/creative-zenxfi3')
-rw-r--r--firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c395
1 files changed, 57 insertions, 338 deletions
diff --git a/firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c b/firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c
index 7afdaa316e..59496f2d24 100644
--- a/firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c
+++ b/firmware/target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c
@@ -32,161 +32,76 @@
#ifdef HAVE_LCD_ENABLE
static bool lcd_on;
#endif
-static unsigned lcd_yuv_options = 0;
-static void setup_parameters(void)
+static void lcd_write_reg(uint16_t reg, uint16_t data)
{
- imx233_lcdif_reset();
- imx233_lcdif_set_lcd_databus_width(BV_LCDIF_CTRL_LCD_DATABUS_WIDTH__16_BIT);
- imx233_lcdif_set_word_length(BV_LCDIF_CTRL_WORD_LENGTH__16_BIT);
- imx233_lcdif_set_timings(2, 2, 3, 3);
- imx233_lcdif_enable_underflow_recover(true);
-}
-
-static void setup_lcd_pins(bool use_lcdif)
-{
- /* WARNING
- * the B1P22 pins is used to gate the speaker! Do NOT drive
- * them as lcd_dotclk and lcd_hsync or it will break audio */
- imx233_pinctrl_acquire(1, 18, "lcd reset");
- imx233_pinctrl_acquire(1, 19, "lcd rs");
- imx233_pinctrl_acquire(1, 20, "lcd wr");
- imx233_pinctrl_acquire(1, 21, "lcd cs");
- imx233_pinctrl_acquire(1, 23, "lcd enable");
- imx233_pinctrl_acquire(1, 25, "lcd vsync");
- //imx233_pinctrl_acquire_mask(1, 0x3ffff, "lcd data");
- if(use_lcdif)
- {
- imx233_pinctrl_set_function(1, 25, PINCTRL_FUNCTION_MAIN); /* lcd_vsync */
- imx233_pinctrl_set_function(1, 21, PINCTRL_FUNCTION_MAIN); /* lcd_cs */
- imx233_pinctrl_set_function(1, 23, PINCTRL_FUNCTION_MAIN); /* lcd_enable */
- imx233_pinctrl_set_function(1, 18, PINCTRL_FUNCTION_MAIN); /* lcd_reset */
- imx233_pinctrl_set_function(1, 19, PINCTRL_FUNCTION_MAIN); /* lcd_rs */
- imx233_pinctrl_set_function(1, 16, PINCTRL_FUNCTION_MAIN); /* lcd_d16 */
- imx233_pinctrl_set_function(1, 17, PINCTRL_FUNCTION_MAIN); /* lcd_d17 */
- imx233_pinctrl_set_function(1, 20, PINCTRL_FUNCTION_MAIN); /* lcd_wr */
- HW_PINCTRL_MUXSELn_CLR(2) = 0xffffffff; /* lcd_d{0-15} */
- }
- else
- {
- HW_PINCTRL_MUXSELn_SET(2) = 0xffffffff; /* lcd_d{0-15} */
- HW_PINCTRL_DOEn_CLR(1) = 0x2bfffff;
- imx233_pinctrl_set_function(1, 16, PINCTRL_FUNCTION_GPIO); /* lcd_d16 */
- imx233_pinctrl_set_function(1, 17, PINCTRL_FUNCTION_GPIO); /* lcd_d17 */
- imx233_pinctrl_set_function(1, 19, PINCTRL_FUNCTION_GPIO); /* lcd_rs */
- imx233_pinctrl_set_function(1, 20, PINCTRL_FUNCTION_GPIO); /* lcd_wr */
- imx233_pinctrl_set_function(1, 21, PINCTRL_FUNCTION_GPIO); /* lcd_cs */
- imx233_pinctrl_set_function(1, 23, PINCTRL_FUNCTION_GPIO); /* lcd_enable */
- imx233_pinctrl_set_function(1, 25, PINCTRL_FUNCTION_GPIO); /* lcd_vsync */
- }
-}
-
-static void common_lcd_enable(bool enable)
-{
- imx233_lcdif_enable(enable);
- setup_lcd_pins(enable); /* use GPIO pins when disable */
+ imx233_lcdif_pio_send(false, 1, &reg);
+ if(reg != 0x22)
+ imx233_lcdif_pio_send(true, 1, &data);
}
-static void setup_lcdif(void)
+static void lcd_init_seq(void)
{
- setup_parameters();
- common_lcd_enable(true);
- imx233_lcdif_enable_bus_master(true);
+ lcd_write_reg(1, 0x11c);
+ lcd_write_reg(2, 0x100);
+ lcd_write_reg(3, 0x1030);
+ lcd_write_reg(8, 0x808);
+ lcd_write_reg(0xc, 0);
+ lcd_write_reg(0xf, 0xc01);
+ lcd_write_reg(0x20, 0);
+ lcd_write_reg(0x21, 0);
+ udelay(30);
+ lcd_write_reg(0x10, 0xa00);
+ lcd_write_reg(0x11, 0x1038);
+ udelay(30);
+ lcd_write_reg(0x12, 0x1010);
+ lcd_write_reg(0x13, 0x50);
+ lcd_write_reg(0x14, 0x4f58);
+ lcd_write_reg(0x30, 0);
+ lcd_write_reg(0x31, 0xdb);
+ lcd_write_reg(0x32, 0);
+ lcd_write_reg(0x33, 0);
+ lcd_write_reg(0x34, 0xdb);
+ lcd_write_reg(0x35, 0);
+ lcd_write_reg(0x36, 0xaf);
+ lcd_write_reg(0x37, 0);
+ lcd_write_reg(0x38, 0xdb);
+ lcd_write_reg(0x39, 0);
+ lcd_write_reg(0x50, 0);
+ lcd_write_reg(0x51, 0x705);
+ lcd_write_reg(0x52, 0xe0a);
+ lcd_write_reg(0x53, 0x300);
+ lcd_write_reg(0x54, 0xa0e);
+ lcd_write_reg(0x55, 0x507);
+ lcd_write_reg(0x56, 0);
+ lcd_write_reg(0x57, 3);
+ lcd_write_reg(0x58, 0x90a);
+ lcd_write_reg(0x59, 0xa09);
+ udelay(30);
+ lcd_write_reg(7, 0x1017);
+ udelay(40);
}
-static void setup_lcdif_clock(void)
+void lcd_init_device(void)
{
/* the LCD seems to work at 24Mhz, so use the xtal clock with no divider */
imx233_clkctrl_enable(CLK_PIX, false);
imx233_clkctrl_set_div(CLK_PIX, 1);
imx233_clkctrl_set_bypass(CLK_PIX, true); /* use XTAL */
imx233_clkctrl_enable(CLK_PIX, true);
-}
-
-static void lcd_write_reg(uint32_t reg, uint32_t data)
-{
- imx233_lcdif_pio_send(false, 2, &reg);
- if(reg != 0x22)
- imx233_lcdif_pio_send(true, 2, &data);
-}
-
-#define REG_UDELAY 0xffffffff
-struct lcd_sequence_entry_t
-{
- uint32_t reg, data;
-};
-
-static void lcd_send_sequence(struct lcd_sequence_entry_t *seq, unsigned count)
-{
- for(;count-- > 0; seq++)
- {
- if(seq->reg == REG_UDELAY)
- udelay(seq->data);
- else
- lcd_write_reg(seq->reg, seq->data);
- }
-}
-
-#define _begin_seq() static struct lcd_sequence_entry_t __seq[] = {
-#define _udelay(a) {REG_UDELAY, a},
-#define _lcd_write_reg(a, b) {a, b},
-#define _end_seq() }; lcd_send_sequence(__seq, sizeof(__seq) / sizeof(__seq[0]));
-
-static void lcd_init_seq(void)
-{
- _begin_seq()
- _lcd_write_reg(1, 0x11c)
- _lcd_write_reg(2, 0x100)
- _lcd_write_reg(3, 0x1030)
- _lcd_write_reg(8, 0x808)
- _lcd_write_reg(0xc, 0)
- _lcd_write_reg(0xf, 0xc01)
- _lcd_write_reg(0x20, 0)
- _lcd_write_reg(0x21, 0)
- _udelay(30)
- _lcd_write_reg(0x10, 0xa00)
- _lcd_write_reg(0x11, 0x1038)
- _udelay(30)
- _lcd_write_reg(0x12, 0x1010)
- _lcd_write_reg(0x13, 0x50)
- _lcd_write_reg(0x14, 0x4f58)
- _lcd_write_reg(0x30, 0)
- _lcd_write_reg(0x31, 0xdb)
- _lcd_write_reg(0x32, 0)
- _lcd_write_reg(0x33, 0)
- _lcd_write_reg(0x34, 0xdb)
- _lcd_write_reg(0x35, 0)
- _lcd_write_reg(0x36, 0xaf)
- _lcd_write_reg(0x37, 0)
- _lcd_write_reg(0x38, 0xdb)
- _lcd_write_reg(0x39, 0)
- _lcd_write_reg(0x50, 0)
- _lcd_write_reg(0x51, 0x705)
- _lcd_write_reg(0x52, 0xe0a)
- _lcd_write_reg(0x53, 0x300)
- _lcd_write_reg(0x54, 0xa0e)
- _lcd_write_reg(0x55, 0x507)
- _lcd_write_reg(0x56, 0)
- _lcd_write_reg(0x57, 3)
- _lcd_write_reg(0x58, 0x90a)
- _lcd_write_reg(0x59, 0xa09)
- _udelay(30)
- _lcd_write_reg(7, 0x1017)
- _udelay(40)
- _end_seq()
-}
-
-void lcd_init_device(void)
-{
- setup_lcdif();
- setup_lcdif_clock();
+ imx233_lcdif_init();
+ imx233_lcdif_set_lcd_databus_width(16);
+ imx233_lcdif_set_word_length(16);
+ imx233_lcdif_set_timings(2, 2, 3, 3);
+ imx233_lcdif_enable_underflow_recover(true);
+ imx233_lcdif_setup_system_pins(16);
// reset device
- BF_SET(LCDIF_CTRL1, RESET);
+ imx233_lcdif_reset_lcd(true);
mdelay(50);
- BF_CLR(LCDIF_CTRL1, RESET);
+ imx233_lcdif_reset_lcd(false);
mdelay(10);
- BF_SET(LCDIF_CTRL1, RESET);
+ imx233_lcdif_reset_lcd(true);
lcd_init_seq();
#ifdef HAVE_LCD_ENABLE
@@ -204,13 +119,9 @@ static void lcd_enable_seq(bool enable)
{
if(!enable)
{
- _begin_seq()
- _end_seq()
}
else
{
- _begin_seq()
- _end_seq()
}
}
@@ -220,12 +131,12 @@ void lcd_enable(bool enable)
return;
lcd_on = enable;
-
+
if(enable)
- common_lcd_enable(true);
+ imx233_lcdif_enable(true);
lcd_enable_seq(enable);
if(!enable)
- common_lcd_enable(false);
+ imx233_lcdif_enable(false);
else
send_event(LCD_EVENT_ACTIVATION, NULL);
}
@@ -258,9 +169,8 @@ void lcd_update_rect(int x, int y, int w, int h)
lcd_write_reg(0x22, 0);
imx233_lcdif_wait_ready();
- imx233_lcdif_set_word_length(BV_LCDIF_CTRL_WORD_LENGTH__16_BIT);
+ imx233_lcdif_set_word_length(16);
imx233_lcdif_set_byte_packing_format(0xf); /* two pixels per 32-bit word */
- imx233_lcdif_set_data_format(false, false, false); /* RGB565, don't care, don't care */
/* there are two cases here:
* - either width = LCD_WIDTH and we can directly memcopy a part of lcd_framebuffer to FRAME
@@ -306,194 +216,3 @@ void lcd_update_rect(int x, int y, int w, int h)
imx233_lcdif_dma_send((void *)FRAME_PHYS_ADDR, w, h);
}
-void lcd_yuv_set_options(unsigned options)
-{
- lcd_yuv_options = options;
-}
-
-#define YFAC (74)
-#define RVFAC (101)
-#define GUFAC (-24)
-#define GVFAC (-51)
-#define BUFAC (128)
-
-static inline int clamp(int val, int min, int max)
-{
- if (val < min)
- val = min;
- else if (val > max)
- val = max;
- return val;
-}
-
-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)
-{
- const unsigned char *ysrc, *usrc, *vsrc;
- int linecounter;
- fb_data *dst, *row_end;
- long z;
-
- /* width and height must be >= 2 and an even number */
- width &= ~1;
- linecounter = height >> 1;
-
- #if LCD_WIDTH >= LCD_HEIGHT
- dst = FBADDR(x,y);
- row_end = dst + width;
- #else
- dst = FBADDR(LCD_WIDTH - y - 1,x);
- row_end = dst + LCD_WIDTH * width;
- #endif
-
- z = stride * src_y;
- ysrc = src[0] + z + src_x;
- usrc = src[1] + (z >> 2) + (src_x >> 1);
- vsrc = src[2] + (usrc - src[1]);
-
- /* stride => amount to jump from end of last row to start of next */
- stride -= width;
-
- /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
-
- do
- {
- do
- {
- int y, cb, cr, rv, guv, bu, r, g, b;
-
- y = YFAC*(*ysrc++ - 16);
- cb = *usrc++ - 128;
- cr = *vsrc++ - 128;
-
- rv = RVFAC*cr;
- guv = GUFAC*cb + GVFAC*cr;
- bu = BUFAC*cb;
-
- r = y + rv;
- g = y + guv;
- b = y + bu;
-
- if ((unsigned)(r | g | b) > 64*256-1)
- {
- r = clamp(r, 0, 64*256-1);
- g = clamp(g, 0, 64*256-1);
- b = clamp(b, 0, 64*256-1);
- }
-
- *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
-
- #if LCD_WIDTH >= LCD_HEIGHT
- dst++;
- #else
- dst += LCD_WIDTH;
- #endif
-
- y = YFAC*(*ysrc++ - 16);
- r = y + rv;
- g = y + guv;
- b = y + bu;
-
- if ((unsigned)(r | g | b) > 64*256-1)
- {
- r = clamp(r, 0, 64*256-1);
- g = clamp(g, 0, 64*256-1);
- b = clamp(b, 0, 64*256-1);
- }
-
- *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
-
- #if LCD_WIDTH >= LCD_HEIGHT
- dst++;
- #else
- dst += LCD_WIDTH;
- #endif
- }
- while (dst < row_end);
-
- ysrc += stride;
- usrc -= width >> 1;
- vsrc -= width >> 1;
-
- #if LCD_WIDTH >= LCD_HEIGHT
- row_end += LCD_WIDTH;
- dst += LCD_WIDTH - width;
- #else
- row_end -= 1;
- dst -= LCD_WIDTH*width + 1;
- #endif
-
- do
- {
- int y, cb, cr, rv, guv, bu, r, g, b;
-
- y = YFAC*(*ysrc++ - 16);
- cb = *usrc++ - 128;
- cr = *vsrc++ - 128;
-
- rv = RVFAC*cr;
- guv = GUFAC*cb + GVFAC*cr;
- bu = BUFAC*cb;
-
- r = y + rv;
- g = y + guv;
- b = y + bu;
-
- if ((unsigned)(r | g | b) > 64*256-1)
- {
- r = clamp(r, 0, 64*256-1);
- g = clamp(g, 0, 64*256-1);
- b = clamp(b, 0, 64*256-1);
- }
-
- *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
-
- #if LCD_WIDTH >= LCD_HEIGHT
- dst++;
- #else
- dst += LCD_WIDTH;
- #endif
-
- y = YFAC*(*ysrc++ - 16);
- r = y + rv;
- g = y + guv;
- b = y + bu;
-
- if ((unsigned)(r | g | b) > 64*256-1)
- {
- r = clamp(r, 0, 64*256-1);
- g = clamp(g, 0, 64*256-1);
- b = clamp(b, 0, 64*256-1);
- }
-
- *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
-
- #if LCD_WIDTH >= LCD_HEIGHT
- dst++;
- #else
- dst += LCD_WIDTH;
- #endif
- }
- while (dst < row_end);
-
- ysrc += stride;
- usrc += stride >> 1;
- vsrc += stride >> 1;
-
- #if LCD_WIDTH >= LCD_HEIGHT
- row_end += LCD_WIDTH;
- dst += LCD_WIDTH - width;
- #else
- row_end -= 1;
- dst -= LCD_WIDTH*width + 1;
- #endif
- }
- while (--linecounter > 0);
-
- #if LCD_WIDTH >= LCD_HEIGHT
- lcd_update_rect(x, y, width, height);
- #else
- lcd_update_rect(LCD_WIDTH - y - height, x, height, width);
- #endif
-}