summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSree Sesha Aravind Vadrevu <svadrevu@codeaurora.org>2014-05-28 12:31:49 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:32:10 -0700
commitaaaa2ae7295759d9d6086267454000cf9574ca72 (patch)
tree996fd4d121c690a1e31f3e5d719b1bc051dd905c
parentfe4c3c2f7531c088c53b1274e72768f91d039494 (diff)
msm: mdss: add support for dedicated hardware cursor
Hardware cursor within mdss from mdss v1.5 onwards is programmed within the SSPP interface and is no longer a separate dedicated stage in the layer mixer. Cursor needs to be staged onto the existing layer mixer stages and always at the top level available. From this version onwards, cursors are expected to be programmed through the overlay interface by the user. Change-Id: Ia225dd92079e0153e9677ff035cf8531e62d5554 Signed-off-by: Sree Sesha Aravind Vadrevu <svadrevu@codeaurora.org> Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
-rw-r--r--Documentation/devicetree/bindings/fb/mdss-mdp.txt14
-rw-r--r--drivers/video/fbdev/msm/mdss.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c48
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c8
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_hwio.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c20
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pipe.c17
-rw-r--r--include/uapi/linux/msm_mdp.h2
9 files changed, 108 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index af2a2de11a34..0bbf724d6653 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -81,6 +81,18 @@ Required properties
offset within status register. Number of tuples
defined should match the number of offsets
defined in property: qcom,mdss-pipe-dma-off
+- qcom,mdss-pipe-cursor-off: Array of offsets for MDP source surface pipes of
+ type cursor, the offsets are calculated from
+ register "mdp_phys" defined in reg property.
+ The number of offsets defined here should
+ reflect the amount of cursor pipes that can be
+ active in MDP for this configuration. Meant for
+ hardware that has hw cursors support as a
+ source pipe.
+- qcom,mdss-pipe-cursor-xin-id: Array of VBIF clients ids (xins) corresponding
+ to the respective cursor pipes. Number of xin ids
+ defined should match the number of offsets
+ defined in property: qcom,mdss-pipe-cursor-off
- qcom,mdss-ctl-off: Array of offset addresses for the available ctl
hw blocks within MDP, these offsets are
calculated from register "mdp_phys" defined in
@@ -472,6 +484,7 @@ Example:
qcom,mdss-pipe-rgb-off = <0x00001E00 0x00002200
0x00002600>;
qcom,mdss-pipe-dma-off = <0x00002A00 0x00002E00>;
+ qcom,mdss-pipe-cursor-off = <0x00035000 0x00037000>;
qcom,mdss-pipe-vig-fetch-id = <1 4 7>;
qcom,mdss-pipe-rgb-fetch-id = <16 17 18>;
qcom,mdss-pipe-dma-fetch-id = <10 13>;
@@ -502,6 +515,7 @@ Example:
qcom,mdss-pipe-vig-xin-id = <0 4 8>;
qcom,mdss-pipe-rgb-xin-id = <1 5 9>;
qcom,mdss-pipe-dma-xin-id = <2 10>;
+ qcom,mdss-pipe-cursor-xin-id = <7 7>;
qcom,mdss-pipe-vig-clk-ctrl-offsets = <0x3AC 0 0>,
<0x3B4 0 0>,
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index 33ec9369ba79..1a766d6ad3cf 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -190,10 +190,13 @@ struct mdss_data_type {
struct mdss_mdp_pipe *vig_pipes;
struct mdss_mdp_pipe *rgb_pipes;
struct mdss_mdp_pipe *dma_pipes;
+ struct mdss_mdp_pipe *cursor_pipes;
u32 nvig_pipes;
u32 nrgb_pipes;
u32 ndma_pipes;
u32 max_target_zorder;
+ u8 ncursor_pipes;
+ u32 max_cursor_size;
DECLARE_BITMAP(mmb_alloc_map, MAX_DRV_SUP_MMB_BLKS);
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c
index 6c353809418b..f88424606522 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -1086,13 +1086,16 @@ static int mdss_mdp_debug_init(struct mdss_data_type *mdata)
return 0;
}
-static void mdss_mdp_max_zorder_init(struct mdss_data_type *mdata)
+static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
{
- mdata->max_target_zorder = MDSS_MDP_STAGE_4;
switch (mdata->mdp_rev) {
case MDSS_MDP_HW_REV_105:
mdata->max_target_zorder = MDSS_MDP_MAX_STAGE;
+ mdata->max_cursor_size = 128;
break;
+ default:
+ mdata->max_target_zorder = MDSS_MDP_STAGE_4;
+ mdata->max_cursor_size = 64;
}
}
@@ -1104,7 +1107,7 @@ static void mdss_hw_rev_init(struct mdss_data_type *mdata)
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
mdata->mdp_rev = MDSS_REG_READ(mdata, MDSS_REG_HW_VERSION);
pr_info_once("MDP Rev=%x\n", mdata->mdp_rev);
- mdss_mdp_max_zorder_init(mdata);
+ mdss_mdp_hw_rev_caps_init(mdata);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
}
@@ -1373,6 +1376,7 @@ static ssize_t mdss_mdp_show_capabilities(struct device *dev,
SPRINT("vig_pipes=%d\n", mdata->nvig_pipes);
SPRINT("dma_pipes=%d\n", mdata->ndma_pipes);
SPRINT("blending_stages=%d\n", mdata->max_target_zorder);
+ SPRINT("cursor_pipes=%d\n", mdata->ncursor_pipes);
SPRINT("smp_count=%d\n", mdata->smp_mb_cnt);
SPRINT("smp_size=%d\n", mdata->smp_mb_size);
SPRINT("smp_mb_per_pipe=%d\n", mdata->smp_mb_per_pipe);
@@ -1803,7 +1807,7 @@ error:
static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev)
{
u32 npipes, dma_off;
- int rc = 0;
+ int rc = 0, i;
u32 nfids = 0, setup_cnt = 0, len, nxids = 0;
u32 *offsets = NULL, *ftch_id = NULL, *xin_id = NULL;
u32 sw_reset_offset = 0;
@@ -1819,6 +1823,8 @@ static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev)
"qcom,mdss-pipe-rgb-off");
mdata->ndma_pipes = mdss_mdp_parse_dt_prop_len(pdev,
"qcom,mdss-pipe-dma-off");
+ mdata->ncursor_pipes = mdss_mdp_parse_dt_prop_len(pdev,
+ "qcom,mdss-pipe-cursor-off");
npipes = mdata->nvig_pipes + mdata->nrgb_pipes + mdata->ndma_pipes;
@@ -2055,9 +2061,43 @@ static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev)
mdata->dma_pipes, mdata->ndma_pipes);
}
+ if (mdata->ncursor_pipes) {
+ mdata->cursor_pipes = devm_kzalloc(&mdata->pdev->dev,
+ sizeof(struct mdss_mdp_pipe) * mdata->nvig_pipes,
+ GFP_KERNEL);
+
+ if (!mdata->cursor_pipes) {
+ pr_err("no mem for cursor_pipes: kzalloc fail\n");
+ rc = -ENOMEM;
+ goto cursor_alloc_fail;
+ }
+ rc = mdss_mdp_parse_dt_handler(pdev,
+ "qcom,mdss-pipe-cursor-off", offsets,
+ mdata->ncursor_pipes);
+ if (rc)
+ goto parse_fail;
+
+ rc = mdss_mdp_parse_dt_handler(pdev,
+ "qcom,mdss-pipe-dma-xin-id", xin_id,
+ mdata->ncursor_pipes);
+ if (rc)
+ goto parse_fail;
+ /* set the fetch id to an invalid value */
+ for (i = 0; i < mdata->ncursor_pipes; i++)
+ ftch_id[i] = -1;
+ rc = mdss_mdp_pipe_addr_setup(mdata, mdata->cursor_pipes,
+ offsets, ftch_id, xin_id, MDSS_MDP_PIPE_TYPE_CURSOR,
+ MDSS_MDP_SSPP_CURSOR0, mdata->ncursor_pipes, 0);
+ if (rc)
+ goto parse_fail;
+ pr_info("dedicated vp cursors detected, num=%d\n",
+ mdata->ncursor_pipes);
+ }
goto parse_done;
parse_fail:
+ kfree(mdata->cursor_pipes);
+cursor_alloc_fail:
kfree(mdata->dma_pipes);
dma_alloc_fail:
kfree(mdata->rgb_pipes);
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 101f95fb081b..2109bfbdfc3c 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -92,6 +92,7 @@ enum mdss_mdp_pipe_type {
MDSS_MDP_PIPE_TYPE_VIG,
MDSS_MDP_PIPE_TYPE_RGB,
MDSS_MDP_PIPE_TYPE_DMA,
+ MDSS_MDP_PIPE_TYPE_CURSOR,
};
enum mdss_mdp_block_type {
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 4b8e3ec60142..e1eeee681eaf 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -2372,6 +2372,9 @@ static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,
pipe->num == MDSS_MDP_SSPP_RGB3) {
/* Add 2 to account for Cursor & Border bits */
mixercfg = 1 << ((3 * pipe->num)+2);
+ } else if (pipe->type == MDSS_MDP_PIPE_TYPE_CURSOR) {
+ mixercfg_extn = BIT(20 + (6 *
+ (pipe->num - MDSS_MDP_SSPP_CURSOR0)));
} else {
mixercfg = 1 << (3 * pipe->num);
}
@@ -2471,6 +2474,9 @@ static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,
pipe->num == MDSS_MDP_SSPP_RGB3) {
/* Add 2 to account for Cursor & Border bits */
mixercfg |= stage << ((3 * pipe->num)+2);
+ } else if (pipe->type == MDSS_MDP_PIPE_TYPE_CURSOR) {
+ mixercfg_extn |= stage << (20 + (6 *
+ (pipe->num - MDSS_MDP_SSPP_CURSOR0)));
} else if (stage < MDSS_MDP_STAGE_6) {
mixercfg |= stage << (3 * pipe->num);
} else {
@@ -2749,6 +2755,8 @@ int mdss_mdp_mixer_pipe_update(struct mdss_mdp_pipe *pipe,
else if (pipe->num == MDSS_MDP_SSPP_VIG3 ||
pipe->num == MDSS_MDP_SSPP_RGB3)
ctl->flush_bits |= BIT(pipe->num) << 10;
+ else if (pipe->type == MDSS_MDP_PIPE_TYPE_CURSOR)
+ ctl->flush_bits |= BIT(22 + pipe->num - MDSS_MDP_SSPP_CURSOR0);
else /* RGB/VIG 0-2 pipes */
ctl->flush_bits |= BIT(pipe->num);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
index 9701589afa56..5e7b07272feb 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h
+++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
@@ -163,6 +163,8 @@ enum mdss_mdp_sspp_index {
MDSS_MDP_SSPP_DMA1,
MDSS_MDP_SSPP_VIG3,
MDSS_MDP_SSPP_RGB3,
+ MDSS_MDP_SSPP_CURSOR0,
+ MDSS_MDP_SSPP_CURSOR1,
MDSS_MDP_MAX_SSPP
};
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 5ac40c27b4b1..40730ea0b46a 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -248,6 +248,19 @@ int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
return -ERANGE;
}
+ /*
+ * Cursor overlays are only supported for targets
+ * with dedicated cursors within VP
+ */
+ if ((req->pipe_type == MDSS_MDP_PIPE_TYPE_CURSOR) &&
+ ((req->z_order != mdata->max_target_zorder) ||
+ !mdata->ncursor_pipes ||
+ (req->src_rect.w > mdata->max_cursor_size))) {
+ pr_err("Inccorect cursor overlay cursor_pipes=%d zorder=%d\n",
+ mdata->ncursor_pipes, req->z_order);
+ return -EINVAL;
+ }
+
if (req->src.width > MAX_IMG_WIDTH ||
req->src.height > MAX_IMG_HEIGHT ||
req->src_rect.w < min_src_size || req->src_rect.h < min_src_size ||
@@ -579,6 +592,9 @@ int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
case PIPE_TYPE_DMA:
pipe_type = MDSS_MDP_PIPE_TYPE_DMA;
break;
+ case PIPE_TYPE_CURSOR:
+ pipe_type = MDSS_MDP_PIPE_TYPE_CURSOR;
+ break;
case PIPE_TYPE_AUTO:
default:
if (req->flags & MDP_OV_PIPE_FORCE_DMA)
@@ -776,6 +792,9 @@ int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
req->priority = pipe->priority;
pipe->req_data = *req;
+ if (pipe->type == MDSS_MDP_PIPE_TYPE_CURSOR)
+ goto cursor_done;
+
if (pipe->flags & MDP_OVERLAY_PP_CFG_EN) {
memcpy(&pipe->pp_cfg, &req->overlay_pp_cfg,
sizeof(struct mdp_overlay_pp_params));
@@ -868,6 +887,7 @@ int mdss_mdp_overlay_pipe_setup(struct msm_fb_data_type *mfd,
goto exit_fail;
}
+cursor_done:
pipe->params_changed++;
pipe->has_buf = 0;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
index 8c63eb879f97..8765d1c1c47c 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
@@ -681,6 +681,11 @@ static struct mdss_mdp_pipe *mdss_mdp_pipe_init(struct mdss_mdp_mixer *mixer,
pipe_share = true;
break;
+ case MDSS_MDP_PIPE_TYPE_CURSOR:
+ pipe_pool = mdata->cursor_pipes;
+ npipes = mdata->ncursor_pipes;
+ break;
+
default:
npipes = 0;
pr_err("invalid pipe type %d\n", type);
@@ -696,6 +701,9 @@ static struct mdss_mdp_pipe *mdss_mdp_pipe_init(struct mdss_mdp_mixer *mixer,
pipe = NULL;
}
+ if (type == MDSS_MDP_PIPE_TYPE_CURSOR)
+ goto cursor_done;
+
if (left_blend_pipe && pipe &&
pipe->priority <= left_blend_pipe->priority) {
pr_debug("priority limitation. l_pipe_prio:%d r_pipe_prio:%d\n",
@@ -747,10 +755,12 @@ static struct mdss_mdp_pipe *mdss_mdp_pipe_init(struct mdss_mdp_mixer *mixer,
return NULL;
kref_get(&pipe->kref);
pr_debug("pipe sharing for pipe=%d\n", pipe->num);
- } else {
- pr_err("no %d type pipes available\n", type);
}
+cursor_done:
+ if (!pipe)
+ pr_err("no %d type pipes available\n", type);
+
return pipe;
}
@@ -1524,7 +1534,8 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
goto update_nobuf;
}
- mdss_mdp_smp_alloc(pipe);
+ if (pipe->type != MDSS_MDP_PIPE_TYPE_CURSOR)
+ mdss_mdp_smp_alloc(pipe);
ret = mdss_mdp_src_addr_setup(pipe, src_data);
if (ret) {
pr_err("addr setup error for pnum=%d\n", pipe->num);
diff --git a/include/uapi/linux/msm_mdp.h b/include/uapi/linux/msm_mdp.h
index 18d085f94570..5b8ba25d30f4 100644
--- a/include/uapi/linux/msm_mdp.h
+++ b/include/uapi/linux/msm_mdp.h
@@ -560,6 +560,7 @@ struct mdp_scale_data {
* @PIPE_TYPE_VIG: VIG pipe.
* @PIPE_TYPE_RGB: RGB pipe.
* @PIPE_TYPE_DMA: DMA pipe.
+ * @PIPE_TYPE_CURSOR: CURSOR pipe.
* @PIPE_TYPE_MAX: Used to track maximum number of pipe type.
*/
enum mdp_overlay_pipe_type {
@@ -567,6 +568,7 @@ enum mdp_overlay_pipe_type {
PIPE_TYPE_VIG,
PIPE_TYPE_RGB,
PIPE_TYPE_DMA,
+ PIPE_TYPE_CURSOR,
PIPE_TYPE_MAX,
};