[PATCH 11/23] add new dispaly mode, such as extended mode, dualview, clone mode
Brad Figg
brad.figg at canonical.com
Thu Aug 27 23:20:51 UTC 2009
From: Green Wan <gwan at marvell.com>
Signed-off-by: Green Wan <gwan at marvell.com>
Signed-off-by: Saeed Bishara <saeed at marvell.com>
Signed-off-by: Brad Figg <brad.figg at canonical.com>
---
drivers/video/marvell/Kconfig | 8 ++
drivers/video/marvell/Makefile | 1 +
drivers/video/marvell/dovefb_base.c | 32 +++++++++-
drivers/video/marvell/dovefb_gfx.c | 123 ++++++++++++++++++++++++++---------
drivers/video/marvell/dovefb_ovly.c | 59 ++++++++++++++---
5 files changed, 182 insertions(+), 41 deletions(-)
diff --git a/drivers/video/marvell/Kconfig b/drivers/video/marvell/Kconfig
index a827ee8..c924eb2 100644
--- a/drivers/video/marvell/Kconfig
+++ b/drivers/video/marvell/Kconfig
@@ -118,12 +118,20 @@ config FB_DOVE_CLCD_DEFAULT_OPTION
depends on FB_DOVE && (FB_DOVE_CLCD || FB_DOVE_CLCD1)
default "lcd0:1280x768-24 at 60,lcd1:1024x768-16 at 60"
+config DOVEFB_DISPLAY_MODE
+ tristate "Support display configuration."
+ depends on FB_DOVE && FB_DOVE_CLCD && FB_DOVE_CLCD1
+ default y if ARCH_DOVE
+ ---help---
+ Say Y here if you want to build driver into kernel. Default is N.
+
config FB_DOVE_CLCD_FLAREON_GV
tristate "Marvell DOVE Color LCD - Flareon GV"
depends on FB_DOVE && (FB_DOVE_CLCD || FB_DOVE_CLCD1)
default y if ARCH_REALVIEW
---help---
Say Y here if your LCD version is on Flareon GV. Default is N.
+
## Following is for MUSTANG LCD config
config FB_MUSTANG_CLCD
tristate "Marvell Mustang Color LCD support"
diff --git a/drivers/video/marvell/Makefile b/drivers/video/marvell/Makefile
index 0ea1549..2c8ae74 100644
--- a/drivers/video/marvell/Makefile
+++ b/drivers/video/marvell/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_FB_DOVE) += dovefb_base.o dovefb_gfx.o dovefb_ovly.o dovef
obj-$(CONFIG_FB_DOVE_DCON) += dovedcon.o
+obj-$(CONFIG_DOVEFB_DISPLAY_MODE) += dovefb_display.o
diff --git a/drivers/video/marvell/dovefb_base.c b/drivers/video/marvell/dovefb_base.c
index 39501ab..3e45db5 100644
--- a/drivers/video/marvell/dovefb_base.c
+++ b/drivers/video/marvell/dovefb_base.c
@@ -41,12 +41,19 @@
#include <video/dovefb.h>
#include <video/dovefbreg.h>
+#include <video/dovefb_display.h>
#include "dovefb_if.h"
#define MAX_HWC_SIZE (64*64*2)
#define DEFAULT_REFRESH 60 /* Hz */
#define DOVEFB_INT_MASK DMA_FRAME_IRQ0_ENA(0x1)
+#if defined(CONFIG_DOVEFB_DISPLAY_MODE_MODULE) || \
+ defined(CONFIG_DOVEFB_DISPLAY_MODE)
+struct display_settings lcd_config;
+EXPORT_SYMBOL(lcd_config);
+#endif
+
static int dovefb_init_layer(struct platform_device *pdev,
enum dovefb_type type, struct dovefb_info *info,
struct resource *res);
@@ -533,7 +540,6 @@ bad_options:
}
#endif
-
static int dovefb_init_layer(struct platform_device *pdev,
enum dovefb_type type, struct dovefb_info *info,
struct resource *res)
@@ -599,6 +605,7 @@ static int dovefb_init_layer(struct platform_device *pdev,
* fix me, currently, vpro occupy a very large dma.
* It's better not to alloc DMA buffer from dma_alloc_xxx
*/
+// if (0 == fb_start) {
#ifdef CONFIG_ARCH_DOVE
dfli->fb_start = dma_alloc_writecombine(dfli->dev, dfli->fb_size,
&dfli->fb_start_dma,
@@ -619,7 +626,14 @@ static int dovefb_init_layer(struct platform_device *pdev,
goto failed;
}
- memset(dfli->fb_start, 0, dfli->fb_size);
+// fb_start = dfli->fb_start;
+// fb_start_dma = dfli->fb_start_dma;
+// } else {
+// dfli->fb_start = fb_start;
+// dfli->fb_start_dma = fb_start_dma;
+// }
+
+ //memset(dfli->fb_start, 0, dfli->fb_size);
fi->fix.smem_start = dfli->fb_start_dma;
fi->fix.smem_len = dfli->fb_size;
fi->screen_base = dfli->fb_start;
@@ -839,6 +853,7 @@ static int __init dovefb_probe(struct platform_device *pdev)
goto failed_irq;
}
+
ret = register_framebuffer(info->vid_plane->fb_info);
if (ret < 0) {
printk(KERN_ERR "doveFB: Failed to register VID FB.\n");
@@ -846,6 +861,19 @@ static int __init dovefb_probe(struct platform_device *pdev)
goto failed_fb;
}
+#if defined(CONFIG_DOVEFB_DISPLAY_MODE_MODULE) || \
+ defined(CONFIG_DOVEFB_DISPLAY_MODE)
+ lcd_config.display_mode = DISPLAY_NORMAL;
+ lcd_config.extend_ratio = 2;
+
+ if (info->id == 0) {
+ lcd_config.lcd0_gfx = info->gfx_plane->fb_info;
+ lcd_config.lcd0_vid = info->vid_plane->fb_info;
+ } else {
+ lcd_config.lcd1_gfx = info->gfx_plane->fb_info;
+ lcd_config.lcd1_vid = info->vid_plane->fb_info;
+ }
+#endif
printk(KERN_INFO " o dovefb: frame buffer device was successfully "
"loaded.\n");
return 0;
diff --git a/drivers/video/marvell/dovefb_gfx.c b/drivers/video/marvell/dovefb_gfx.c
index 6229bf5..c829dc7 100755
--- a/drivers/video/marvell/dovefb_gfx.c
+++ b/drivers/video/marvell/dovefb_gfx.c
@@ -42,12 +42,17 @@
#include "../edid.h"
#include <video/dovefb.h>
#include <video/dovefbreg.h>
+#include <video/dovefb_display.h>
#include "dovefb_if.h"
#define MAX_HWC_SIZE (64*64*2)
#define DEFAULT_REFRESH 60 /* Hz */
+#if defined(CONFIG_DOVEFB_DISPLAY_MODE_MODULE) || \
+ defined(CONFIG_DOVEFB_DISPLAY_MODE)
+extern struct display_settings lcd_config;
+#endif
static int dovefb_fill_edid(struct fb_info *fi,
struct dovefb_mach_info *dmi);
static int wait_for_vsync(struct dovefb_layer_info *dfli);
@@ -242,12 +247,8 @@ static void set_clock_divider(struct dovefb_layer_info *dfli,
int needed_pixclk;
u64 div_result;
u32 x = 0;
-#ifdef CONFIG_DOVE_REV_Z0
+ struct dovefb_info *info = dfli->info;
struct dovefb_mach_info *dmi = dfli->dev->platform_data;
-#else
- u32 axi_div, lcd_div, is_ext;
-#endif
-
/*
* Notice: The field pixclock is used by linux fb
@@ -274,10 +275,13 @@ static void set_clock_divider(struct dovefb_layer_info *dfli,
* Calc divider according to refresh rate.
*/
div_result = 1000000000000ll;
+
+ if(info->fixed_output)
+ m = &info->out_vmode;
+
do_div(div_result, m->pixclock);
needed_pixclk = (u32)div_result;
-#ifdef CONFIG_DOVE_REV_Z0
divider_int = dmi->sclk_clock / needed_pixclk;
/* check whether divisor is too small. */
if (divider_int < 2) {
@@ -285,15 +289,10 @@ static void set_clock_divider(struct dovefb_layer_info *dfli,
"Try smaller resolution\n");
divider_int = 2;
}
-#else
- calc_best_clock_div(needed_pixclk, &axi_div, &lcd_div, &is_ext);
- divider_int = lcd_div;
-
- printk(KERN_INFO "pix_clock = %d, axi_div = %d, lcd_div = %d, is_ext = %d.\n",
- needed_pixclk, axi_div, lcd_div, is_ext);
- set_external_lcd_clock(axi_div, is_ext);
-#endif /* CONFIG_DOVE_REV_Z0 */
+#ifndef CONFIG_DOVE_REV_Z0
+ set_external_lcd_clock(2, 0);
+#endif /* !CONFIG_DOVE_REV_Z0 */
/*
* Set setting to reg.
@@ -310,7 +309,8 @@ static void set_dma_control0(struct dovefb_layer_info *dfli)
* Set bit to enable graphics DMA.
*/
x = readl(dfli->reg_base + LCD_SPU_DMA_CTRL0);
- x |= (dfli->active && dfli->enabled) ? CFG_GRA_ENA_MASK : 0;
+ //x |= (dfli->active && dfli->enabled) ? CFG_GRA_ENA_MASK : 0;
+ x |= CFG_GRA_ENA_MASK;
dfli->active = 0;
/*
@@ -323,6 +323,11 @@ static void set_dma_control0(struct dovefb_layer_info *dfli)
x &= ~0x10000000;
/*
+ * enable horizontal smooth scaling.
+ */
+ x |= 0x1 << 14;
+
+ /*
* Cursor enabled?
*/
if (dfli->cursor_enabled)
@@ -391,10 +396,32 @@ static void set_graphics_start(struct fb_info *fi, int xoffset, int yoffset)
int pixel_offset;
unsigned long addr;
- pixel_offset = (yoffset * var->xres_virtual) + xoffset;
+#if defined(CONFIG_DOVEFB_DISPLAY_MODE_MODULE) || \
+ defined(CONFIG_DOVEFB_DISPLAY_MODE)
+ if (lcd_config.display_mode < 3) {
+ pixel_offset = (yoffset * var->xres_virtual) + xoffset;
+
+ addr = dfli->fb_start_dma + (pixel_offset * (var->bits_per_pixel >> 3));
+ writel(addr, dfli->reg_base + LCD_CFG_GRA_START_ADDR0);
+ if (lcd_config.display_mode == DISPLAY_DUALVIEW) {
+ struct dovefb_layer_info *dfli1 = lcd_config.lcd1_gfx->par;
+ int pixel_offset1;
+ unsigned long addr1;
+
+
+ pixel_offset1 = (yoffset * var->xres_virtual) + xoffset;
+
+ addr1 = dfli->fb_start_dma + (pixel_offset1 * (var->bits_per_pixel >> 3));
+ writel(addr1, dfli1->reg_base + LCD_CFG_GRA_START_ADDR0);
+
+ }
+ }
+#else
+ pixel_offset = (yoffset * var->xres_virtual) + xoffset;
- addr = dfli->fb_start_dma + (pixel_offset * (var->bits_per_pixel >> 3));
- writel(addr, dfli->reg_base + LCD_CFG_GRA_START_ADDR0);
+ addr = dfli->fb_start_dma + (pixel_offset * (var->bits_per_pixel >> 3));
+ writel(addr, dfli->reg_base + LCD_CFG_GRA_START_ADDR0);
+#endif
}
static int dovefb_pan_display(struct fb_var_screeninfo *var,
@@ -486,21 +513,20 @@ static int dovefb_gfx_set_par(struct fb_info *fi)
fi->fix.visual = FB_VISUAL_TRUECOLOR;
fi->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
- /*
- * Disable panel output while we setup the display.
- */
- x = readl(dfli->reg_base + LCD_SPU_DUMB_CTRL);
- writel(x & ~1, dfli->reg_base + LCD_SPU_DUMB_CTRL);
+ x = readl(dfli->reg_base + LCD_SPU_DMA_CTRL0);
+ if ((x & CFG_GRA_ENA_MASK))
+ wait_for_vsync(dfli);
/*
* Configure global panel parameters.
*/
- if (info->fixed_output)
+ if (info->fixed_output) {
writel((info->out_vmode.yres << 16) | info->out_vmode.xres,
dfli->reg_base + LCD_SPU_V_H_ACTIVE);
- else
+ } else {
writel((var->yres << 16) | var->xres,
dfli->reg_base + LCD_SPU_V_H_ACTIVE);
+ }
/*
* convet var to video mode
@@ -518,18 +544,54 @@ static int dovefb_gfx_set_par(struct fb_info *fi)
/*
* Configure graphics DMA parameters.
*/
- set_graphics_start(fi, fi->var.xoffset, fi->var.yoffset);
+#if defined(CONFIG_DOVEFB_DISPLAY_MODE_MODULE) || \
+ defined(CONFIG_DOVEFB_DISPLAY_MODE)
+ switch (lcd_config.display_mode) {
+ case DISPLAY_EXTENDED:
+ if (1 == dfli->info->id) {
+ set_graphics_start(fi, fi->var.xoffset+(var->xres/2), fi->var.yoffset);
+ break;
+ }
+ case DISPLAY_NORMAL:
+ case DISPLAY_CLONE:
+ case DISPLAY_DUALVIEW:
+ set_graphics_start(fi, fi->var.xoffset, fi->var.yoffset);
+ break;
+ default:
+ ;
+ }
+#else
+ set_graphics_start(fi, fi->var.xoffset, fi->var.yoffset);
+#endif
x = readl(dfli->reg_base + LCD_CFG_GRA_PITCH);
x = (x & ~0xFFFF) | ((var->xres_virtual * var->bits_per_pixel) >> 3);
writel(x, dfli->reg_base + LCD_CFG_GRA_PITCH);
- writel((var->yres << 16) | var->xres,
+
+#if defined(CONFIG_DOVEFB_DISPLAY_MODE_MODULE) || \
+ defined(CONFIG_DOVEFB_DISPLAY_MODE)
+ switch (lcd_config.display_mode) {
+ case DISPLAY_EXTENDED:
+ writel((var->yres << 16) | (var->xres*lcd_config.extend_ratio/4),
+ dfli->reg_base + LCD_SPU_GRA_HPXL_VLN);
+ break;
+ case DISPLAY_NORMAL:
+ case DISPLAY_CLONE:
+ case DISPLAY_DUALVIEW:
+ writel((var->yres << 16) | (var->xres),
dfli->reg_base + LCD_SPU_GRA_HPXL_VLN);
- writel((var->yres << 16) | var->xres,
+ break;
+ default:
+ ;
+ }
+#else
+ writel((var->yres << 16) | (var->xres),
dfli->reg_base + LCD_SPU_GRA_HPXL_VLN);
+#endif
- if (info->fixed_output)
+ if (info->fixed_output) {
writel((info->out_vmode.yres << 16) | info->out_vmode.xres,
dfli->reg_base + LCD_SPU_GZM_HPXL_VLN);
+ }
else
writel((var->yres << 16) | var->xres,
dfli->reg_base + LCD_SPU_GZM_HPXL_VLN);
@@ -941,7 +1003,8 @@ static void dovefb_set_defaults(struct dovefb_layer_info *dfli)
{
writel(0x80000001, dfli->reg_base + LCD_CFG_SCLK_DIV);
writel(0x00000000, dfli->reg_base + LCD_SPU_BLANKCOLOR);
- writel(dfli->info->io_pin_allocation,
+ writel(dfli->info->io_pin_allocation |
+ (0x3 << 18),
dfli->reg_base + SPU_IOPAD_CONTROL);
writel(0x00000000, dfli->reg_base + LCD_CFG_GRA_START_ADDR1);
writel(0x00000000, dfli->reg_base + LCD_SPU_GRA_OVSA_HPXL_VLN);
diff --git a/drivers/video/marvell/dovefb_ovly.c b/drivers/video/marvell/dovefb_ovly.c
index 6bd9fe5..775f80b 100755
--- a/drivers/video/marvell/dovefb_ovly.c
+++ b/drivers/video/marvell/dovefb_ovly.c
@@ -41,12 +41,17 @@
#include <video/dovefb.h>
#include <video/dovefbreg.h>
+#include <video/dovefb_display.h>
#include "dovefb_if.h"
#define MAX_QUEUE_NUM 60
#define RESET_BUF 0x1
#define FREE_ENTRY 0x2
+#if defined(CONFIG_DOVEFB_DISPLAY_MODE_MODULE) || \
+ defined(CONFIG_DOVEFB_DISPLAY_MODE)
+extern struct display_settings lcd_config;
+#endif
static int dovefb_ovly_set_par(struct fb_info *fi);
static void set_graphics_start(struct fb_info *fi, int xoffset, int yoffset);
static void set_dma_control0(struct dovefb_layer_info *dfli);
@@ -549,23 +554,32 @@ static int dovefb_ovly_ioctl(struct fb_info *fi, unsigned int cmd,
break;
case DOVEFB_IOCTL_GET_FBID:
mutex_lock(&dfli->access_ok);
- copy_to_user(argp, &dfli->cur_fbid, sizeof(unsigned int));
+ if (copy_to_user(argp, &dfli->cur_fbid, sizeof(unsigned int))) {
+ mutex_unlock(&dfli->access_ok);
+ return -EFAULT;
+ }
mutex_unlock(&dfli->access_ok);
break;
case DOVEFB_IOCTL_GET_SRC_MODE:
mutex_lock(&dfli->access_ok);
- copy_to_user(argp, &dfli->src_mode, sizeof(int));
+ if (copy_to_user(argp, &dfli->src_mode, sizeof(int))) {
+ mutex_unlock(&dfli->access_ok);
+ return -EFAULT;
+ }
mutex_unlock(&dfli->access_ok);
break;
case DOVEFB_IOCTL_SET_SRC_MODE:
mutex_lock(&dfli->access_ok);
- copy_from_user(&dfli->src_mode, argp, sizeof(int));
+ if (copy_from_user(&dfli->src_mode, argp, sizeof(int))) {
+ mutex_unlock(&dfli->access_ok);
+ return -EFAULT;
+ }
mutex_unlock(&dfli->access_ok);
break;
case DOVEFB_IOCTL_GET_FBPA:
{
struct shm_private_info info;
- int i, index;
+ int index;
if (copy_from_user(&info, argp,
sizeof(struct shm_private_info)))
@@ -577,7 +591,8 @@ static int dovefb_ovly_ioctl(struct fb_info *fi, unsigned int cmd,
/* calc physical address. */
info.fb_pa = (unsigned long)(dfli->fb_start_dma+
(index*info.width*info.height*MAX_YUV_PIXEL));
- copy_to_user(argp, &info, sizeof(struct shm_private_info));
+ if (copy_to_user(argp, &info, sizeof(struct shm_private_info)))
+ return -EFAULT;
break;
}
@@ -808,6 +823,11 @@ static void set_dma_control0(struct dovefb_layer_info *dfli)
x &= 0xef0fff01;
/*
+ * enable horizontal smooth scaling.
+ */
+ x |= 0x1 << 6;
+
+ /*
* If we are in a pseudo-color mode, we need to enable
* palette lookup.
*/
@@ -893,7 +913,8 @@ static void set_graphics_start(struct fb_info *fi, int xoffset, int yoffset)
pixel_offset = (yoffset * var->xres_virtual) + xoffset;
if (dfli->new_addr) {
- addr = dfli->new_addr;
+ addr = dfli->new_addr +
+ (pixel_offset * (var->bits_per_pixel >> 3));
} else {
addr = dfli->fb_start_dma +
(pixel_offset * (var->bits_per_pixel >> 3));
@@ -928,6 +949,7 @@ static int dovefb_ovly_set_par(struct fb_info *fi)
struct fb_var_screeninfo *var = &fi->var;
int pix_fmt;
int xzoom, yzoom;
+ int xbefzoom;
/*
* Determine which pixel format we're going to use.
@@ -955,12 +977,31 @@ static int dovefb_ovly_set_par(struct fb_info *fi)
/*
* Configure graphics DMA parameters.
*/
+#if defined(CONFIG_DOVEFB_DISPLAY_MODE_MODULE) || \
+ defined(CONFIG_DOVEFB_DISPLAY_MODE)
+ switch (lcd_config.display_mode) {
+ case DISPLAY_NORMAL:
+ case DISPLAY_CLONE:
+ case DISPLAY_DUALVIEW:
+ set_graphics_start(fi, fi->var.xoffset, fi->var.yoffset);
+ xbefzoom = var->xres/2;
+ break;
+ case DISPLAY_EXTENDED:
+ xbefzoom = var->xres/2/2;
+ set_graphics_start(fi, fi->var.xoffset+(var->xres/2), fi->var.yoffset);
+ default:
+ set_graphics_start(fi, fi->var.xoffset, fi->var.yoffset);
+ xbefzoom = var->xres/2;
+ ;
+ }
+#else
+ xbefzoom = var->xres/2;
set_graphics_start(fi, fi->var.xoffset, fi->var.yoffset);
-
+#endif
if ((dfli->pix_fmt >= 0) && (dfli->pix_fmt < 10)) {
writel((var->xres_virtual * var->bits_per_pixel) >> 3,
dfli->reg_base + LCD_SPU_DMA_PITCH_YC);
- writel((var->yres << 16) | var->xres,
+ writel((var->yres << 16) | xbefzoom,
dfli->reg_base + LCD_SPU_DMA_HPXL_VLN);
writel((var->yres << 16) | var->xres,
dfli->reg_base + LCD_SPU_DZM_HPXL_VLN);
@@ -978,7 +1019,7 @@ static int dovefb_ovly_set_par(struct fb_info *fi)
dfli->reg_base + LCD_SPU_DMA_PITCH_UV);
}
- writel((var->yres << 16) | var->xres,
+ writel((var->yres << 16) | (xbefzoom*2),
dfli->reg_base + LCD_SPU_DMA_HPXL_VLN);
if (info->fixed_output == 0) {
yzoom = dfli->surface.viewPortInfo.zoomYSize;
--
1.6.0.4
More information about the kernel-team
mailing list