summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVeera Sundaram Sankaran <veeras@codeaurora.org>2014-08-29 09:43:08 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:34:28 -0700
commit95498f571dac89517497e672be6a1e2781fe7fb2 (patch)
treea863ff69aca7a94183a5eff844ef48c5d6634dd3
parentea8e9aff9ecead467876d4fc38f26150dac23390 (diff)
msm: mdss: Fix hardware cursor configuration for right mixer
The right mixer for hwcursor was not configured, making it to work only on dsi0. This change configures the left and right mixers appropriately based on single/dual dsi. Change-Id: Ib12589777b3b7a2a202447c89bb079ffb969cf7c Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c276
1 files changed, 171 insertions, 105 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index faf2616f0751..cff8c5b1d40b 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -2334,27 +2334,135 @@ static struct attribute_group mdp_overlay_sysfs_group = {
.attrs = mdp_overlay_sysfs_attrs,
};
+static void mdss_mdp_hw_cursor_setpos(struct mdss_mdp_mixer *mixer,
+ struct mdss_rect *roi, u32 start_x, u32 start_y)
+{
+ int roi_xy = (roi->y << 16) | roi->x;
+ int start_xy = (start_y << 16) | start_x;
+ int roi_size = (roi->h << 16) | roi->w;
+
+ if (!mixer) {
+ pr_err("mixer not available\n");
+ return;
+ }
+ mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_XY, roi_xy);
+ mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_START_XY, start_xy);
+ mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_SIZE, roi_size);
+}
+
+static void mdss_mdp_hw_cursor_setimage(struct mdss_mdp_mixer *mixer,
+ struct fb_cursor *cursor, u32 cursor_addr, struct mdss_rect *roi)
+{
+ int calpha_en, transp_en, alpha, size;
+ struct fb_image *img = &cursor->image;
+ u32 blendcfg;
+ int roi_size = 0;
+
+ if (!mixer) {
+ pr_err("mixer not available\n");
+ return;
+ }
+
+ if (img->bg_color == 0xffffffff)
+ transp_en = 0;
+ else
+ transp_en = 1;
+
+ alpha = (img->fg_color & 0xff000000) >> 24;
+
+ if (alpha)
+ calpha_en = 0x0; /* xrgb */
+ else
+ calpha_en = 0x2; /* argb */
+
+ roi_size = (roi->h << 16) | roi->w;
+ size = (img->height << 16) | img->width;
+ mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_IMG_SIZE, size);
+ mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_SIZE, roi_size);
+ mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_STRIDE,
+ img->width * 4);
+ mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_BASE_ADDR,
+ cursor_addr);
+ blendcfg = mdp_mixer_read(mixer, MDSS_MDP_REG_LM_CURSOR_BLEND_CONFIG);
+ blendcfg &= ~0x1;
+ blendcfg |= (transp_en << 3) | (calpha_en << 1);
+ mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_BLEND_CONFIG,
+ blendcfg);
+ if (calpha_en)
+ mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_BLEND_PARAM,
+ alpha);
+
+ if (transp_en) {
+ mdp_mixer_write(mixer,
+ MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_LOW0,
+ ((img->bg_color & 0xff00) << 8) |
+ (img->bg_color & 0xff));
+ mdp_mixer_write(mixer,
+ MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_LOW1,
+ ((img->bg_color & 0xff0000) >> 16));
+ mdp_mixer_write(mixer,
+ MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_HIGH0,
+ ((img->bg_color & 0xff00) << 8) |
+ (img->bg_color & 0xff));
+ mdp_mixer_write(mixer,
+ MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_HIGH1,
+ ((img->bg_color & 0xff0000) >> 16));
+ }
+}
+
+static void mdss_mdp_hw_cursor_blend_config(struct mdss_mdp_mixer *mixer,
+ struct fb_cursor *cursor)
+{
+ u32 blendcfg;
+ if (!mixer) {
+ pr_err("mixer not availbale\n");
+ return;
+ }
+
+ blendcfg = mdp_mixer_read(mixer, MDSS_MDP_REG_LM_CURSOR_BLEND_CONFIG);
+ if (!cursor->enable != !(blendcfg & 0x1)) {
+ if (cursor->enable) {
+ pr_debug("enable hw cursor on mixer=%d\n", mixer->num);
+ blendcfg |= 0x1;
+ } else {
+ pr_debug("disable hw cursor on mixer=%d\n", mixer->num);
+ blendcfg &= ~0x1;
+ }
+
+ mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_BLEND_CONFIG,
+ blendcfg);
+ mixer->cursor_enabled = cursor->enable;
+ mixer->params_changed++;
+ }
+
+}
+
static int mdss_mdp_hw_cursor_update(struct msm_fb_data_type *mfd,
struct fb_cursor *cursor)
{
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
- struct mdss_mdp_mixer *mixer;
+ struct mdss_mdp_mixer *mixer_left = NULL;
+ struct mdss_mdp_mixer *mixer_right = NULL;
struct fb_image *img = &cursor->image;
- u32 blendcfg;
+ struct fbcurpos cursor_hot;
+ struct mdss_rect roi;
int ret = 0;
u32 xres = mfd->fbi->var.xres;
u32 yres = mfd->fbi->var.yres;
u32 start_x = img->dx;
u32 start_y = img->dy;
- u32 roi_x = 0;
- u32 roi_y = 0;
- int roi_w = 0;
- int roi_h = 0;
- int roi_size = 0;
+ u32 left_lm_w = left_lm_w_from_mfd(mfd);
- mixer = mdss_mdp_mixer_get(mdp5_data->ctl, MDSS_MDP_MIXER_MUX_DEFAULT);
- if (!mixer)
+ mixer_left = mdss_mdp_mixer_get(mdp5_data->ctl,
+ MDSS_MDP_MIXER_MUX_DEFAULT);
+ if (!mixer_left)
return -ENODEV;
+ if (is_split_lm(mfd)) {
+ mixer_right = mdss_mdp_mixer_get(mdp5_data->ctl,
+ MDSS_MDP_MIXER_MUX_RIGHT);
+ if (!mixer_right)
+ return -ENODEV;
+ }
if (!mfd->cursor_buf && (cursor->set & FB_CUR_SETIMAGE)) {
mfd->cursor_buf = dma_alloc_coherent(NULL, MDSS_MDP_CURSOR_SIZE,
@@ -2377,9 +2485,6 @@ static int mdss_mdp_hw_cursor_update(struct msm_fb_data_type *mfd,
ret);
return ret;
}
-
- mixer->cursor_hotx = 0;
- mixer->cursor_hoty = 0;
}
if ((img->width > MDSS_MDP_CURSOR_WIDTH) ||
@@ -2387,17 +2492,15 @@ static int mdss_mdp_hw_cursor_update(struct msm_fb_data_type *mfd,
(img->depth != 32) || (start_x >= xres) || (start_y >= yres))
return -EINVAL;
- pr_debug("mixer=%d enable=%x set=%x\n", mixer->num, cursor->enable,
- cursor->set);
-
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
- blendcfg = mdp_mixer_read(mixer, MDSS_MDP_REG_LM_CURSOR_BLEND_CONFIG);
+ pr_debug("enable=%x set=%x\n", cursor->enable, cursor->set);
+ memset(&cursor_hot, 0, sizeof(struct fbcurpos));
+ memset(&roi, 0, sizeof(struct mdss_rect));
if (cursor->set & FB_CUR_SETHOT) {
if ((cursor->hot.x < img->width) &&
(cursor->hot.y < img->height)) {
- mixer->cursor_hotx = cursor->hot.x;
- mixer->cursor_hoty = cursor->hot.y;
+ cursor_hot.x = cursor->hot.x;
+ cursor_hot.y = cursor->hot.y;
/* Update cursor position */
cursor->set |= FB_CUR_SETPOS;
} else {
@@ -2406,33 +2509,25 @@ static int mdss_mdp_hw_cursor_update(struct msm_fb_data_type *mfd,
}
}
- if (start_x > mixer->cursor_hotx) {
- start_x -= mixer->cursor_hotx;
+ if (start_x > cursor_hot.x) {
+ start_x -= cursor_hot.x;
} else {
- roi_x = mixer->cursor_hotx - start_x;
+ roi.x = cursor_hot.x - start_x;
start_x = 0;
}
- if (start_y > mixer->cursor_hoty) {
- start_y -= mixer->cursor_hoty;
+ if (start_y > cursor_hot.y) {
+ start_y -= cursor_hot.y;
} else {
- roi_y = mixer->cursor_hoty - start_y;
+ roi.y = cursor_hot.y - start_y;
start_y = 0;
}
- roi_w = min(xres - start_x, img->width - roi_x);
- roi_h = min(yres - start_y, img->height - roi_y);
- roi_size = (roi_h << 16) | roi_w;
+ roi.w = min(xres - start_x, img->width - roi.x);
+ roi.h = min(yres - start_y, img->height - roi.y);
- if (cursor->set & FB_CUR_SETPOS) {
- mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_XY,
- (roi_y << 16) | roi_x);
- mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_START_XY,
- (start_y << 16) | start_x);
- mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_SIZE, roi_size);
- }
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
if (cursor->set & FB_CUR_SETIMAGE) {
- int calpha_en, transp_en, alpha, size;
u32 cursor_addr;
ret = copy_from_user(mfd->cursor_buf, img->data,
img->width * img->height * 4);
@@ -2452,78 +2547,49 @@ static int mdss_mdp_hw_cursor_update(struct msm_fb_data_type *mfd,
}
cursor_addr = mfd->cursor_buf_phys;
}
-
- if (img->bg_color == 0xffffffff)
- transp_en = 0;
- else
- transp_en = 1;
-
- alpha = (img->fg_color & 0xff000000) >> 24;
-
- if (alpha)
- calpha_en = 0x0; /* xrgb */
- else
- calpha_en = 0x2; /* argb */
-
- size = (img->height << 16) | img->width;
- mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_IMG_SIZE, size);
- mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_SIZE, roi_size);
- mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_STRIDE,
- img->width * 4);
- mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_BASE_ADDR,
- cursor_addr);
-
- wmb();
-
- blendcfg &= ~0x1;
- blendcfg |= (transp_en << 3) | (calpha_en << 1);
- mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_BLEND_CONFIG,
- blendcfg);
- if (calpha_en)
- mdp_mixer_write(mixer,
- MDSS_MDP_REG_LM_CURSOR_BLEND_PARAM,
- alpha);
-
- if (transp_en) {
- mdp_mixer_write(mixer,
- MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_LOW0,
- ((img->bg_color & 0xff00) << 8) |
- (img->bg_color & 0xff));
- mdp_mixer_write(mixer,
- MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_LOW1,
- ((img->bg_color & 0xff0000) >> 16));
- mdp_mixer_write(mixer,
- MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_HIGH0,
- ((img->bg_color & 0xff00) << 8) |
- (img->bg_color & 0xff));
- mdp_mixer_write(mixer,
- MDSS_MDP_REG_LM_CURSOR_BLEND_TRANSP_HIGH1,
- ((img->bg_color & 0xff0000) >> 16));
- }
-
- mixer->cursor_hotx = 0;
- mixer->cursor_hoty = 0;
- }
-
- if (!cursor->enable != !(blendcfg & 0x1)) {
- if (cursor->enable) {
- pr_debug("enable hw cursor on mixer=%d\n", mixer->num);
- blendcfg |= 0x1;
- } else {
- pr_debug("disable hw cursor on mixer=%d\n", mixer->num);
- blendcfg &= ~0x1;
- }
-
- mdp_mixer_write(mixer, MDSS_MDP_REG_LM_CURSOR_BLEND_CONFIG,
- blendcfg);
-
- mixer->cursor_enabled = cursor->enable;
- mixer->params_changed++;
+ mdss_mdp_hw_cursor_setimage(mixer_left, cursor, cursor_addr,
+ &roi);
+ if (is_split_lm(mfd))
+ mdss_mdp_hw_cursor_setimage(mixer_right, cursor,
+ cursor_addr, &roi);
+ }
+
+ if ((start_x + roi.w) <= left_lm_w) {
+ if (cursor->set & FB_CUR_SETPOS)
+ mdss_mdp_hw_cursor_setpos(mixer_left, &roi, start_x,
+ start_y);
+ mdss_mdp_hw_cursor_blend_config(mixer_left, cursor);
+ cursor->enable = false;
+ mdss_mdp_hw_cursor_blend_config(mixer_right, cursor);
+ } else if (start_x >= left_lm_w) {
+ start_x -= left_lm_w;
+ if (cursor->set & FB_CUR_SETPOS)
+ mdss_mdp_hw_cursor_setpos(mixer_right, &roi, start_x,
+ start_y);
+ mdss_mdp_hw_cursor_blend_config(mixer_right, cursor);
+ cursor->enable = false;
+ mdss_mdp_hw_cursor_blend_config(mixer_left, cursor);
+ } else {
+ struct mdss_rect roi_right = roi;
+ roi.w = left_lm_w - start_x;
+ if (cursor->set & FB_CUR_SETPOS)
+ mdss_mdp_hw_cursor_setpos(mixer_left, &roi, start_x,
+ start_y);
+ mdss_mdp_hw_cursor_blend_config(mixer_left, cursor);
+
+ roi_right.x = 0;
+ roi_right.w = (start_x + roi_right.w) - left_lm_w;
+ start_x = 0;
+ if (cursor->set & FB_CUR_SETPOS)
+ mdss_mdp_hw_cursor_setpos(mixer_right, &roi_right,
+ start_x, start_y);
+ mdss_mdp_hw_cursor_blend_config(mixer_right, cursor);
}
- mixer->ctl->flush_bits |= BIT(6) << mixer->num;
+ mixer_left->ctl->flush_bits |= BIT(6) << mixer_left->num;
+ if (is_split_lm(mfd))
+ mixer_right->ctl->flush_bits |= BIT(6) << mixer_right->num;
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
-
return 0;
}