summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx233/lcdif-imx233.c
diff options
context:
space:
mode:
authorAmaury Pouly <pamaury@rockbox.org>2011-05-01 13:02:46 +0000
committerAmaury Pouly <pamaury@rockbox.org>2011-05-01 13:02:46 +0000
commit08fb3f65745a237e2c1eae55d856ff27702246e5 (patch)
treea56ce11ac20e4df0e36de9195306c10b71752538 /firmware/target/arm/imx233/lcdif-imx233.c
parentc0838cbfd8e45621fe3450aee1bf9458ff420d16 (diff)
Sansa Fuze+: initial commit (bootloader only, LCD basically working)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29808 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/imx233/lcdif-imx233.c')
-rw-r--r--firmware/target/arm/imx233/lcdif-imx233.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/firmware/target/arm/imx233/lcdif-imx233.c b/firmware/target/arm/imx233/lcdif-imx233.c
new file mode 100644
index 0000000000..0b96cbf2bc
--- /dev/null
+++ b/firmware/target/arm/imx233/lcdif-imx233.c
@@ -0,0 +1,171 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (c) 2011 by Amaury Pouly
+ *
+ * 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 "lcdif-imx233.h"
+
+static unsigned lcdif_word_length = 0;
+static unsigned lcdif_byte_packing = 0;
+
+void imx233_lcdif_enable_bus_master(bool enable)
+{
+ if(enable)
+ __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__LCDIF_MASTER;
+ else
+ __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__LCDIF_MASTER;
+}
+
+void imx233_lcdif_enable(bool enable)
+{
+ if(enable)
+ __REG_CLR(HW_LCDIF_CTRL) = __BLOCK_CLKGATE;
+ else
+ __REG_SET(HW_LCDIF_CTRL) = __BLOCK_CLKGATE;
+}
+
+void imx233_lcdif_reset(void)
+{
+ //imx233_reset_block(&HW_LCDIF_CTRL);// doesn't work
+ while(HW_LCDIF_CTRL & __BLOCK_CLKGATE)
+ HW_LCDIF_CTRL &= ~__BLOCK_CLKGATE;
+ while(!(HW_LCDIF_CTRL & __BLOCK_SFTRST))
+ HW_LCDIF_CTRL |= __BLOCK_SFTRST;
+ while(HW_LCDIF_CTRL & __BLOCK_CLKGATE)
+ HW_LCDIF_CTRL &= ~__BLOCK_CLKGATE;
+ while(HW_LCDIF_CTRL & __BLOCK_SFTRST)
+ HW_LCDIF_CTRL &= ~__BLOCK_SFTRST;
+ while(HW_LCDIF_CTRL & __BLOCK_CLKGATE)
+ HW_LCDIF_CTRL &= ~__BLOCK_CLKGATE;
+ __REG_SET(HW_LCDIF_CTRL1) = HW_LCDIF_CTRL1__RESET;
+}
+
+void imx233_lcdif_set_timings(unsigned data_setup, unsigned data_hold,
+ unsigned cmd_setup, unsigned cmd_hold)
+{
+ HW_LCDIF_TIMING = (data_setup << HW_LCDIF_TIMING__DATA_SETUP_BP) |
+ (data_hold << HW_LCDIF_TIMING__DATA_HOLD_BP) |
+ (cmd_setup << HW_LCDIF_TIMING__CMD_SETUP_BP) |
+ (cmd_hold << HW_LCDIF_TIMING__CMD_HOLD_BP);
+}
+
+void imx233_lcdif_set_lcd_databus_width(unsigned width)
+{
+ __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__LCD_DATABUS_WIDTH_BM;
+ __REG_SET(HW_LCDIF_CTRL) = width;
+}
+
+void imx233_lcdif_set_word_length(unsigned word_length)
+{
+ __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__WORD_LENGTH_BM;
+ __REG_SET(HW_LCDIF_CTRL) = word_length;
+ lcdif_word_length = word_length;
+}
+
+unsigned imx233_lcdif_enable_irqs(unsigned irq_bm)
+{
+ unsigned old_msk = (HW_LCDIF_CTRL1 & HW_LCDIF_CTRL1__IRQ_EN_BM) >>HW_LCDIF_CTRL1__IRQ_EN_BP ;
+ /* clear irq status */
+ __REG_CLR(HW_LCDIF_CTRL1) = irq_bm << HW_LCDIF_CTRL1__IRQ_BP;
+ /* disable irqs */
+ __REG_CLR(HW_LCDIF_CTRL1) = HW_LCDIF_CTRL1__IRQ_EN_BM;
+ /* enable irqs */
+ __REG_SET(HW_LCDIF_CTRL1) = irq_bm << HW_LCDIF_CTRL1__IRQ_EN_BP;
+
+ return old_msk;
+}
+
+void imx233_lcdif_set_byte_packing_format(unsigned byte_packing)
+{
+ __REG_CLR(HW_LCDIF_CTRL1) = HW_LCDIF_CTRL1__BYTE_PACKING_FORMAT_BM;
+ __REG_SET(HW_LCDIF_CTRL1) = byte_packing << HW_LCDIF_CTRL1__BYTE_PACKING_FORMAT_BP;
+ lcdif_byte_packing = byte_packing;
+}
+
+void imx233_lcdif_set_data_format(bool data_fmt_16, bool data_fmt_18, bool data_fmt_24)
+{
+ if(data_fmt_16)
+ __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_FORMAT_16_BIT;
+ else
+ __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_FORMAT_16_BIT;
+ if(data_fmt_18)
+ __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_FORMAT_18_BIT;
+ else
+ __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_FORMAT_18_BIT;
+ if(data_fmt_24)
+ __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_FORMAT_24_BIT;
+ else
+ __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_FORMAT_24_BIT;
+}
+
+void imx233_lcdif_wait_ready(void)
+{
+ while(HW_LCDIF_CTRL & HW_LCDIF_CTRL__RUN);
+}
+
+void imx233_lcdif_pio_send(bool data_mode, unsigned len, uint32_t *buf)
+{
+ unsigned max_xfer_size = 0xffff;
+ if(len == 0)
+ return;
+ if(lcdif_word_length == HW_LCDIF_CTRL__WORD_LENGTH_16_BIT)
+ max_xfer_size = 0x1fffe;
+ imx233_lcdif_wait_ready();
+ unsigned msk = imx233_lcdif_enable_irqs(0);
+ imx233_lcdif_enable_bus_master(false);
+
+ do
+ {
+ unsigned burst = MIN(len, max_xfer_size);
+ len -= burst;
+ unsigned count = burst;
+ if(lcdif_word_length != HW_LCDIF_CTRL__WORD_LENGTH_8_BIT)
+ {
+ if(burst & 1)
+ burst++;
+ count = burst / 2;
+ }
+ else
+ count = burst;
+ HW_LCDIF_TRANSFER_COUNT = 0;
+ HW_LCDIF_TRANSFER_COUNT = 0x10000 | count;
+ __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_SELECT | HW_LCDIF_CTRL__RUN;
+ if(data_mode)
+ __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_SELECT;
+ __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__RUN;
+ burst = (burst + 3) / 4;
+ while(burst-- > 0)
+ {
+ while(HW_LCDIF_STAT & HW_LCDIF_STAT__LFIFO_FULL);
+ HW_LCDIF_DATA = *buf++;
+ }
+ while(HW_LCDIF_CTRL & HW_LCDIF_CTRL__RUN);
+ }while(len > 0);
+ imx233_lcdif_enable_bus_master(true);
+ imx233_lcdif_enable_irqs(msk);
+}
+
+void imx233_lcdif_dma_send(void *buf, unsigned width, unsigned height)
+{
+ HW_LCDIF_CUR_BUF = (uint32_t)buf;
+ HW_LCDIF_TRANSFER_COUNT = 0;
+ HW_LCDIF_TRANSFER_COUNT = (height << 16) | width;
+ __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__RUN;
+ __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_SELECT;
+ __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__RUN;
+}