summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlison Wang <b18965@freescale.com>2012-12-11 15:36:08 +0800
committerEd Nash <enash@enash-desktop.(none)>2012-12-12 14:46:31 -0500
commit97bb163197f3dc3405af90b5159e0f6b8a302586 (patch)
tree2d4238dbfebf53162357551d46f43da5c6402e7d
parentefe491be15ead3bbcf7e715337fdee7dfa41f699 (diff)
ENGR00216076-2: DCU: Update DCU driver for PM and blending issue
Fix layers blending and reinitialization issue for DCU driver. Update power management part for DCU driver. Signed-off-by: Alison Wang <b18965@freescale.com>
-rw-r--r--arch/arm/plat-mxc/devices/platform-mvf-dcu.c4
-rw-r--r--arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h52
-rw-r--r--drivers/video/mvf_dcu.c47
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/mvf-fb.h74
5 files changed, 112 insertions, 66 deletions
diff --git a/arch/arm/plat-mxc/devices/platform-mvf-dcu.c b/arch/arm/plat-mxc/devices/platform-mvf-dcu.c
index 13258aba9bb0..0fe5099eca34 100644
--- a/arch/arm/plat-mxc/devices/platform-mvf-dcu.c
+++ b/arch/arm/plat-mxc/devices/platform-mvf-dcu.c
@@ -38,8 +38,8 @@ int __init mvf_dcu_init(int id)
}
const struct mvf_dcu_data mvfa5_dcu_data[] __initconst = {
- mvf_dcu_data_entry_single(MVF, 0, SZ_4K, mvf_dcu_init),
- mvf_dcu_data_entry_single(MVF, 1, SZ_4K, mvf_dcu_init),
+ mvf_dcu_data_entry_single(MVF, 0, SZ_8K, mvf_dcu_init),
+ mvf_dcu_data_entry_single(MVF, 1, SZ_8K, mvf_dcu_init),
};
struct platform_device *__init mvf_add_dcu(
diff --git a/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h b/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h
index b9d8dd3b93bb..9a5ba8e396a9 100644
--- a/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h
+++ b/arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h
@@ -14,6 +14,7 @@
#define __MVF_DCU_FB_H__
#include <linux/types.h>
+#include <linux/mvf-fb.h>
struct mvf_dcu_platform_data {
char *mode_str;
@@ -21,11 +22,6 @@ struct mvf_dcu_platform_data {
int (*init) (int);
};
-struct mfb_alpha {
- int enable;
- int alpha;
-};
-
struct dfb_chroma_key {
int enable;
__u8 red_max;
@@ -36,60 +32,14 @@ struct dfb_chroma_key {
__u8 blue_min;
};
-struct layer_display_offset {
- int x_layer_d;
- int y_layer_d;
-};
-
#define DCU_LCD_ENABLE_PIN 30
#define MFB_SET_CHROMA_KEY _IOW('M', 1, struct mfb_chroma_key)
#define MFB_SET_BRIGHTNESS _IOW('M', 3, __u8)
-#define MFB_SET_ALPHA 0x80014d00
-#define MFB_GET_ALPHA 0x40014d00
-#define MFB_SET_LAYER 0x80084d04
-#define MFB_GET_LAYER 0x40084d04
-
-#define FBIOGET_GWINFO 0x46E0
-#define FBIOPUT_GWINFO 0x46E1
-
#ifdef __KERNEL__
#include <linux/spinlock.h>
-/*
- * These are the fields of control descriptor for every layer
- */
-struct dcu_layer_desc {
- u32 layer_num;
- u32 width;
- u32 height;
- u32 posx;
- u32 posy;
- u32 addr;
- u32 blend;
- u32 chroma_key_en;
- u32 lut_offset;
- u32 rle_en;
- u32 bpp;
- u32 trans;
- u32 safety_en;
- u32 data_sel_clut;
- u32 tile_en;
- u32 en;
- u32 ck_r_min;
- u32 ck_r_max;
- u32 ck_g_min;
- u32 ck_g_max;
- u32 ck_b_min;
- u32 ck_b_max;
- u32 tile_width;
- u32 tile_height;
- u32 trans_fgcolor;
- u32 trans_bgcolor;
-} __packed;
-
-
/* DCU registers */
#define DCU_CTRLDESCCURSOR1 0x0000
#define DCU_CTRLDESCCURSOR1_HEIGHT(x) (x << 16)
diff --git a/drivers/video/mvf_dcu.c b/drivers/video/mvf_dcu.c
index 719e465b77e6..d9fc6fa664c7 100644
--- a/drivers/video/mvf_dcu.c
+++ b/drivers/video/mvf_dcu.c
@@ -138,6 +138,8 @@ static struct mfb_info mfb_template[] = {
},
};
+static int total_open_layers = 0;
+
static int mvf_dcu_enable_panel(struct fb_info *info)
{
@@ -422,11 +424,6 @@ static void update_lcdc(struct fb_info *info)
writel(DCU_THRESHOLD_LS_BF_VS(0x3) | DCU_THRESHOLD_OUT_BUF_HIGH(0x78) |
DCU_THRESHOLD_OUT_BUF_LOW(0), dcu->base + DCU_THRESHOLD);
- writel(0, dcu->base + DCU_INT_STATUS);
- writel(0, dcu->base + DCU_PARR_ERR_STA_1);
- writel(0, dcu->base + DCU_PARR_ERR_STA_2);
- writel(0, dcu->base + DCU_PARR_ERR_STA_3);
-
/* Enable the DCU */
enable_lcdc(info);
}
@@ -718,10 +715,34 @@ static int mvf_dcu_ioctl(struct fb_info *info, unsigned int cmd,
static int mvf_dcu_open(struct fb_info *info, int user)
{
struct mfb_info *mfbi = info->par;
+ struct mvf_dcu_fb_data *dcu = mfbi->parent;
+ int i;
int ret = 0;
mfbi->index = info->node;
spin_lock(&dcu_lock);
+
+ /* if first time any layer open (e.g., at boot time) reset all */
+ if (total_open_layers == 0) {
+
+ writel(0, dcu->base + DCU_INT_STATUS);
+ writel(0, dcu->base + DCU_PARR_ERR_STA_1);
+ writel(0, dcu->base + DCU_PARR_ERR_STA_2);
+ writel(0, dcu->base + DCU_PARR_ERR_STA_3);
+
+ for (i = 0; i < 64; i++) {
+ writel(0, dcu->base + DCU_CTRLDESCLN_0(i));
+ writel(0, dcu->base + DCU_CTRLDESCLN_1(i));
+ writel(0, dcu->base + DCU_CTRLDESCLN_2(i));
+ writel(0, dcu->base + DCU_CTRLDESCLN_3(i));
+ writel(0, dcu->base + DCU_CTRLDESCLN_4(i));
+ writel(0, dcu->base + DCU_CTRLDESCLN_5(i));
+ writel(0, dcu->base + DCU_CTRLDESCLN_6(i));
+ writel(0, dcu->base + DCU_CTRLDESCLN_7(i));
+ writel(0, dcu->base + DCU_CTRLDESCLN_8(i));
+ }
+ }
+
mfbi->count++;
if (mfbi->count == 1) {
pr_debug("open layer index %d\n", mfbi->index);
@@ -729,6 +750,8 @@ static int mvf_dcu_open(struct fb_info *info, int user)
ret = mvf_dcu_set_par(info);
if (ret < 0)
mfbi->count--;
+ else
+ total_open_layers++;
}
spin_unlock(&dcu_lock);
@@ -747,6 +770,8 @@ static int mvf_dcu_release(struct fb_info *info, int user)
ret = mvf_dcu_disable_panel(info);
if (ret < 0)
mfbi->count++;
+ else
+ total_open_layers--;
}
spin_unlock(&dcu_lock);
@@ -895,21 +920,17 @@ static void free_irq_local(int irq, struct mvf_dcu_fb_data *dcu)
static int mvf_dcu_suspend(struct platform_device *pdev,
pm_message_t state)
{
- struct mvf_dcu_fb_data *dcu;
-
- dcu = dev_get_drvdata(&pdev->dev);
- disable_lcdc(dcu->mvf_dcu_info[0]);
+ struct mvf_dcu_fb_data *dcu = dev_get_drvdata(&pdev->dev);
+ clk_disable(dcu->clk);
return 0;
}
static int mvf_dcu_resume(struct platform_device *pdev)
{
- struct mvf_dcu_fb_data *dcu;
-
- dcu = dev_get_drvdata(&pdev->dev);
- enable_lcdc(dcu->mvf_dcu_info[0]);
+ struct mvf_dcu_fb_data *dcu = dev_get_drvdata(&pdev->dev);
+ clk_enable(dcu->clk);
return 0;
}
#else
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index c65d1b9eb546..947d36f054e5 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -35,6 +35,7 @@ header-y += mxc_si4702.h
header-y += mxc_sim_interface.h
header-y += mxc_v4l2.h
header-y += mxcfb.h
+header-y += mvf-fb.h
header-y += pmic_adc.h
header-y += pmic_battery.h
header-y += pmic_external.h
diff --git a/include/linux/mvf-fb.h b/include/linux/mvf-fb.h
new file mode 100644
index 000000000000..836767697d76
--- /dev/null
+++ b/include/linux/mvf-fb.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * Freescale DCU Frame Buffer device driver ioctls
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __MVF_FB_H__
+#define __MVF_FB_H__
+
+#include <linux/fb.h>
+
+/* ioctls */
+
+#define MFB_SET_ALPHA 0x80014d00
+#define MFB_GET_ALPHA 0x40014d00
+#define MFB_SET_LAYER 0x80084d04
+#define MFB_GET_LAYER 0x40084d04
+
+#define FBIOGET_GWINFO 0x46E0
+#define FBIOPUT_GWINFO 0x46E1
+
+#ifndef u32
+#define u32 unsigned int
+#endif
+
+struct mfb_alpha {
+ int enable;
+ int alpha;
+};
+
+struct layer_display_offset {
+ int x_layer_d;
+ int y_layer_d;
+};
+
+/*
+ * These are the fields of control descriptor for every layer
+ */
+struct dcu_layer_desc {
+ u32 layer_num;
+ u32 width;
+ u32 height;
+ u32 posx;
+ u32 posy;
+ u32 addr;
+ u32 blend;
+ u32 chroma_key_en;
+ u32 lut_offset;
+ u32 rle_en;
+ u32 bpp;
+ u32 trans;
+ u32 safety_en;
+ u32 data_sel_clut;
+ u32 tile_en;
+ u32 en;
+ u32 ck_r_min;
+ u32 ck_r_max;
+ u32 ck_g_min;
+ u32 ck_g_max;
+ u32 ck_b_min;
+ u32 ck_b_max;
+ u32 tile_width;
+ u32 tile_height;
+ u32 trans_fgcolor;
+ u32 trans_bgcolor;
+} __packed;
+
+#endif