summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/fb/mdss-mdp.txt22
-rw-r--r--drivers/video/fbdev/msm/mdss.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c54
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h10
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_hwio.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pipe.c33
-rw-r--r--include/uapi/linux/msm_mdp.h2
7 files changed, 122 insertions, 2 deletions
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 964d3060ac31..9c9cbbd49c41 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -338,6 +338,23 @@ Fudge Factors: Fudge factors are used to boost demand for
command mode panels.
- qcom,max-bandwidth-per-pipe-kbps: This value indicates the max bandwidth in KB
that a single pipe can support without underflow.
+- qcom,mdss-has-panic-ctrl: Boolean property to indicate if panic/robust signal
+ control feature is available or not.
+- qcom,mdss-pipe-vig-panic-ctrl-offsets: Array of panic/robust signal offsets
+ corresponding to the respective VIG pipes.
+ Number of signal offsets should match the
+ number of offsets defined in property:
+ qcom,mdss-pipe-vig-off
+- qcom,mdss-pipe-rgb-panic-ctrl-offsets: Array of panic/robust signal offsets
+ corresponding to the respective RGB pipes.
+ Number of signal offsets should match the
+ number of offsets defined in property:
+ qcom,mdss-pipe-rgb-off
+- qcom,mdss-pipe-dma-panic-ctrl-offsets: Array of panic/robust signal offsets
+ corresponding to the respective DMA pipes.
+ Number of signal offsets should match the
+ number of offsets defined in property:
+ qcom,mdss-pipe-dma-off
Optional subnodes:
Child nodes representing the frame buffer virtual devices.
@@ -464,6 +481,11 @@ Example:
qcom,mdss-pipe-dma-clk-ctrl-offsets = <0x3AC 8 12>,
<0x3B4 8 12>;
+ qcom,mdss-has-panic-ctrl;
+ qcom,mdss-pipe-vig-panic-ctrl-offsets = <0 1 2 3>;
+ qcom,mdss-pipe-rgb-panic-ctrl-offsets = <4 5 6 7>;
+ qcom,mdss-pipe-dma-panic-ctrl-offsets = <8 9>;
+
qcom,mdss-pipe-sw-reset-off = <0x0128>;
qcom,mdss-pipe-vig-sw-reset-map = <5 6 7 8>;
qcom,mdss-pipe-rgb-sw-reset-map = <9 10 11 12>;
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index 225fe345fffe..31f94e254e05 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -122,6 +122,7 @@ struct mdss_data_type {
u32 irq_buzy;
u32 has_bwc;
u32 has_decimation;
+ bool has_panic_ctrl;
u32 wfd_mode;
u32 has_no_lut_read;
u8 has_wb_ad;
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c
index 75f2e77a8c4d..307b3458b924 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -1726,6 +1726,46 @@ static int mdss_mdp_parse_dt_pipe_clk_ctrl(struct platform_device *pdev,
return rc;
}
+static void mdss_mdp_parse_dt_pipe_panic_ctrl(struct platform_device *pdev,
+ char *prop_name, struct mdss_mdp_pipe *pipe_list, u32 npipes)
+{
+ int rc = 0;
+ int i, j;
+ size_t len;
+ const u32 *arr;
+ struct mdss_mdp_pipe *pipe = NULL;
+ struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+
+ arr = of_get_property(pdev->dev.of_node, prop_name, (int *) &len);
+ if (arr) {
+ len /= sizeof(u32);
+ for (i = 0, j = 0; i < len; j++) {
+ if (j >= npipes) {
+ pr_err("invalid panic ctrl enries for prop: %s\n",
+ prop_name);
+ goto error;
+ }
+
+ pipe = &pipe_list[j];
+ pipe->panic_ctrl_ndx = be32_to_cpu(arr[i++]);
+ }
+ if (j != npipes) {
+ pr_err("%s: %d entries found. required %d\n",
+ prop_name, j, npipes);
+ rc = -EINVAL;
+ goto error;
+ }
+ } else {
+ pr_debug("panic ctrl enabled but property '%s' not found\n",
+ prop_name);
+ rc = -EINVAL;
+ }
+
+error:
+ if (rc)
+ mdata->has_panic_ctrl = false;
+}
+
static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev)
{
u32 npipes, dma_off;
@@ -1954,6 +1994,20 @@ static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev)
mdata->ndma_pipes);
}
+ mdata->has_panic_ctrl = of_property_read_bool(pdev->dev.of_node,
+ "qcom,mdss-has-panic-ctrl");
+ if (mdata->has_panic_ctrl) {
+ mdss_mdp_parse_dt_pipe_panic_ctrl(pdev,
+ "qcom,mdss-pipe-vig-panic-ctrl-offsets",
+ mdata->vig_pipes, mdata->nvig_pipes);
+ mdss_mdp_parse_dt_pipe_panic_ctrl(pdev,
+ "qcom,mdss-pipe-rgb-panic-ctrl-offsets",
+ mdata->rgb_pipes, mdata->nrgb_pipes);
+ mdss_mdp_parse_dt_pipe_panic_ctrl(pdev,
+ "qcom,mdss-pipe-dma-panic-ctrl-offsets",
+ mdata->dma_pipes, mdata->ndma_pipes);
+ }
+
goto parse_done;
parse_fail:
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 0ca1396b4d5b..398e34ad6310 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -368,6 +368,7 @@ struct mdss_mdp_pipe {
char __iomem *base;
u32 ftch_id;
u32 xin_id;
+ u32 panic_ctrl_ndx;
struct mdss_mdp_shared_reg_ctrl clk_ctrl;
struct mdss_mdp_shared_reg_ctrl clk_status;
struct mdss_mdp_shared_reg_ctrl sw_reset;
@@ -554,6 +555,14 @@ static inline int mdss_mdp_line_buffer_width(void)
return MAX_LINE_BUFFER_WIDTH;
}
+static inline int mdss_mdp_panic_signal_supported(
+ struct mdss_data_type *mdata, struct mdss_mdp_pipe *pipe)
+{
+ return (IS_MDSS_MAJOR_MINOR_SAME(mdata->mdp_rev, MDSS_MDP_HW_REV_105) &&
+ pipe->mixer_left &&
+ pipe->mixer_left->type == MDSS_MDP_MIXER_TYPE_INTF);
+}
+
irqreturn_t mdss_mdp_isr(int irq, void *ptr);
int mdss_iommu_attach(struct mdss_data_type *mdata);
int mdss_iommu_dettach(struct mdss_data_type *mdata);
@@ -726,6 +735,7 @@ int mdss_mdp_ctl_addr_setup(struct mdss_data_type *mdata, u32 *ctl_offsets,
u32 *wb_offsets, u32 len);
int mdss_mdp_pipe_fetch_halt(struct mdss_mdp_pipe *pipe);
+int mdss_mdp_pipe_panic_signal_ctrl(struct mdss_mdp_pipe *pipe, bool enable);
int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe);
int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
struct mdss_mdp_data *src_data);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
index 02f21a4ab85e..7fc4818444c6 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h
+++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
@@ -42,6 +42,8 @@
#define MDSS_MDP_REG_HIST_INTR_CLEAR 0x00024
#define MMSS_MDP_MDP_SSPP_SPARE_0 0x00028
+#define MMSS_MDP_PANIC_ROBUST_CTRL 0x00178
+
#define MDSS_MDP_REG_VIDEO_INTF_UNDERFLOW_CTL 0x002E0
#define MDSS_MDP_REG_SPLIT_DISPLAY_EN 0x002F4
#define MDSS_MDP_REG_SPLIT_DISPLAY_UPPER_PIPE_CTRL 0x002F8
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
index f899c7f558bb..35689008bbf4 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
@@ -53,6 +53,27 @@ static inline u32 mdss_mdp_pipe_read(struct mdss_mdp_pipe *pipe, u32 reg)
return readl_relaxed(pipe->base + reg);
}
+int mdss_mdp_pipe_panic_signal_ctrl(struct mdss_mdp_pipe *pipe, bool enable)
+{
+ uint32_t panic_robust_ctrl;
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
+ if (!mdata->has_panic_ctrl)
+ goto end;
+
+ panic_robust_ctrl = readl_relaxed(mdata->mdp_base +
+ MMSS_MDP_PANIC_ROBUST_CTRL);
+ if (enable)
+ panic_robust_ctrl |= BIT(pipe->panic_ctrl_ndx);
+ else
+ panic_robust_ctrl &= ~BIT(pipe->panic_ctrl_ndx);
+ writel_relaxed(panic_robust_ctrl,
+ mdata->mdp_base + MMSS_MDP_PANIC_ROBUST_CTRL);
+
+end:
+ return 0;
+}
+
static u32 mdss_mdp_smp_mmb_reserve(struct mdss_mdp_pipe_smp_map *smp_map,
size_t n)
{
@@ -609,6 +630,9 @@ static struct mdss_mdp_pipe *mdss_mdp_pipe_init(struct mdss_mdp_mixer *mixer,
return NULL;
}
+ if (pipe && mdss_mdp_pipe_panic_signal_ctrl(pipe, false))
+ return NULL;
+
if (pipe && mdss_mdp_pipe_is_sw_reset_available(mdata)) {
force_off_mask =
BIT(pipe->clk_ctrl.bit_off + CLK_FORCE_OFF_OFFSET);
@@ -759,15 +783,17 @@ static void mdss_mdp_pipe_free(struct kref *kref)
pr_debug("ndx=%x pnum=%d\n", pipe->ndx, pipe->num);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+ mdss_mdp_pipe_panic_signal_ctrl(pipe, false);
+
if (pipe->play_cnt) {
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
mdss_mdp_pipe_fetch_halt(pipe);
mdss_mdp_pipe_sspp_term(pipe);
mdss_mdp_smp_free(pipe);
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
} else {
mdss_mdp_smp_unreserve(pipe);
}
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
pipe->flags = 0;
pipe->is_right_blend = false;
@@ -1380,6 +1406,9 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG)
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_VIG_OP_MODE,
opmode);
+
+ if (mdss_mdp_panic_signal_supported(mdata, pipe))
+ mdss_mdp_pipe_panic_signal_ctrl(pipe, true);
}
if ((pipe->flags & MDP_VPU_PIPE) && (src_data == NULL ||
diff --git a/include/uapi/linux/msm_mdp.h b/include/uapi/linux/msm_mdp.h
index 0ea47d495353..8300297dec35 100644
--- a/include/uapi/linux/msm_mdp.h
+++ b/include/uapi/linux/msm_mdp.h
@@ -98,6 +98,8 @@
#define MDSS_MDP_HW_REV_102_1 MDSS_MDP_REV(1, 2, 1) /* 8974 v3.0 (Pro) */
#define MDSS_MDP_HW_REV_103 MDSS_MDP_REV(1, 3, 0) /* 8084 v1.0 */
#define MDSS_MDP_HW_REV_103_1 MDSS_MDP_REV(1, 3, 1) /* 8084 v1.1 */
+#define MDSS_MDP_HW_REV_105 MDSS_MDP_REV(1, 5, 0) /* 8994 v1.0 */
+#define MDSS_MDP_HW_REV_106 MDSS_MDP_REV(1, 6, 0) /* 8916 v1.0 */
#define MDSS_MDP_HW_REV_200 MDSS_MDP_REV(2, 0, 0) /* 8092 v1.0 */
enum {