msm_fb: Make buffers aligned to 4K page boundary
This change makes the frame buffers aligned to the page
boundary. Improves GPU performance since accessing the
frame buffer from page boundary is faster.
CRs-fixed: 325134
Change-Id: I6ce4477f62536a3cd81064e26dc08f2b199e181b
Signed-off-by: Padmanabhan Komanduru <pkomandu@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index aef957a..e6b342f 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -29,15 +29,19 @@
#include "board-8930.h"
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 3) /* 4 bpp x 3 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+ (roundup((1376 * 768 * 4), 4096) * 3) /* 4 bpp x 3 pages */
#else
-#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 2) /* 4 bpp x 2 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+ (roundup((1376 * 768 * 4), 4096) * 2) /* 4 bpp x 2 pages */
#endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-#define MSM_FB_EXT_BUF_SIZE (1920 * 1088 * 2 * 1) /* 2 bpp x 1 page */
+#define MSM_FB_EXT_BUF_SIZE \
+ (roundup((1920 * 1088 * 2), 4096) * 1) /* 2 bpp x 1 page */
#elif defined(CONFIG_FB_MSM_TVOUT)
-#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#define MSM_FB_EXT_BUF_SIZE \
+ (roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
#else
#define MSM_FB_EXT_BUF_SIZE 0
#endif
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index e0498e1..9a98058 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -29,15 +29,19 @@
#include "board-8960.h"
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_PRIM_BUF_SIZE (1920 * 1200 * 4 * 3) /* 4 bpp x 3 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+ (roundup((1920 * 1200 * 4), 4096) * 3) /* 4 bpp x 3 pages */
#else
-#define MSM_FB_PRIM_BUF_SIZE (1920 * 1200 * 4 * 2) /* 4 bpp x 2 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+ (roundup((1920 * 1200 * 4), 4096) * 2) /* 4 bpp x 2 pages */
#endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-#define MSM_FB_EXT_BUF_SIZE (1920 * 1088 * 2 * 1) /* 2 bpp x 1 page */
+#define MSM_FB_EXT_BUF_SIZE \
+ (roundup((1920 * 1088 * 2), 4096) * 1) /* 2 bpp x 1 page */
#elif defined(CONFIG_FB_MSM_TVOUT)
-#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#define MSM_FB_EXT_BUF_SIZE \
+ (roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
#else
#define MSM_FB_EXT_BUF_SIZE 0
#endif
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index 011a4d4..4e856b1 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -28,10 +28,10 @@
#include "board-msm7627a.h"
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_SIZE 0x260000
+#define MSM_FB_SIZE 0x261000
#define MSM7x25A_MSM_FB_SIZE 0xE1000
#else
-#define MSM_FB_SIZE 0x195000
+#define MSM_FB_SIZE 0x196000
#define MSM7x25A_MSM_FB_SIZE 0x96000
#endif
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 77b232d..c31e6d9 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2643,15 +2643,19 @@
#endif /* CONFIG_MSM_DSPS */
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_PRIM_BUF_SIZE (1024 * 600 * 4 * 3) /* 4 bpp x 3 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+ (roundup((1024 * 600 * 4), 4096) * 3) /* 4 bpp x 3 pages */
#else
-#define MSM_FB_PRIM_BUF_SIZE (1024 * 600 * 4 * 2) /* 4 bpp x 2 pages */
+#define MSM_FB_PRIM_BUF_SIZE \
+ (roundup((1024 * 600 * 4), 4096) * 2) /* 4 bpp x 2 pages */
#endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-#define MSM_FB_EXT_BUF_SIZE (1920 * 1080 * 2 * 1) /* 2 bpp x 1 page */
+#define MSM_FB_EXT_BUF_SIZE \
+ (roundup((1920 * 1080 * 2), 4096) * 1) /* 2 bpp x 1 page */
#elif defined(CONFIG_FB_MSM_TVOUT)
-#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#define MSM_FB_EXT_BUF_SIZE \
+ (roundup((720 * 576 * 2), 4096) * 2) /* 2 bpp x 2 pages */
#else
#define MSM_FB_EXT_BUFT_SIZE 0
#endif
diff --git a/drivers/video/msm/mdp4_overlay_atv.c b/drivers/video/msm/mdp4_overlay_atv.c
index 5cdafe1..0b707d7 100644
--- a/drivers/video/msm/mdp4_overlay_atv.c
+++ b/drivers/video/msm/mdp4_overlay_atv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2012 Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -38,13 +38,16 @@
{
uint8 *buf;
int bpp, ptype;
+ int yres, remainder;
struct fb_info *fbi;
struct fb_var_screeninfo *var;
struct msm_fb_data_type *mfd;
struct mdp4_overlay_pipe *pipe;
+ struct msm_panel_info *panel_info;
int ret;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ panel_info = &mfd->panel_info;
if (!mfd)
return -ENODEV;
@@ -55,10 +58,28 @@
fbi = mfd->fbi;
var = &fbi->var;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
if (atv_pipe == NULL) {
ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -150,16 +171,36 @@
uint8 *buf;
int bpp;
unsigned long flag;
+ int yres, remainder;
struct mdp4_overlay_pipe *pipe;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
if (!mfd->panel_power_on)
return;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* no need to power on cmd block since it's lcdc mode */
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
mutex_lock(&mfd->dma->ov_mutex);
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 3f12827..a3be2af 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -96,13 +96,16 @@
int hsync_end_x;
uint8 *buf;
int bpp, ptype;
+ int yres, remainder;
struct fb_info *fbi;
struct fb_var_screeninfo *var;
struct msm_fb_data_type *mfd;
struct mdp4_overlay_pipe *pipe;
+ struct msm_panel_info *panel_info;
int ret;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ panel_info = &mfd->panel_info;
if (!mfd)
return -ENODEV;
@@ -115,10 +118,28 @@
fbi = mfd->fbi;
var = &fbi->var;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
if (dsi_pipe == NULL) {
ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -295,7 +316,9 @@
{
struct fb_info *fbi;
struct mdp4_overlay_pipe *pipe;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
int bpp;
+ int yres, remainder;
uint8 *buf = NULL;
if (dsi_pipe == NULL)
@@ -314,10 +337,28 @@
fbi = mfd->fbi;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
if (pipe->is_3d) {
pipe->src_height = pipe->src_height_3d;
@@ -648,16 +689,36 @@
struct fb_info *fbi = mfd->fbi;
uint8 *buf;
int bpp;
+ int yres, remainder;
struct mdp4_overlay_pipe *pipe;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
if (!mfd->panel_power_on)
return;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* no need to power on cmd block since it's dsi video mode */
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
mutex_lock(&mfd->dma->ov_mutex);
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 3dece1f..ae498fc 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -84,8 +84,11 @@
struct msm_fb_data_type *mfd;
struct mdp4_overlay_pipe *pipe;
int ret;
+ int yres, remainder;
+ struct msm_panel_info *panel_info;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ panel_info = &mfd->panel_info;
if (!mfd)
return -ENODEV;
@@ -98,6 +101,17 @@
fbi = mfd->fbi;
var = &fbi->var;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* MDP cmd block enable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
if (is_mdp4_hw_reset()) {
@@ -107,8 +121,15 @@
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
if (lcdc_pipe == NULL) {
ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -552,16 +573,36 @@
struct fb_info *fbi = mfd->fbi;
uint8 *buf;
int bpp;
+ int yres, remainder;
struct mdp4_overlay_pipe *pipe;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
if (!mfd->panel_power_on)
return;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* no need to power on cmd block since it's lcdc mode */
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
mutex_lock(&mfd->dma->ov_mutex);
diff --git a/drivers/video/msm/mdp_dma.c b/drivers/video/msm/mdp_dma.c
index 3997814..e8b288f 100644
--- a/drivers/video/msm/mdp_dma.c
+++ b/drivers/video/msm/mdp_dma.c
@@ -522,14 +522,37 @@
boolean sync)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct fb_info *fbi = mfd->fbi;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
MDPIBUF *iBuf;
int bpp = info->var.bits_per_pixel / 8;
+ int yres, remainder;
+
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
down(&mfd->sem);
+
iBuf = &mfd->ibuf;
iBuf->buf = (uint8 *) info->fix.smem_start;
- iBuf->buf += info->var.xoffset * bpp +
- info->var.yoffset * info->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ iBuf->buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ iBuf->buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ iBuf->buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
iBuf->ibuf_width = info->var.xres_virtual;
iBuf->bpp = bpp;
diff --git a/drivers/video/msm/mdp_dma_dsi_video.c b/drivers/video/msm/mdp_dma_dsi_video.c
index 505eb74..0e76a07 100644
--- a/drivers/video/msm/mdp_dma_dsi_video.c
+++ b/drivers/video/msm/mdp_dma_dsi_video.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -67,14 +67,17 @@
int hsync_end_x;
uint8 *buf;
uint32 dma2_cfg_reg;
+ int yres, remainder;
int bpp;
struct fb_info *fbi;
struct fb_var_screeninfo *var;
struct msm_fb_data_type *mfd;
+ struct msm_panel_info *panel_info;
int ret;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ panel_info = &mfd->panel_info;
if (!mfd)
return -ENODEV;
@@ -85,10 +88,29 @@
fbi = mfd->fbi;
var = &fbi->var;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_OUT_SEL_DSI_VIDEO;
@@ -239,17 +261,38 @@
uint8 *buf;
int bpp;
unsigned long flag;
+ int yres, remainder;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
int irq_block = MDP_DMA2_TERM;
if (!mfd->panel_power_on)
return;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
down(&mfd->dma->mutex);
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
/* no need to power on cmd block since it's dsi mode */
/* starting address */
MDP_OUTP(MDP_BASE + DMA_P_BASE + 0x8, (uint32) buf);
diff --git a/drivers/video/msm/mdp_dma_lcdc.c b/drivers/video/msm/mdp_dma_lcdc.c
index ee50faf..5dada35 100644
--- a/drivers/video/msm/mdp_dma_lcdc.c
+++ b/drivers/video/msm/mdp_dma_lcdc.c
@@ -89,12 +89,15 @@
struct fb_info *fbi;
struct fb_var_screeninfo *var;
struct msm_fb_data_type *mfd;
+ struct msm_panel_info *panel_info;
uint32 dma_base;
uint32 timer_base = LCDC_BASE;
uint32 block = MDP_DMA2_BLOCK;
int ret;
+ int yres, remainder;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ panel_info = &mfd->panel_info;
if (!mfd)
return -ENODEV;
@@ -105,12 +108,32 @@
fbi = mfd->fbi;
var = &fbi->var;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* MDP cmd block enable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp + fbi->var.yoffset * fbi->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_OUT_SEL_LCDC;
@@ -319,15 +342,28 @@
void mdp_lcdc_update(struct msm_fb_data_type *mfd)
{
struct fb_info *fbi = mfd->fbi;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
uint8 *buf;
int bpp;
unsigned long flag;
uint32 dma_base;
+ int yres, remainder;
int irq_block = MDP_DMA2_TERM;
#ifdef CONFIG_FB_MSM_MDP40
int intr = INTR_DMA_P_DONE;
#endif
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
if (!mfd->panel_power_on)
return;
@@ -335,8 +371,16 @@
/* no need to power on cmd block since it's lcdc mode */
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
dma_base = DMA_P_BASE;
diff --git a/drivers/video/msm/mdp_dma_tv.c b/drivers/video/msm/mdp_dma_tv.c
index 66d9422..1305e03 100644
--- a/drivers/video/msm/mdp_dma_tv.c
+++ b/drivers/video/msm/mdp_dma_tv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -39,12 +39,15 @@
int mdp_dma3_on(struct platform_device *pdev)
{
struct msm_fb_data_type *mfd;
+ struct msm_panel_info *panel_info;
struct fb_info *fbi;
uint8 *buf;
int bpp;
int ret = 0;
+ int yres, remainder;
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
+ panel_info = &mfd->panel_info;
if (!mfd)
return -ENODEV;
@@ -53,13 +56,33 @@
return -EINVAL;
fbi = mfd->fbi;
+
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* MDP cmd block enable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
/* starting address[31..8] of Video frame buffer is CS0 */
MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
@@ -112,15 +135,37 @@
uint8 *buf;
int bpp;
unsigned long flag;
+ int yres, remainder;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
if (!mfd->panel_power_on)
return;
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
/* no need to power on cmd block since dma3 is running */
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
- fbi->var.yoffset * fbi->fix.line_length;
+
+ if (fbi->var.yoffset < yres) {
+ buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
+
MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3);
spin_lock_irqsave(&mdp_spin_lock, flag);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 4160c4d..019acce 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -973,6 +973,7 @@
struct fb_var_screeninfo *var;
int *id;
int fbram_offset;
+ int remainder, remainder_mode2;
/*
* fb info initialization
@@ -1109,15 +1110,28 @@
fix->line_length = msm_fb_line_length(mfd->index, panel_info->xres,
bpp);
+
+ /* Make sure all buffers can be addressed on a page boundary by an x
+ * and y offset */
+
+ remainder = (fix->line_length * panel_info->yres) % PAGE_SIZE;
+ if (!remainder)
+ remainder = PAGE_SIZE;
+ remainder_mode2 = (fix->line_length *
+ panel_info->mode2_yres) % PAGE_SIZE;
+ if (!remainder_mode2)
+ remainder_mode2 = PAGE_SIZE;
+
/* calculate smem_len based on max size of two supplied modes */
- fix->smem_len = roundup(MAX(msm_fb_line_length(mfd->index,
- panel_info->xres,
- bpp) *
- panel_info->yres * mfd->fb_page,
- msm_fb_line_length(mfd->index,
+ fix->smem_len = MAX((msm_fb_line_length(mfd->index, panel_info->xres,
+ bpp) *
+ panel_info->yres + PAGE_SIZE -
+ remainder) * mfd->fb_page,
+ (msm_fb_line_length(mfd->index,
panel_info->mode2_xres,
bpp) *
- panel_info->mode2_yres * mfd->fb_page), PAGE_SIZE);
+ panel_info->mode2_yres + PAGE_SIZE -
+ remainder_mode2) * mfd->fb_page);