aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Kocialkowski2015-01-22 18:48:57 +0100
committerPaul Kocialkowski2015-07-15 15:07:27 +0200
commitcd3e436019984b7222ac602fafc34e4757c9ff4d (patch)
tree7a3a5ced8716305e5ece29959cf4cf3e6578b599
parenta65e65ab6ee83426bebe9175b06e98f445c577c2 (diff)
WIP: Video import from LGE release
-rw-r--r--board/lge/sniper/Makefile2
-rwxr-xr-xboard/lge/sniper/hub_dispc.c2634
-rwxr-xr-xboard/lge/sniper/hub_dpi.c281
-rwxr-xr-xboard/lge/sniper/hub_dsi.c3205
-rwxr-xr-xboard/lge/sniper/hub_dss.h479
-rwxr-xr-xboard/lge/sniper/panel-hub.c629
6 files changed, 7229 insertions, 1 deletions
diff --git a/board/lge/sniper/Makefile b/board/lge/sniper/Makefile
index 94897160f98..88f0a45f09b 100644
--- a/board/lge/sniper/Makefile
+++ b/board/lge/sniper/Makefile
@@ -5,4 +5,4 @@
# SPDX-License-Identifier: GPL-2.0+
#
-obj-y := sniper.o
+obj-y := sniper.o hub_dispc.o hub_dpi.o hub_dsi.o panel-hub.o
diff --git a/board/lge/sniper/hub_dispc.c b/board/lge/sniper/hub_dispc.c
new file mode 100755
index 00000000000..158a9d93474
--- /dev/null
+++ b/board/lge/sniper/hub_dispc.c
@@ -0,0 +1,2634 @@
+/* u-boot/board/hub/hub_dispc.c
+ *
+ * Author: Kyungtae Oh <kyungtae.oh@lge.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <asm/arch/bits.h>
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/cpu.h>
+#include <asm/errno.h>
+#include "hub_dss.h"
+
+#define cpu_is_omap7xx() 0
+#define cpu_is_omap15xx() 0
+#define cpu_is_omap16xx() 0
+#define cpu_is_omap24xx() 0
+#define cpu_is_omap242x() 0
+#define cpu_is_omap243x() 0
+#define cpu_is_omap34xx() 1
+#define cpu_is_omap343x() 1
+#define cpu_is_omap3630() 1
+
+#define CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK 0
+
+/* handy sizes */
+#define SZ_16 0x00000010
+#define SZ_256 0x00000100
+#define SZ_512 0x00000200
+
+#define DSS_BASE 0x48050000
+
+#define DSS_SZ_REGS SZ_512
+
+struct dss_reg {
+ u16 idx;
+};
+
+#define DSS_REG(idx) ((const struct dss_reg) { idx })
+
+#define DSS_REVISION DSS_REG(0x0000)
+#define DSS_SYSCONFIG DSS_REG(0x0010)
+#define DSS_SYSSTATUS DSS_REG(0x0014)
+#define DSS_IRQSTATUS DSS_REG(0x0018)
+#define DSS_CONTROL DSS_REG(0x0040)
+#define DSS_SDI_CONTROL DSS_REG(0x0044)
+#define DSS_PLL_CONTROL DSS_REG(0x0048)
+#define DSS_SDI_STATUS DSS_REG(0x005C)
+
+/* DISPC */
+#define DISPC_BASE 0x48050400
+
+#define DISPC_SZ_REGS SZ_1K
+
+struct dispc_reg { u16 idx; };
+
+#define DISPC_REG(idx) ((const struct dispc_reg) { idx })
+
+/* DISPC common */
+#define DISPC_REVISION DISPC_REG(0x0000)
+#define DISPC_SYSCONFIG DISPC_REG(0x0010)
+#define DISPC_SYSSTATUS DISPC_REG(0x0014)
+#define DISPC_IRQSTATUS DISPC_REG(0x0018)
+#define DISPC_IRQENABLE DISPC_REG(0x001C)
+#define DISPC_CONTROL DISPC_REG(0x0040)
+#define DISPC_CONFIG DISPC_REG(0x0044)
+#define DISPC_CAPABLE DISPC_REG(0x0048)
+#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C)
+#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050)
+#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054)
+#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058)
+#define DISPC_LINE_STATUS DISPC_REG(0x005C)
+#define DISPC_LINE_NUMBER DISPC_REG(0x0060)
+#define DISPC_TIMING_H DISPC_REG(0x0064)
+#define DISPC_TIMING_V DISPC_REG(0x0068)
+#define DISPC_POL_FREQ DISPC_REG(0x006C)
+#define DISPC_DIVISOR DISPC_REG(0x0070)
+#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074)
+#define DISPC_SIZE_DIG DISPC_REG(0x0078)
+#define DISPC_SIZE_LCD DISPC_REG(0x007C)
+
+/* DISPC GFX plane */
+#define DISPC_GFX_BA0 DISPC_REG(0x0080)
+#define DISPC_GFX_BA1 DISPC_REG(0x0084)
+#define DISPC_GFX_POSITION DISPC_REG(0x0088)
+#define DISPC_GFX_SIZE DISPC_REG(0x008C)
+#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0)
+#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4)
+#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8)
+#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC)
+#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0)
+#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4)
+#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8)
+
+#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4)
+#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8)
+#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC)
+
+#define DISPC_CPR_COEF_R DISPC_REG(0x0220)
+#define DISPC_CPR_COEF_G DISPC_REG(0x0224)
+#define DISPC_CPR_COEF_B DISPC_REG(0x0228)
+
+#define DISPC_GFX_PRELOAD DISPC_REG(0x022C)
+
+/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */
+#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx)
+
+#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000)
+#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004)
+#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008)
+#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C)
+#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010)
+#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014)
+#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018)
+#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C)
+#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020)
+#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024)
+#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028)
+#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C)
+#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030)
+
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8)
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8)
+/* coef index i = {0, 1, 2, 3, 4} */
+#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4)
+/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
+#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4)
+
+#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04)
+
+
+#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
+ DISPC_IRQ_OCP_ERR | \
+ DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
+ DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
+ DISPC_IRQ_SYNC_LOST | \
+ DISPC_IRQ_SYNC_LOST_DIGIT)
+
+#define DISPC_MAX_NR_ISRS 8
+
+#define LPR_GFX_FIFO_HIGH_THRES 0xB9C
+#define LPR_GFX_FIFO_LOW_THRES 0x7F8
+#define DISPC_VID_ATTRIBUTES_ENABLE (1 << 0)
+#define DSS_CONTROL_APLL_CLK 1
+//static int lpr_enabled;
+static int gfx_in_use;
+
+#define REG_GET(idx, start, end) \
+ FLD_GET(dispc_read_reg(idx), start, end)
+
+#define REG_FLD_MOD(idx, val, start, end) \
+ dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
+
+static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES,
+ DISPC_VID_ATTRIBUTES(0),
+ DISPC_VID_ATTRIBUTES(1) };
+
+static struct {
+ void volatile *base;
+ unsigned long dpll4_m4_ck;
+ unsigned long cache_req_pck;
+ unsigned long cache_prate;
+ struct dispc_clock_info cache_cinfo;
+ u32 fifo_size[3];
+ //spinlock_t irq_lock;
+ //spinlock_t lpr_lock;
+ u32 irq_error_mask;
+ //struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
+ u32 error_irqs;
+ //struct work_struct error_work;
+ u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
+} dispc;
+
+
+static inline void dispc_write_reg(const struct dispc_reg idx, u32 val)
+{
+ //__raw_writel(val, dispc.base + idx.idx);
+ __raw_writel(val, DISPC_BASE + idx.idx);
+}
+
+static inline u32 dispc_read_reg(const struct dispc_reg idx)
+{
+ //return __raw_readl(dispc.base + idx.idx);
+ return __raw_readl(DISPC_BASE + idx.idx);
+}
+
+#define SR(reg) \
+ dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
+#define RR(reg) \
+ dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)])
+
+unsigned long clk_get_dpll4_m4_ckrate(void)
+{
+ if (cpu_is_omap3630())
+ dispc.dpll4_m4_ck = 1728000000;
+ else
+ dispc.dpll4_m4_ck = 48000000;
+ return dispc.dpll4_m4_ck;
+}
+
+int clk_set_dpll4_m4_ckrate(unsigned long rate)
+{
+ dispc.dpll4_m4_ck = rate;
+ return 0;
+}
+
+unsigned long clk_get_fck1_ckrate(void)
+{
+ if (cpu_is_omap3630())
+ return 132923076;
+ else
+ return 96000000;
+}
+
+void omap_dispc_set_lcd_size(int x, int y)
+{
+ BUG_ON((x > (1 << 11)) || (y > (1 << 11)));
+ //enable_lcd_clocks(1);
+ dss_clk_enable(1);
+ MOD_REG_FLD(DISPC_SIZE_LCD, FLD_MASK(16, 11) | FLD_MASK(0, 11),
+ ((y - 1) << 16) | (x - 1));
+ //enable_lcd_clocks(0);
+ dss_clk_enable(0);
+}
+
+void dispc_save_context(void)
+{
+ if (cpu_is_omap24xx())
+ return;
+
+ SR(SYSCONFIG);
+ SR(IRQENABLE);
+ SR(CONTROL);
+ SR(CONFIG);
+ SR(DEFAULT_COLOR0);
+ SR(DEFAULT_COLOR1);
+ SR(TRANS_COLOR0);
+ SR(TRANS_COLOR1);
+ SR(LINE_NUMBER);
+ SR(TIMING_H);
+ SR(TIMING_V);
+ SR(POL_FREQ);
+ SR(DIVISOR);
+ SR(GLOBAL_ALPHA);
+ SR(SIZE_DIG);
+ SR(SIZE_LCD);
+
+ SR(GFX_BA0);
+ SR(GFX_BA1);
+ SR(GFX_POSITION);
+ SR(GFX_SIZE);
+ SR(GFX_ATTRIBUTES);
+ SR(GFX_FIFO_THRESHOLD);
+ SR(GFX_ROW_INC);
+ SR(GFX_PIXEL_INC);
+ SR(GFX_WINDOW_SKIP);
+ SR(GFX_TABLE_BA);
+
+ SR(DATA_CYCLE1);
+ SR(DATA_CYCLE2);
+ SR(DATA_CYCLE3);
+
+ SR(CPR_COEF_R);
+ SR(CPR_COEF_G);
+ SR(CPR_COEF_B);
+
+ SR(GFX_PRELOAD);
+
+ /* VID1 */
+ SR(VID_BA0(0));
+ SR(VID_BA1(0));
+ SR(VID_POSITION(0));
+ SR(VID_SIZE(0));
+ SR(VID_ATTRIBUTES(0));
+ SR(VID_FIFO_THRESHOLD(0));
+ SR(VID_ROW_INC(0));
+ SR(VID_PIXEL_INC(0));
+ SR(VID_FIR(0));
+ SR(VID_PICTURE_SIZE(0));
+ SR(VID_ACCU0(0));
+ SR(VID_ACCU1(0));
+
+ SR(VID_FIR_COEF_H(0, 0));
+ SR(VID_FIR_COEF_H(0, 1));
+ SR(VID_FIR_COEF_H(0, 2));
+ SR(VID_FIR_COEF_H(0, 3));
+ SR(VID_FIR_COEF_H(0, 4));
+ SR(VID_FIR_COEF_H(0, 5));
+ SR(VID_FIR_COEF_H(0, 6));
+ SR(VID_FIR_COEF_H(0, 7));
+
+ SR(VID_FIR_COEF_HV(0, 0));
+ SR(VID_FIR_COEF_HV(0, 1));
+ SR(VID_FIR_COEF_HV(0, 2));
+ SR(VID_FIR_COEF_HV(0, 3));
+ SR(VID_FIR_COEF_HV(0, 4));
+ SR(VID_FIR_COEF_HV(0, 5));
+ SR(VID_FIR_COEF_HV(0, 6));
+ SR(VID_FIR_COEF_HV(0, 7));
+
+ SR(VID_CONV_COEF(0, 0));
+ SR(VID_CONV_COEF(0, 1));
+ SR(VID_CONV_COEF(0, 2));
+ SR(VID_CONV_COEF(0, 3));
+ SR(VID_CONV_COEF(0, 4));
+
+ SR(VID_FIR_COEF_V(0, 0));
+ SR(VID_FIR_COEF_V(0, 1));
+ SR(VID_FIR_COEF_V(0, 2));
+ SR(VID_FIR_COEF_V(0, 3));
+ SR(VID_FIR_COEF_V(0, 4));
+ SR(VID_FIR_COEF_V(0, 5));
+ SR(VID_FIR_COEF_V(0, 6));
+ SR(VID_FIR_COEF_V(0, 7));
+
+ SR(VID_PRELOAD(0));
+
+ /* VID2 */
+ SR(VID_BA0(1));
+ SR(VID_BA1(1));
+ SR(VID_POSITION(1));
+ SR(VID_SIZE(1));
+ SR(VID_ATTRIBUTES(1));
+ SR(VID_FIFO_THRESHOLD(1));
+ SR(VID_ROW_INC(1));
+ SR(VID_PIXEL_INC(1));
+ SR(VID_FIR(1));
+ SR(VID_PICTURE_SIZE(1));
+ SR(VID_ACCU0(1));
+ SR(VID_ACCU1(1));
+
+ SR(VID_FIR_COEF_H(1, 0));
+ SR(VID_FIR_COEF_H(1, 1));
+ SR(VID_FIR_COEF_H(1, 2));
+ SR(VID_FIR_COEF_H(1, 3));
+ SR(VID_FIR_COEF_H(1, 4));
+ SR(VID_FIR_COEF_H(1, 5));
+ SR(VID_FIR_COEF_H(1, 6));
+ SR(VID_FIR_COEF_H(1, 7));
+
+ SR(VID_FIR_COEF_HV(1, 0));
+ SR(VID_FIR_COEF_HV(1, 1));
+ SR(VID_FIR_COEF_HV(1, 2));
+ SR(VID_FIR_COEF_HV(1, 3));
+ SR(VID_FIR_COEF_HV(1, 4));
+ SR(VID_FIR_COEF_HV(1, 5));
+ SR(VID_FIR_COEF_HV(1, 6));
+ SR(VID_FIR_COEF_HV(1, 7));
+
+ SR(VID_CONV_COEF(1, 0));
+ SR(VID_CONV_COEF(1, 1));
+ SR(VID_CONV_COEF(1, 2));
+ SR(VID_CONV_COEF(1, 3));
+ SR(VID_CONV_COEF(1, 4));
+
+ SR(VID_FIR_COEF_V(1, 0));
+ SR(VID_FIR_COEF_V(1, 1));
+ SR(VID_FIR_COEF_V(1, 2));
+ SR(VID_FIR_COEF_V(1, 3));
+ SR(VID_FIR_COEF_V(1, 4));
+ SR(VID_FIR_COEF_V(1, 5));
+ SR(VID_FIR_COEF_V(1, 6));
+ SR(VID_FIR_COEF_V(1, 7));
+
+ SR(VID_PRELOAD(1));
+}
+
+void dispc_restore_context(void)
+{
+ RR(SYSCONFIG);
+ RR(IRQENABLE);
+ /*RR(CONTROL);*/
+ RR(CONFIG);
+ RR(DEFAULT_COLOR0);
+ RR(DEFAULT_COLOR1);
+ RR(TRANS_COLOR0);
+ RR(TRANS_COLOR1);
+ RR(LINE_NUMBER);
+ RR(TIMING_H);
+ RR(TIMING_V);
+ RR(POL_FREQ);
+ RR(DIVISOR);
+ RR(GLOBAL_ALPHA);
+ RR(SIZE_DIG);
+ RR(SIZE_LCD);
+
+ RR(GFX_BA0);
+ RR(GFX_BA1);
+ RR(GFX_POSITION);
+ RR(GFX_SIZE);
+ RR(GFX_ATTRIBUTES);
+ RR(GFX_FIFO_THRESHOLD);
+ RR(GFX_ROW_INC);
+ RR(GFX_PIXEL_INC);
+ RR(GFX_WINDOW_SKIP);
+ RR(GFX_TABLE_BA);
+
+ RR(DATA_CYCLE1);
+ RR(DATA_CYCLE2);
+ RR(DATA_CYCLE3);
+
+ RR(CPR_COEF_R);
+ RR(CPR_COEF_G);
+ RR(CPR_COEF_B);
+
+ RR(GFX_PRELOAD);
+
+ /* VID1 */
+ RR(VID_BA0(0));
+ RR(VID_BA1(0));
+ RR(VID_POSITION(0));
+ RR(VID_SIZE(0));
+ RR(VID_ATTRIBUTES(0));
+ RR(VID_FIFO_THRESHOLD(0));
+ RR(VID_ROW_INC(0));
+ RR(VID_PIXEL_INC(0));
+ RR(VID_FIR(0));
+ RR(VID_PICTURE_SIZE(0));
+ RR(VID_ACCU0(0));
+ RR(VID_ACCU1(0));
+
+ RR(VID_FIR_COEF_H(0, 0));
+ RR(VID_FIR_COEF_H(0, 1));
+ RR(VID_FIR_COEF_H(0, 2));
+ RR(VID_FIR_COEF_H(0, 3));
+ RR(VID_FIR_COEF_H(0, 4));
+ RR(VID_FIR_COEF_H(0, 5));
+ RR(VID_FIR_COEF_H(0, 6));
+ RR(VID_FIR_COEF_H(0, 7));
+
+ RR(VID_FIR_COEF_HV(0, 0));
+ RR(VID_FIR_COEF_HV(0, 1));
+ RR(VID_FIR_COEF_HV(0, 2));
+ RR(VID_FIR_COEF_HV(0, 3));
+ RR(VID_FIR_COEF_HV(0, 4));
+ RR(VID_FIR_COEF_HV(0, 5));
+ RR(VID_FIR_COEF_HV(0, 6));
+ RR(VID_FIR_COEF_HV(0, 7));
+
+ RR(VID_CONV_COEF(0, 0));
+ RR(VID_CONV_COEF(0, 1));
+ RR(VID_CONV_COEF(0, 2));
+ RR(VID_CONV_COEF(0, 3));
+ RR(VID_CONV_COEF(0, 4));
+
+ RR(VID_FIR_COEF_V(0, 0));
+ RR(VID_FIR_COEF_V(0, 1));
+ RR(VID_FIR_COEF_V(0, 2));
+ RR(VID_FIR_COEF_V(0, 3));
+ RR(VID_FIR_COEF_V(0, 4));
+ RR(VID_FIR_COEF_V(0, 5));
+ RR(VID_FIR_COEF_V(0, 6));
+ RR(VID_FIR_COEF_V(0, 7));
+
+ RR(VID_PRELOAD(0));
+
+ /* VID2 */
+ RR(VID_BA0(1));
+ RR(VID_BA1(1));
+ RR(VID_POSITION(1));
+ RR(VID_SIZE(1));
+ RR(VID_ATTRIBUTES(1));
+ RR(VID_FIFO_THRESHOLD(1));
+ RR(VID_ROW_INC(1));
+ RR(VID_PIXEL_INC(1));
+ RR(VID_FIR(1));
+ RR(VID_PICTURE_SIZE(1));
+ RR(VID_ACCU0(1));
+ RR(VID_ACCU1(1));
+
+ RR(VID_FIR_COEF_H(1, 0));
+ RR(VID_FIR_COEF_H(1, 1));
+ RR(VID_FIR_COEF_H(1, 2));
+ RR(VID_FIR_COEF_H(1, 3));
+ RR(VID_FIR_COEF_H(1, 4));
+ RR(VID_FIR_COEF_H(1, 5));
+ RR(VID_FIR_COEF_H(1, 6));
+ RR(VID_FIR_COEF_H(1, 7));
+
+ RR(VID_FIR_COEF_HV(1, 0));
+ RR(VID_FIR_COEF_HV(1, 1));
+ RR(VID_FIR_COEF_HV(1, 2));
+ RR(VID_FIR_COEF_HV(1, 3));
+ RR(VID_FIR_COEF_HV(1, 4));
+ RR(VID_FIR_COEF_HV(1, 5));
+ RR(VID_FIR_COEF_HV(1, 6));
+ RR(VID_FIR_COEF_HV(1, 7));
+
+ RR(VID_CONV_COEF(1, 0));
+ RR(VID_CONV_COEF(1, 1));
+ RR(VID_CONV_COEF(1, 2));
+ RR(VID_CONV_COEF(1, 3));
+ RR(VID_CONV_COEF(1, 4));
+
+ RR(VID_FIR_COEF_V(1, 0));
+ RR(VID_FIR_COEF_V(1, 1));
+ RR(VID_FIR_COEF_V(1, 2));
+ RR(VID_FIR_COEF_V(1, 3));
+ RR(VID_FIR_COEF_V(1, 4));
+ RR(VID_FIR_COEF_V(1, 5));
+ RR(VID_FIR_COEF_V(1, 6));
+ RR(VID_FIR_COEF_V(1, 7));
+
+ RR(VID_PRELOAD(1));
+
+ /* enable last, because LCD & DIGIT enable are here */
+ RR(CONTROL);
+}
+
+#undef SR
+#undef RR
+
+bool dispc_go_busy(enum omap_channel channel)
+{
+ int bit;
+
+ dss_clk_enable(1);
+ if (channel == OMAP_DSS_CHANNEL_LCD)
+ bit = 5; /* GOLCD */
+ else
+ bit = 6; /* GODIGIT */
+
+ if (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
+ dss_clk_enable(0);
+ return 1;
+ }
+ else
+ {
+ dss_clk_enable(0);
+ return 0;
+ }
+}
+
+void dispc_go(enum omap_channel channel)
+{
+ int bit;
+
+ dss_clk_enable(1);
+
+ if (channel == OMAP_DSS_CHANNEL_LCD)
+ bit = 0; /* LCDENABLE */
+ else
+ bit = 1; /* DIGITALENABLE */
+
+ /* if the channel is not enabled, we don't need GO */
+ if (REG_GET(DISPC_CONTROL, bit, bit) == 0)
+ return;//goto end;
+
+ if (channel == OMAP_DSS_CHANNEL_LCD)
+ bit = 5; /* GOLCD */
+ else
+ bit = 6; /* GODIGIT */
+
+ if (REG_GET(DISPC_CONTROL, bit, bit) == 1) {
+ //DSSERR("GO bit not down for channel %d\n", channel);
+ return;//goto end;
+ }
+
+ REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
+//end:
+// dss_clk_enable(0);
+}
+
+static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
+{
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value);
+}
+
+static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
+{
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value);
+}
+
+static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
+{
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value);
+}
+
+static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
+ int vscaleup, int five_taps)
+{
+ /* Coefficients for horizontal up-sampling */
+ static const u32 coef_hup[8] = {
+ 0x00800000,
+ 0x0D7CF800,
+ 0x1E70F5FF,
+ 0x335FF5FE,
+ 0xF74949F7,
+ 0xF55F33FB,
+ 0xF5701EFE,
+ 0xF87C0DFF,
+ };
+
+ /* Coefficients for horizontal down-sampling */
+ static const u32 coef_hdown[8] = {
+ 0x24382400,
+ 0x28371FFE,
+ 0x2C361BFB,
+ 0x303516F9,
+ 0x11343311,
+ 0x1635300C,
+ 0x1B362C08,
+ 0x1F372804,
+ };
+
+ /* Coefficients for horizontal and vertical up-sampling */
+ static const u32 coef_hvup[2][8] = {
+ {
+ 0x00800000,
+ 0x037B02FF,
+ 0x0C6F05FE,
+ 0x205907FB,
+ 0x00404000,
+ 0x075920FE,
+ 0x056F0CFF,
+ 0x027B0300,
+ },
+ {
+ 0x00800000,
+ 0x0D7CF8FF,
+ 0x1E70F5FE,
+ 0x335FF5FB,
+ 0xF7404000,
+ 0xF55F33FE,
+ 0xF5701EFF,
+ 0xF87C0D00,
+ },
+ };
+
+ /* Coefficients for horizontal and vertical down-sampling */
+ static const u32 coef_hvdown[2][8] = {
+ {
+ 0x24382400,
+ 0x28391F04,
+ 0x2D381B08,
+ 0x3237170C,
+ 0x123737F7,
+ 0x173732F9,
+ 0x1B382DFB,
+ 0x1F3928FE,
+ },
+ {
+ 0x24382400,
+ 0x28371F04,
+ 0x2C361B08,
+ 0x3035160C,
+ 0x113433F7,
+ 0x163530F9,
+ 0x1B362CFB,
+ 0x1F3728FE,
+ },
+ };
+
+ /* Coefficients for vertical up-sampling */
+ static const u32 coef_vup[8] = {
+ 0x00000000,
+ 0x0000FF00,
+ 0x0000FEFF,
+ 0x0000FBFE,
+ 0x000000F7,
+ 0x0000FEFB,
+ 0x0000FFFE,
+ 0x000000FF,
+ };
+
+
+ /* Coefficients for vertical down-sampling */
+ static const u32 coef_vdown[8] = {
+ 0x00000000,
+ 0x000004FE,
+ 0x000008FB,
+ 0x00000CF9,
+ 0x0000F711,
+ 0x0000F90C,
+ 0x0000FB08,
+ 0x0000FE04,
+ };
+
+ const u32 *h_coef;
+ const u32 *hv_coef;
+ const u32 *hv_coef_mod;
+ const u32 *v_coef;
+ int i;
+
+ if (hscaleup)
+ h_coef = coef_hup;
+ else
+ h_coef = coef_hdown;
+
+ if (vscaleup) {
+ hv_coef = coef_hvup[five_taps];
+ v_coef = coef_vup;
+
+ if (hscaleup)
+ hv_coef_mod = NULL;
+ else
+ hv_coef_mod = coef_hvdown[five_taps];
+ } else {
+ hv_coef = coef_hvdown[five_taps];
+ v_coef = coef_vdown;
+
+ if (hscaleup)
+ hv_coef_mod = coef_hvup[five_taps];
+ else
+ hv_coef_mod = NULL;
+ }
+
+ for (i = 0; i < 8; i++) {
+ u32 h, hv;
+
+ h = h_coef[i];
+
+ hv = hv_coef[i];
+
+ if (hv_coef_mod) {
+ hv &= 0xffffff00;
+ hv |= (hv_coef_mod[i] & 0xff);
+ }
+
+ _dispc_write_firh_reg(plane, i, h);
+ _dispc_write_firhv_reg(plane, i, hv);
+ }
+
+ if (!five_taps)
+ return;
+
+ for (i = 0; i < 8; i++) {
+ u32 v;
+ v = v_coef[i];
+ _dispc_write_firv_reg(plane, i, v);
+ }
+}
+
+static void _dispc_setup_color_conv_coef(void)
+{
+ const struct color_conv_coef {
+ int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
+ int full_range;
+ } ctbl_bt601_5 = {
+ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
+ };
+
+ const struct color_conv_coef *ct;
+
+#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
+
+ ct = &ctbl_bt601_5;
+
+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry));
+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb));
+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr));
+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by));
+ dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb));
+
+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry));
+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb));
+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr));
+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by));
+ dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb));
+
+#undef CVAL
+
+ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11);
+ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11);
+}
+
+
+static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
+{
+ const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0,
+ DISPC_VID_BA0(0),
+ DISPC_VID_BA0(1) };
+
+ dispc_write_reg(ba0_reg[plane], paddr);
+}
+
+static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
+{
+ const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1,
+ DISPC_VID_BA1(0),
+ DISPC_VID_BA1(1) };
+
+ dispc_write_reg(ba1_reg[plane], paddr);
+}
+
+static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
+{
+ const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION,
+ DISPC_VID_POSITION(0),
+ DISPC_VID_POSITION(1) };
+
+ u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
+ dispc_write_reg(pos_reg[plane], val);
+}
+
+static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
+{
+ const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE,
+ DISPC_VID_PICTURE_SIZE(0),
+ DISPC_VID_PICTURE_SIZE(1) };
+ u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+ dispc_write_reg(siz_reg[plane], val);
+}
+
+static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
+{
+ u32 val;
+ const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0),
+ DISPC_VID_SIZE(1) };
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+ dispc_write_reg(vsi_reg[plane-1], val);
+}
+
+static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
+{
+
+ BUG_ON(plane == OMAP_DSS_VIDEO1);
+
+ if (plane == OMAP_DSS_GFX)
+ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
+ else if (plane == OMAP_DSS_VIDEO2)
+ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
+}
+
+static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
+{
+ const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC,
+ DISPC_VID_PIXEL_INC(0),
+ DISPC_VID_PIXEL_INC(1) };
+
+ dispc_write_reg(ri_reg[plane], inc);
+}
+
+static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
+{
+ const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC,
+ DISPC_VID_ROW_INC(0),
+ DISPC_VID_ROW_INC(1) };
+
+ dispc_write_reg(ri_reg[plane], inc);
+}
+
+static void _dispc_set_color_mode(enum omap_plane plane,
+ enum omap_color_mode color_mode)
+{
+ u32 m = 0;
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_CLUT1:
+ m = 0x0; break;
+ case OMAP_DSS_COLOR_CLUT2:
+ m = 0x1; break;
+ case OMAP_DSS_COLOR_CLUT4:
+ m = 0x2; break;
+ case OMAP_DSS_COLOR_CLUT8:
+ m = 0x3; break;
+ case OMAP_DSS_COLOR_RGB12U:
+ m = 0x4; break;
+ case OMAP_DSS_COLOR_ARGB16:
+ m = 0x5; break;
+ case OMAP_DSS_COLOR_RGB16:
+ m = 0x6; break;
+ case OMAP_DSS_COLOR_RGB24U:
+ m = 0x8; break;
+ case OMAP_DSS_COLOR_RGB24P:
+ m = 0x9; break;
+ case OMAP_DSS_COLOR_YUV2:
+ m = 0xa; break;
+ case OMAP_DSS_COLOR_UYVY:
+ m = 0xb; break;
+ case OMAP_DSS_COLOR_ARGB32:
+ m = 0xc; break;
+ case OMAP_DSS_COLOR_RGBA32:
+ m = 0xd; break;
+ case OMAP_DSS_COLOR_RGBX32:
+ m = 0xe; break;
+ default:
+ BUG(); break;
+ }
+
+ REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1);
+}
+
+static void _dispc_set_channel_out(enum omap_plane plane,
+ enum omap_channel channel)
+{
+ int shift;
+ u32 val;
+
+ switch (plane) {
+ case OMAP_DSS_GFX:
+ shift = 8;
+ break;
+ case OMAP_DSS_VIDEO1:
+ case OMAP_DSS_VIDEO2:
+ shift = 16;
+ break;
+ default:
+ BUG();
+ return;
+ }
+
+ val = dispc_read_reg(dispc_reg_att[plane]);
+ val = FLD_MOD(val, channel, shift, shift);
+ dispc_write_reg(dispc_reg_att[plane], val);
+}
+
+void dispc_set_burst_size(enum omap_plane plane,
+ enum omap_burst_size burst_size)
+{
+ int shift;
+ u32 val;
+
+ dss_clk_enable(1);
+
+ switch (plane) {
+ case OMAP_DSS_GFX:
+ shift = 6;
+ break;
+ case OMAP_DSS_VIDEO1:
+ case OMAP_DSS_VIDEO2:
+ shift = 14;
+ break;
+ default:
+ BUG();
+ return;
+ }
+
+ val = dispc_read_reg(dispc_reg_att[plane]);
+ val = FLD_MOD(val, burst_size, shift+1, shift);
+ dispc_write_reg(dispc_reg_att[plane], val);
+
+ dss_clk_enable(0);
+}
+
+static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
+{
+ u32 val;
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ val = dispc_read_reg(dispc_reg_att[plane]);
+ val = FLD_MOD(val, enable, 9, 9);
+ dispc_write_reg(dispc_reg_att[plane], val);
+}
+
+void dispc_enable_replication(enum omap_plane plane, bool enable)
+{
+ int bit;
+
+ if (plane == OMAP_DSS_GFX)
+ bit = 5;
+ else
+ bit = 10;
+
+ dss_clk_enable(1);
+ REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit);
+ dss_clk_enable(0);
+}
+
+void dispc_set_lcd_size(u16 width, u16 height)
+{
+ u32 val;
+ BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
+ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+ dss_clk_enable(1);
+ dispc_write_reg(DISPC_SIZE_LCD, val);
+ dss_clk_enable(0);
+}
+
+void dispc_set_digit_size(u16 width, u16 height)
+{
+ u32 val;
+ BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
+ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
+ dss_clk_enable(1);
+ dispc_write_reg(DISPC_SIZE_DIG, val);
+ dss_clk_enable(0);
+}
+
+static void dispc_read_plane_fifo_sizes(void)
+{
+ const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS,
+ DISPC_VID_FIFO_SIZE_STATUS(0),
+ DISPC_VID_FIFO_SIZE_STATUS(1) };
+ u32 size;
+ int plane;
+
+ dss_clk_enable(1);
+
+ for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
+ if (cpu_is_omap24xx())
+ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
+ else if (cpu_is_omap34xx())
+ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
+ else
+ BUG();
+
+ dispc.fifo_size[plane] = size;
+ }
+
+ dss_clk_enable(0);
+}
+
+u32 dispc_get_plane_fifo_size(enum omap_plane plane)
+{
+ return dispc.fifo_size[plane];
+}
+
+void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
+{
+ const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
+ DISPC_VID_FIFO_THRESHOLD(0),
+ DISPC_VID_FIFO_THRESHOLD(1) };
+ dss_clk_enable(1);
+
+ if (cpu_is_omap24xx())
+ dispc_write_reg(ftrs_reg[plane],
+ FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0));
+ else
+ dispc_write_reg(ftrs_reg[plane],
+ FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0));
+
+ dss_clk_enable(0);
+}
+
+void dispc_enable_fifomerge(bool enable)
+{
+ dss_clk_enable(1);
+
+ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
+
+ dss_clk_enable(0);
+}
+
+static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
+{
+ u32 val;
+ const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
+ DISPC_VID_FIR(1) };
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ if (cpu_is_omap24xx())
+ val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
+ else
+ val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
+ dispc_write_reg(fir_reg[plane-1], val);
+}
+
+static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
+{
+ u32 val;
+ const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0),
+ DISPC_VID_ACCU0(1) };
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
+ dispc_write_reg(ac0_reg[plane-1], val);
+}
+
+static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
+{
+ u32 val;
+ const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0),
+ DISPC_VID_ACCU1(1) };
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0);
+ dispc_write_reg(ac1_reg[plane-1], val);
+}
+
+
+static void _dispc_set_scaling(enum omap_plane plane,
+ u16 orig_width, u16 orig_height,
+ u16 out_width, u16 out_height,
+ bool ilace, bool five_taps,
+ bool fieldmode)
+{
+ int fir_hinc;
+ int fir_vinc;
+ int hscaleup, vscaleup;
+ int accu0 = 0;
+ int accu1 = 0;
+ u32 l;
+
+ BUG_ON(plane == OMAP_DSS_GFX);
+
+ hscaleup = orig_width <= out_width;
+ vscaleup = orig_height <= out_height;
+
+ _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps);
+
+ if (!orig_width || orig_width == out_width)
+ fir_hinc = 0;
+ else
+ fir_hinc = 1024 * orig_width / out_width;
+
+ if (!orig_height || orig_height == out_height)
+ fir_vinc = 0;
+ else
+ fir_vinc = 1024 * orig_height / out_height;
+
+ _dispc_set_fir(plane, fir_hinc, fir_vinc);
+
+ l = dispc_read_reg(dispc_reg_att[plane]);
+ l &= ~((0x0f << 5) | (0x3 << 21));
+
+ l |= fir_hinc ? (1 << 5) : 0;
+ l |= fir_vinc ? (1 << 6) : 0;
+
+ l |= hscaleup ? 0 : (1 << 7);
+ l |= vscaleup ? 0 : (1 << 8);
+
+ l |= five_taps ? (1 << 21) : 0;
+ l |= five_taps ? (1 << 22) : 0;
+
+ dispc_write_reg(dispc_reg_att[plane], l);
+
+ /*
+ * field 0 = even field = bottom field
+ * field 1 = odd field = top field
+ */
+ if (ilace && !fieldmode) {
+ accu1 = 0;
+ accu0 = (fir_vinc / 2) & 0x3ff;
+ if (accu0 >= 1024/2) {
+ accu1 = 1024/2;
+ accu0 -= accu1;
+ }
+ }
+
+ _dispc_set_vid_accu0(plane, 0, accu0);
+ _dispc_set_vid_accu1(plane, 0, accu1);
+}
+
+static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
+ bool mirroring, enum omap_color_mode color_mode)
+{
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+ color_mode == OMAP_DSS_COLOR_UYVY) {
+ int vidrot = 0;
+
+ if (mirroring) {
+ switch (rotation) {
+ case 0:
+ vidrot = 2;
+ break;
+ case 1:
+ vidrot = 1;
+ break;
+ case 2:
+ vidrot = 0;
+ break;
+ case 3:
+ vidrot = 3;
+ break;
+ }
+ } else {
+ switch (rotation) {
+ case 0:
+ vidrot = 0;
+ break;
+ case 1:
+ vidrot = 1;
+ break;
+ case 2:
+ vidrot = 2;
+ break;
+ case 3:
+ vidrot = 3;
+ break;
+ }
+ }
+
+ REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12);
+
+ if (rotation == 1 || rotation == 3)
+ REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18);
+ else
+ REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18);
+ } else {
+ REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12);
+ REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18);
+ }
+}
+
+static s32 pixinc(int pixels, u8 ps)
+{
+ if (pixels == 1)
+ return 1;
+ else if (pixels > 1)
+ return 1 + (pixels - 1) * ps;
+ else if (pixels < 0)
+ return 1 - (-pixels + 1) * ps;
+ else
+ BUG();
+}
+
+static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
+ u16 screen_width,
+ u16 width, u16 height,
+ enum omap_color_mode color_mode, bool fieldmode,
+ unsigned int field_offset,
+ unsigned *offset0, unsigned *offset1,
+ s32 *row_inc, s32 *pix_inc)
+{
+ u8 ps;
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+ case OMAP_DSS_COLOR_ARGB16:
+ ps = 2;
+ break;
+
+ case OMAP_DSS_COLOR_RGB24P:
+ ps = 3;
+ break;
+
+ case OMAP_DSS_COLOR_RGB24U:
+ case OMAP_DSS_COLOR_ARGB32:
+ case OMAP_DSS_COLOR_RGBA32:
+ case OMAP_DSS_COLOR_RGBX32:
+ case OMAP_DSS_COLOR_YUV2:
+ case OMAP_DSS_COLOR_UYVY:
+ ps = 4;
+ break;
+
+ default:
+ BUG();
+ return;
+ }
+
+ /*
+ * field 0 = even field = bottom field
+ * field 1 = odd field = top field
+ */
+ switch (rotation + mirror * 4) {
+ case 0:
+ case 2:
+ /*
+ * If the pixel format is YUV or UYVY divide the width
+ * of the image by 2 for 0 and 180 degree rotation.
+ */
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+ color_mode == OMAP_DSS_COLOR_UYVY)
+ width = width >> 1;
+ case 1:
+ case 3:
+ *offset1 = 0;
+ if (field_offset)
+ *offset0 = field_offset * screen_width * ps;
+ else
+ *offset0 = 0;
+
+ *row_inc = pixinc(1 + (screen_width - width) +
+ (fieldmode ? screen_width : 0),
+ ps);
+ *pix_inc = pixinc(1, ps);
+ break;
+
+ case 4:
+ case 6:
+ /* If the pixel format is YUV or UYVY divide the width
+ * of the image by 2 for 0 degree and 180 degree
+ */
+ if (color_mode == OMAP_DSS_COLOR_YUV2 ||
+ color_mode == OMAP_DSS_COLOR_UYVY)
+ width = width >> 1;
+ case 5:
+ case 7:
+ *offset1 = 0;
+ if (field_offset)
+ *offset0 = field_offset * screen_width * ps;
+ else
+ *offset0 = 0;
+ *row_inc = pixinc(1 - (screen_width + width) -
+ (fieldmode ? screen_width : 0),
+ ps);
+ *pix_inc = pixinc(1, ps);
+ break;
+
+ default:
+ BUG();
+ }
+}
+
+static void calc_dma_rotation_offset(u8 rotation, bool mirror,
+ u16 screen_width,
+ u16 width, u16 height,
+ enum omap_color_mode color_mode, bool fieldmode,
+ unsigned int field_offset,
+ unsigned *offset0, unsigned *offset1,
+ s32 *row_inc, s32 *pix_inc)
+{
+ u8 ps;
+ u16 fbw, fbh;
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+ case OMAP_DSS_COLOR_ARGB16:
+ ps = 2;
+ break;
+
+ case OMAP_DSS_COLOR_RGB24P:
+ ps = 3;
+ break;
+
+ case OMAP_DSS_COLOR_RGB24U:
+ case OMAP_DSS_COLOR_ARGB32:
+ case OMAP_DSS_COLOR_RGBA32:
+ case OMAP_DSS_COLOR_RGBX32:
+ ps = 4;
+ break;
+
+ case OMAP_DSS_COLOR_YUV2:
+ case OMAP_DSS_COLOR_UYVY:
+ ps = 2;
+ break;
+ default:
+ BUG();
+ return;
+ }
+
+ /* width & height are overlay sizes, convert to fb sizes */
+
+ if (rotation == 0 || rotation == 2) {
+ fbw = width;
+ fbh = height;
+ } else {
+ fbw = height;
+ fbh = width;
+ }
+
+ /*
+ * field 0 = even field = bottom field
+ * field 1 = odd field = top field
+ */
+ switch (rotation + mirror * 4) {
+ case 0:
+ *offset1 = 0;
+ if (field_offset)
+ *offset0 = *offset1 + field_offset * screen_width * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(1 + (screen_width - fbw) +
+ (fieldmode ? screen_width : 0),
+ ps);
+ *pix_inc = pixinc(1, ps);
+ break;
+ case 1:
+ *offset1 = screen_width * (fbh - 1) * ps;
+ if (field_offset)
+ *offset0 = *offset1 + field_offset * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
+ (fieldmode ? 1 : 0), ps);
+ *pix_inc = pixinc(-screen_width, ps);
+ break;
+ case 2:
+ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
+ if (field_offset)
+ *offset0 = *offset1 - field_offset * screen_width * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(-1 -
+ (screen_width - fbw) -
+ (fieldmode ? screen_width : 0),
+ ps);
+ *pix_inc = pixinc(-1, ps);
+ break;
+ case 3:
+ *offset1 = (fbw - 1) * ps;
+ if (field_offset)
+ *offset0 = *offset1 - field_offset * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
+ (fieldmode ? 1 : 0), ps);
+ *pix_inc = pixinc(screen_width, ps);
+ break;
+
+ /* mirroring */
+ case 0 + 4:
+ *offset1 = (fbw - 1) * ps;
+ if (field_offset)
+ *offset0 = *offset1 + field_offset * screen_width * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(screen_width * 2 - 1 +
+ (fieldmode ? screen_width : 0),
+ ps);
+ *pix_inc = pixinc(-1, ps);
+ break;
+
+ case 1 + 4:
+ *offset1 = 0;
+ if (field_offset)
+ *offset0 = *offset1 + field_offset * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
+ (fieldmode ? 1 : 0),
+ ps);
+ *pix_inc = pixinc(screen_width, ps);
+ break;
+
+ case 2 + 4:
+ *offset1 = screen_width * (fbh - 1) * ps;
+ if (field_offset)
+ *offset0 = *offset1 - field_offset * screen_width * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(1 - screen_width * 2 -
+ (fieldmode ? screen_width : 0),
+ ps);
+ *pix_inc = pixinc(1, ps);
+ break;
+
+ case 3 + 4:
+ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
+ if (field_offset)
+ *offset0 = *offset1 - field_offset * ps;
+ else
+ *offset0 = *offset1;
+ *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
+ (fieldmode ? 1 : 0),
+ ps);
+ *pix_inc = pixinc(-screen_width, ps);
+ break;
+
+ default:
+ BUG();
+ }
+}
+
+static unsigned long calc_fclk_five_taps(u16 width, u16 height,
+ u16 out_width, u16 out_height, enum omap_color_mode color_mode)
+{
+ u32 fclk = 0;
+ /* FIXME venc pclk? */
+ u64 tmp, pclk = dispc_pclk_rate();
+
+ if (height > out_height) {
+ /* FIXME get real display PPL */
+ unsigned int ppl = 800;
+
+ tmp = pclk * height * out_width;
+ do_div(tmp, 2 * out_height * ppl);
+ fclk = tmp;
+
+ if (height > 2 * out_height && ppl != out_width) {
+ tmp = pclk * (height - 2 * out_height) * out_width;
+ do_div(tmp, 2 * out_height * (ppl - out_width));
+ fclk = max(fclk, (u32) tmp);
+ }
+ }
+
+ if (width > out_width) {
+ tmp = pclk * width;
+ do_div(tmp, out_width);
+ fclk = max(fclk, (u32) tmp);
+
+ if (color_mode == OMAP_DSS_COLOR_RGB24U)
+ fclk <<= 1;
+ }
+
+ return fclk;
+}
+
+static unsigned long calc_fclk(u16 width, u16 height,
+ u16 out_width, u16 out_height)
+{
+ unsigned int hf, vf;
+
+ /*
+ * FIXME how to determine the 'A' factor
+ * for the no downscaling case ?
+ */
+
+ if (width > 3 * out_width)
+ hf = 4;
+ else if (width > 2 * out_width)
+ hf = 3;
+ else if (width > out_width)
+ hf = 2;
+ else
+ hf = 1;
+
+ if (height > out_height)
+ vf = 2;
+ else
+ vf = 1;
+
+ /* FIXME venc pclk? */
+ return dispc_pclk_rate() * vf * hf;
+}
+
+void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out)
+{
+ dss_clk_enable(1);
+ _dispc_set_channel_out(plane, channel_out);
+ dss_clk_enable(0);
+}
+
+static int _dispc_setup_plane(enum omap_plane plane,
+ u32 paddr, u16 screen_width,
+ u16 pos_x, u16 pos_y,
+ u16 width, u16 height,
+ u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+ u8 rotation, int mirror,
+ u8 global_alpha)
+{
+ const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
+ bool five_taps = 0;
+ bool fieldmode = 0;
+ int cconv = 0;
+ unsigned offset0, offset1;
+ s32 row_inc;
+ s32 pix_inc;
+ u16 frame_height = height;
+ unsigned int field_offset = 0;
+
+ if (paddr == 0)
+ return -EINVAL;
+
+ if (ilace && height == out_height)
+ fieldmode = 1;
+
+ if (ilace) {
+ if (fieldmode)
+ height /= 2;
+ pos_y /= 2;
+ out_height /= 2;
+ }
+
+ if (plane == OMAP_DSS_GFX) {
+ if (width != out_width || height != out_height)
+ return -EINVAL;
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_ARGB16:
+ case OMAP_DSS_COLOR_RGB16:
+ case OMAP_DSS_COLOR_RGB24P:
+ case OMAP_DSS_COLOR_RGB24U:
+ case OMAP_DSS_COLOR_ARGB32:
+ case OMAP_DSS_COLOR_RGBA32:
+ case OMAP_DSS_COLOR_RGBX32:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ } else {
+ /* video plane */
+
+ unsigned long fclk = 0;
+
+ if (out_width < width / maxdownscale ||
+ out_width > width * 8)
+ return -EINVAL;
+
+ if (out_height < height / maxdownscale ||
+ out_height > height * 8)
+ return -EINVAL;
+
+ switch (color_mode) {
+ case OMAP_DSS_COLOR_RGB16:
+ case OMAP_DSS_COLOR_RGB24P:
+ case OMAP_DSS_COLOR_RGB24U:
+ case OMAP_DSS_COLOR_RGBX32:
+ break;
+
+ case OMAP_DSS_COLOR_ARGB16:
+ case OMAP_DSS_COLOR_ARGB32:
+ case OMAP_DSS_COLOR_RGBA32:
+ if (plane == OMAP_DSS_VIDEO1)
+ return -EINVAL;
+ break;
+
+ case OMAP_DSS_COLOR_YUV2:
+ case OMAP_DSS_COLOR_UYVY:
+ cconv = 1;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* Must use 5-tap filter? */
+ five_taps = height > out_height * 2;
+
+ if (!five_taps) {
+ fclk = calc_fclk(width, height,
+ out_width, out_height);
+
+ /* Try 5-tap filter if 3-tap fclk is too high */
+ if (cpu_is_omap34xx() && height > out_height &&
+ fclk > dispc_fclk_rate())
+ five_taps = TRUE;
+ }
+
+ if (width > (2048 >> five_taps))
+ return -EINVAL;
+
+ if (five_taps)
+ fclk = calc_fclk_five_taps(width, height,
+ out_width, out_height, color_mode);
+
+ if (fclk > dispc_fclk_rate())
+ return -EINVAL;
+ }
+
+ if (ilace && !fieldmode) {
+ /*
+ * when downscaling the bottom field may have to start several
+ * source lines below the top field. Unfortunately ACCUI
+ * registers will only hold the fractional part of the offset
+ * so the integer part must be added to the base address of the
+ * bottom field.
+ */
+ if (!height || height == out_height)
+ field_offset = 0;
+ else
+ field_offset = height / out_height / 2;
+ }
+
+ /* Fields are independent but interleaved in memory. */
+ if (fieldmode)
+ field_offset = 1;
+
+ if (rotation_type == OMAP_DSS_ROT_DMA)
+ calc_dma_rotation_offset(rotation, mirror,
+ screen_width, width, frame_height, color_mode,
+ fieldmode, field_offset,
+ &offset0, &offset1, &row_inc, &pix_inc);
+ else
+ calc_vrfb_rotation_offset(rotation, mirror,
+ screen_width, width, frame_height, color_mode,
+ fieldmode, field_offset,
+ &offset0, &offset1, &row_inc, &pix_inc);
+
+ _dispc_set_color_mode(plane, color_mode);
+
+ _dispc_set_plane_ba0(plane, paddr + offset0);
+ _dispc_set_plane_ba1(plane, paddr + offset1);
+
+ _dispc_set_row_inc(plane, row_inc);
+ _dispc_set_pix_inc(plane, pix_inc);
+
+ _dispc_set_plane_pos(plane, pos_x, pos_y);
+
+ _dispc_set_pic_size(plane, width, height);
+
+ if (plane != OMAP_DSS_GFX) {
+ _dispc_set_scaling(plane, width, height,
+ out_width, out_height,
+ ilace, five_taps, fieldmode);
+ _dispc_set_vid_size(plane, out_width, out_height);
+ _dispc_set_vid_color_conv(plane, cconv);
+ }
+
+ _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
+
+ if (plane != OMAP_DSS_VIDEO1)
+ _dispc_setup_global_alpha(plane, global_alpha);
+
+ return 0;
+}
+
+static void _dispc_enable_plane(enum omap_plane plane, bool enable)
+{
+ REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0);
+}
+
+static void _enable_lcd_out(bool enable)
+{
+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
+}
+
+void dispc_enable_lcd_out(bool enable)
+{
+ bool is_on;
+
+ dss_clk_enable(1);
+
+ /* When we disable LCD output, we need to wait until frame is done.
+ * Otherwise the DSS is still working, and turning off the clocks
+ * prevents DSS from going to OFF mode */
+ is_on = REG_GET(DISPC_CONTROL, 0, 0);
+
+ if (!enable && is_on) {
+ mdelay(100);
+ }
+
+ _enable_lcd_out(enable);
+
+ if (!enable && is_on) {
+ mdelay(100);
+ }
+
+ dss_clk_enable(0);
+}
+
+static void _enable_digit_out(bool enable)
+{
+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
+}
+
+void dispc_lcd_enable_signal_polarity(bool act_high)
+{
+ dss_clk_enable(1);
+ REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
+ dss_clk_enable(0);
+}
+
+void dispc_lcd_enable_signal(bool enable)
+{
+ dss_clk_enable(1);
+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28);
+ dss_clk_enable(0);
+}
+
+void dispc_pck_free_enable(bool enable)
+{
+ dss_clk_enable(1);
+ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
+ dss_clk_enable(0);
+}
+
+void dispc_enable_fifohandcheck(bool enable)
+{
+ dss_clk_enable(1);
+ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
+ dss_clk_enable(0);
+}
+
+
+void dispc_set_lcd_display_type(enum omap_lcd_display_type type)
+{
+ int mode;
+
+ switch (type) {
+ case OMAP_DSS_LCD_DISPLAY_STN:
+ mode = 0;
+ break;
+
+ case OMAP_DSS_LCD_DISPLAY_TFT:
+ mode = 1;
+ break;
+
+ default:
+ BUG();
+ return;
+ }
+
+ dss_clk_enable(1);
+ REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
+ dss_clk_enable(0);
+}
+
+void dispc_set_loadmode(enum omap_dss_load_mode mode)
+{
+ dss_clk_enable(1);
+ REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1);
+ dss_clk_enable(0);
+}
+
+
+void dispc_set_default_color(enum omap_channel channel, u32 color)
+{
+ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
+ DISPC_DEFAULT_COLOR1 };
+
+ dss_clk_enable(1);
+ dispc_write_reg(def_reg[channel], color);
+ dss_clk_enable(0);
+}
+
+u32 dispc_get_default_color(enum omap_channel channel)
+{
+ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0,
+ DISPC_DEFAULT_COLOR1 };
+ u32 l;
+
+ BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
+ channel != OMAP_DSS_CHANNEL_LCD);
+
+ dss_clk_enable(1);
+ l = dispc_read_reg(def_reg[channel]);
+ dss_clk_enable(0);
+
+ return l;
+}
+
+void dispc_set_trans_key(enum omap_channel ch,
+ enum omap_dss_trans_key_type type,
+ u32 trans_key)
+{
+ const struct dispc_reg tr_reg[] = {
+ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
+
+ dss_clk_enable(1);
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
+ else /* OMAP_DSS_CHANNEL_DIGIT */
+ REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
+
+ dispc_write_reg(tr_reg[ch], trans_key);
+ dss_clk_enable(0);
+}
+
+void dispc_get_trans_key(enum omap_channel ch,
+ enum omap_dss_trans_key_type *type,
+ u32 *trans_key)
+{
+ const struct dispc_reg tr_reg[] = {
+ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 };
+
+ dss_clk_enable(1);
+ if (type) {
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ *type = REG_GET(DISPC_CONFIG, 11, 11);
+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
+ *type = REG_GET(DISPC_CONFIG, 13, 13);
+ else
+ BUG();
+ }
+
+ if (trans_key)
+ *trans_key = dispc_read_reg(tr_reg[ch]);
+ dss_clk_enable(0);
+}
+
+void dispc_enable_trans_key(enum omap_channel ch, bool enable)
+{
+ dss_clk_enable(1);
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
+ else /* OMAP_DSS_CHANNEL_DIGIT */
+ REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
+ dss_clk_enable(0);
+}
+void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
+{
+ dss_clk_enable(1);
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
+ else /* OMAP_DSS_CHANNEL_DIGIT */
+ REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
+ dss_clk_enable(0);
+}
+bool dispc_alpha_blending_enabled(enum omap_channel ch)
+{
+ bool enabled;
+
+ dss_clk_enable(1);
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ enabled = REG_GET(DISPC_CONFIG, 18, 18);
+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
+ enabled = REG_GET(DISPC_CONFIG, 18, 18);
+ else
+ BUG();
+ dss_clk_enable(0);
+
+ return enabled;
+
+}
+
+
+bool dispc_trans_key_enabled(enum omap_channel ch)
+{
+ bool enabled;
+
+ dss_clk_enable(1);
+ if (ch == OMAP_DSS_CHANNEL_LCD)
+ enabled = REG_GET(DISPC_CONFIG, 10, 10);
+ else if (ch == OMAP_DSS_CHANNEL_DIGIT)
+ enabled = REG_GET(DISPC_CONFIG, 12, 12);
+ else
+ BUG();
+ dss_clk_enable(0);
+
+ return enabled;
+}
+
+
+void dispc_set_tft_data_lines(u8 data_lines)
+{
+ int code;
+
+ switch (data_lines) {
+ case 12:
+ code = 0;
+ break;
+ case 16:
+ code = 1;
+ break;
+ case 18:
+ code = 2;
+ break;
+ case 24:
+ code = 3;
+ break;
+ default:
+ BUG();
+ return;
+ }
+
+ dss_clk_enable(1);
+ REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
+ //dispc_write_reg(DISPC_GFX_ATTRIBUTES, 0x8D); // TEDCHO
+ dss_clk_enable(0);
+}
+
+void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
+{
+ u32 l;
+ int stallmode;
+ int gpout0 = 1;
+ int gpout1;
+
+ switch (mode) {
+ case OMAP_DSS_PARALLELMODE_BYPASS:
+ stallmode = 0;
+ gpout1 = 1;
+ break;
+
+ case OMAP_DSS_PARALLELMODE_RFBI:
+ stallmode = 1;
+ gpout1 = 0;
+ break;
+
+ case OMAP_DSS_PARALLELMODE_DSI:
+ stallmode = 1;
+ gpout1 = 1;
+ break;
+
+ default:
+ BUG();
+ return;
+ }
+
+ dss_clk_enable(1);
+
+ l = dispc_read_reg(DISPC_CONTROL);
+
+ l = FLD_MOD(l, stallmode, 11, 11);
+ l = FLD_MOD(l, gpout0, 15, 15);
+ l = FLD_MOD(l, gpout1, 16, 16);
+
+ dispc_write_reg(DISPC_CONTROL, l);
+
+ dss_clk_enable(0);
+}
+
+static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
+ int vsw, int vfp, int vbp)
+{
+ if (0/*cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0*/) {
+ if (hsw < 1 || hsw > 64 ||
+ hfp < 1 || hfp > 256 ||
+ hbp < 1 || hbp > 256 ||
+ vsw < 1 || vsw > 64 ||
+ vfp < 0 || vfp > 255 ||
+ vbp < 0 || vbp > 255)
+ return FALSE;
+ } else {
+ if (hsw < 1 || hsw > 256 ||
+ hfp < 1 || hfp > 4096 ||
+ hbp < 1 || hbp > 4096 ||
+ vsw < 1 || vsw > 256 ||
+ vfp < 0 || vfp > 4095 ||
+ vbp < 0 || vbp > 4095)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
+{
+ return _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
+ timings->hbp, timings->vsw,
+ timings->vfp, timings->vbp);
+}
+
+static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
+ int vsw, int vfp, int vbp)
+{
+ u32 timing_h, timing_v;
+
+ if (0/*cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0*/) {
+ timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
+ FLD_VAL(hbp-1, 27, 20);
+
+ timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
+ FLD_VAL(vbp, 27, 20);
+ } else {
+ timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
+ FLD_VAL(hbp-1, 31, 20);
+
+ timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
+ FLD_VAL(vbp, 31, 20);
+ }
+
+ dss_clk_enable(1);
+ dispc_write_reg(DISPC_TIMING_H, timing_h);
+ dispc_write_reg(DISPC_TIMING_V, timing_v);
+ dss_clk_enable(0);
+}
+
+/* change name to mode? */
+void dispc_set_lcd_timings(struct omap_video_timings *timings)
+{
+ unsigned xtot, ytot;
+ unsigned long ht, vt;
+
+ if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
+ timings->hbp, timings->vsw,
+ timings->vfp, timings->vbp))
+ BUG();
+
+ _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp,
+ timings->vsw, timings->vfp, timings->vbp);
+
+ dispc_set_lcd_size(timings->x_res, timings->y_res);
+
+ xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
+ ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
+
+ ht = (timings->pixel_clock * 1000) / xtot;
+ vt = (timings->pixel_clock * 1000) / xtot / ytot;
+}
+
+void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div)
+{
+ BUG_ON(lck_div < 1);
+ BUG_ON(pck_div < 2);
+
+ dss_clk_enable(1);
+ dispc_write_reg(DISPC_DIVISOR,
+ FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
+ dss_clk_enable(0);
+}
+
+static void dispc_get_lcd_divisor(int *lck_div, int *pck_div)
+{
+ u32 l;
+ l = dispc_read_reg(DISPC_DIVISOR);
+ *lck_div = FLD_GET(l, 23, 16);
+ *pck_div = FLD_GET(l, 7, 0);
+}
+
+inline void dss_write_reg(const struct dss_reg idx, u32 val)
+{
+ __raw_writel(val, DSS_BASE + idx.idx);
+}
+
+static inline u32 dss_read_reg(const struct dss_reg idx)
+{
+ return __raw_readl(DSS_BASE + idx.idx);
+}
+
+int dss_get_dispc_clk_source(void)
+{
+ return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
+}
+
+unsigned long dispc_fclk_rate(void)
+{
+ unsigned long r = 0;
+
+ if (dss_get_dispc_clk_source() == 0)
+ r = clk_get_fck1_ckrate();
+ else
+ r = dsi_get_dsi1_pll_rate();
+ //BUG();
+
+ return r;
+}
+
+unsigned long dispc_lclk_rate(void)
+{
+ int lcd;
+ unsigned long r;
+ u32 l;
+
+ l = dispc_read_reg(DISPC_DIVISOR);
+
+ lcd = FLD_GET(l, 23, 16);
+
+ r = dispc_fclk_rate();
+
+ return r / lcd;
+}
+
+unsigned long dispc_pclk_rate(void)
+{
+ int lcd, pcd;
+ unsigned long r;
+ u32 l;
+
+ l = dispc_read_reg(DISPC_DIVISOR);
+
+ lcd = FLD_GET(l, 23, 16);
+ pcd = FLD_GET(l, 7, 0);
+
+ r = dispc_fclk_rate();
+
+ return r / lcd / pcd;
+}
+
+static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc,
+ bool ihs, bool ivs, u8 acbi, u8 acb)
+{
+ u32 l = 0;
+
+ l |= FLD_VAL(onoff, 17, 17);
+ l |= FLD_VAL(rf, 16, 16);
+ l |= FLD_VAL(ieo, 15, 15);
+ l |= FLD_VAL(ipc, 14, 14);
+ l |= FLD_VAL(ihs, 13, 13);
+ l |= FLD_VAL(ivs, 12, 12);
+ l |= FLD_VAL(acbi, 11, 8);
+ l |= FLD_VAL(acb, 7, 0);
+
+ dss_clk_enable(1);
+ dispc_write_reg(DISPC_POL_FREQ, l);
+ dss_clk_enable(0);
+}
+
+void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb)
+{
+ _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0,
+ (config & OMAP_DSS_LCD_RF) != 0,
+ (config & OMAP_DSS_LCD_IEO) != 0,
+ (config & OMAP_DSS_LCD_IPC) != 0,
+ (config & OMAP_DSS_LCD_IHS) != 0,
+ (config & OMAP_DSS_LCD_IVS) != 0,
+ acbi, acb);
+}
+
+void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
+ u16 *lck_div, u16 *pck_div)
+{
+ u16 pcd_min = is_tft ? 2 : 3;
+ unsigned long best_pck;
+ u16 best_ld, cur_ld;
+ u16 best_pd, cur_pd;
+
+ best_pck = 0;
+ best_ld = 0;
+ best_pd = 0;
+
+ for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
+ unsigned long lck = fck / cur_ld;
+
+ for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
+ unsigned long pck = lck / cur_pd;
+ long old_delta = abs(best_pck - req_pck);
+ long new_delta = abs(pck - req_pck);
+
+ if (best_pck == 0 || new_delta < old_delta) {
+ best_pck = pck;
+ best_ld = cur_ld;
+ best_pd = cur_pd;
+
+ if (pck == req_pck)
+ goto found;
+ }
+
+ if (pck < req_pck)
+ break;
+ }
+
+ if (lck / pcd_min < req_pck)
+ break;
+ }
+
+found:
+ *lck_div = best_ld;
+ *pck_div = best_pd;
+}
+
+int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
+ struct dispc_clock_info *cinfo)
+{
+ unsigned long prate;
+ struct dispc_clock_info cur, best;
+ int match = 0;
+ int min_fck_per_pck;
+ unsigned long fck_rate = clk_get_fck1_ckrate();
+
+ if (cpu_is_omap34xx())
+ prate = clk_get_dpll4_m4_ckrate();
+ else
+ prate = 0;
+
+ if (req_pck == dispc.cache_req_pck &&
+ ((cpu_is_omap34xx() && prate == dispc.cache_prate) ||
+ dispc.cache_cinfo.fck == fck_rate)) {
+ *cinfo = dispc.cache_cinfo;
+ return 0;
+ }
+
+ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
+
+ if (min_fck_per_pck &&
+ req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
+ //DSSERR("Requested pixel clock not possible with the current "
+ // "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
+ //"the constraint off.\n");
+ min_fck_per_pck = 0;
+ }
+
+retry:
+ memset(&cur, 0, sizeof(cur));
+ memset(&best, 0, sizeof(best));
+
+ if (cpu_is_omap24xx()) {
+ /* XXX can we change the clock on omap2? */
+ cur.fck = clk_get_fck1_ckrate();
+ cur.fck_div = 1;
+
+ match = 1;
+
+ find_lck_pck_divs(is_tft, req_pck, cur.fck,
+ &cur.lck_div, &cur.pck_div);
+
+ cur.lck = cur.fck / cur.lck_div;
+ cur.pck = cur.lck / cur.pck_div;
+
+ best = cur;
+
+ goto found;
+ } else if (cpu_is_omap34xx()) {
+ if (cpu_is_omap3630())
+ cur.fck_div = 32;
+ else
+ cur.fck_div = 16;
+
+ for ( ; cur.fck_div > 0; --cur.fck_div) {
+ if (cpu_is_omap3630())
+ cur.fck = prate / cur.fck_div ;
+ else
+ cur.fck = prate / cur.fck_div * 2;
+
+ if (cur.fck > DISPC_MAX_FCK)
+ continue;
+
+ if (min_fck_per_pck &&
+ cur.fck < req_pck * min_fck_per_pck)
+ continue;
+
+ match = 1;
+
+ find_lck_pck_divs(is_tft, req_pck, cur.fck,
+ &cur.lck_div, &cur.pck_div);
+
+ cur.lck = cur.fck / cur.lck_div;
+ cur.pck = cur.lck / cur.pck_div;
+
+ if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) {
+ best = cur;
+
+ if (cur.pck == req_pck)
+ goto found;
+ }
+ }
+ } else {
+ BUG();
+ }
+
+found:
+ if (!match) {
+ if (min_fck_per_pck) {
+ //DSSERR("Could not find suitable clock settings.\n"
+ // "Turning FCK/PCK constraint off and"
+ //"trying again.\n");
+ min_fck_per_pck = 0;
+ goto retry;
+ }
+
+ //DSSERR("Could not find suitable clock settings.\n");
+
+ return -EINVAL;
+ }
+
+ if (cinfo)
+ *cinfo = best;
+
+ dispc.cache_req_pck = req_pck;
+ dispc.cache_prate = prate;
+ dispc.cache_cinfo = best;
+
+ return 0;
+}
+
+int dispc_set_clock_div(struct dispc_clock_info *cinfo)
+{
+ unsigned long prate;
+ int r;
+
+ if (cpu_is_omap34xx()) {
+ prate = clk_get_dpll4_m4_ckrate();
+ }
+
+ if (cpu_is_omap34xx()) {
+ r = clk_set_dpll4_m4_ckrate(prate / cinfo->fck_div);
+ if (r)
+ return r;
+ }
+
+ dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div);
+ //dispc_set_lcd_divisor(cinfo->lck_div, 5);
+
+ return 0;
+}
+
+int dispc_get_clock_div(struct dispc_clock_info *cinfo)
+{
+ cinfo->fck = clk_get_fck1_ckrate();
+
+ if (cpu_is_omap34xx()) {
+ unsigned long prate;
+ prate = clk_get_dpll4_m4_ckrate();
+ cinfo->fck_div = prate / (cinfo->fck / 2);
+ } else {
+ cinfo->fck_div = 0;
+ }
+
+ cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16);
+ cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0);
+
+ cinfo->lck = cinfo->fck / cinfo->lck_div;
+ cinfo->pck = cinfo->lck / cinfo->pck_div;
+
+ return 0;
+}
+
+
+void dispc_enable_sidle(void)
+{
+ REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */
+}
+
+void dispc_disable_sidle(void)
+{
+ REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
+}
+
+static void _omap_dispc_initial_config(void)
+{
+ u32 l;
+
+ l = dispc_read_reg(DISPC_SYSCONFIG);
+ l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */
+ l = FLD_MOD(l, 1, 4, 3); /*NO idle*//*2: SIDLEMODE: smart idle */
+ l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */
+ l = FLD_MOD(l, 0, 0, 0); /*NO autoidle*//*1: AUTOIDLE */
+ dispc_write_reg(DISPC_SYSCONFIG, l);
+
+ /* FUNCGATED */
+ REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
+
+ _dispc_setup_color_conv_coef();
+
+ dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
+
+ dispc_read_plane_fifo_sizes();
+}
+
+static void _omap_dispc_set_irqs(void)
+{
+ u32 mask;
+ u32 old_mask;
+ //int i;
+ //struct omap_dispc_isr_data *isr_data;
+
+ mask = dispc.irq_error_mask;
+
+#if 0
+ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
+ isr_data = &dispc.registered_isr[i];
+
+ if (isr_data->isr == NULL)
+ continue;
+
+ mask |= isr_data->mask;
+ }
+#endif
+
+ old_mask = dispc_read_reg(DISPC_IRQENABLE);
+ /* clear the irqstatus for newly enabled irqs */
+ //dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
+
+ dispc_write_reg(DISPC_IRQENABLE, mask);
+
+}
+
+static void _omap_dispc_initialize_irq(void)
+{
+ //unsigned long flags;
+
+ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
+
+ /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
+ * so clear it */
+ dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
+
+ _omap_dispc_set_irqs();
+}
+
+#define DSS_REG_GET(idx, start, end) \
+ FLD_GET(dss_read_reg(idx), start, end)
+
+#define DSS_REG_FLD_MOD(idx, val, start, end) \
+ dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
+
+static int _omap_dss_wait_reset(void)
+{
+ unsigned timeout = 1000;
+
+ while (DSS_REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
+ udelay(1);
+ if (!--timeout) {
+ //DSSERR("soft reset failed\n");
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static int _omap_dss_reset(void)
+{
+ /* Soft reset */
+ DSS_REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
+ return _omap_dss_wait_reset();
+}
+
+int dispc_init(void)
+{
+ //u32 rev;
+
+ dss_clk_enable(1);
+
+ _omap_dispc_initial_config();
+
+ _omap_dispc_initialize_irq();
+
+ //dispc_save_context();
+
+ //rev = dispc_read_reg(DISPC_REVISION);
+ //printf("OMAP DISPC rev %d.%d\n",
+ // FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
+
+ //dispc_set_channel_out(OMAP_DSS_GFX, OMAP_DSS_CHANNEL_LCD);
+
+ configure_dispc();
+
+ //dss_clk_enable(0);
+
+ return 0;
+}
+
+static int configure_overlay(enum omap_plane plane)
+{
+ struct overlay_cache_data *c = &hub_overlay;
+ u16 outw, outh;
+ u16 x, y, w, h;
+ u32 paddr;
+ int r;
+ u32 size;
+
+#if 1
+ //printf("kyungtae_test1\n");
+ size = dispc_get_plane_fifo_size(plane);
+ //printf("kyungtae_test2 size = %lu\n",size);
+
+ dsi_get_overlay_fifo_thresholds(plane, size,
+ c->burst_size, c->fifo_low,
+ c->fifo_high);
+ //printf("kyungtae_test3\n");
+
+#endif
+
+ x = c->pos_x;
+ y = c->pos_y;
+ w = c->width;
+ h = c->height;
+ outw = c->out_width == 0 ? c->width : c->out_width;
+ outh = c->out_height == 0 ? c->height : c->out_height;
+ paddr = c->paddr;
+
+ r = dispc_setup_plane(plane,
+ paddr,
+ c->screen_width,
+ x, y,
+ w, h,
+ outw, outh,
+ c->color_mode,
+ c->ilace,
+ c->rotation_type,
+ c->rotation,
+ c->mirror,
+ c->global_alpha);
+
+ if (r) {
+ /* this shouldn't happen */
+ printf("dispc_setup_plane failed for ovl %d\n", plane);
+ dispc_enable_plane(plane, 0);
+ return r;
+ }
+
+ dispc_enable_replication(plane, c->replication);
+
+ dispc_set_burst_size(plane, c->burst_size);
+ dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high);
+
+ dispc_enable_plane(plane, 1);
+
+ return 0;
+}
+
+static void configure_manager(enum omap_channel channel)
+{
+ //DSSDBGF("%d", channel);
+
+ dispc_set_trans_key(channel, OMAP_DSS_COLOR_KEY_GFX_DST, 0);
+ dispc_enable_trans_key(channel, 0);
+ dispc_enable_alpha_blending(channel, 0);
+}
+
+int configure_dispc(void)
+{
+ int r = 0;
+
+ r = configure_overlay(OMAP_DSS_GFX);
+ if (r)
+ return r;
+
+ configure_manager(OMAP_DSS_CHANNEL_LCD);
+
+ dispc_go(OMAP_DSS_GFX);
+
+ return r;
+}
+
+int dispc_enable_plane(enum omap_plane plane, bool enable)
+{
+ dss_clk_enable(1);
+ _dispc_enable_plane(plane, enable);
+
+ if (plane == OMAP_DSS_GFX) {
+ if (enable)
+ gfx_in_use = 1;
+ else
+ gfx_in_use = 0;
+ }
+
+ dss_clk_enable(0);
+
+ return 0;
+}
+
+int dispc_setup_plane(enum omap_plane plane,
+ u32 paddr, u16 screen_width,
+ u16 pos_x, u16 pos_y,
+ u16 width, u16 height,
+ u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+ u8 rotation, bool mirror, u8 global_alpha)
+{
+ int r = 0;
+
+ dss_clk_enable(1);
+
+ r = _dispc_setup_plane(plane,
+ paddr, screen_width,
+ pos_x, pos_y,
+ width, height,
+ out_width, out_height,
+ color_mode, ilace,
+ rotation_type,
+ rotation, mirror,
+ global_alpha);
+
+ dss_clk_enable(0);
+
+ return r;
+}
+
+void dispc_configure_image(u32 image)
+{
+ struct overlay_cache_data *c = &hub_overlay;
+
+ if (image == NULL)
+ c->paddr = CONFIG_FB_ADDRESS;
+ else
+ c->paddr = image;
+
+ configure_dispc();
+}
diff --git a/board/lge/sniper/hub_dpi.c b/board/lge/sniper/hub_dpi.c
new file mode 100755
index 00000000000..40f7b689516
--- /dev/null
+++ b/board/lge/sniper/hub_dpi.c
@@ -0,0 +1,281 @@
+/* u-boot/board/hub/hub_dpi.c
+ *
+ * Author: Kyungtae Oh <kyungtae.oh@lge.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <common.h>
+#include <asm/arch/bits.h>
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/cpu.h>
+#include <asm/errno.h>
+#include "hub_dss.h"
+
+
+#define LCD_XRES 480
+#define LCD_YRES 800
+
+/* [skykrkrk@lge.com] 2010-01-14, optimized clock speed : 26.585MHz. if 24700 is selected, pixel-clock will be 24.686MHz */
+#define LCD_PIXCLOCK_OPT 26583
+#define LCD_PIXCLOCK_MIN 24700 /* NEC MIN PIX Clock is 21.8MHz */
+#define LCD_PIXCLOCK_TYP 26000 /* Typical PIX clock is 23.8MHz */
+#define LCD_PIXCLOCK_MAX 27300 /* Maximum is 25.7MHz */
+
+/* Current Pixel clock */
+#define LCD_PIXEL_CLOCK LCD_PIXCLOCK_OPT
+
+//PAULK: not used
+static struct omap_video_timings hub_panel_timings = {
+ /* LGE_CHANGE_S [HEAVEN:FW:tosungmin@lge.com] 2009-09-07, lcd drivers */
+ .x_res = LCD_XRES,
+ .y_res = LCD_YRES,
+ .pixel_clock = LCD_PIXEL_CLOCK,
+ .hfp = 1, //right_margin - 1
+ .hsw = 1, //hsync_len - 1
+ .hbp = 1, //left_margin - 1
+ .vfp = 0, //lower_margin
+ .vsw = 1, //vsync_len - 1
+ .vbp = 0, //upper_margin
+
+};
+
+static u32 hub_config = (OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |OMAP_DSS_LCD_IHS);
+static u8 data_lines = 24;
+static int hub_acbi = 0; /* ac-bias pin transitions per interrupt */
+/* Unit: line clocks */
+static int hub_acb = 0; /* ac-bias pin frequency */
+static int dss_state = OMAP_DSS_DISPLAY_DISABLED;
+
+static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req,
+ unsigned long *fck, int *lck_div, int *pck_div)
+{
+ struct dsi_clock_info cinfo;
+ int r;
+
+ r = dsi_pll_calc_pck(is_tft, pck_req, &cinfo);
+ if (r)
+ return r;
+
+ r = dsi_pll_program(&cinfo);
+ if (r)
+ return r;
+
+ dss_select_clk_source(0, 1);
+
+ dispc_set_lcd_divisor(cinfo.lck_div, cinfo.pck_div);
+
+ *fck = cinfo.dsi1_pll_fclk;
+ *lck_div = cinfo.lck_div;
+ *pck_div = cinfo.pck_div;
+
+ return 0;
+}
+
+static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
+ unsigned long *fck, int *lck_div, int *pck_div)
+{
+ struct dispc_clock_info cinfo;
+ int r;
+
+ r = dispc_calc_clock_div(is_tft, pck_req, &cinfo);
+ if (r)
+ return r;
+
+ r = dispc_set_clock_div(&cinfo);
+ if (r)
+ return r;
+
+ *fck = cinfo.fck;
+ *lck_div = cinfo.lck_div;
+ *pck_div = cinfo.pck_div;
+
+ return 0;
+}
+
+//PAULK: Not called
+static int dpi_set_mode(void)
+{
+ int lck_div, pck_div;
+ unsigned long fck;
+ unsigned long pck;
+ bool is_tft;
+ int r = 0;
+
+ //dss_clk_enable(1);
+
+ dispc_set_pol_freq(hub_config, hub_acbi, hub_acb);
+
+ is_tft = (hub_config & OMAP_DSS_LCD_TFT) != 0;
+
+ r = dpi_set_dsi_clk(is_tft, hub_panel_timings.pixel_clock * 1000,
+ &fck, &lck_div, &pck_div);
+ //r = dpi_set_dispc_clk(is_tft, hub_panel_timings.pixel_clock * 1000,
+ // &fck, &lck_div, &pck_div);
+ if (r)
+ goto err0;
+
+ pck = fck / lck_div / pck_div / 1000;
+
+ if (pck != hub_panel_timings.pixel_clock) {
+#if 0
+ DSSWARN("Could not find exact pixel clock. "
+ "Requested %d kHz, got %lu kHz\n",
+ t->pixel_clock, pck);
+#endif
+ hub_panel_timings.pixel_clock = pck;
+ }
+
+ dispc_set_lcd_timings(&hub_panel_timings);
+ return 0;
+
+err0:
+ //dss_clk_enable(0);
+ printf("dpi_set_mode_err0\n");
+ return r;
+}
+
+// PAULK: NOT ACTUALLY CALLED
+static int dpi_basic_init(void)
+{
+ bool is_tft;
+
+ is_tft = (hub_config & OMAP_DSS_LCD_TFT) != 0;
+
+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
+ dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT :
+ OMAP_DSS_LCD_DISPLAY_STN);
+ dispc_set_tft_data_lines(data_lines);
+
+ return 0;
+}
+
+int dss_clk_enable(bool enable)
+{
+//#define FCK_DSS_ON 0x00000005 /* tv+dss1 (not dss2) */
+#define FCK_DSS_ON 0x00000007 /* tv+dss1+dss2 */
+#define ICK_DSS_ON 0x00000001
+
+ if(enable) {
+ sr32(CM_FCLKEN_DSS, 0, 32, FCK_DSS_ON);
+ sr32(CM_ICLKEN_DSS, 0, 32, ICK_DSS_ON);
+ }
+ else {
+ //sr32(CM_FCLKEN_DSS, 0, 32, 0x0);
+ //sr32(CM_ICLKEN_DSS, 0, 32, 0x0);
+ }
+
+ return 0;
+}
+
+// PAULK: NOT ACTUALLY CALLED
+static int dpi_display_enable(void)
+{
+ static int r;
+
+ //dss_clk_enable(1);
+
+ r = dpi_basic_init();
+ if (r)
+ goto err0;
+
+ //dss_clk_enable(1);
+
+ r = dsi_pll_init(1, 1);
+
+ //r = dpi_set_mode();
+ //if (r)
+ // goto err0;
+
+ mdelay(2);
+
+ //dispc_enable_lcd_out(1);
+
+ //dss_state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
+
+err0:
+ //dispc_enable_lcd_out(0);
+ //dss_clk_enable(0);
+ printf("kyungtae_dpi_display_enable_err0");
+ return r;
+}
+
+//PAULK: never called
+static void dpi_set_timings(struct omap_video_timings *timings)
+{
+ if (dss_state == OMAP_DSS_DISPLAY_ACTIVE) {
+ dpi_set_mode();
+ dispc_go(OMAP_DSS_CHANNEL_LCD);
+ }
+}
+
+static int dpi_check_timings(struct omap_video_timings *timings)
+{
+ bool is_tft;
+ int r;
+ int lck_div, pck_div;
+ unsigned long fck;
+ unsigned long pck;
+
+ if (!dispc_lcd_timings_ok(timings))
+ return -EINVAL;
+
+ if (timings->pixel_clock == 0)
+ return -EINVAL;
+
+ is_tft = (hub_config & OMAP_DSS_LCD_TFT) != 0;
+ {
+ struct dsi_clock_info cinfo;
+ r = dsi_pll_calc_pck(is_tft, timings->pixel_clock * 1000,
+ &cinfo);
+
+ if (r)
+ return r;
+
+ fck = cinfo.dsi1_pll_fclk;
+ lck_div = cinfo.lck_div;
+ pck_div = cinfo.pck_div;
+ }
+#if 0
+ {
+ struct dispc_clock_info cinfo;
+ r = dispc_calc_clock_div(is_tft, timings->pixel_clock * 1000,
+ &cinfo);
+
+ if (r)
+ return r;
+
+ fck = cinfo.fck;
+ lck_div = cinfo.lck_div;
+ pck_div = cinfo.pck_div;
+ }
+#endif
+ pck = fck / lck_div / pck_div / 1000;
+
+ timings->pixel_clock = pck;
+
+ return 0;
+}
+
+static void dpi_get_timings(struct omap_video_timings *timings)
+{
+ *timings = hub_panel_timings;
+}
+
+//PAULK: not actually called
+int dpi_init(void)
+{
+ dpi_display_enable();
+ return 0;
+}
+
diff --git a/board/lge/sniper/hub_dsi.c b/board/lge/sniper/hub_dsi.c
new file mode 100755
index 00000000000..9b8b3774a73
--- /dev/null
+++ b/board/lge/sniper/hub_dsi.c
@@ -0,0 +1,3205 @@
+/* u-boot/board/hub/hub_dsi.c
+ *
+ * Author: Kyungtae Oh <kyungtae.oh@lge.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <asm/arch/bits.h>
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/cpu.h>
+#include <asm/errno.h>
+
+#include "hub_dss.h"
+
+
+#define LCD_XRES 480
+#define LCD_YRES 800
+
+#define INIT_COMPLETION(x) ((x).done = 0)
+
+
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+
+/* handy sizes */
+#define SZ_16 0x00000010
+#define SZ_256 0x00000100
+#define SZ_512 0x00000200
+
+#define DSS_BASE 0x48050000
+
+#define DSS_SZ_REGS SZ_512
+
+struct dss_reg {
+ u16 idx;
+};
+
+#define DSS_REG(idx) ((const struct dss_reg) { idx })
+
+#define DSS_REVISION DSS_REG(0x0000)
+#define DSS_SYSCONFIG DSS_REG(0x0010)
+#define DSS_SYSSTATUS DSS_REG(0x0014)
+#define DSS_IRQSTATUS DSS_REG(0x0018)
+#define DSS_CONTROL DSS_REG(0x0040)
+#define DSS_SDI_CONTROL DSS_REG(0x0044)
+#define DSS_PLL_CONTROL DSS_REG(0x0048)
+#define DSS_SDI_STATUS DSS_REG(0x005C)
+
+/*#define VERBOSE_IRQ*/
+#define __iomem
+
+#define DSI_BASE 0x4804FC00
+
+#if defined(CONFIG_SNIPER)
+#define DSI_CLOCK_POLARITY 0 /* +/- pin order */
+#define DSI_DATA0_POLARITY 0 /* +/- pin order */
+#define DSI_DATA1_POLARITY 0 /* +/- pin order */
+#define DSI_CLOCK_LANE 3 /* Clock lane position: 1 */
+#define DSI_DATA0_LANE 1 /* Data0 lane position: 2 */
+#define DSI_DATA1_LANE 2 /* Data1 lane position: 3 */
+#define DSI_CTRL_PIXEL_SIZE 24 /* Pixel size */
+#define DSI_LP_CLK_HZ 10000000 /* LP CLK Hard coding */
+#define DSI_DDR_CLK_HZ 190000000 /* DDR CLK Hard coding */
+#define DSI_DIV_REGN 20
+#define DSI_DIV_REGM 110
+#define DSI_DIV_REGM3 3
+#define DSI_DIV_REGM4 10
+#define DSI_DIV_LCK_DIV 2
+#define DSI_DIV_PCK_DIV 4
+
+#define DSI_DSS_CLK_FCK2 26000000 /* 26MHz */
+
+
+#define CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK 0
+
+#endif
+static int dsi_ext_te = 0;
+
+static int dss_state = OMAP_DSS_DISPLAY_DISABLED;
+
+struct dsi_reg { u16 idx; };
+
+#define DSI_REG(idx) ((const struct dsi_reg) { idx })
+
+#define DSI_SZ_REGS SZ_1K
+/* DSI Protocol Engine */
+
+#define DSI_REVISION DSI_REG(0x0000)
+#define DSI_SYSCONFIG DSI_REG(0x0010)
+#define DSI_SYSSTATUS DSI_REG(0x0014)
+#define DSI_IRQSTATUS DSI_REG(0x0018)
+#define DSI_IRQENABLE DSI_REG(0x001C)
+#define DSI_CTRL DSI_REG(0x0040)
+#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048)
+#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C)
+#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050)
+#define DSI_CLK_CTRL DSI_REG(0x0054)
+#define DSI_TIMING1 DSI_REG(0x0058)
+#define DSI_TIMING2 DSI_REG(0x005C)
+#define DSI_VM_TIMING1 DSI_REG(0x0060)
+#define DSI_VM_TIMING2 DSI_REG(0x0064)
+#define DSI_VM_TIMING3 DSI_REG(0x0068)
+#define DSI_CLK_TIMING DSI_REG(0x006C)
+#define DSI_TX_FIFO_VC_SIZE DSI_REG(0x0070)
+#define DSI_RX_FIFO_VC_SIZE DSI_REG(0x0074)
+#define DSI_COMPLEXIO_CFG2 DSI_REG(0x0078)
+#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(0x007C)
+#define DSI_VM_TIMING4 DSI_REG(0x0080)
+#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(0x0084)
+#define DSI_VM_TIMING5 DSI_REG(0x0088)
+#define DSI_VM_TIMING6 DSI_REG(0x008C)
+#define DSI_VM_TIMING7 DSI_REG(0x0090)
+#define DSI_STOPCLK_TIMING DSI_REG(0x0094)
+#define DSI_VC_CTRL(n) DSI_REG(0x0100 + (n * 0x20))
+#define DSI_VC_TE(n) DSI_REG(0x0104 + (n * 0x20))
+#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(0x0108 + (n * 0x20))
+#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(0x010C + (n * 0x20))
+#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(0x0110 + (n * 0x20))
+#define DSI_VC_IRQSTATUS(n) DSI_REG(0x0118 + (n * 0x20))
+#define DSI_VC_IRQENABLE(n) DSI_REG(0x011C + (n * 0x20))
+
+/* DSIPHY_SCP */
+
+#define DSI_DSIPHY_CFG0 DSI_REG(0x200 + 0x0000)
+#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004)
+#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008)
+#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014)
+
+/* DSI_PLL_CTRL_SCP */
+
+#define DSI_PLL_CONTROL DSI_REG(0x300 + 0x0000)
+#define DSI_PLL_STATUS DSI_REG(0x300 + 0x0004)
+#define DSI_PLL_GO DSI_REG(0x300 + 0x0008)
+#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C)
+#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010)
+
+#define REG_GET(idx, start, end) \
+ FLD_GET(dsi_read_reg(idx), start, end)
+
+#define REG_FLD_MOD(idx, val, start, end) \
+ dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end))
+
+/* Global interrupts */
+#define DSI_IRQ_VC0 (1 << 0)
+#define DSI_IRQ_VC1 (1 << 1)
+#define DSI_IRQ_VC2 (1 << 2)
+#define DSI_IRQ_VC3 (1 << 3)
+#define DSI_IRQ_WAKEUP (1 << 4)
+#define DSI_IRQ_RESYNC (1 << 5)
+#define DSI_IRQ_PLL_LOCK (1 << 7)
+#define DSI_IRQ_PLL_UNLOCK (1 << 8)
+#define DSI_IRQ_PLL_RECALL (1 << 9)
+#define DSI_IRQ_COMPLEXIO_ERR (1 << 10)
+#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14)
+#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15)
+#define DSI_IRQ_TE_TRIGGER (1 << 16)
+#define DSI_IRQ_ACK_TRIGGER (1 << 17)
+#define DSI_IRQ_SYNC_LOST (1 << 18)
+#define DSI_IRQ_LDO_POWER_GOOD (1 << 19)
+#define DSI_IRQ_TA_TIMEOUT (1 << 20)
+#define DSI_IRQ_ERROR_MASK \
+ (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
+ DSI_IRQ_TA_TIMEOUT)
+#define DSI_IRQ_CHANNEL_MASK 0xf
+
+/* Virtual channel interrupts */
+#define DSI_VC_IRQ_CS (1 << 0)
+#define DSI_VC_IRQ_ECC_CORR (1 << 1)
+#define DSI_VC_IRQ_PACKET_SENT (1 << 2)
+#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3)
+#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4)
+#define DSI_VC_IRQ_BTA (1 << 5)
+#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6)
+#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7)
+#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
+#define DSI_VC_IRQ_ERROR_MASK \
+ (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
+ DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
+ DSI_VC_IRQ_FIFO_TX_UDF)
+
+/* ComplexIO interrupts */
+#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0)
+#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1)
+#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2)
+#define DSI_CIO_IRQ_ERRESC1 (1 << 5)
+#define DSI_CIO_IRQ_ERRESC2 (1 << 6)
+#define DSI_CIO_IRQ_ERRESC3 (1 << 7)
+#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10)
+#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11)
+#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12)
+#define DSI_CIO_IRQ_STATEULPS1 (1 << 15)
+#define DSI_CIO_IRQ_STATEULPS2 (1 << 16)
+#define DSI_CIO_IRQ_STATEULPS3 (1 << 17)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24)
+#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
+#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
+#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
+
+#define DSI_DT_DCS_SHORT_WRITE_0 0x05
+#define DSI_DT_DCS_SHORT_WRITE_1 0x15
+#define DSI_DT_DCS_READ 0x06
+#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37
+#define DSI_DT_NULL_PACKET 0x09
+#define DSI_DT_DCS_LONG_WRITE 0x39
+
+#define DSI_DT_RX_ACK_WITH_ERR 0x02
+#define DSI_DT_RX_DCS_LONG_READ 0x1c
+#define DSI_DT_RX_SHORT_READ_1 0x21
+#define DSI_DT_RX_SHORT_READ_2 0x22
+
+#define FINT_MAX 2100000
+#define FINT_MIN 750000
+#define REGN_MAX (1 << 7)
+#define REGM_MAX ((1 << 11) - 1)
+#define REGM3_MAX (1 << 4)
+#define REGM4_MAX (1 << 4)
+
+enum fifo_size {
+ DSI_FIFO_SIZE_0 = 0,
+ DSI_FIFO_SIZE_32 = 1,
+ DSI_FIFO_SIZE_64 = 2,
+ DSI_FIFO_SIZE_96 = 3,
+ DSI_FIFO_SIZE_128 = 4,
+};
+
+struct dsi_update_region {
+ bool dirty;
+ u16 x, y, w, h;
+ //struct omap_dss_device *device; //kyungtaeoh
+};
+struct completion {
+ unsigned int done;
+// wait_queue_head_t wait;
+};
+
+static struct
+{
+ void volatile *base;
+
+ unsigned long dsi1_pll_fclk; /* Hz */
+ unsigned long dsi2_pll_fclk; /* Hz */
+ unsigned long dsiphy; /* Hz */
+ unsigned long ddr_clk; /* Hz */
+
+ //struct regulator *vdds_dsi_reg;
+
+ struct {
+ //struct omap_dss_device *dssdev; //kyungtae
+ enum fifo_size fifo_size;
+ int dest_per; /* destination peripheral 0-3 */
+ } vc[4];
+#if 0
+ struct mutex lock;
+ struct mutex bus_lock;
+#endif
+ unsigned pll_locked;
+
+ struct completion bta_completion;
+
+ //struct task_struct *thread;
+
+ //wait_queue_head_t waitqueue;
+
+ //spinlock_t update_lock;
+ bool framedone_received;
+ struct dsi_update_region update_region;
+ struct dsi_update_region active_update_region;
+#if 0
+ struct completion update_completion;
+#endif
+ enum omap_dss_update_mode user_update_mode;
+ enum omap_dss_update_mode update_mode;
+
+ bool te_enabled;
+ bool use_ext_te;
+
+ unsigned long cache_req_pck;
+ unsigned long cache_clk_freq;
+ struct dsi_clock_info cache_cinfo;
+
+ u32 errors;
+ //spinlock_t errors_lock;
+} dsi;
+
+static inline void dsi_write_reg(const struct dsi_reg idx, u32 val)
+{
+ //printf("dsi_write_reg\n");
+ __raw_writel(val, DSI_BASE + idx.idx);
+}
+
+static inline u32 dsi_read_reg(const struct dsi_reg idx)
+{
+ //printf("dsi_read_reg\n");
+
+ return __raw_readl(DSI_BASE + idx.idx);
+}
+
+static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum,
+ int value)
+{
+ int t = 100000;
+ //printf("dsi_wait_for_bit_change\n");
+
+ while (REG_GET(idx, bitnum, bitnum) != value) {
+ if (--t == 0)
+ return !value;
+ }
+
+ return value;
+}
+
+#define dsi_perf_mark_setup()
+#define dsi_perf_mark_start()
+#define dsi_perf_mark_start_auto()
+#define dsi_perf_show(x)
+
+static void print_irq_status(u32 status)
+{
+#ifndef VERBOSE_IRQ
+ if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
+ return;
+#endif
+ //printf("DSI IRQ: 0x%x: ", status);
+
+#define PIS(x) \
+ if (status & DSI_IRQ_##x) \
+ printf(#x " ");
+#ifdef VERBOSE_IRQ
+ PIS(VC0);
+ PIS(VC1);
+ PIS(VC2);
+ PIS(VC3);
+#endif
+ PIS(WAKEUP);
+ PIS(RESYNC);
+ PIS(PLL_LOCK);
+ PIS(PLL_UNLOCK);
+ PIS(PLL_RECALL);
+ PIS(COMPLEXIO_ERR);
+ PIS(HS_TX_TIMEOUT);
+ PIS(LP_RX_TIMEOUT);
+ PIS(TE_TRIGGER);
+ PIS(ACK_TRIGGER);
+ PIS(SYNC_LOST);
+ PIS(LDO_POWER_GOOD);
+ PIS(TA_TIMEOUT);
+#undef PIS
+
+ printf("\n");
+}
+
+static void print_irq_status_vc(int channel, u32 status)
+{
+#ifndef VERBOSE_IRQ
+ if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
+ return;
+#endif
+ //printf("DSI VC(%d) IRQ 0x%x: ", channel, status);
+
+#define PIS(x) \
+ if (status & DSI_VC_IRQ_##x) \
+ printf(#x " ");
+ PIS(CS);
+ PIS(ECC_CORR);
+#ifdef VERBOSE_IRQ
+ PIS(PACKET_SENT);
+#endif
+ PIS(FIFO_TX_OVF);
+ PIS(FIFO_RX_OVF);
+ PIS(BTA);
+ PIS(ECC_NO_CORR);
+ PIS(FIFO_TX_UDF);
+ PIS(PP_BUSY_CHANGE);
+#undef PIS
+ printf("\n");
+}
+
+static void print_irq_status_cio(u32 status)
+{
+ printf("DSI CIO IRQ 0x%x: ", status);
+
+#define PIS(x) \
+ if (status & DSI_CIO_IRQ_##x) \
+ printf(#x " ");
+ PIS(ERRSYNCESC1);
+ PIS(ERRSYNCESC2);
+ PIS(ERRSYNCESC3);
+ PIS(ERRESC1);
+ PIS(ERRESC2);
+ PIS(ERRESC3);
+ PIS(ERRCONTROL1);
+ PIS(ERRCONTROL2);
+ PIS(ERRCONTROL3);
+ PIS(STATEULPS1);
+ PIS(STATEULPS2);
+ PIS(STATEULPS3);
+ PIS(ERRCONTENTIONLP0_1);
+ PIS(ERRCONTENTIONLP1_1);
+ PIS(ERRCONTENTIONLP0_2);
+ PIS(ERRCONTENTIONLP1_2);
+ PIS(ERRCONTENTIONLP0_3);
+ PIS(ERRCONTENTIONLP1_3);
+ PIS(ULPSACTIVENOT_ALL0);
+ PIS(ULPSACTIVENOT_ALL1);
+#undef PIS
+
+ printf("\n");
+}
+
+
+static int debug_irq;
+
+/* called from dss */
+void dsi_irq_handler(void)
+{
+ u32 irqstatus, vcstatus, ciostatus;
+ int i;
+
+ irqstatus = dsi_read_reg(DSI_IRQSTATUS);
+
+ if (irqstatus & DSI_IRQ_ERROR_MASK) {
+ //printf("DSI error, irqstatus %x\n", irqstatus);
+ print_irq_status(irqstatus);
+ //spin_lock(&dsi.errors_lock);
+ dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK;
+ //spin_unlock(&dsi.errors_lock);
+ } else if (debug_irq) {
+ print_irq_status(irqstatus);
+ }
+
+ for (i = 0; i < 4; ++i) {
+ if ((irqstatus & (1<<i)) == 0)
+ continue;
+
+ vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
+
+// if (vcstatus & DSI_VC_IRQ_BTA)
+// complete(&dsi.bta_completion);
+
+ if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
+ //printf("DSI VC(%d) error, vc irqstatus %x\n",
+ // i, vcstatus);
+ print_irq_status_vc(i, vcstatus);
+ } else if (debug_irq) {
+ print_irq_status_vc(i, vcstatus);
+ }
+
+ dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus);
+ }
+
+ if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
+ ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
+
+ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
+
+ //printf("DSI CIO error, cio irqstatus %x\n", ciostatus);
+ print_irq_status_cio(ciostatus);
+ }
+
+ dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
+}
+
+
+static void _dsi_initialize_irq(void)
+{
+ u32 l;
+ int i;
+
+ /* disable all interrupts */
+ dsi_write_reg(DSI_IRQENABLE, 0);
+ for (i = 0; i < 4; ++i)
+ dsi_write_reg(DSI_VC_IRQENABLE(i), 0);
+ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0);
+
+ /* clear interrupt status */
+ l = dsi_read_reg(DSI_IRQSTATUS);
+ dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK);
+
+ for (i = 0; i < 4; ++i) {
+ l = dsi_read_reg(DSI_VC_IRQSTATUS(i));
+ dsi_write_reg(DSI_VC_IRQSTATUS(i), l);
+ }
+
+ l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
+ dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l);
+
+ /* enable error irqs */
+ l = DSI_IRQ_ERROR_MASK;
+ dsi_write_reg(DSI_IRQENABLE, l);
+
+ l = DSI_VC_IRQ_ERROR_MASK;
+ for (i = 0; i < 4; ++i)
+ dsi_write_reg(DSI_VC_IRQENABLE(i), l);
+
+ /* XXX zonda responds incorrectly, causing control error:
+ Exit from LP-ESC mode to LP11 uses wrong transition states on the
+ data lines LP0 and LN0. */
+ dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE,
+ -1 & (~DSI_CIO_IRQ_ERRCONTROL2));
+}
+
+static u32 dsi_get_errors(void)
+{
+ //unsigned long flags;
+ u32 e;
+ //spin_lock_irqsave(&dsi.errors_lock, flags);
+ e = dsi.errors;
+ dsi.errors = 0;
+ //spin_unlock_irqrestore(&dsi.errors_lock, flags);
+ return e;
+}
+
+static void dsi_vc_enable_bta_irq(int channel)
+{
+ u32 l;
+
+ l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
+ l |= DSI_VC_IRQ_BTA;
+ dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
+}
+
+static void dsi_vc_disable_bta_irq(int channel)
+{
+ u32 l;
+
+ l = dsi_read_reg(DSI_VC_IRQENABLE(channel));
+ l &= ~DSI_VC_IRQ_BTA;
+ dsi_write_reg(DSI_VC_IRQENABLE(channel), l);
+}
+
+/* DSI func clock. this could also be DSI2_PLL_FCLK */
+static inline void enable_clocks(bool enable)
+{
+ //printf("dsi_enable_clocks\n");
+
+ //if (enable)
+ //dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
+ dss_clk_enable(enable);
+ //else
+ // dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
+}
+
+/* source clock for DSI PLL. this could also be PCLKFREE */
+static inline void dsi_enable_pll_clock(bool enable)
+{
+ //printf("dsi_enable_pll_clock\n");
+
+ //if (enable)
+ //dss_clk_enable(DSS_CLK_FCK2);
+ dss_clk_enable(enable);
+ //else
+ // dss_clk_disable(DSS_CLK_FCK2);
+
+ if (enable && dsi.pll_locked) {
+ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1)
+ printf("cannot lock PLL when enabling clocks\n");
+ }
+}
+
+#define _dsi_print_reset_status()
+
+
+static inline int dsi_if_enable(bool enable)
+{
+ //DSSDBG("dsi_if_enable(%d)\n", enable);
+ //printf("dsi_if_enable\n");
+
+ enable = enable ? 1 : 0;
+ REG_FLD_MOD(DSI_CTRL, enable, 0, 0); /* IF_EN */
+
+ if (wait_for_bit_change(DSI_CTRL, 0, enable) != enable) {
+ printf("Failed to set dsi_if_enable to %d\n", enable);
+ return -EIO;
+ }
+
+ return 0;
+}
+ /* dss.c file */
+static inline u32 dss_read_reg(const struct dss_reg idx)
+{
+ return __raw_readl(DSS_BASE + idx.idx);
+}
+
+void dss_select_clk_source(bool dsi, bool dispc)
+{
+ u32 r;
+ r = dss_read_reg(DSS_CONTROL);
+ r = FLD_MOD(r, dsi, 1, 1); /* DSI_CLK_SWITCH */
+ r = FLD_MOD(r, dispc, 0, 0); /* DISPC_CLK_SWITCH */
+ dss_write_reg(DSS_CONTROL, r);
+ //printf("dsi_dss_select_clk_source\n");
+}
+
+int dss_get_dsi_clk_source(void)
+{
+ //printf("dsi_dss_get_dsi_clk_source\n");
+
+ return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1);
+}
+
+static unsigned long dsi_fclk_rate(void)
+{
+ unsigned long r;
+ //printf("dsi_fclk_rate\n");
+
+ if (dss_get_dsi_clk_source() == 0) {
+ /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */
+ r = clk_get_fck1_ckrate();
+ } else {
+ /* DSI FCLK source is DSI2_PLL_FCLK */
+ r = dsi.dsi2_pll_fclk;
+ }
+
+ return r;
+}
+
+static int dsi_set_lp_clk_divisor(void)
+{
+ unsigned n;
+ unsigned long dsi_fclk;
+ unsigned long lp_clk, lp_clk_req;
+ //printf("dsi_set_lp_clk_divisor\n");
+
+ dsi_fclk = dsi_fclk_rate();
+
+ lp_clk_req = DSI_LP_CLK_HZ;
+
+ for (n = 1; n < (1 << 13) - 1; ++n) {
+ lp_clk = dsi_fclk / 2 / n;
+ if (lp_clk <= lp_clk_req)
+ break;
+ }
+
+ if (n == (1 << 13) - 1) {
+ //printf("Failed to find LP_CLK_DIVISOR\n");
+ return -EINVAL;
+ }
+
+ //printf("LP_CLK_DIV %u, LP_CLK %lu (req %lu)\n", n, lp_clk, lp_clk_req);
+
+ REG_FLD_MOD(DSI_CLK_CTRL, n, 12, 0); /* LP_CLK_DIVISOR */
+ if (dsi_fclk > 30*1000*1000)
+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 21, 21); /* LP_RX_SYNCHRO_ENABLE */
+
+ return 0;
+}
+
+
+enum dsi_pll_power_state {
+ DSI_PLL_POWER_OFF = 0x0,
+ DSI_PLL_POWER_ON_HSCLK = 0x1,
+ DSI_PLL_POWER_ON_ALL = 0x2,
+ DSI_PLL_POWER_ON_DIV = 0x3,
+};
+
+static int dsi_pll_power(enum dsi_pll_power_state state)
+{
+ int t = 0;
+ //printf("dsi_pll_power\n");
+
+ REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */
+
+ /* PLL_PWR_STATUS */
+ while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) {
+ udelay(1);
+ if (t++ > 1000) {
+ printf("Failed to set DSI PLL power mode to %d\n",
+ state);
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+/* LGE_CHANGE_S [kyungtae.oh@lge.com] 2010-03-16, for dsi interface set */
+#if defined(CONFIG_SNIPER)
+/* calculate clock rates using dividers in cinfo */
+static int dsi_calc_clock_rates(struct dsi_clock_info *cinfo)
+{
+ //printf("dsi_calc_clock_rates\n");
+
+ if (cinfo->regn == 0 || cinfo->regn > REGN_MAX)
+ return -EINVAL;
+
+ if (cinfo->regm == 0 || cinfo->regm > REGM_MAX)
+ return -EINVAL;
+
+ if (cinfo->regm3 > REGM3_MAX)
+ return -EINVAL;
+
+ if (cinfo->regm4 > REGM4_MAX)
+ return -EINVAL;
+
+ if (cinfo->use_dss2_fck) {
+ //cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2);
+ cinfo->clkin = DSI_DSS_CLK_FCK2;
+ /* XXX it is unclear if highfreq should be used
+ * with DSS2_FCK source also */
+ cinfo->highfreq = 0;
+ } else {
+ cinfo->clkin = dispc_pclk_rate();
+
+ if (cinfo->clkin < 32000000)
+ cinfo->highfreq = 0;
+ else
+ cinfo->highfreq = 1;
+ }
+
+ cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1));
+
+ if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN)
+ return -EINVAL;
+
+ cinfo->dsiphy = 2 * cinfo->regm * cinfo->fint;
+
+ if (cinfo->dsiphy > 1800 * 1000 * 1000)
+ return -EINVAL;
+
+ if (cinfo->regm3 > 0)
+ cinfo->dsi1_pll_fclk = cinfo->dsiphy / cinfo->regm3;
+ else
+ cinfo->dsi1_pll_fclk = 0;
+
+ if (cinfo->regm4 > 0)
+ cinfo->dsi2_pll_fclk = cinfo->dsiphy / cinfo->regm4;
+ else
+ cinfo->dsi2_pll_fclk = 0;
+
+ return 0;
+}
+#endif
+/* LGE_CHANGE_E [kyungtae.oh@lge.com] 2010-03-16, for dsi interface set */
+
+int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
+ struct dsi_clock_info *cinfo)
+{
+ struct dsi_clock_info cur, best;
+ int min_fck_per_pck;
+ int match = 0;
+ unsigned long dss_clk_fck2;
+ //printf("dsi_pll_calc_pck\n");
+
+ dss_clk_fck2 = DSI_DSS_CLK_FCK2;
+
+ if (req_pck == dsi.cache_req_pck &&
+ dsi.cache_cinfo.clkin == dss_clk_fck2) {
+ //DSSDBG("DSI clock info found from cache\n");
+ *cinfo = dsi.cache_cinfo;
+ return 0;
+ }
+
+ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
+
+ if (min_fck_per_pck &&
+ req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
+#if 0
+ DSSERR("Requested pixel clock not possible with the current "
+ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
+ "the constraint off.\n");
+#endif
+ min_fck_per_pck = 0;
+ }
+
+ //DSSDBG("dsi_pll_calc\n");
+
+retry:
+ memset(&best, 0, sizeof(best));
+
+ memset(&cur, 0, sizeof(cur));
+ cur.clkin = dss_clk_fck2;
+ cur.use_dss2_fck = 1;
+ cur.highfreq = 0;
+
+ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
+ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
+ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
+ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
+ if (cur.highfreq == 0)
+ cur.fint = cur.clkin / cur.regn;
+ else
+ cur.fint = cur.clkin / (2 * cur.regn);
+
+ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
+ continue;
+
+ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
+ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
+ unsigned long a, b;
+
+ a = 2 * cur.regm * (cur.clkin/1000);
+ b = cur.regn * (cur.highfreq + 1);
+ cur.dsiphy = a / b * 1000;
+
+ if (cur.dsiphy > 1800 * 1000 * 1000)
+ break;
+
+ /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */
+ for (cur.regm3 = 1; cur.regm3 < REGM3_MAX;
+ ++cur.regm3) {
+ cur.dsi1_pll_fclk = cur.dsiphy / cur.regm3;
+
+ /* this will narrow down the search a bit,
+ * but still give pixclocks below what was
+ * requested */
+ if (cur.dsi1_pll_fclk < req_pck)
+ break;
+
+ if (cur.dsi1_pll_fclk > DISPC_MAX_FCK)
+ continue;
+
+ if (min_fck_per_pck &&
+ cur.dsi1_pll_fclk <
+ req_pck * min_fck_per_pck)
+ continue;
+
+ match = 1;
+
+ find_lck_pck_divs(is_tft, req_pck,
+ cur.dsi1_pll_fclk,
+ &cur.lck_div,
+ &cur.pck_div);
+
+ cur.lck = cur.dsi1_pll_fclk / cur.lck_div;
+ cur.pck = cur.lck / cur.pck_div;
+
+ if (abs(cur.pck - req_pck) <
+ abs(best.pck - req_pck)) {
+ best = cur;
+
+ if (cur.pck == req_pck)
+ goto found;
+ }
+ }
+ }
+ }
+found:
+ if (!match) {
+ if (min_fck_per_pck) {
+ min_fck_per_pck = 0;
+ goto retry;
+ }
+
+ printf("Could not find suitable clock settings.\n");
+
+ return -EINVAL;
+ }
+
+ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
+ best.regm4 = best.dsiphy / 48000000;
+ if (best.regm4 > REGM4_MAX)
+ best.regm4 = REGM4_MAX;
+ else if (best.regm4 == 0)
+ best.regm4 = 1;
+ best.dsi2_pll_fclk = best.dsiphy / best.regm4;
+
+ if (cinfo)
+ *cinfo = best;
+
+ dsi.cache_req_pck = req_pck;
+ dsi.cache_clk_freq = 0;
+ dsi.cache_cinfo = best;
+
+ return 0;
+}
+
+static int dsi_pll_calc_ddrfreq(unsigned long clk_freq,
+ struct dsi_clock_info *cinfo)
+{
+ struct dsi_clock_info cur, best;
+ const bool use_dss2_fck = 1;
+ unsigned long datafreq;
+ unsigned long dss_clk_fck2;
+ //printf("dsi_pll_calc_ddr_freq\n");
+
+ dss_clk_fck2 = DSI_DSS_CLK_FCK2;
+
+ if (clk_freq == dsi.cache_clk_freq &&
+ dsi.cache_cinfo.clkin == dss_clk_fck2) {
+ printf("DSI clock info found from cache\n");
+ *cinfo = dsi.cache_cinfo;
+ return 0;
+ }
+
+ datafreq = clk_freq * 4;
+
+ memset(&best, 0, sizeof(best));
+
+ memset(&cur, 0, sizeof(cur));
+ cur.use_dss2_fck = use_dss2_fck;
+ if (use_dss2_fck) {
+ cur.clkin = dss_clk_fck2;
+ cur.highfreq = 0;
+ } else {
+ cur.clkin = dispc_pclk_rate();
+ if (cur.clkin < 32000000)
+ cur.highfreq = 0;
+ else
+ cur.highfreq = 1;
+ }
+
+ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
+ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
+ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
+ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) {
+ if (cur.highfreq == 0)
+ cur.fint = cur.clkin / cur.regn;
+ else
+ cur.fint = cur.clkin / (2 * cur.regn);
+
+ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN)
+ continue;
+
+ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
+ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) {
+ unsigned long a, b;
+
+ a = 2 * cur.regm * (cur.clkin/1000);
+ b = cur.regn * (cur.highfreq + 1);
+ cur.dsiphy = a / b * 1000;
+
+ if (cur.dsiphy > 1800 * 1000 * 1000)
+ break;
+
+ if (abs(cur.dsiphy - datafreq) <
+ abs(best.dsiphy - datafreq)) {
+ best = cur;
+ /* DSSDBG("best %ld\n", best.dsiphy); */
+ }
+
+ if (cur.dsiphy == datafreq)
+ goto found;
+ }
+ }
+found:
+ /* DSI1_PLL_FCLK (regm3) is not used. Set it to something sane. */
+ best.regm3 = best.dsiphy / 48000000;
+ if (best.regm3 > REGM3_MAX)
+ best.regm3 = REGM3_MAX;
+ else if (best.regm3 == 0)
+ best.regm3 = 1;
+ best.dsi1_pll_fclk = best.dsiphy / best.regm3;
+
+ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */
+ best.regm4 = best.dsiphy / 48000000;
+ if (best.regm4 > REGM4_MAX)
+ best.regm4 = REGM4_MAX;
+ else if (best.regm4 == 0)
+ best.regm4 = 1;
+ best.dsi2_pll_fclk = best.dsiphy / best.regm4;
+
+ if (cinfo)
+ *cinfo = best;
+
+ dsi.cache_clk_freq = clk_freq;
+ dsi.cache_req_pck = 0;
+ dsi.cache_cinfo = best;
+
+ return 0;
+}
+
+int dsi_pll_program(struct dsi_clock_info *cinfo)
+{
+ int r = 0;
+ u32 l;
+
+ //printf("dsi_pll_program\n");
+
+ dsi.dsiphy = cinfo->dsiphy;
+ dsi.ddr_clk = dsi.dsiphy / 4;
+ dsi.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
+ dsi.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
+
+ REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
+
+ l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
+ l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
+ l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */
+ l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */
+ l = FLD_MOD(l, cinfo->regm3 - 1, 22, 19); /* DSI_CLOCK_DIV */
+ l = FLD_MOD(l, cinfo->regm4 - 1, 26, 23); /* DSIPROTO_CLOCK_DIV */
+ dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
+
+ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
+ l = FLD_MOD(l, 7, 4, 1); /* DSI_PLL_FREQSEL */
+ /* DSI_PLL_CLKSEL */
+ l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, 11, 11);
+ l = FLD_MOD(l, cinfo->highfreq, 12, 12); /* DSI_PLL_HIGHFREQ */
+ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
+ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
+ l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
+ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
+
+ REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
+
+ if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) {
+ printf("dsi pll go bit not going down.\n");
+ r = -EIO;
+ goto err;
+ }
+
+ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) {
+ printf("cannot lock PLL\n");
+ r = -EIO;
+ goto err;
+ }
+
+ dsi.pll_locked = 1;
+
+ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
+ l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */
+ l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */
+ l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */
+ l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */
+ l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */
+ l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */
+ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
+ l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */
+ l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */
+ l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */
+ l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */
+ l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */
+ l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */
+ l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */
+ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
+
+ //printf("PLL config done\n");
+err:
+ return r;
+}
+
+#if defined(CONFIG_SNIPER)
+int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
+{
+ int r = 0;
+ u32 l;
+ int f;
+
+/*
+ dsi.current_cinfo.fint = cinfo->fint;
+ dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr;
+ dsi.current_cinfo.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
+ dsi.current_cinfo.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
+ dsi.current_cinfo.regn = cinfo->regn; dsi.current_cinfo.regm = cinfo->regm;
+ dsi.current_cinfo.regm3 = cinfo->regm3; dsi.current_cinfo.regm4 = cinfo->regm4;
+*/
+
+ dsi.cache_cinfo.fint = cinfo->fint;
+ dsi.cache_cinfo.dsiphy = cinfo->dsiphy;
+ dsi.cache_cinfo.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
+ dsi.cache_cinfo.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
+ dsi.cache_cinfo.regn = cinfo->regn;
+ dsi.cache_cinfo.regm = cinfo->regm;
+ dsi.cache_cinfo.regm3 = cinfo->regm3;
+ dsi.cache_cinfo.regm4 = cinfo->regm4;
+
+ dsi.dsiphy = cinfo->dsiphy;
+ dsi.ddr_clk = dsi.dsiphy / 4;
+ dsi.dsi1_pll_fclk = cinfo->dsi1_pll_fclk;
+ dsi.dsi2_pll_fclk = cinfo->dsi2_pll_fclk;
+#if 0
+ printf("DSI Fint %ld\n", cinfo->fint);
+
+ printf("clkin (%s) rate %ld, highfreq %d\n",
+ cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree",
+ cinfo->clkin,
+ cinfo->highfreq);
+
+ /* DSIPHY == CLKIN4DDR */
+ printf("CLKIN4DDR = 2 * %d / %d * %lu / %d = %lu\n",
+ cinfo->regm,
+ cinfo->regn,
+ cinfo->clkin,
+ cinfo->highfreq + 1,
+ cinfo->dsiphy);
+
+ printf("Data rate on 1 DSI lane %ld Mbps\n",
+ cinfo->dsiphy / 1000 / 1000 / 2);
+
+ printf("Clock lane freq %ld Hz\n", cinfo->dsiphy / 4);
+
+ printf("regm3 = %d, dsi1_pll_fclk = %lu\n",
+ cinfo->regm3, cinfo->dsi1_pll_fclk);
+ printf("regm4 = %d, dsi2_pll_fclk = %lu\n",
+ cinfo->regm4, cinfo->dsi2_pll_fclk);
+#endif
+ REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */
+
+ l = dsi_read_reg(DSI_PLL_CONFIGURATION1);
+ l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
+ l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */
+ l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */
+ l = FLD_MOD(l, cinfo->regm3 > 0 ? cinfo->regm3 - 1 : 0,
+ 22, 19); /* DSI_CLOCK_DIV */
+ l = FLD_MOD(l, cinfo->regm4 > 0 ? cinfo->regm4 - 1 : 0,
+ 26, 23); /* DSIPROTO_CLOCK_DIV */
+ dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
+
+ BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000);
+ if (cinfo->fint < 1000000)
+ f = 0x3;
+ else if (cinfo->fint < 1250000)
+ f = 0x4;
+ else if (cinfo->fint < 1500000)
+ f = 0x5;
+ else if (cinfo->fint < 1750000)
+ f = 0x6;
+ else
+ f = 0x7;
+
+ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
+ l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
+ l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1,
+ 11, 11); /* DSI_PLL_CLKSEL */
+ l = FLD_MOD(l, cinfo->highfreq,
+ 12, 12); /* DSI_PLL_HIGHFREQ */
+ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
+ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
+ l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
+ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
+
+ REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
+
+ if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) {
+ //printf("dsi pll go bit not going down.\n");
+ r = -EIO;
+ goto err;
+ }
+
+ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) {
+ //printf("cannot lock PLL\n");
+ r = -EIO;
+ goto err;
+ }
+
+ dsi.pll_locked = 1;
+
+ l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
+ l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */
+ l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */
+ l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */
+ l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */
+ l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */
+ l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */
+ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
+ l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */
+ l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */
+ l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */
+ l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */
+ l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */
+ l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */
+ l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */
+ dsi_write_reg(DSI_PLL_CONFIGURATION2, l);
+
+ //printf("PLL config done\n");
+err:
+ return r;
+}
+#endif
+/* LGE_CHANGE_E [kyungtae.oh@lge.com] 2010-03-16, for dsi interface set */
+
+// PAULK =1 =0
+int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv)
+{
+ int r = 0;
+ enum dsi_pll_power_state pwstate;
+ struct dispc_clock_info cinfo;
+
+ //printf("PLL init\n");
+
+ enable_clocks(1);
+ dsi_enable_pll_clock(1);
+
+ /* XXX this should be calculated depending on the screen size,
+ * required framerate and DSI speed.
+ * For now 48MHz is enough for 864x480@60 with 360Mbps/lane
+ * with two lanes */
+ r = dispc_calc_clock_div(1, 48 * 1000 * 1000, &cinfo);
+ if (r)
+ goto err0;
+
+ r = dispc_set_clock_div(&cinfo);
+ if (r) {
+ printf("Failed to set basic clocks\n");
+ goto err0;
+ }
+
+ //r = regulator_enable(dsi.vdds_dsi_reg);
+ //if (r)
+ // goto err0;
+
+ /* XXX PLL does not come out of reset without this... */
+ dispc_pck_free_enable(1);
+
+ if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
+ printf("PLL not coming out of reset.\n");
+ r = -ENODEV;
+ goto err1;
+ }
+
+ /* XXX ... but if left on, we get problems when planes do not
+ * fill the whole display. No idea about this */
+ dispc_pck_free_enable(0);
+
+ if (enable_hsclk && enable_hsdiv)
+ pwstate = DSI_PLL_POWER_ON_ALL;
+ else if (enable_hsclk)
+ pwstate = DSI_PLL_POWER_ON_HSCLK;
+ else if (enable_hsdiv)
+ pwstate = DSI_PLL_POWER_ON_DIV;
+ else
+ pwstate = DSI_PLL_POWER_OFF;
+
+ r = dsi_pll_power(pwstate);
+
+ if (r)
+ goto err1;
+
+ //printf("PLL init done\n");
+
+ return 0;
+err1:
+ //printf("pll_err1\n");
+err0:
+ //printf("pll_err0\n");
+ //enable_clocks(0);
+ //dsi_enable_pll_clock(0);
+ return r;
+}
+
+void dsi_pll_uninit(void)
+{
+ enable_clocks(0);
+ dsi_enable_pll_clock(0);
+ printf("dsi_pll_uninit\n");
+
+ dsi.pll_locked = 0;
+ dsi_pll_power(DSI_PLL_POWER_OFF);
+ //regulator_disable(dsi.vdds_dsi_reg);
+ //DSSDBG("PLL uninit done\n");
+}
+
+unsigned long dsi_get_dsi1_pll_rate(void)
+{
+ //printf("dsi_get_dsi1_pll_rate\n");
+
+ return dsi.dsi1_pll_fclk;
+}
+
+unsigned long dsi_get_dsi2_pll_rate(void)
+{
+ printf("dsi_get_dsi2_pll_rate\n");
+ return dsi.dsi2_pll_fclk;
+}
+
+enum dsi_complexio_power_state {
+ DSI_COMPLEXIO_POWER_OFF = 0x0,
+ DSI_COMPLEXIO_POWER_ON = 0x1,
+ DSI_COMPLEXIO_POWER_ULPS = 0x2,
+};
+
+static int dsi_complexio_power(enum dsi_complexio_power_state state)
+{
+ int t = 0;
+
+ /* PWR_CMD */
+ REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27);
+
+ /* PWR_STATUS */
+ while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) {
+ udelay(1);
+ if (t++ > 1000) {
+ printf("failed to set complexio power state to "
+ "%d\n", state);
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static void dsi_complexio_config(void)
+{
+ u32 r;
+
+ int clk_lane = DSI_CLOCK_LANE;
+ int data1_lane = DSI_DATA0_LANE;
+ int data2_lane = DSI_DATA1_LANE;
+ int clk_pol = DSI_CLOCK_POLARITY;
+ int data1_pol = DSI_DATA0_POLARITY;
+ int data2_pol = DSI_DATA1_POLARITY;
+ //printf("dsi_complexio_config\n");
+
+ r = dsi_read_reg(DSI_COMPLEXIO_CFG1);
+ r = FLD_MOD(r, clk_lane, 2, 0);
+ r = FLD_MOD(r, clk_pol, 3, 3);
+ r = FLD_MOD(r, data1_lane, 6, 4);
+ r = FLD_MOD(r, data1_pol, 7, 7);
+ r = FLD_MOD(r, data2_lane, 10, 8);
+ r = FLD_MOD(r, data2_pol, 11, 11);
+ dsi_write_reg(DSI_COMPLEXIO_CFG1, r);
+
+ /* The configuration of the DSI complex I/O (number of data lanes,
+ position, differential order) should not be changed while
+ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
+ the hardware to take into account a new configuration of the complex
+ I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
+ follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
+ then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
+ DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
+ DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
+ DSI complex I/O configuration is unknown. */
+
+ /*
+ REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
+ REG_FLD_MOD(DSI_CTRL, 0, 0, 0);
+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20);
+ REG_FLD_MOD(DSI_CTRL, 1, 0, 0);
+ */
+}
+
+static inline unsigned ns2ddr(unsigned ns)
+{
+ /* convert time in ns to ddr ticks, rounding up */
+ return (ns * (dsi.ddr_clk/1000/1000) + 999) / 1000;
+}
+
+static inline unsigned ddr2ns(unsigned ddr)
+{
+ return ddr * 1000 * 1000 / (dsi.ddr_clk / 1000);
+}
+
+static void dsi_complexio_timings(void)
+{
+ u32 r;
+ u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit;
+ u32 tlpx_half, tclk_trail, tclk_zero;
+ u32 tclk_prepare;
+ //printf("dsi_complexio_timings\n");
+
+ /* calculate timings */
+
+ /* 1 * DDR_CLK = 2 * UI */
+
+ /* min 40ns + 4*UI max 85ns + 6*UI */
+ ths_prepare = ns2ddr(70) + 2;
+
+ /* min 145ns + 10*UI */
+ ths_prepare_ths_zero = ns2ddr(175) + 2;
+
+ /* min max(8*UI, 60ns+4*UI) */
+ ths_trail = ns2ddr(60) + 5;
+
+ /* min 100ns */
+ ths_exit = ns2ddr(145);
+
+ /* tlpx min 50n */
+ tlpx_half = ns2ddr(25);
+
+ /* min 60ns */
+ tclk_trail = ns2ddr(60) + 2;
+
+ /* min 38ns, max 95ns */
+ tclk_prepare = ns2ddr(65);
+
+ /* min tclk-prepare + tclk-zero = 300ns */
+ tclk_zero = ns2ddr(260);
+
+ /* program timings */
+
+ r = dsi_read_reg(DSI_DSIPHY_CFG0);
+ r = FLD_MOD(r, ths_prepare, 31, 24);
+ r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16);
+ r = FLD_MOD(r, ths_trail, 15, 8);
+ r = FLD_MOD(r, ths_exit, 7, 0);
+ dsi_write_reg(DSI_DSIPHY_CFG0, r);
+
+ r = dsi_read_reg(DSI_DSIPHY_CFG1);
+ r = FLD_MOD(r, tlpx_half, 22, 16);
+ r = FLD_MOD(r, tclk_trail, 15, 8);
+ r = FLD_MOD(r, tclk_zero, 7, 0);
+ dsi_write_reg(DSI_DSIPHY_CFG1, r);
+
+ r = dsi_read_reg(DSI_DSIPHY_CFG2);
+ r = FLD_MOD(r, tclk_prepare, 7, 0);
+ dsi_write_reg(DSI_DSIPHY_CFG2, r);
+}
+
+
+static int dsi_complexio_init(void)
+{
+ int r = 0;
+
+ //DSSDBG("dsi_complexio_init\n");
+ //printf("dsi_complexio_init\n");
+
+ /* CIO_CLK_ICG, enable L3 clk to CIO */
+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
+
+ /* A dummy read using the SCP interface to any DSIPHY register is
+ * required after DSIPHY reset to complete the reset of the DSI complex
+ * I/O. */
+ dsi_read_reg(DSI_DSIPHY_CFG5);
+
+ if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) {
+ //printf("ComplexIO PHY not coming out of reset.\n");
+ r = -ENODEV;
+ goto err;
+ }
+
+ dsi_complexio_config();
+
+ r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON);
+
+ if (r)
+ goto err;
+
+ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) {
+ //printf("ComplexIO not coming out of reset.\n");
+ r = -ENODEV;
+ goto err;
+ }
+
+ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
+ //printf("ComplexIO LDO power down.\n");
+ r = -ENODEV;
+ goto err;
+ }
+
+ dsi_complexio_timings();
+
+ /*
+ The configuration of the DSI complex I/O (number of data lanes,
+ position, differential order) should not be changed while
+ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the
+ hardware to recognize a new configuration of the complex I/O (done
+ in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow
+ this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next
+ reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20]
+ LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN
+ bit to 1. If the sequence is not followed, the DSi complex I/O
+ configuration is undetermined.
+ */
+ dsi_if_enable(1);
+ dsi_if_enable(0);
+ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
+ dsi_if_enable(1);
+ dsi_if_enable(0);
+
+ //printf("CIO init done\n");
+err:
+ return r;
+}
+
+static void dsi_complexio_uninit(void)
+{
+ //printf("dsi_complexio_uninit\n");
+
+ dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF);
+}
+
+static int _dsi_wait_reset(void)
+{
+ int i = 0;
+ //printf("dsi_wait_reset\n");
+
+ while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) {
+ if (i++ > 5) {
+ printf("soft reset failed\n");
+ return -ENODEV;
+ }
+ udelay(1);
+ }
+
+ return 0;
+}
+
+static int _dsi_reset(void)
+{
+ //printf("dsi_reset\n");
+
+ /* Soft reset */
+ REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1);
+ return _dsi_wait_reset();
+}
+
+
+static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2,
+ enum fifo_size size3, enum fifo_size size4)
+{
+ u32 r = 0;
+ int add = 0;
+ int i;
+ //printf("dsi_config_tx_fifo\n");
+
+ dsi.vc[0].fifo_size = size1;
+ dsi.vc[1].fifo_size = size2;
+ dsi.vc[2].fifo_size = size3;
+ dsi.vc[3].fifo_size = size4;
+
+ for (i = 0; i < 4; i++) {
+ u8 v;
+ int size = dsi.vc[i].fifo_size;
+
+ if (add + size > 4) {
+ printf("Illegal FIFO configuration\n");
+ BUG();
+ }
+
+ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
+ r |= v << (8 * i);
+ //printf("TX FIFO vc %d: size %d, add %d\n", i, size, add);
+ add += size;
+ }
+
+ dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r);
+}
+
+static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2,
+ enum fifo_size size3, enum fifo_size size4)
+{
+ u32 r = 0;
+ int add = 0;
+ int i;
+
+ dsi.vc[0].fifo_size = size1;
+ dsi.vc[1].fifo_size = size2;
+ dsi.vc[2].fifo_size = size3;
+ dsi.vc[3].fifo_size = size4;
+
+ for (i = 0; i < 4; i++) {
+ u8 v;
+ int size = dsi.vc[i].fifo_size;
+
+ if (add + size > 4) {
+ //printf("Illegal FIFO configuration\n");
+ BUG();
+ }
+
+ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
+ r |= v << (8 * i);
+ //printf("RX FIFO vc %d: size %d, add %d\n", i, size, add);
+ add += size;
+ }
+
+ dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r);
+}
+
+static int dsi_force_tx_stop_mode_io(void)
+{
+ u32 r;
+ //printf("dsi_force_tx_stop_mode_io\n");
+
+ r = dsi_read_reg(DSI_TIMING1);
+ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
+ dsi_write_reg(DSI_TIMING1, r);
+
+ if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) {
+ printf("TX_STOP bit not going down\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void dsi_vc_print_status(int channel)
+{
+ u32 r;
+
+ r = dsi_read_reg(DSI_VC_CTRL(channel));
+#if 0
+ printf("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, "
+ "TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, ",
+ channel,
+ FLD_GET(r, 5, 5),
+ FLD_GET(r, 6, 6),
+ FLD_GET(r, 15, 15),
+ FLD_GET(r, 16, 16),
+ FLD_GET(r, 20, 20));
+#endif
+ r = dsi_read_reg(DSI_TX_FIFO_VC_EMPTINESS);
+ //printf("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff);
+}
+
+static void dsi_vc_config(int channel)
+{
+ u32 r;
+
+ //DSSDBG("dsi_vc_config %d\n", channel);
+ //printf("dsi_vc_config\n");
+
+ r = dsi_read_reg(DSI_VC_CTRL(channel));
+
+ r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */
+ r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
+ r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
+ r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
+ r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
+ r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
+ r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
+
+ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
+ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
+
+ dsi_write_reg(DSI_VC_CTRL(channel), r);
+}
+
+static void dsi_vc_config_vp(int channel)
+{
+ u32 r;
+
+ //DSSDBG("dsi_vc_config_vp\n");
+
+ r = dsi_read_reg(DSI_VC_CTRL(channel));
+
+ r = FLD_MOD(r, 1, 1, 1); /* SOURCE, 1 = video port */
+ r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */
+ r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */
+ r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */
+ r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
+ r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
+ r = FLD_MOD(r, 1, 9, 9); /* MODE_SPEED, high speed on/off */
+
+ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
+ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
+
+ dsi_write_reg(DSI_VC_CTRL(channel), r);
+}
+
+
+static int dsi_vc_enable(int channel, bool enable)
+{
+ //DSSDBG("dsi_vc_enable channel %d, enable %d\n", channel, enable);
+ //printf("dsi_vc_enable\n");
+
+ enable = enable ? 1 : 0;
+
+ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0);
+
+ if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) {
+ printf("Failed to set dsi_vc_enable to %d\n", enable);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+void dsi_vc_enable_hs(int channel, bool enable)
+{
+ //DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
+ //printf("dsi_vc_enable_hs\n");
+
+ dsi_vc_enable(channel, 0);
+ dsi_if_enable(0);
+
+ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9);
+
+ dsi_vc_enable(channel, 1);
+ dsi_if_enable(1);
+
+ dsi_force_tx_stop_mode_io();
+}
+
+void dsi_hs_enable(int value)
+{
+ if (value==0)
+ dsi_vc_enable_hs(0,0);
+ else
+ dsi_vc_enable_hs(0,1);
+}
+
+static void dsi_vc_flush_long_data(int channel)
+{
+ //printf("dsi_vc_flush_long_data\n");
+
+ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
+ u32 val;
+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
+#if 0
+ DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n",
+ (val >> 0) & 0xff,
+ (val >> 8) & 0xff,
+ (val >> 16) & 0xff,
+ (val >> 24) & 0xff);
+#endif
+ }
+}
+
+static u16 dsi_vc_flush_receive_data(int channel)
+{
+ printf("dsi_vc_flush_receive_data\n");
+
+ /* RX_FIFO_NOT_EMPTY */
+ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
+ u32 val;
+ u8 dt;
+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
+ //DSSDBG("\trawval %#08x\n", val);
+ dt = FLD_GET(val, 5, 0);
+ if (dt == DSI_DT_RX_ACK_WITH_ERR) {
+ //u16 err = FLD_GET(val, 23, 8);
+ //dsi_show_rx_ack_with_err(err);
+ } else if (dt == DSI_DT_RX_SHORT_READ_1) {
+ printf("\tDCS short response, 1 byte: %#x\n",
+ FLD_GET(val, 23, 8));
+ } else if (dt == DSI_DT_RX_SHORT_READ_2) {
+ printf("\tDCS short response, 2 byte: %#x\n",
+ FLD_GET(val, 23, 8));
+ } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
+ printf("\tDCS long response, len %d\n",
+ FLD_GET(val, 23, 8));
+ dsi_vc_flush_long_data(channel);
+ } else {
+ printf("\tunknown datatype 0x%02x\n", dt);
+ }
+ }
+ return 0;
+}
+
+static int dsi_vc_send_bta(int channel)
+{
+ unsigned long tmo = 0;
+ //printf("dsi_vc_send_bta\n");
+
+ /*DSSDBG("dsi_vc_send_bta_sync %d\n", channel); */
+
+ if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */
+ printf("rx fifo not empty when sending BTA, dumping data:\n");
+ dsi_vc_flush_receive_data(channel);
+ }
+
+ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
+
+ while (REG_GET(DSI_VC_CTRL(channel), 6, 6) == 1) {
+ if (tmo++>1000*100){
+ printf("kyungter vc_send_bta error\n");
+ return 0;//-EIO;
+ }
+ //udelay(10);
+ }
+ return 0;
+}
+
+/* LGE_CHANGE_S [kyungtae.oh@lge.com] 2010-03-16, for dsi interface set */
+#if defined (CONFIG_SNIPER)
+int dsi_vc_send_bta_sync(int channel)
+#else
+static int dsi_vc_send_bta_sync(int channel)
+#endif
+/* LGE_CHANGE_E [kyungtae.oh@lge.com] 2010-03-16, for dsi interface set */
+{
+ int r = 0;
+ u32 err;
+ //printf("dsi_vc_send_bta_sync\n");
+
+ //INIT_COMPLETION(dsi.bta_completion);
+
+ dsi_vc_enable_bta_irq(channel);
+
+ r = dsi_vc_send_bta(channel);
+ if (r)
+ goto err;
+
+err:
+ dsi_vc_disable_bta_irq(channel);
+
+ return r;
+}
+
+static inline void dsi_vc_write_long_header(int channel, u8 data_type,
+ u16 len, u8 ecc)
+{
+ u32 val;
+ u8 data_id;
+ //printf("dsi_vc_write_long_header\n");
+
+ //WARN_ON(!mutex_is_locked(&dsi.bus_lock));
+
+ /*data_id = data_type | channel << 6; */
+ data_id = data_type | dsi.vc[channel].dest_per << 6;
+
+ val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) |
+ FLD_VAL(ecc, 31, 24);
+
+ dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val);
+}
+
+static inline void dsi_vc_write_long_payload(int channel,
+ u8 b1, u8 b2, u8 b3, u8 b4)
+{
+ u32 val;
+ //printf("dsi_vc_write_long_payload\n");
+
+ val = b4 << 24 | b3 << 16 | b2 << 8 | b1 << 0;
+
+/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n",
+ b1, b2, b3, b4, val); */
+
+ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val);
+}
+
+static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len,
+ u8 ecc)
+{
+ /*u32 val; */
+ int i;
+ u8 *p;
+ int r = 0;
+ u8 b1, b2, b3, b4;
+ //printf("dsi_vc_send_long\n");
+#if 0
+ if (dsi.debug_write)
+ DSSDBG("dsi_vc_send_long, %d bytes\n", len);
+#endif
+ /* len + header */
+ if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) {
+ //printf("unable to send long packet: packet too long.\n");
+ return -EINVAL;
+ }
+
+ dsi_vc_write_long_header(channel, data_type, len, ecc);
+
+ /*dsi_vc_print_status(0); */
+
+ p = data;
+ for (i = 0; i < len >> 2; i++) {
+ //if (dsi.debug_write)
+ // DSSDBG("\tsending full packet %d\n", i);
+ /*dsi_vc_print_status(0); */
+
+ b1 = *p++;
+ b2 = *p++;
+ b3 = *p++;
+ b4 = *p++;
+
+ dsi_vc_write_long_payload(channel, b1, b2, b3, b4);
+ }
+
+ i = len % 4;
+ if (i) {
+ b1 = 0; b2 = 0; b3 = 0;
+
+ //if (dsi.debug_write)
+ // DSSDBG("\tsending remainder bytes %d\n", i);
+
+ switch (i) {
+ case 3:
+ b1 = *p++;
+ b2 = *p++;
+ b3 = *p++;
+ break;
+ case 2:
+ b1 = *p++;
+ b2 = *p++;
+ break;
+ case 1:
+ b1 = *p++;
+ break;
+ }
+
+ dsi_vc_write_long_payload(channel, b1, b2, b3, 0);
+ }
+
+ return r;
+}
+
+static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc)
+{
+ u32 r;
+ u8 data_id;
+ //printf("dsi_vc_send_short\n");
+
+ //WARN_ON(!mutex_is_locked(&dsi.bus_lock));
+#if 0
+ if (dsi.debug_write)
+ DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n",
+ channel,
+ data_type, data & 0xff, (data >> 8) & 0xff);
+#endif
+ if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) {
+ //printf("ERROR FIFO FULL, aborting transfer\n");
+ return -EINVAL;
+ }
+
+ data_id = data_type | dsi.vc[channel].dest_per << 6;
+
+ r = (data_id << 0) | (data << 8) | (ecc << 24);
+
+ dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r);
+
+ return 0;
+}
+
+int dsi_vc_send_null(int channel)
+{
+ u8 nullpkg[] = {0, 0, 0, 0};
+ //printf("dsi_vc_send_null\n");
+ return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0);
+}
+//EXPORT_SYMBOL(dsi_vc_send_null);
+
+int dsi_vc_write_nosync(int channel, u8 data_type, u8 *data, int len)
+{
+ int r;
+ BUG_ON(len == 0);
+ //printf("dsi_vc_write_nosync\n");
+
+ if (len == 1)
+ r = dsi_vc_send_short(channel, data_type, data[0], 0);
+ else if (len == 2)
+ r = dsi_vc_send_short(channel, data_type,
+ data[0] | (data[1] << 8), 0);
+ else
+ r = dsi_vc_send_long(channel, data_type, data, len, 0);
+
+ return r;
+}
+//EXPORT_SYMBOL(dsi_vc_write_nosync);
+#if 0
+int dsi_vc_write(int channel, u8 data_type, u8 *data, int len)
+{
+ int r = -1;
+ //printf("dsi_vc_write\n");
+ r = dsi_vc_write_nosync(channel, data_type, data, len);
+ if (r)
+ return r;
+ r = dsi_vc_send_bta_sync(channel);
+
+ return r;
+}
+#endif
+//EXPORT_SYMBOL(dsi_vc_write);
+
+int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len)
+{
+ u8 data_type;
+ //printf("dsi_vc_dcs_write_nosync\n");
+
+ BUG_ON(len == 0);
+
+ if (len == 1)
+ data_type = DSI_DT_DCS_SHORT_WRITE_0;
+ else if (len == 2)
+ data_type = DSI_DT_DCS_SHORT_WRITE_1;
+ else
+ data_type = DSI_DT_DCS_LONG_WRITE;
+
+ return dsi_vc_write_nosync(channel, data_type, data, len);
+}
+EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
+
+int dsi_vc_dcs_write(int channel, u8 *data, int len)
+{
+ int r;
+ //printf("dsi_vc_dcs_write\n");
+
+ r = dsi_vc_dcs_write_nosync(channel, data, len);
+ if (r)
+ return r;
+
+ /* Some devices need time to process the msg in low power mode.
+ This also makes the write synchronous, and checks that
+ the peripheral is still alive */
+ r = dsi_vc_send_bta_sync(channel);
+
+ return r;
+}
+EXPORT_SYMBOL(dsi_vc_dcs_write);
+
+int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen)
+{
+ u32 val;
+ u8 dt;
+ int r;
+ //printf("dsi_vc_dcs_read\n");
+#if 0
+ if (dsi.debug_read)
+ DSSDBG("dsi_vc_dcs_read\n");
+#endif
+ r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0);
+ if (r)
+ return r;
+
+ r = dsi_vc_send_bta_sync(channel);
+ if (r)
+ return r;
+
+ /* RX_FIFO_NOT_EMPTY */
+ if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) udelay(2000);
+ if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) {
+ //printf("RX fifo empty when trying to read.\n");
+ return -EIO;
+ }
+
+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
+#if 0
+ if (dsi.debug_read)
+ DSSDBG("\theader: %08x\n", val);
+#endif
+ dt = FLD_GET(val, 5, 0);
+ if (dt == DSI_DT_RX_ACK_WITH_ERR) {
+ //u16 err = FLD_GET(val, 23, 8);
+ //dsi_show_rx_ack_with_err(err);
+ return -1;
+
+ } else if (dt == DSI_DT_RX_SHORT_READ_1) {
+ u8 data = FLD_GET(val, 15, 8);
+#if 0
+ if (dsi.debug_read)
+ DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
+#endif
+ if (buflen < 1)
+ return -1;
+
+ buf[0] = data;
+
+ return 1;
+ } else if (dt == DSI_DT_RX_SHORT_READ_2) {
+ u16 data = FLD_GET(val, 23, 8);
+#if 0
+ if (dsi.debug_read)
+ DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
+#endif
+ if (buflen < 2)
+ return -1;
+
+ buf[0] = data & 0xff;
+ buf[1] = (data >> 8) & 0xff;
+
+ return 2;
+ } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
+ int w;
+ int len = FLD_GET(val, 23, 8);
+#if 0
+ if (dsi.debug_read)
+ DSSDBG("\tDCS long response, len %d\n", len);
+#endif
+ if (len > buflen)
+ return -1;
+
+ /* two byte checksum ends the packet, not included in len */
+ for (w = 0; w < len + 2;) {
+ int b;
+ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
+#if 0
+ if (dsi.debug_read)
+ DSSDBG("\t\t%02x %02x %02x %02x\n",
+ (val >> 0) & 0xff,
+ (val >> 8) & 0xff,
+ (val >> 16) & 0xff,
+ (val >> 24) & 0xff);
+#endif
+ for (b = 0; b < 4; ++b) {
+ if (w < len)
+ buf[w] = (val >> (b * 8)) & 0xff;
+ /* we discard the 2 byte checksum */
+ ++w;
+ }
+ }
+
+ return len;
+
+ } else {
+ //printf("\tunknown datatype 0x%02x\n", dt);
+ return -1;
+ }
+}
+EXPORT_SYMBOL(dsi_vc_dcs_read);
+
+
+int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
+{
+ //printf("dsi_vc_set_max_rx_packet_size\n");
+
+ return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
+ len, 0);
+}
+EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
+
+int dsi_vc_generic_write(int channel, u8 cmd, u8 *data, int len)
+{
+ int r;
+ //printf("dsi_vc_generic_write\n");
+
+ r = dsi_vc_send_long(channel, cmd, data, len, 0);
+ if (r)
+ return r;
+
+ r = dsi_vc_send_bta_sync(channel);
+ return r;
+}
+EXPORT_SYMBOL(dsi_vc_generic_write);
+
+int dsi_vc_generic_write_short(int channel, u8 cmd, u8 *data, int len)
+{
+ int r;
+ //printf("dsi_vc_generic_write_short\n");
+ if( len == 1) {
+ r = dsi_vc_send_short(channel, cmd, data[0], 0);
+ } else {
+ r = dsi_vc_send_short(channel, cmd, data[0] | (data[1] << 8), 0);
+ }
+ if (r)
+ return r;
+
+ r = dsi_vc_send_bta_sync(channel);
+ return r;
+}
+EXPORT_SYMBOL(dsi_vc_generic_write_short);
+
+int dsi_vc_write(int channel, u8 data_type, u8 *data, int len)
+{
+ int r = -1;
+
+ switch (data_type) {
+ case 0x03:
+ case 0x13:
+ case 0x23:
+ r = dsi_vc_generic_write_short(channel, data_type, data, len);
+ break;
+ case 0x29:
+ r = dsi_vc_generic_write(channel, data_type, data, len);
+ break;
+ case 0x05:
+ case 0x15:
+ case 0x39:
+ r = dsi_vc_dcs_write(channel, data, len);
+ break;
+ default:
+ printf("wrong cmd!");
+ }
+ return r;
+}
+
+static int dsi_set_lp_rx_timeout(int ns, int x4, int x16)
+{
+ u32 r;
+ unsigned long fck;
+ int ticks;
+ //printf("dsi_set_lp_rx_timeout\n");
+
+ /* ticks in DSI_FCK */
+
+ fck = dsi_fclk_rate();
+ ticks = (fck / 1000 / 1000) * ns / 1000;
+
+ if (ticks > 0x1fff) {
+ //printf("LP_TX_TO too high\n");
+ return -EINVAL;
+ }
+
+ r = dsi_read_reg(DSI_TIMING2);
+ r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */
+ r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */
+ r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */
+ r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */
+ dsi_write_reg(DSI_TIMING2, r);
+#if 0
+ printf("LP_RX_TO %ld ns (%#x ticks)\n",
+ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
+ (fck / 1000 / 1000),
+ ticks);
+#endif
+ return 0;
+}
+
+static int dsi_set_ta_timeout(int ns, int x8, int x16)
+{
+ u32 r;
+ unsigned long fck;
+ int ticks;
+ //printf("dsi_set_ta_timeout\n");
+
+ /* ticks in DSI_FCK */
+
+ fck = dsi_fclk_rate();
+ ticks = (fck / 1000 / 1000) * ns / 1000;
+
+ if (ticks > 0x1fff) {
+ //printf("TA_TO too high\n");
+ return -EINVAL;
+ }
+
+ r = dsi_read_reg(DSI_TIMING1);
+ r = FLD_MOD(r, 1, 31, 31); /* TA_TO */
+ r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */
+ r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */
+ r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */
+ dsi_write_reg(DSI_TIMING1, r);
+#if 0
+ printf("TA_TO %ld ns (%#x ticks)\n",
+ (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) /
+ (fck / 1000 / 1000),
+ ticks);
+#endif
+ return 0;
+}
+
+static int dsi_set_stop_state_counter(int ns, int x4, int x16)
+{
+ u32 r;
+ unsigned long fck;
+ int ticks;
+ //printf("dsi_set_stop_state_counter\n");
+
+ /* ticks in DSI_FCK */
+
+ fck = dsi_fclk_rate();
+ ticks = (fck / 1000 / 1000) * ns / 1000;
+
+ if (ticks > 0x1fff) {
+ //printf("STOP_STATE_COUNTER_IO too high\n");
+ return -EINVAL;
+ }
+
+ r = dsi_read_reg(DSI_TIMING1);
+ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
+ r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */
+ r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */
+ r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */
+ dsi_write_reg(DSI_TIMING1, r);
+#if 0
+ printf("STOP_STATE_COUNTER %ld ns (%#x ticks)\n",
+ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
+ (fck / 1000 / 1000),
+ ticks);
+#endif
+ return 0;
+}
+
+static int dsi_set_hs_tx_timeout(int ns, int x4, int x16)
+{
+ u32 r;
+ unsigned long fck;
+ int ticks;
+ //printf("dsi_set_hs_tx_timeout\n");
+
+ /* ticks in TxByteClkHS */
+
+ fck = dsi.ddr_clk / 4;
+ ticks = (fck / 1000 / 1000) * ns / 1000;
+
+ if (ticks > 0x1fff) {
+ //DSSERR("HS_TX_TO too high\n");
+ return -EINVAL;
+ }
+
+ r = dsi_read_reg(DSI_TIMING2);
+ r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */
+ r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */
+ r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */
+ r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */
+ dsi_write_reg(DSI_TIMING2, r);
+#if 0
+ printf("HS_TX_TO %ld ns (%#x ticks)\n",
+ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
+ (fck / 1000 / 1000),
+ ticks);
+#endif
+ return 0;
+}
+static int dsi_proto_config(void)
+{
+ u32 r;
+ int buswidth = 0;
+ int div;
+ //printf("dsi_proto_config\n");
+
+ dsi_config_tx_fifo(DSI_FIFO_SIZE_128,
+ DSI_FIFO_SIZE_0,
+ DSI_FIFO_SIZE_0,
+ DSI_FIFO_SIZE_0);
+
+ dsi_config_rx_fifo(DSI_FIFO_SIZE_128,
+ DSI_FIFO_SIZE_0,
+ DSI_FIFO_SIZE_0,
+ DSI_FIFO_SIZE_0);
+
+ /* XXX what values for the timeouts? */
+ dsi_set_stop_state_counter(1000, 0, 0);
+
+ dsi_set_ta_timeout(50000, 1, 1);
+
+ /* 3000ns * 16 */
+ dsi_set_lp_rx_timeout(3000, 0, 1);
+
+ /* 10000ns * 4 */
+ dsi_set_hs_tx_timeout(10000, 1, 0);
+
+ switch (DSI_CTRL_PIXEL_SIZE) {
+ case 16:
+ buswidth = 0;
+ break;
+ case 18:
+ buswidth = 1;
+ break;
+ case 24:
+ buswidth = 2;
+ break;
+ default:
+ BUG();
+ }
+
+ r = dsi_read_reg(DSI_CTRL);
+ r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */
+ r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */
+ r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */
+
+ div = dispc_lclk_rate() / dispc_pclk_rate();
+ r = FLD_MOD(r, div == 2 ? 0 : 1, 4, 4); /* VP_CLK_RATIO */
+ r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
+ r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
+ r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
+ r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
+ r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
+ r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */
+ r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */
+
+ dsi_write_reg(DSI_CTRL, r);
+
+ /* we configure vc0 for L4 communication, and
+ * vc1 for dispc */
+ dsi_vc_config(0);
+ dsi_vc_config_vp(1);
+
+ /* set all vc targets to peripheral 0 */
+ dsi.vc[0].dest_per = 0;
+ dsi.vc[1].dest_per = 0;
+ dsi.vc[2].dest_per = 0;
+ dsi.vc[3].dest_per = 0;
+
+ return 0;
+}
+
+static void dsi_proto_timings(void)
+{
+ unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
+ unsigned tclk_pre, tclk_post;
+ unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
+ unsigned ths_trail, ths_exit;
+ unsigned ddr_clk_pre, ddr_clk_post;
+ unsigned enter_hs_mode_lat, exit_hs_mode_lat;
+ unsigned ths_eot;
+ u32 r;
+ //printf("dsi_proto_timings\n");
+
+ r = dsi_read_reg(DSI_DSIPHY_CFG0);
+ ths_prepare = FLD_GET(r, 31, 24);
+ ths_prepare_ths_zero = FLD_GET(r, 23, 16);
+ ths_zero = ths_prepare_ths_zero - ths_prepare;
+ ths_trail = FLD_GET(r, 15, 8);
+ ths_exit = FLD_GET(r, 7, 0);
+
+ r = dsi_read_reg(DSI_DSIPHY_CFG1);
+ tlpx = FLD_GET(r, 22, 16) * 2;
+ tclk_trail = FLD_GET(r, 15, 8);
+ tclk_zero = FLD_GET(r, 7, 0);
+
+ r = dsi_read_reg(DSI_DSIPHY_CFG2);
+ tclk_prepare = FLD_GET(r, 7, 0);
+
+ /* min 8*UI */
+ tclk_pre = 20;
+ /* min 60ns + 52*UI */
+ tclk_post = ns2ddr(60) + 26;
+
+ /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */
+ if (DSI_DATA0_LANE != 0 && DSI_DATA1_LANE != 0)
+ ths_eot = 2;
+ else
+ ths_eot = 4;
+
+ ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
+ 4);
+ ddr_clk_post = DIV_ROUND_UP(tclk_post + tclk_trail, 4) + ths_eot;
+
+ BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255);
+ BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255);
+
+ r = dsi_read_reg(DSI_CLK_TIMING);
+ r = FLD_MOD(r, ddr_clk_pre, 15, 8);
+ r = FLD_MOD(r, ddr_clk_post, 7, 0);
+ dsi_write_reg(DSI_CLK_TIMING, r);
+#if 0
+ DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n",
+ ddr_clk_pre,
+ ddr_clk_post);
+#endif
+ enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) +
+ DIV_ROUND_UP(ths_prepare, 4) +
+ DIV_ROUND_UP(ths_zero + 3, 4);
+
+ exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot;
+
+ r = FLD_VAL(enter_hs_mode_lat, 31, 16) |
+ FLD_VAL(exit_hs_mode_lat, 15, 0);
+ dsi_write_reg(DSI_VM_TIMING7, r);
+#if 0
+ DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
+ enter_hs_mode_lat, exit_hs_mode_lat);
+#endif
+}
+
+
+#define DSI_DECL_VARS \
+ int __dsi_cb = 0; u32 __dsi_cv = 0;
+
+#define DSI_FLUSH(ch) \
+ if (__dsi_cb > 0) { \
+ /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
+ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
+ __dsi_cb = __dsi_cv = 0; \
+ }
+
+#define DSI_PUSH(ch, data) \
+ do { \
+ __dsi_cv |= (data) << (__dsi_cb * 8); \
+ /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
+ if (++__dsi_cb > 3) \
+ DSI_FLUSH(ch); \
+ } while (0)
+
+static int dsi_update_screen_l4(int x, int y, int w, int h)
+{
+ struct overlay_cache_data *c = &hub_overlay;
+
+ /* Note: supports only 24bit colors in 32bit container */
+ int first = 1;
+ int fifo_stalls = 0;
+ int max_dsi_packet_size;
+ int max_data_per_packet;
+ int max_pixels_per_packet;
+ int pixels_left;
+ int bytespp = DSI_CTRL_PIXEL_SIZE / 8;
+ int scr_width;
+ u32 __iomem *data;
+ int start_offset;
+ int horiz_inc;
+ int current_x;
+
+ debug_irq = 0;
+
+// DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
+// x, y, w, h);
+
+ //ovl = c;
+
+ if (c->color_mode != OMAP_DSS_COLOR_RGB24U)
+ return -EINVAL;
+
+ //if (c->pixel_size != 24)
+ // return -EINVAL;
+
+ scr_width = c->screen_width;
+
+ data = c->vaddr; //kyungtae check
+
+ start_offset = scr_width * y + x;
+ horiz_inc = scr_width - w;
+ current_x = x;
+
+ /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes
+ * in fifo */
+
+ /* When using CPU, max long packet size is TX buffer size */
+ max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4;
+
+ /* we seem to get better perf if we divide the tx fifo to half,
+ and while the other half is being sent, we fill the other half
+ max_dsi_packet_size /= 2; */
+
+ max_data_per_packet = max_dsi_packet_size - 4 - 1;
+
+ max_pixels_per_packet = max_data_per_packet / bytespp;
+
+ printf("max_pixels_per_packet %d\n", max_pixels_per_packet);
+
+ pixels_left = w * h;
+
+ printf("total pixels %d\n", pixels_left);
+
+ data += start_offset;
+
+ while (pixels_left > 0) {
+ /* 0x2c = write_memory_start */
+ /* 0x3c = write_memory_continue */
+ u8 dcs_cmd = first ? 0x2c : 0x3c;
+ int pixels;
+ DSI_DECL_VARS;
+ first = 0;
+
+#if 1
+ /* using fifo not empty */
+ /* TX_FIFO_NOT_EMPTY */
+ while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) {
+ udelay(1);
+ fifo_stalls++;
+ if (fifo_stalls > 0xfffff) {
+ printf("fifo stalls overflow, pixels left %d\n",
+ pixels_left);
+ dsi_if_enable(0);
+ return -EIO;
+ }
+ }
+#elif 1
+ /* using fifo emptiness */
+ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
+ max_dsi_packet_size) {
+ fifo_stalls++;
+ if (fifo_stalls > 0xfffff) {
+ DSSERR("fifo stalls overflow, pixels left %d\n",
+ pixels_left);
+ dsi_if_enable(0);
+ return -EIO;
+ }
+ }
+#else
+ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) {
+ fifo_stalls++;
+ if (fifo_stalls > 0xfffff) {
+ DSSERR("fifo stalls overflow, pixels left %d\n",
+ pixels_left);
+ dsi_if_enable(0);
+ return -EIO;
+ }
+ }
+#endif
+ pixels = min(max_pixels_per_packet, pixels_left);
+
+ pixels_left -= pixels;
+
+ dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE,
+ 1 + pixels * bytespp, 0);
+
+ DSI_PUSH(0, dcs_cmd);
+
+ while (pixels-- > 0) {
+ u32 pix = __raw_readl(data++);
+
+ DSI_PUSH(0, (pix >> 16) & 0xff);
+ DSI_PUSH(0, (pix >> 8) & 0xff);
+ DSI_PUSH(0, (pix >> 0) & 0xff);
+
+ current_x++;
+ if (current_x == x+w) {
+ current_x = x;
+ data += horiz_inc;
+ }
+ }
+
+ DSI_FLUSH(0);
+ }
+
+ return 0;
+}
+
+
+void dsi_update_screen_dispc(u16 x, u16 y, u16 w, u16 h)
+{
+ int bytespp = DSI_CTRL_PIXEL_SIZE/ 8;
+ int len;
+ int total_len;
+ int packet_payload;
+ int packet_len;
+ u32 l;
+ bool use_te_trigger;
+ //printf("dsi_update_screen_dispc\n");
+ dss_state = OMAP_DSS_DISPLAY_ACTIVE;
+
+
+#if !defined(CONFIG_SNIPER)
+ unsigned bytespl;
+ unsigned bytespf;
+ const unsigned line_buf_size = 1023 * 3;
+
+ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
+#if 0
+ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO)
+ DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
+ x, y, w, h);
+#endif
+ bytespp = DSI_CTRL_PIXEL_SIZE / 8;
+ bytespl = w * bytespp;
+ bytespf = bytespl * h;
+// 480x3x800
+
+// 6x480
+
+ /* NOTE: packet_payload has to be equal to N * bytespl, where N is
+ * number of lines in a packet. See errata about VP_CLK_RATIO */
+
+ if (bytespf < line_buf_size)
+ packet_payload = bytespf;
+ else
+ packet_payload = (line_buf_size) / bytespl * bytespl; // 480x6
+
+ packet_len = packet_payload + 1; /* 1 byte for DCS cmd */
+ total_len = (bytespf / packet_payload) * packet_len; // 400 x (6x480+1)
+
+ if (bytespf % packet_payload)
+ total_len += (bytespf % packet_payload) + 1;
+
+ if (0)
+ dsi_vc_print_status(1);
+#else
+ dispc_enable_lcd_out(1);
+
+ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te;
+ //use_te_trigger = 1;
+ dsi.update_mode = OMAP_DSS_UPDATE_MANUAL ;
+
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
+ printf("dsi_update_screen_dispc(%d,%d %dx%d)\n",
+ x, y, w, h);
+
+ len = w * h * bytespp;
+
+ /* XXX: one packet could be longer, I think? Line buffer is
+ * 1024 x 24bits, but we have to put DCS cmd there also.
+ * 1023 * 3 should work, but causes strange color effects. */
+ packet_payload = min(w, (u16)1020) * bytespp;
+
+ packet_len = packet_payload + 1; /* 1 byte for DCS cmd */
+ total_len = (len / packet_payload) * packet_len;
+
+ if (len % packet_payload)
+ total_len += (len % packet_payload) + 1;
+
+ if (0)
+ dsi_vc_print_status(1);
+#endif
+
+ l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
+ dsi_write_reg(DSI_VC_TE(1), l);
+
+ dsi_vc_write_long_header(1, DSI_DT_DCS_LONG_WRITE, packet_len, 0);
+
+ if (use_te_trigger)
+ l = FLD_MOD(l, 1, 30, 30); /* TE_EN */
+ else
+ l = FLD_MOD(l, 1, 31, 31); /* TE_START */
+ dsi_write_reg(DSI_VC_TE(1), l);
+
+ dispc_disable_sidle();
+
+ if (use_te_trigger)
+ dsi_vc_send_bta(1);
+ //dsi_handle_framedone();
+}
+
+static void dsi_framedone_irq_callback(void *data, u32 mask)
+{
+ dispc_enable_sidle();
+
+ dsi.framedone_received = 1;
+ //wake_up(&dsi.waitqueue);
+}
+
+
+static void dsi_set_update_region( u16 x, u16 y, u16 w, u16 h)
+{
+ //spin_lock(&dsi.update_lock);
+ if (dsi.update_region.dirty) {
+ dsi.update_region.x = min(x, dsi.update_region.x);
+ dsi.update_region.y = min(y, dsi.update_region.y);
+ dsi.update_region.w = max(w, dsi.update_region.w);
+ dsi.update_region.h = max(h, dsi.update_region.h);
+ } else {
+ dsi.update_region.x = x;
+ dsi.update_region.y = y;
+ dsi.update_region.w = w;
+ dsi.update_region.h = h;
+ }
+
+ //dsi.update_region.device = dssdev;
+ dsi.update_region.dirty = 1;
+
+ //spin_unlock(&dsi.update_lock);
+
+}
+
+
+static void dsi_start_auto_update(void)
+{
+ u16 w , h ;
+ //int i;
+
+ //DSSDBG("starting auto update\n");
+
+ /* In automatic mode the overlay settings are applied like on DPI/SDI.
+ * Mark the overlays dirty, so that we get the overlays configured, as
+ * manual mode has left them in bad shape after config partia planes */
+ //configure_dispc(); //kyungtae
+#if 0
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ struct omap_overlay *ovl;
+ ovl = omap_dss_get_overlay(i);
+ if (ovl->manager == dssdev->manager)
+ ovl->info_dirty = true;
+ }
+ dssdev->manager->apply(dssdev->manager);
+#endif
+
+
+ w = LCD_XRES;
+ h = LCD_YRES;
+ //dssdev->get_resolution(dssdev, &w, &h);
+
+ dsi_set_update_region(0, 0, w, h);
+
+ dsi_perf_mark_start_auto();
+
+ //wake_up(&dsi.waitqueue);
+}
+
+static int dsi_display_enable_te(bool enable)
+{
+
+ if (!dsi.te_enabled)
+ return -ENOENT;
+
+ //dsi_bus_lock();
+
+ dsi.te_enabled = enable;
+
+ if (dss_state != OMAP_DSS_DISPLAY_ACTIVE)
+ return 0;
+
+ //dsi_set_te(enable);
+// end:
+// dsi_bus_unlock();
+
+ return 0;
+
+}
+
+
+static int dsi_set_te(bool enable)
+{
+ //dssdev->driver->enable_te(dssdev, enable);
+ dsi_display_enable_te(enable);
+
+ if (!dsi.use_ext_te) {
+ if (enable) {
+ /* disable LP_RX_TO, so that we can receive TE. Time
+ * to wait for TE is longer than the timer allows */
+ REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */
+ } else {
+ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
+ }
+ }
+
+ return 0;
+}
+
+void dsi_handle_framedone(void)
+{
+ u32 l;
+ unsigned long tmo;
+ //int i = 0;
+ //printf("dsi_handle_framedone\n");
+
+ l = REG_GET(DSI_VC_TE(1), 23, 0); /* TE_SIZE */
+
+ /* We get FRAMEDONE when DISPC has finished sending pixels and turns
+ * itself off. However, DSI still has the pixels in its buffers, and is
+ * sending the data. Thus we have to wait until we can do a new
+ * transfer or turn the clocks off. There shouldn't be much stuff in
+ * DSI buffers, if any, so we'll just busyloop */
+
+ if (REG_GET(DSI_VC_TE(1), 30, 30))
+ printf("TE_EN not zero\n");
+
+ if (REG_GET(DSI_VC_TE(1), 31, 31))
+ printf("TE_START not zero\n");
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
+ printf("FRAMEDONE\n");
+
+ if (l > 0) {
+ tmo = 0;
+ while (REG_GET(DSI_VC_TE(1), 23, 0) > 0) {
+ if (tmo++>1000*100){
+ printf("kyungter frame_done error\n");
+ return -EIO;
+ udelay(10);
+ }
+ }
+ }
+
+ if (REG_GET(DSI_VC_TE(1), 30, 30))
+ printf("TE_EN not zero\n");
+
+ if (REG_GET(DSI_VC_TE(1), 31, 31))
+ printf("TE_START not zero\n");
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL)
+ printf("FRAMEDONE\n");
+
+#if 0
+ if (l)
+ DSSWARN("FRAMEDONE irq too early, %d bytes, %d loops\n", l, i);
+#else
+ //if (l > 1024*3)
+ // DSSWARN("FRAMEDONE irq too early, %d bytes, %d loops\n", l, i);
+#endif
+
+//#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
+// dispc_fake_vsync_irq();
+//#endif
+}
+
+static int dsi_display_init_dispc(void)
+{
+ //int r;
+ //printf("dsi_display_init_dispc\n");
+
+ //r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL, //check
+ // DISPC_IRQ_FRAMEDONE);
+ //if (r) {
+ //DSSERR("can't get FRAMEDONE irq\n");
+ // return r;
+ //}
+
+ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
+
+ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI);
+ dispc_enable_fifohandcheck(1);
+
+ dispc_set_tft_data_lines(DSI_CTRL_PIXEL_SIZE);
+
+ {
+ struct omap_video_timings timings = {
+ .x_res = LCD_XRES,
+ .y_res = LCD_YRES,
+ .pixel_clock = 26583,
+ .hsw = 1,
+ .hfp = 1,
+ .hbp = 1,
+ .vsw = 1,
+ .vfp = 0,
+ .vbp = 0,
+ };
+
+ dispc_set_lcd_timings(&timings);
+ }
+
+ return 0;
+}
+#if 0
+static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
+{
+ omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL,
+ DISPC_IRQ_FRAMEDONE);
+}
+#endif
+/* LGE_CHANGE_S [kyungtae.oh@lge.com] 2010-03-16, for dsi interface set */
+#if defined(CONFIG_SNIPER)
+static int dsi_configure_dsi_clocks(void)
+{
+ struct dsi_clock_info cinfo;
+ int r;
+ //printf("dsi_configure_dsi_clocks\n");
+
+ /* we always use DSS2_FCK as input clock */
+ cinfo.use_dss2_fck = 1;
+ cinfo.regn = DSI_DIV_REGN;
+ cinfo.regm = DSI_DIV_REGM;
+ cinfo.regm3 = DSI_DIV_REGM3;
+ cinfo.regm4 = DSI_DIV_REGM4;
+ r = dsi_calc_clock_rates(&cinfo);
+ if (r)
+ return r;
+
+ r = dsi_pll_set_clock_div(&cinfo);
+ if (r) {
+ //printf("Failed to set dsi clocks\n");
+ return r;
+ }
+
+ return 0;
+}
+#endif
+/* LGE_CHANGE_E [kyungtae.oh@lge.com] 2010-03-16, for dsi interface set */
+
+static int dsi_display_init_dsi(void)
+{
+ struct dsi_clock_info cinfo;
+ int r;
+ //printf("dsi_display_init_dsi\n");
+
+ _dsi_print_reset_status();
+
+ r = dsi_pll_init(1, 0);
+ if (r)
+ goto err0;
+
+/* LGE_CHANGE_S [kyungtae.oh@lge.com] 2010-03-16, for dsi interface set */
+#if defined(CONFIG_SNIPER)
+ r = dsi_configure_dsi_clocks();
+ if (r)
+ goto err1;
+
+ dss_select_clk_source(1, 1);
+#else
+ r = dsi_pll_calc_ddrfreq(DSI_DDR_CLK_HZ, &cinfo);
+ if (r)
+ goto err1;
+
+ r = dsi_pll_program(&cinfo);
+ if (r)
+ goto err1;
+#endif
+/* LGE_CHANGE_E [kyungtae.oh@lge.com] 2010-03-16, for dsi interface set */
+
+
+ //DSSDBG("PLL OK\n");
+
+ r = dsi_complexio_init();
+ if (r)
+ goto err1;
+
+ _dsi_print_reset_status();
+
+ dsi_proto_timings();
+ dsi_set_lp_clk_divisor();
+
+ if (1)
+ _dsi_print_reset_status();
+
+ r = dsi_proto_config();
+ if (r)
+ goto err2;
+
+ /* enable interface */
+ dsi_vc_enable(0, 1);
+ dsi_vc_enable(1, 1);
+ dsi_if_enable(1);
+ dsi_force_tx_stop_mode_io();
+#if 0 //kyungtaeoh
+ if (dssdev->driver->enable) {
+ r = dssdev->driver->enable(dssdev);
+ if (r)
+ goto err3;
+ }
+#endif
+ /* enable high-speed after initial config */
+ dsi_vc_enable_hs(0, 1);
+
+ return 0;
+err3:
+ //dsi_if_enable(0);
+ printf("init_err3\n");
+err2:
+ //dsi_complexio_uninit();
+ printf("init_err2\n");
+err1:
+ //dsi_pll_uninit();
+ printf("init_err1\n");
+err0:
+ return r;
+}
+
+static void dsi_display_uninit_dsi(void)
+{
+ //printf("dsi_display_uninit_dsi\n");
+
+ dsi_complexio_uninit();
+ dsi_pll_uninit();
+}
+
+static int dsi_core_init(void)
+{
+ //printf("dsi_core_init\n");
+
+ /* Autoidle */
+ REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0);
+
+ /* ENWAKEUP */
+ REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2);
+
+ /* SIDLEMODE smart-idle */
+ REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3); //kyungtae
+ //REG_FLD_MOD(DSI_SYSCONFIG, 1, 4, 3);
+
+ _dsi_initialize_irq();
+
+ return 0;
+}
+
+static int dsi_display_enable(void)
+{
+
+ int r = 0;
+ //printf("dsi_display_enabled\n");
+
+ enable_clocks(1);
+ dsi_enable_pll_clock(1);
+
+ r = _dsi_reset();
+ if (r)
+ goto err2;
+
+ dsi_core_init();
+
+ r = dsi_display_init_dispc();
+ if (r)
+ goto err2;
+
+ r = dsi_display_init_dsi();
+ if (r)
+ goto err3;
+
+ dsi.user_update_mode = OMAP_DSS_UPDATE_MANUAL;
+ dsi.te_enabled = 0;
+
+ dsi_set_te(dsi.te_enabled);
+ dsi.use_ext_te = dsi_ext_te;
+
+/* PAULK: not executed */
+ dsi.update_mode = dsi.user_update_mode;
+ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO)
+ dsi_start_auto_update();
+
+ //dsi_bus_unlock();
+ //mutex_unlock(&dsi.lock);
+ dss_state = OMAP_DSS_DISPLAY_ACTIVE;
+ mdelay(2);
+ //printf("kyungtae dpi_display_enable mdelay\n");
+ //dispc_enable_lcd_out(1);
+
+ return 0;
+
+err3:
+ //dsi_display_uninit_dispc();
+ //printk("test_err3");
+err2:
+ //enable_clocks(0);
+ //dsi_enable_pll_clock(0);
+//err1:
+// omap_dss_stop_device(dssdev);
+//err0:
+ //printk("test_err0");
+ //dsi_bus_unlock();
+ //mutex_unlock(&dsi.lock);
+ //DSSDBG("dsi_display_enable FAILED\n");
+ return r;
+}
+
+int dsi_display_update(u16 x, u16 y, u16 w, u16 h)
+{
+ int r = 0;
+ u16 dw, dh;
+
+ //DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h);
+
+ //mutex_lock(&dsi.lock);
+ //printf("dsi_display_update\n");
+
+ if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL)
+ goto end;
+
+ if (dss_state != OMAP_DSS_DISPLAY_ACTIVE)
+ goto end;
+
+ //dssdev->get_resolution(dssdev, &dw, &dh);
+ dw = LCD_XRES;
+ dh = LCD_YRES;
+ if (x > dw || y > dh)
+ goto end;
+
+ if (x + w > dw)
+ w = dw - x;
+
+ if (y + h > dh)
+ h = dh - y;
+
+ if (w == 0 || h == 0)
+ goto end;
+
+ dsi_set_update_region(x, y, w, h);
+
+ //wake_up(&dsi.waitqueue);
+
+end:
+ //mutex_unlock(&dsi.lock);
+
+ return r;
+}
+
+static int dsi_display_sync(void)
+{
+ bool wait;
+
+// DSSDBG("dsi_display_sync()\n");
+
+ //mutex_lock(&dsi.lock);
+ //dsi_bus_lock();
+ //printf("dsi_display_sync\n");
+
+ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL &&
+ dsi.update_region.dirty) {
+ //INIT_COMPLETION(dsi.update_completion);
+ wait = 1;
+ } else {
+ wait = 0;
+ }
+
+ //dsi_bus_unlock();
+ //mutex_unlock(&dsi.lock);
+
+ if (wait)
+// wait_for_completion_interruptible(&dsi.update_completion);
+ mdelay(100);
+
+// DSSDBG("dsi_display_sync() done\n");
+ return 0;
+}
+
+static int dsi_display_set_update_mode(enum omap_dss_update_mode mode)
+{
+ //DSSDBGF("%d", mode);
+ //printf("dsi_display_set_update_mode\n");
+
+ //mutex_lock(&dsi.lock);
+ //dsi_bus_lock();
+
+ if (dsi.update_mode != mode) {
+ dsi.user_update_mode = mode;
+ dsi.update_mode = mode;
+
+ if (dss_state == OMAP_DSS_DISPLAY_ACTIVE &&
+ mode == OMAP_DSS_UPDATE_AUTO)
+ dsi_start_auto_update();
+
+ //dsi_start_auto_update(); //kyungtae
+
+ }
+
+ //dsi_bus_unlock();
+ //mutex_unlock(&dsi.lock);
+
+ return 0;
+}
+
+static enum omap_dss_update_mode dsi_display_get_update_mode(void)
+{
+ //printf("dsi_display_get_update_mode\n");
+
+ return dsi.update_mode;
+}
+
+static int dsi_display_get_te(void)
+{
+ return dsi.te_enabled;
+}
+
+void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
+ u32 fifo_size, enum omap_burst_size burst_size,
+ u32 fifo_low, u32 fifo_high)
+{
+ unsigned burst_size_bytes;
+
+ burst_size = OMAP_DSS_BURST_16x32;
+ burst_size_bytes = 16 * 32 / 8;
+
+ fifo_high = fifo_size - burst_size_bytes;
+ fifo_low = 0;
+}
+
+int dsi_init(void)
+{
+ //u32 rev;
+
+ //spin_lock_init(&dsi.errors_lock);
+ dsi.errors = 0;
+ //printf("dsi_init\n");
+
+ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED;
+ dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED;
+
+ //dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS);
+ //if (!dsi.base) {
+ //DSSERR("can't ioremap DSI\n");
+ // return -ENOMEM;
+ //}
+ dsi_display_enable();
+ dss_state == OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
+}
diff --git a/board/lge/sniper/hub_dss.h b/board/lge/sniper/hub_dss.h
new file mode 100755
index 00000000000..fe36dc5a940
--- /dev/null
+++ b/board/lge/sniper/hub_dss.h
@@ -0,0 +1,479 @@
+/* u-boot/board/hub/hub_dss.h
+ *
+ * Author: Kyungtae Oh <kyungtae.oh@lge.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __OMAP2_DSS_H
+#define __OMAP2_DSS_H
+
+typedef _Bool bool;
+extern void sr32(u32 addr, u32 start_bit, u32 num_bits, u32 value);
+
+//display.h
+#define DISPC_IRQ_FRAMEDONE (1 << 0)
+#define DISPC_IRQ_VSYNC (1 << 1)
+#define DISPC_IRQ_EVSYNC_EVEN (1 << 2)
+#define DISPC_IRQ_EVSYNC_ODD (1 << 3)
+#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4)
+#define DISPC_IRQ_PROG_LINE_NUM (1 << 5)
+#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6)
+#define DISPC_IRQ_GFX_END_WIN (1 << 7)
+#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8)
+#define DISPC_IRQ_OCP_ERR (1 << 9)
+#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10)
+#define DISPC_IRQ_VID1_END_WIN (1 << 11)
+#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12)
+#define DISPC_IRQ_VID2_END_WIN (1 << 13)
+#define DISPC_IRQ_SYNC_LOST (1 << 14)
+#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15)
+#define DISPC_IRQ_WAKEUP (1 << 16)
+
+struct omap_dss_device;
+struct omap_overlay_manager;
+
+enum omap_display_type {
+ OMAP_DISPLAY_TYPE_NONE = 0,
+ OMAP_DISPLAY_TYPE_DPI = 1 << 0,
+ OMAP_DISPLAY_TYPE_DBI = 1 << 1,
+ OMAP_DISPLAY_TYPE_SDI = 1 << 2,
+ OMAP_DISPLAY_TYPE_DSI = 1 << 3,
+ OMAP_DISPLAY_TYPE_VENC = 1 << 4,
+ OMAP_DISPLAY_TYPE_HDMI = 1 << 5,
+};
+
+enum omap_plane {
+ OMAP_DSS_GFX = 0,
+ OMAP_DSS_VIDEO1 = 1,
+ OMAP_DSS_VIDEO2 = 2
+};
+
+enum omap_channel {
+ OMAP_DSS_CHANNEL_LCD = 0,
+ OMAP_DSS_CHANNEL_DIGIT = 1,
+};
+
+enum omap_color_mode {
+ OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */
+ OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */
+ OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */
+ OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */
+ OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12, 16-bit container */
+ OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */
+ OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */
+ OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */
+ OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */
+ OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */
+ OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */
+ OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */
+ OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */
+ OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */
+
+ OMAP_DSS_COLOR_GFX_OMAP3 =
+ OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
+ OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
+ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
+ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
+ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
+
+ OMAP_DSS_COLOR_VID_OMAP3 =
+ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
+ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
+ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
+ OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
+};
+
+enum omap_lcd_display_type {
+ OMAP_DSS_LCD_DISPLAY_STN,
+ OMAP_DSS_LCD_DISPLAY_TFT,
+};
+
+enum omap_dss_load_mode {
+ OMAP_DSS_LOAD_CLUT_AND_FRAME = 0,
+ OMAP_DSS_LOAD_CLUT_ONLY = 1,
+ OMAP_DSS_LOAD_FRAME_ONLY = 2,
+ OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3,
+};
+
+enum omap_dss_trans_key_type {
+ OMAP_DSS_COLOR_KEY_GFX_DST = 0,
+ OMAP_DSS_COLOR_KEY_VID_SRC = 1,
+};
+
+enum omap_rfbi_te_mode {
+ OMAP_DSS_RFBI_TE_MODE_1 = 1,
+ OMAP_DSS_RFBI_TE_MODE_2 = 2,
+};
+
+enum omap_panel_config {
+ OMAP_DSS_LCD_IVS = 1<<0,
+ OMAP_DSS_LCD_IHS = 1<<1,
+ OMAP_DSS_LCD_IPC = 1<<2,
+ OMAP_DSS_LCD_IEO = 1<<3,
+ OMAP_DSS_LCD_RF = 1<<4,
+ OMAP_DSS_LCD_ONOFF = 1<<5,
+
+ OMAP_DSS_LCD_TFT = 1<<20,
+};
+
+enum omap_dss_venc_type {
+ OMAP_DSS_VENC_TYPE_COMPOSITE,
+ OMAP_DSS_VENC_TYPE_SVIDEO,
+};
+
+enum omap_display_caps {
+ OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
+};
+
+enum omap_dss_update_mode {
+ OMAP_DSS_UPDATE_DISABLED = 0,
+ OMAP_DSS_UPDATE_AUTO,
+ OMAP_DSS_UPDATE_MANUAL,
+};
+
+enum omap_dss_display_state {
+ OMAP_DSS_DISPLAY_DISABLED = 0,
+ OMAP_DSS_DISPLAY_ACTIVE,
+ OMAP_DSS_DISPLAY_SUSPENDED,
+};
+
+/* XXX perhaps this should be removed */
+enum omap_dss_overlay_managers {
+ OMAP_DSS_OVL_MGR_LCD,
+ OMAP_DSS_OVL_MGR_TV,
+};
+
+enum omap_dss_rotation_type {
+ OMAP_DSS_ROT_DMA = 0,
+ OMAP_DSS_ROT_VRFB = 1,
+};
+
+enum omap_overlay_caps {
+ OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
+ OMAP_DSS_OVL_CAP_DISPC = 1 << 1,
+};
+
+enum omap_overlay_manager_caps {
+ OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
+};
+
+/* RFBI */
+
+struct rfbi_timings {
+ int cs_on_time;
+ int cs_off_time;
+ int we_on_time;
+ int we_off_time;
+ int re_on_time;
+ int re_off_time;
+ int we_cycle_time;
+ int re_cycle_time;
+ int cs_pulse_width;
+ int access_time;
+
+ int clk_div;
+
+ u32 tim[5]; /* set by rfbi_convert_timings() */
+
+ int converted;
+};
+
+
+
+//dss.h
+/* OMAP TRM gives bitfields as start:end, where start is the higher bit
+ number. For example 7:0 */
+#define FLD_MASK(start, end) (((1 << (start - end + 1)) - 1) << (end))
+#define FLD_VAL(val, start, end) (((val) << end) & FLD_MASK(start, end))
+#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
+#define FLD_MOD(orig, val, start, end) \
+ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
+
+#define MOD_REG_FLD(reg, mask, val) \
+ dispc_write_reg((reg), (dispc_read_reg(reg) & ~(mask)) | (val));
+
+#define DISPC_MAX_FCK 173000000
+
+enum omap_burst_size {
+ OMAP_DSS_BURST_4x32 = 0,
+ OMAP_DSS_BURST_8x32 = 1,
+ OMAP_DSS_BURST_16x32 = 2,
+};
+
+enum omap_parallel_interface_mode {
+ OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
+ OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
+ OMAP_DSS_PARALLELMODE_DSI,
+};
+
+enum dss_clock {
+ DSS_CLK_ICK = 1 << 0,
+ DSS_CLK_FCK1 = 1 << 1,
+ DSS_CLK_FCK2 = 1 << 2,
+ DSS_CLK_54M = 1 << 3,
+ DSS_CLK_96M = 1 << 4,
+};
+
+struct dispc_clock_info {
+ /* rates that we get with dividers below */
+ unsigned long fck;
+ unsigned long lck;
+ unsigned long pck;
+
+ /* dividers */
+ u16 fck_div;
+ u16 lck_div;
+ u16 pck_div;
+};
+
+struct dsi_clock_info {
+ /* rates that we get with dividers below */
+ unsigned long fint;
+ unsigned long dsiphy;
+ unsigned long clkin;
+ unsigned long dsi1_pll_fclk;
+ unsigned long dsi2_pll_fclk;
+ unsigned long lck;
+ unsigned long pck;
+
+ /* dividers */
+ u16 regn;
+ u16 regm;
+ u16 regm3;
+ u16 regm4;
+
+ u16 lck_div;
+ u16 pck_div;
+
+ u8 highfreq;
+ bool use_dss2_fck;
+};
+
+struct omap_video_timings {
+ /* Unit: pixels */
+ u16 x_res;
+ /* Unit: pixels */
+ u16 y_res;
+ /* Unit: KHz */
+ u32 pixel_clock;
+ /* Unit: pixel clocks */
+ u16 hsw; /* Horizontal synchronization pulse width */
+ /* Unit: pixel clocks */
+ u16 hfp; /* Horizontal front porch */
+ /* Unit: pixel clocks */
+ u16 hbp; /* Horizontal back porch */
+ /* Unit: line clocks */
+ u16 vsw; /* Vertical synchronization pulse width */
+ /* Unit: line clocks */
+ u16 vfp; /* Vertical front porch */
+ /* Unit: line clocks */
+ u16 vbp; /* Vertical back porch */
+};
+
+struct overlay_cache_data {
+ /* If TRUE, cache changed, but not written to shadow registers. Set
+ * in apply(), cleared when registers written. */
+ bool dirty;
+ /* If TRUE, shadow registers contain changed values not yet in real
+ * registers. Set when writing to shadow registers, cleared at
+ * VSYNC/EVSYNC */
+ bool shadow_dirty;
+
+ bool enabled;
+
+ u32 paddr;
+ void volatile *vaddr;
+ u16 screen_width;
+ u16 width;
+ u16 height;
+ enum omap_color_mode color_mode;
+ u8 rotation;
+ enum omap_dss_rotation_type rotation_type;
+ bool mirror;
+
+ u16 pos_x;
+ u16 pos_y;
+ u16 out_width; /* if 0, out_width == width */
+ u16 out_height; /* if 0, out_height == height */
+ u8 global_alpha;
+
+ enum omap_channel channel;
+ bool replication;
+ bool ilace;
+
+ enum omap_burst_size burst_size;
+ u32 fifo_low;
+ u32 fifo_high;
+
+ bool manual_update;
+};
+
+extern unsigned int lg_boot_logo[];
+static struct overlay_cache_data hub_overlay = {
+ .paddr = lg_boot_logo,
+ .screen_width = 480,
+ .width = 480,
+ .height = 800,
+ .color_mode = OMAP_DSS_COLOR_ARGB32,
+ .ilace = 0,
+ .rotation = 0,
+ .rotation_type = OMAP_DSS_ROT_DMA,
+ .mirror = 0,
+ .pos_x = 0,
+ .pos_y = 0,
+ .out_width = 480,
+ .out_height = 800,
+ .global_alpha = 255,
+ .channel = OMAP_DSS_GFX,
+ .replication = 0,
+ .burst_size = OMAP_DSS_BURST_16x32,
+ .fifo_low = 0,
+ .fifo_high = 960,
+ .manual_update = 0,
+};
+
+/* DISPC */
+int dispc_init(void);
+void dispc_exit(void);
+//void dispc_dump_clocks(struct seq_file *s);
+//void dispc_dump_regs(struct seq_file *s);
+void dispc_irq_handler(void);
+void dispc_fake_vsync_irq(void);
+
+void dispc_save_context(void);
+void dispc_restore_context(void);
+
+void dispc_enable_sidle(void);
+void dispc_disable_sidle(void);
+
+void dispc_lcd_enable_signal_polarity(bool act_high);
+void dispc_lcd_enable_signal(bool enable);
+void dispc_pck_free_enable(bool enable);
+void dispc_enable_fifohandcheck(bool enable);
+
+void dispc_set_lcd_size(u16 width, u16 height);
+void dispc_set_digit_size(u16 width, u16 height);
+u32 dispc_get_plane_fifo_size(enum omap_plane plane);
+void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
+void dispc_enable_fifomerge(bool enable);
+void dispc_set_burst_size(enum omap_plane plane,
+ enum omap_burst_size burst_size);
+
+void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
+void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
+void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
+void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
+void dispc_set_channel_out(enum omap_plane plane,
+ enum omap_channel channel_out);
+
+int dispc_setup_plane(enum omap_plane plane,
+ u32 paddr, u16 screen_width,
+ u16 pos_x, u16 pos_y,
+ u16 width, u16 height,
+ u16 out_width, u16 out_height,
+ enum omap_color_mode color_mode,
+ bool ilace,
+ enum omap_dss_rotation_type rotation_type,
+ u8 rotation, bool mirror,
+ u8 global_alpha);
+
+bool dispc_go_busy(enum omap_channel channel);
+void dispc_go(enum omap_channel channel);
+void dispc_enable_lcd_out(bool enable);
+void dispc_enable_digit_out(bool enable);
+int dispc_enable_plane(enum omap_plane plane, bool enable);
+void dispc_enable_replication(enum omap_plane plane, bool enable);
+
+void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode);
+void dispc_set_tft_data_lines(u8 data_lines);
+void dispc_set_lcd_display_type(enum omap_lcd_display_type type);
+void dispc_set_loadmode(enum omap_dss_load_mode mode);
+
+void dispc_set_default_color(enum omap_channel channel, u32 color);
+u32 dispc_get_default_color(enum omap_channel channel);
+void dispc_set_trans_key(enum omap_channel ch,
+ enum omap_dss_trans_key_type type,
+ u32 trans_key);
+void dispc_get_trans_key(enum omap_channel ch,
+ enum omap_dss_trans_key_type *type,
+ u32 *trans_key);
+void dispc_enable_trans_key(enum omap_channel ch, bool enable);
+void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
+bool dispc_trans_key_enabled(enum omap_channel ch);
+bool dispc_alpha_blending_enabled(enum omap_channel ch);
+
+bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
+void dispc_set_lcd_timings(struct omap_video_timings *timings);
+unsigned long dispc_fclk_rate(void);
+unsigned long dispc_lclk_rate(void);
+unsigned long dispc_pclk_rate(void);
+void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb);
+void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
+ u16 *lck_div, u16 *pck_div);
+int dispc_calc_clock_div(bool is_tft, unsigned long req_pck,
+ struct dispc_clock_info *cinfo);
+int dispc_set_clock_div(struct dispc_clock_info *cinfo);
+int dispc_get_clock_div(struct dispc_clock_info *cinfo);
+void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div);
+unsigned long clk_get_fck1_ckrate(void);
+
+int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck,
+ struct dsi_clock_info *cinfo);
+int dsi_pll_program(struct dsi_clock_info *cinfo);
+void dss_select_clk_source(bool dsi, bool dispc);
+int russo_panel_dcs_write_1(u8 dcs_cmd, u8 param);
+//int russo_panel_setup_update(u16 x, u16 y, u16 w, u16 h);
+
+
+
+
+int configure_dispc(void);
+
+int dss_clk_enable(bool enable);
+
+#define BUG() do { \
+ \
+ while (1); /* dead-loop */ \
+} while (0)
+
+#define BUG_ON(condition) do { if (condition) ; } while(0)
+
+#define mdelay(n) ({ unsigned long msec = (n); while (msec--) udelay(1000); })
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define do_div(n,base) ({ \
+ int __res; \
+ __res = ((unsigned long) n) % (unsigned) base; \
+ n = ((unsigned long) n) / (unsigned) base; \
+ __res; \
+})
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define abs(x) ({ \
+ int __x = (x); \
+ (__x < 0) ? -__x : __x; \
+ })
+
+
+void omap_rfbi_write_command(const void *buf, u32 len);
+void omap_rfbi_read_data(void *buf, u32 len);
+void omap_rfbi_write_data(const void *buf, u32 len);
+
+#endif
diff --git a/board/lge/sniper/panel-hub.c b/board/lge/sniper/panel-hub.c
new file mode 100755
index 00000000000..5b3e0ad08bb
--- /dev/null
+++ b/board/lge/sniper/panel-hub.c
@@ -0,0 +1,629 @@
+/* u-boot/board/hub/panel-hub.c
+ *
+ * Author: Kyungtae Oh <kyungtae.oh@lge.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <common.h>
+#include <asm/arch/bits.h>
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/cpu.h>
+#include <asm/errno.h>
+
+#include "hub_dss.h"
+
+#define LCD_XRES 480
+#define LCD_YRES 800
+
+#define BUG() do { \
+ \
+ while (1); /* dead-loop */ \
+} while (0)
+
+/* DSI Virtual channel. Hardcoded for now. */
+#define TCH 0
+
+#define DCS_READ_NUM_ERRORS 0x05
+#define DCS_READ_POWER_MODE 0x0a
+#define DCS_READ_MADCTL 0x0b
+#define DCS_READ_PIXEL_FORMAT 0x0c
+#define DCS_RDDSDR 0x0f
+#define DCS_SLEEP_IN 0x10
+#define DCS_SLEEP_OUT 0x11
+#define DCS_DISPLAY_OFF 0x28
+#define DCS_DISPLAY_ON 0x29
+#define DCS_COLUMN_ADDR 0x2a
+#define DCS_PAGE_ADDR 0x2b
+#define DCS_MEMORY_WRITE 0x2c
+#define DCS_TEAR_OFF 0x34
+#define DCS_TEAR_ON 0x35
+#define DCS_MEM_ACC_CTRL 0x36
+#define DCS_PIXEL_FORMAT 0x3a
+#define DCS_BRIGHTNESS 0x51
+#define DCS_CTRL_DISPLAY 0x53
+#define DCS_WRITE_CABC 0x55
+#define DCS_READ_CABC 0x56
+#define DCS_GET_ID 0xf8 /*sunggyun.yu@lge.com for B-prj*/
+
+/* #define HUB_PANEL_USE_ESD_CHECK */
+//#define HUB_PANEL_ESD_CHECK_PERIOD msecs_to_jiffies(5000)
+
+#define HUB_PANEL_LCD_RESET_N 34
+#define HUB_PANEL_LCD_CS 54
+
+#if 0
+enum {
+#if 0
+ STAR01,
+ STAR02,
+ STAR03,
+ STAR04,
+ STAR05,
+ STAR06,
+ STAR07,
+ STAR08,
+ STAR09,
+#endif
+ CMD_GATESET_8_1,
+ CMD_GATESET_8_2,
+ CMD_SET_PARTIAL_AREA,
+ CMD_SET_SCROLL_AREA,
+ CMD_SET_ADDRESS_MODE,
+ CMD_SET_SCROLL_START,
+ CMD_SET_PIXEL_FOMAT,
+// CMD_SET_TEAR_SCANLINE,////
+ CMD_EX_VSYNC_EN,
+ CMD_VCSEL,
+ CMD_SETVGMPM,
+ CMD_RBIAS1,
+ CMD_RBIAS2,
+ CMD_SET_DDVDHP,
+ CMD_SET_DDVDHM,
+ CMD_SET_VGH,
+ CMD_SET_VGL,
+ CMD_SET_VCL,
+ CMD_NUMBER_OF_LINES,
+ CMD_NUMBER_OF_FP_LINES,
+ CMD_GATESET_1,
+ CMD_1H_PERIOD,
+ CMD_SOURCE_PRECHARGE,
+ CMD_SOURCE_PRECHARGE_TIMING,
+ CMD_SOURCE_LEVEL,
+ CMD_NUMBER_OF_BP_LINES,
+ CMD_GATESET_2,
+ CMD_GATESET_3,
+ CMD_GATESET_4,
+ CMD_GATESET_5,
+ CMD_GATESET_6,
+ CMD_GATESET_7,
+ CMD_GATESET_9,
+ CMD_FLHW,
+ CMD_VCKHW,
+ CMD_FLT,
+ CMD_TCTRL,
+ CMD_DOTINV,
+ CMD_ON_OFF_SEQUENCE_PERIOD,
+ CMD_PONSEQA,
+ CMD_PONSEQB,
+ CMD_PONSEQC,
+ CMD_POFSEQA,
+ CMD_POFSEQB,
+ CMD_POFSEQC,
+ CMD_MANUAL_BRIGHTNESS,
+ CMD_MINIMUM_BRIGHTNESS,
+ CMD_BACKLIGHTCONTROL,
+ CMD_CABC_PWM,
+ CMD_CABC_1,
+ CMD_CABC_BRIGHTNESS_1,
+ CMD_CABC_BRIGHTNESS_2,
+ CMD_CABC_2,
+ CMD_BRT_REV,
+ CMD_TE,
+ CMD_HIGH_SPEED_RAM,
+ CMD_GAMMA_SETTING_R_POS,
+ CMD_GAMMA_SETTING_R_NEG,
+ CMD_GAMMA_SETTING_G_POS,
+ CMD_GAMMA_SETTING_G_NEG,
+ CMD_GAMMA_SETTING_B_POS,
+ CMD_GAMMA_SETTING_B_NEG,
+ NUM_CMD,
+ CMD_SET_TEAR_SCANLINE,
+};
+
+u8 lcd_command_for_mipi[][22] = {
+#if 0
+ [STAR01 ] = {0x15,0x02,0xBD,0x00,},
+ [STAR02 ] = {0x15,0x02,0xBD,0x00,},
+ [STAR03 ] = {0x15,0x02,0xBC,0x1A,},
+ [STAR04 ] = {0x15,0x02,0xBD,0x08,},
+ [STAR05 ] = {0x39,0x05,0x03,0x00,0xBC,0xFF,0xFF,},
+ [STAR06 ] = {0x15,0x02,0xBD,0x0B,},
+ [STAR07 ] = {0x15,0x02,0xBC,0xCC,},
+ [STAR08 ] = {0x15,0x02,0xBD,0x11,},
+ [STAR09 ] = {0x15,0x02,0xBC,0xFF,},
+#endif
+ [CMD_GATESET_8_1 ] = {0x23,0x02,0xCF,0x30,},
+ [CMD_GATESET_8_2 ] = {0x23,0x02,0xCF,0x30,},
+ [CMD_SET_PARTIAL_AREA ] = {0x39,0x05,0x30,0x00,0x00,0x03,0x1F,},
+ [CMD_SET_SCROLL_AREA ] = {0x39,0x07,0x33,0x00,0x00,0x03,0x20,0x00,0x00,},
+ [CMD_SET_ADDRESS_MODE ] = {0x15,0x02,0x36,0x0A,},
+ [CMD_SET_SCROLL_START ] = {0x39,0x03,0x37,0x00,0x00,},
+ [CMD_SET_PIXEL_FOMAT ] = {0x15,0x02,0x3A,0x07,},
+// [CMD_SET_TEAR_SCANLINE ] = {0x39,0x03,0x44,0x00,0x00,},////
+ [CMD_EX_VSYNC_EN ] = {0x23,0x02,0x71,0x00,},
+ [CMD_VCSEL ] = {0x23,0x02,0xB2,0x00,},
+ [CMD_SETVGMPM ] = {0x23,0x02,0xB4,0xAA,},
+ [CMD_RBIAS1 ] = {0x23,0x02,0xB5,0x33,},
+ [CMD_RBIAS2 ] = {0x23,0x02,0xB6,0x03,},
+ [CMD_SET_DDVDHP ] = {0x29,0x11,0xB7,0x1A,0x33,0x03,0x03,0x03,0x00,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x01,0x01,0x01,},
+ [CMD_SET_DDVDHM ] = {0x29,0x0E,0xB8,0x1C,0x53,0x03,0x03,0x00,0x01,0x02,0x00,0x00,0x04,0x00,0x01,0x01,},
+ [CMD_SET_VGH ] = {0x29,0x0B,0xB9,0x0C,0x01,0x01,0x00,0x00,0x00,0x02,0x00,0x02,0x01,},
+ [CMD_SET_VGL ] = {0x29,0x0B,0xBA,0x0D,0x01,0x01,0x00,0x00,0x00,0x02,0x00,0x02,0x01,},
+ [CMD_SET_VCL ] = {0x29,0x08,0xBB,0x00,0x00,0x00,0x00,0x01,0x02,0x01,},
+ [CMD_NUMBER_OF_LINES ] = {0x23,0x02,0xC1,0x01,},
+ [CMD_NUMBER_OF_FP_LINES ] = {0x23,0x02,0xC2,0x08,},
+ [CMD_GATESET_1 ] = {0x23,0x02,0xC3,0x04,},
+ [CMD_1H_PERIOD ] = {0x23,0x02,0xC4,0x4C,},
+ [CMD_SOURCE_PRECHARGE ] = {0x23,0x02,0xC5,0x07,},
+ [CMD_SOURCE_PRECHARGE_TIMING] = {0x29,0x03,0xC6,0xC4,0x04,},
+ [CMD_SOURCE_LEVEL ] = {0x23,0x02,0xC7,0x00,},
+ [CMD_NUMBER_OF_BP_LINES ] = {0x23,0x02,0xC8,0x02,},
+ [CMD_GATESET_2 ] = {0x23,0x02,0xC9,0x10,},
+ [CMD_GATESET_3 ] = {0x29,0x03,0xCA,0x04,0x04,},
+ [CMD_GATESET_4 ] = {0x23,0x02,0xCB,0x03,},
+ [CMD_GATESET_5 ] = {0x23,0x02,0xCC,0x12,},
+ [CMD_GATESET_6 ] = {0x23,0x02,0xCD,0x12,},
+ [CMD_GATESET_7 ] = {0x23,0x02,0xCE,0x30,},
+ [CMD_GATESET_9 ] = {0x23,0x02,0xD0,0x40,},
+ [CMD_FLHW ] = {0x23,0x02,0xD1,0x22,},
+ [CMD_VCKHW ] = {0x23,0x02,0xD2,0x22,},
+ [CMD_FLT ] = {0x23,0x02,0xD3,0x04,},
+ [CMD_TCTRL ] = {0x23,0x02,0xD4,0x14,},
+ [CMD_DOTINV ] = {0x23,0x02,0xD6,0x01,},
+ [CMD_ON_OFF_SEQUENCE_PERIOD ] = {0x23,0x02,0xD7,0x00,},
+ [CMD_PONSEQA ] = {0x29,0x0A,0xD8,0x01,0x05,0x06,0x0D,0x18,0x09,0x22,0x23,0x00,},
+ [CMD_PONSEQB ] = {0x29,0x03,0xD9,0x24,0x01,},
+ [CMD_PONSEQC ] = {0x29,0x06,0xDE,0x09,0x0F,0x21,0x12,0x04,},
+ [CMD_POFSEQA ] = {0x29,0x07,0xDF,0x02,0x06,0x06,0x06,0x06,0x00,},
+ [CMD_POFSEQB ] = {0x23,0x02,0xE0,0x01,},
+ [CMD_POFSEQC ] = {0x29,0x06,0xE1,0x00,0x00,0x00,0x00,0x00,},
+ [CMD_MANUAL_BRIGHTNESS ] = {0x23,0x02,0x51,0xFF,},
+ [CMD_MINIMUM_BRIGHTNESS ] = {0x23,0x02,0x52,0x00,},
+ [CMD_BACKLIGHTCONTROL ] = {0x23,0x02,0x53,0x40,},
+ [CMD_CABC_PWM ] = {0x29,0x03,0xE2,0x00,0x00,},
+ [CMD_CABC_1 ] = {0x23,0x02,0xE3,0x03,},
+ [CMD_CABC_BRIGHTNESS_1 ] = {0x29,0x09,0xE4,0x66,0x7B,0x90,0xA5,0xBB,0xC7,0xE1,0xE5,},
+ [CMD_CABC_BRIGHTNESS_2 ] = {0x29,0x09,0xE5,0xC5,0xC5,0xC9,0xC9,0xD1,0xE1,0xF1,0xFE,},
+ [CMD_CABC_2 ] = {0x23,0x02,0xE7,0x2A,},
+ [CMD_BRT_REV ] = {0x23,0x02,0xE8,0x00,},
+ [CMD_TE ] = {0x23,0x02,0xE9,0x00,},
+ [CMD_HIGH_SPEED_RAM ] = {0x23,0x02,0xEA,0x01,},
+ [CMD_GAMMA_SETTING_R_POS ] = {0x29,0x09,0xEB,0x00,0x33,0x12,0x10,0x98,0x88,0x87,0x0B,},
+ [CMD_GAMMA_SETTING_R_NEG ] = {0x29,0x09,0xEC,0x00,0x33,0x12,0x10,0x98,0x88,0x87,0x0B,},
+ [CMD_GAMMA_SETTING_G_POS ] = {0x29,0x09,0xED,0x00,0x33,0x12,0x10,0x98,0x88,0x87,0x0B,},
+ [CMD_GAMMA_SETTING_G_NEG ] = {0x29,0x09,0xEE,0x00,0x33,0x12,0x10,0x98,0x88,0x87,0x0B,},
+ [CMD_GAMMA_SETTING_B_POS ] = {0x29,0x09,0xEF,0x00,0x33,0x12,0x10,0x98,0x88,0x87,0x0B,},
+ [CMD_GAMMA_SETTING_B_NEG ] = {0x29,0x09,0xF0,0x00,0x33,0x12,0x10,0x98,0x88,0x87,0x0B,},
+ [NUM_CMD] = {0,},
+ [CMD_SET_TEAR_SCANLINE ] = {0x39,0x03,0x44,0x00,0x00,},
+};
+#else
+enum {
+ MIPI_SETTING,
+ CMD_SET_ADDRESS_MODE,
+ CMD_SET_SCROLL_START,
+ CMD_SETVGMPM,
+ CMD_SET_DDVDHP,
+ CMD_SET_DDVDHM,
+ CMD_SET_VGH,
+ CMD_SET_VGL,
+ CMD_NUMBER_OF_LINES,
+ CMD_1H_PERIOD,
+ CMD_SOURCE_PRECHARGE,
+ CMD_SOURCE_PRECHARGE_TIMING,
+ CMD_GATESET_3,
+ CMD_DOTINV,
+ CMD_PONSEQA,
+ CMD_PONSEQC,
+ CMD_BACKLIGHTCONTROL,
+ CMD_HIGH_SPEED_RAM,
+ CMD_GAMMA_SETTING_R_POS,
+ CMD_GAMMA_SETTING_R_NEG,
+ CMD_GAMMA_SETTING_G_POS,
+ CMD_GAMMA_SETTING_G_NEG,
+ CMD_GAMMA_SETTING_B_POS,
+ CMD_GAMMA_SETTING_B_NEG,
+ NUM_CMD,
+ CMD_SET_TEAR_SCANLINE,
+};
+
+u8 lcd_command_for_mipi[][22] = {
+ [MIPI_SETTING ] = {0x39,0x13,0xBC,0x12,0x8A,0x02,0x04,0xFF,0xFF,0xFF,0x10,0xFF,0xFF,0x00,0xA6,0x14,0x0A,0x19,0x00,0x00,0xFF,},
+ [CMD_SET_ADDRESS_MODE ] = {0x15,0x02,0x36,0x0A,},
+ [CMD_SET_SCROLL_START ] = {0x39,0x03,0x37,0x00,0x00,},
+ [CMD_SETVGMPM ] = {0x23,0x02,0xB4,0xAA,},
+ [CMD_SET_DDVDHP ] = {0x29,0x11,0xB7,0x1A,0x33,0x03,0x03,0x03,0x00,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x01,0x01,0x01,},
+ [CMD_SET_DDVDHM ] = {0x29,0x0E,0xB8,0x1C,0x53,0x03,0x03,0x00,0x01,0x02,0x00,0x00,0x04,0x00,0x01,0x01,},
+ [CMD_SET_VGH ] = {0x29,0x0B,0xB9,0x0A,0x01,0x01,0x00,0x00,0x00,0x02,0x00,0x02,0x01,},
+ [CMD_SET_VGL ] = {0x29,0x0B,0xBA,0x0F,0x01,0x01,0x00,0x00,0x00,0x02,0x00,0x02,0x01,},
+ [CMD_NUMBER_OF_LINES ] = {0x23,0x02,0xC1,0x01,},
+ [CMD_1H_PERIOD ] = {0x23,0x02,0xC4,0x4C,},
+ [CMD_SOURCE_PRECHARGE ] = {0x23,0x02,0xC5,0x07,},
+ [CMD_SOURCE_PRECHARGE_TIMING] = {0x29,0x03,0xC6,0xC4,0x04,},
+ [CMD_GATESET_3 ] = {0x29,0x03,0xCA,0x04,0x04,},
+ [CMD_DOTINV ] = {0x23,0x02,0xD6,0x01,},
+ [CMD_PONSEQA ] = {0x29,0x0A,0xD8,0x01,0x05,0x06,0x0D,0x18,0x09,0x22,0x23,0x00,},
+ [CMD_PONSEQC ] = {0x29,0x06,0xDE,0x09,0x0F,0x21,0x12,0x04,},
+ [CMD_BACKLIGHTCONTROL ] = {0x23,0x02,0x53,0x40,},
+ [CMD_HIGH_SPEED_RAM ] = {0x23,0x02,0xEA,0x01,},
+ [CMD_GAMMA_SETTING_R_POS ] = {0x29,0x09,0xEB,0x00,0x33,0x12,0x10,0x98,0x88,0x87,0x0B,},
+ [CMD_GAMMA_SETTING_R_NEG ] = {0x29,0x09,0xEC,0x00,0x33,0x12,0x10,0x98,0x88,0x87,0x0B,},
+ [CMD_GAMMA_SETTING_G_POS ] = {0x29,0x09,0xED,0x00,0x33,0x12,0x10,0x98,0x88,0x87,0x0B,},
+ [CMD_GAMMA_SETTING_G_NEG ] = {0x29,0x09,0xEE,0x00,0x33,0x12,0x10,0x98,0x88,0x87,0x0B,},
+ [CMD_GAMMA_SETTING_B_POS ] = {0x29,0x09,0xEF,0x00,0x33,0x12,0x10,0x98,0x88,0x87,0x0B,},
+ [CMD_GAMMA_SETTING_B_NEG ] = {0x29,0x09,0xF0,0x00,0x33,0x12,0x10,0x98,0x88,0x87,0x0B,},
+ [NUM_CMD] = {0,},
+ [CMD_SET_TEAR_SCANLINE ] = {0x39,0x03,0x44,0x00,0x00,},
+};
+#endif
+
+#define LCD_CMD(a) (lcd_command_for_mipi[(a)][0])
+#define LCD_DAT(a) (&lcd_command_for_mipi[(a)][2])
+#define LCD_LEN(a) (lcd_command_for_mipi[(a)][1])
+
+struct hub_panel_data {
+ unsigned long hw_guard_end; /* next value of jiffies when we can
+ * issue the next sleep in/out command
+ */
+ unsigned long hw_guard_wait; /* max guard time in jiffies */
+#if 0//kyungtae
+ struct omap_dss_device *dssdev;
+#endif
+ bool enabled;
+ u8 rotate;
+ bool mirror;
+
+ bool te_enabled;
+ bool use_ext_te;
+ //struct completion te_completion;
+
+ bool use_dsi_bl;
+
+ bool intro_printed;
+#if 0//kyungtae
+ struct workqueue_struct *esd_wq;
+ struct delayed_work esd_work;
+#endif
+};
+
+extern void dsi_hs_enable(int value);
+
+int dsi_vc_send_bta_sync(int channel);
+
+static int hub_panel_dcs_read_1(u8 dcs_cmd, u8 *data)
+{
+ int r;
+ u8 buf[1];
+
+ r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1);
+
+ if (r < 0)
+ return r;
+
+ *data = buf[0];
+
+ return 0;
+}
+
+static int hub_panel_dcs_write_0(u8 dcs_cmd)
+{
+ return dsi_vc_dcs_write(TCH, &dcs_cmd, 1);
+}
+
+int hub_panel_dcs_write_1(u8 dcs_cmd, u8 param)
+{
+ u8 buf[2];
+ buf[0] = dcs_cmd;
+ buf[1] = param;
+ return dsi_vc_dcs_write(TCH, buf, 2);
+}
+
+#if 0////
+static int hub_panel_sleep_in(struct hub_panel_data *td)
+{
+ int r;
+
+ //hw_guard_wait(td);
+ mdelay(120);//kyungtae
+
+ r = hub_panel_dcs_write_1(DCS_SLEEP_IN, 0);
+ if (r)
+ return r;
+
+ //hw_guard_start(td, 120);
+ mdelay(50);
+
+ return 0;
+}
+#endif////
+
+static int hub_panel_sleep_out(struct hub_panel_data *td)
+{
+ int r;
+
+ //hw_guard_wait(td);
+
+ r = hub_panel_dcs_write_1(DCS_SLEEP_OUT, 0);
+ if (r)
+ return r;
+
+ //hw_guard_start(td, 120);
+
+ mdelay(100);
+
+ return 0;
+}
+
+#if 0////
+static int hub_panel_get_id(u8 *buf)
+{
+ int r;
+
+ r = dsi_vc_dcs_read(TCH, DCS_GET_ID, buf, 3);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static int hub_panel_set_addr_mode(u8 rotate, bool mirror)
+{
+ int r;
+ u8 mode;
+ int b5, b6, b7;
+
+ r = hub_panel_dcs_read_1(DCS_READ_MADCTL, &mode);
+
+ if (r)
+ return r;
+
+ switch (rotate) {
+ default:
+ case 0:
+ b7 = 0;
+ b6 = 0;
+ b5 = 0;
+ break;
+ case 1:
+ b7 = 0;
+ b6 = 1;
+ b5 = 1;
+ break;
+ case 2:
+ b7 = 1;
+ b6 = 1;
+ b5 = 0;
+ break;
+ case 3:
+ b7 = 1;
+ b6 = 0;
+ b5 = 1;
+ break;
+ }
+
+ if (mirror)
+ b6 = !b6;
+
+ mode &= ~((1<<7) | (1<<6) | (1<<5));
+ mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
+
+ return hub_panel_dcs_write_1(DCS_MEM_ACC_CTRL, mode);
+}
+
+int hub_panel_set_update_window(u16 x, u16 y, u16 w, u16 h)
+{
+ int r;
+ u16 x1 = x;
+ u16 x2 = x + w - 1;
+ u16 y1 = y;
+ u16 y2 = y + h - 1;
+
+ u8 buf[5];
+ buf[0] = DCS_COLUMN_ADDR;
+ buf[1] = (x1 >> 8) & 0xff;
+ buf[2] = (x1 >> 0) & 0xff;
+ buf[3] = (x2 >> 8) & 0xff;
+ buf[4] = (x2 >> 0) & 0xff;
+
+ r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
+ if (r)
+ return r;
+
+ buf[0] = DCS_PAGE_ADDR;
+ buf[1] = (y1 >> 8) & 0xff;
+ buf[2] = (y1 >> 0) & 0xff;
+ buf[3] = (y2 >> 8) & 0xff;
+ buf[4] = (y2 >> 0) & 0xff;
+
+ r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf));
+ if (r)
+ return r;
+ dsi_vc_send_bta_sync(TCH);
+ return r;
+}
+#endif////
+
+static int hub_panel_enable_te(bool enable)
+{
+ //struct hub_panel_data *td = dev_get_drvdata(&dssdev->dev);
+ int r;
+
+ //td->te_enabled = enable;
+ //enable = 1;
+
+ if (enable)
+ r = hub_panel_dcs_write_1(DCS_TEAR_ON, 0);
+ else
+ r = hub_panel_dcs_write_0(DCS_TEAR_OFF);
+ return r;
+}
+
+void hub_panel_reset_lcd(void)
+{
+ printf("[LCD]%s\n", __func__);
+
+ extern void aat2862_ldo_enabled(int enable);
+
+ omap_set_gpio_direction(HUB_PANEL_LCD_RESET_N, 0);
+ mdelay(2);
+ omap_set_gpio_dataout(HUB_PANEL_LCD_RESET_N, 0);
+ aat2862_ldo_enabled(1);
+ mdelay(50);
+ omap_set_gpio_dataout(HUB_PANEL_LCD_RESET_N, 1);
+ mdelay(10);
+
+ return;
+
+}
+
+static int lcd_present(void)
+{
+ u8 data = 0;
+ hub_panel_dcs_read_1(0x0a, &data);
+ if (data == 0x94)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+int hub_panel_enable(void)
+{
+ int i, r;
+ struct hub_panel_data *td;
+
+ hub_panel_reset_lcd();
+
+ /* it seems we have to wait a bit until hub_panel is ready */
+ mdelay(20);
+
+ // initialize device
+ dsi_hs_enable(0);
+ for (i = 0; i < NUM_CMD; i++) {
+ dsi_vc_write(TCH, LCD_CMD(i), LCD_DAT(i), LCD_LEN(i));
+ }
+ dsi_hs_enable(1);
+
+ r = hub_panel_sleep_out(td);
+
+ hub_panel_dcs_write_1(DCS_DISPLAY_ON, 0);
+//// hub_panel_enable_te(1);
+ printf("DISPLAY ON & start tearing ON\n");
+
+// dsi_vc_write(TCH, LCD_CMD(CMD_SET_TEAR_SCANLINE), LCD_DAT(CMD_SET_TEAR_SCANLINE), LCD_LEN(CMD_SET_TEAR_SCANLINE));
+// hub_panel_enable_te(1);
+ mdelay(50); //after 1 frame
+
+ return 0;
+}
+
+int hub_panel_init_lcd(void)
+{
+ u32 val;
+ val = *((volatile unsigned int *)0x48005000) | (1<<13);
+ *((volatile unsigned int *)0x48005000) = val;
+ val = *((volatile unsigned int *)0x48005010) | (1<<13);
+ *((volatile unsigned int *)0x48005010) = val;
+
+ omap_set_gpio_direction(HUB_PANEL_LCD_CS,0);
+ omap_set_gpio_dataout(HUB_PANEL_LCD_CS, 1);
+ hub_panel_enable();
+ if (!lcd_present())
+ hub_add_bootargs(" nolcd");
+
+// u8 mode;
+
+// hub_panel_dcs_read_1(DCS_READ_MADCTL, &mode);
+// printf("skykrkrk MADCTL 0x%02x\n", mode);
+
+ return 0;
+}
+
+#if 0////
+static void hub_panel_setup_update(u16 x, u16 y, u16 w, u16 h)
+{
+ hub_panel_set_update_window(x, y, w, h);
+}
+
+static int hub_panel_memory_read(void *buf, size_t size,
+ u16 x, u16 y, u16 w, u16 h)
+{
+ int r;
+ int first = 1;
+ int plen;
+ unsigned buf_used = 0;
+
+ if (size < w * h * 3)
+ return -ENOMEM;
+
+ size = min(w * h * 3, LCD_XRES * LCD_YRES * 3);
+
+ /* plen 1 or 2 goes into short packet. until checksum error is fixed,
+ * use short packets. plen 32 works, but bigger packets seem to cause
+ * an error. */
+ if (size % 2)
+ plen = 1;
+ else
+ plen = 2;
+
+ hub_panel_setup_update(x, y, w, h);
+
+ r = dsi_vc_set_max_rx_packet_size(TCH, plen);
+ if (r)
+ return r;
+
+ while (buf_used < size) {
+ u8 dcs_cmd = first ? 0x2e : 0x3e;
+ first = 0;
+
+ r = dsi_vc_dcs_read(TCH, dcs_cmd,
+ buf + buf_used, size - buf_used);
+
+ if (r < 0) {
+ //dev_err(&dssdev->dev, "read error\n");
+ goto err;
+ }
+
+ buf_used += r;
+#if 0
+ if (r < plen) {
+ dev_err(&dssdev->dev, "short read\n");
+ break;
+ }
+
+ if (signal_pending(current)) {
+ dev_err(&dssdev->dev, "signal pending, "
+ "aborting memory read\n");
+ r = -ERESTARTSYS;
+ goto err;
+ }
+#endif
+ }
+
+ r = buf_used;
+
+err:
+ dsi_vc_set_max_rx_packet_size(TCH, 1);
+
+ return r;
+}
+#endif////