diff options
author | Alison Wang <b18965@freescale.com> | 2012-12-11 15:36:08 +0800 |
---|---|---|
committer | Ed Nash <enash@enash-desktop.(none)> | 2012-12-12 14:46:31 -0500 |
commit | 97bb163197f3dc3405af90b5159e0f6b8a302586 (patch) | |
tree | 2d4238dbfebf53162357551d46f43da5c6402e7d | |
parent | efe491be15ead3bbcf7e715337fdee7dfa41f699 (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.c | 4 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/mvf-dcu-fb.h | 52 | ||||
-rw-r--r-- | drivers/video/mvf_dcu.c | 47 | ||||
-rw-r--r-- | include/linux/Kbuild | 1 | ||||
-rw-r--r-- | include/linux/mvf-fb.h | 74 |
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 |