summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/msm/Makefile1
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_intf.c14
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_intf.h1
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_lm.c4
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdp_ctl.h1
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdp_top.c110
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdp_top.h66
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_sspp.c2
8 files changed, 193 insertions, 6 deletions
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 7c73657b399e..b7fa5c05e12d 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -89,5 +89,6 @@ obj-$(CONFIG_DRM_MSM) += sde/sde_hw_catalog.o \
sde/sde_hw_sspp.o \
sde/sde_hw_wb.o \
sde/sde_hw_pingpong.o \
+ sde/sde_hw_mdp_top.o \
sde/sde_hw_interrupts.o \
sde/sde_mdp_formats.o
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_intf.c b/drivers/gpu/drm/msm/sde/sde_hw_intf.c
index 072cb6770bc8..8dd306720e90 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_intf.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_intf.c
@@ -13,6 +13,7 @@
#include "sde_hwio.h"
#include "sde_hw_catalog.h"
#include "sde_hw_intf.h"
+#include "sde_hw_mdp_top.h"
#define INTF_TIMING_ENGINE_EN 0x000
#define INTF_CONFIG 0x004
@@ -205,10 +206,16 @@ static void sde_hw_intf_enable_timing_engine(
/* Display interface select */
if (enable) {
- intf_sel = SDE_REG_READ(c, DISP_INTF_SEL);
+ /* top block */
+ struct sde_hw_mdp *mdp = sde_hw_mdptop_init(MDP_TOP,
+ c->base_off,
+ intf->mdss);
+ struct sde_hw_blk_reg_map *top = &mdp->hw;
- intf_sel |= (intf->cap->type << ((intf->idx) * 8));
- SDE_REG_WRITE(c, DISP_INTF_SEL, intf_sel);
+ intf_sel = SDE_REG_READ(top, DISP_INTF_SEL);
+
+ intf_sel |= (intf->cap->type << ((intf->idx - INTF_0) * 8));
+ SDE_REG_WRITE(top, DISP_INTF_SEL, intf_sel);
}
SDE_REG_WRITE(c, INTF_TIMING_ENGINE_EN,
@@ -366,6 +373,7 @@ struct sde_hw_intf *sde_hw_intf_init(enum sde_intf idx,
*/
c->idx = idx;
c->cap = cfg;
+ c->mdss = m;
_setup_intf_ops(&c->ops, c->cap->features);
/*
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_intf.h b/drivers/gpu/drm/msm/sde/sde_hw_intf.h
index 2dc8c52209f0..2de57868901a 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_intf.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_intf.h
@@ -85,6 +85,7 @@ struct sde_hw_intf {
/* intf */
enum sde_intf idx;
const struct sde_intf_cfg *cap;
+ const struct sde_mdss_cfg *mdss;
/* ops */
struct sde_hw_intf_ops ops;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_lm.c b/drivers/gpu/drm/msm/sde/sde_hw_lm.c
index 03704ddf4980..56ebe8fa05b5 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_lm.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_lm.c
@@ -76,7 +76,7 @@ static void sde_hw_lm_setup_out(struct sde_hw_mixer *ctx,
SDE_REG_WRITE(c, LM_OUT_SIZE, outsize);
/* SPLIT_LEFT_RIGHT */
- opmode = (opmode & ~(1 << 31)) | (mixer->right_mixer & 1 << 31);
+ opmode = (opmode & ~(1 << 31)) | ((mixer->right_mixer) ? (1 << 31) : 0);
SDE_REG_WRITE(c, LM_OP_MODE, opmode);
}
@@ -128,7 +128,7 @@ static void sde_hw_lm_setup_blendcfg(struct sde_hw_mixer *ctx,
fg->const_alpha);
SDE_REG_WRITE(c, LM_BLEND0_BG_ALPHA + stage_off,
bg->const_alpha);
- SDE_REG_WRITE(c, LM_OP_MODE, blend_op);
+ SDE_REG_WRITE(c, LM_BLEND0_OP + stage_off, blend_op);
}
static void sde_hw_lm_setup_color3(struct sde_hw_mixer *ctx,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdp_ctl.h b/drivers/gpu/drm/msm/sde/sde_hw_mdp_ctl.h
index d46064c57ba4..e914abd69906 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdp_ctl.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_mdp_ctl.h
@@ -14,6 +14,7 @@
#define _SDE_HW_MDP_CTL_H
#include "sde_hw_mdss.h"
+#include "sde_hw_mdp_util.h"
#include "sde_hw_catalog.h"
struct sde_hw_ctl;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.c b/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.c
new file mode 100644
index 000000000000..92c08fff2031
--- /dev/null
+++ b/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.c
@@ -0,0 +1,110 @@
+/* Copyright (c) 2015-2017, The Linux Foundation. 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "sde_hwio.h"
+#include "sde_hw_catalog.h"
+#include "sde_hw_mdp_top.h"
+
+#define SPLIT_DISPLAY_ENABLE 0x2F4
+#define LOWER_PIPE_CTRL 0x2F8
+#define UPPER_PIPE_CTRL 0x3F0
+#define TE_LINE_INTERVAL 0x3F4
+
+static void sde_hw_setup_split_pipe_control(struct sde_hw_mdp *mdp,
+ struct split_pipe_cfg *cfg)
+{
+ struct sde_hw_blk_reg_map *c = &mdp->hw;
+ u32 upper_pipe;
+ u32 lower_pipe;
+
+ if (cfg->en) {
+ upper_pipe = BIT(8);
+ lower_pipe = BIT(8);
+
+ if (cfg->mode == INTF_MODE_CMD) {
+ upper_pipe |= BIT(0);
+ lower_pipe |= BIT(0);
+ }
+
+ SDE_REG_WRITE(c, LOWER_PIPE_CTRL, lower_pipe);
+ SDE_REG_WRITE(c, UPPER_PIPE_CTRL, upper_pipe);
+ }
+
+ SDE_REG_WRITE(c, SPLIT_DISPLAY_ENABLE, cfg->en & 0x1);
+}
+
+static void _setup_mdp_ops(struct sde_hw_mdp_ops *ops,
+ unsigned long cap)
+{
+ ops->setup_split_pipe = sde_hw_setup_split_pipe_control;
+}
+
+static const struct sde_mdp_cfg *_top_offset(enum sde_mdp mdp,
+ const struct sde_mdss_cfg *m,
+ void __iomem *addr,
+ struct sde_hw_blk_reg_map *b)
+{
+ int i;
+
+ for (i = 0; i < m->mdp_count; i++) {
+ if (mdp == m->mdp[i].id) {
+ b->base_off = addr;
+ b->blk_off = m->mdp[i].base;
+ b->hwversion = m->hwversion;
+ return &m->mdp[i];
+ }
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+struct sde_hw_mdp *sde_hw_mdptop_init(enum sde_mdp idx,
+ void __iomem *addr,
+ const struct sde_mdss_cfg *m)
+{
+ static struct sde_hw_mdp *c;
+ const struct sde_mdp_cfg *cfg;
+
+ /* mdp top is singleton */
+ if (c) {
+ pr_err(" %s returning %pK", __func__, c);
+ return c;
+ }
+
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
+ pr_err(" %s returning %pK", __func__, c);
+ if (!c)
+ return ERR_PTR(-ENOMEM);
+
+ cfg = _top_offset(idx, m, addr, &c->hw);
+ if (IS_ERR_OR_NULL(cfg)) {
+ kfree(c);
+ return ERR_PTR(-EINVAL);
+ }
+
+ /*
+ * Assign ops
+ */
+ c->idx = idx;
+ c->cap = cfg;
+ _setup_mdp_ops(&c->ops, c->cap->features);
+
+ /*
+ * Perform any default initialization for the intf
+ */
+ return c;
+}
+
+void sde_hw_mdp_destroy(struct sde_hw_mdp *mdp)
+{
+}
+
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.h b/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.h
new file mode 100644
index 000000000000..216a27e93d46
--- /dev/null
+++ b/drivers/gpu/drm/msm/sde/sde_hw_mdp_top.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2015-2017, The Linux Foundation. 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _SDE_HW_MDP_TOP_H
+#define _SDE_HW_MDP_TOP_H
+
+#include "sde_hw_catalog.h"
+#include "sde_hw_mdss.h"
+#include "sde_hw_mdp_util.h"
+
+struct sde_hw_mdp;
+
+/**
+ * struct split_pipe_cfg - pipe configuration for dual display panels
+ * @en : Enable/disable dual pipe confguration
+ * @mode : Panel interface mode
+ */
+struct split_pipe_cfg {
+ bool en;
+ enum sde_intf_mode mode;
+};
+
+/**
+ * struct sde_hw_mdp_ops - interface to the MDP TOP Hw driver functions
+ * Assumption is these functions will be called after clocks are enabled.
+ * @setup_split_pipe : Programs the pipe control registers
+ */
+struct sde_hw_mdp_ops {
+ void (*setup_split_pipe)(struct sde_hw_mdp *mdp,
+ struct split_pipe_cfg *p);
+};
+
+struct sde_hw_mdp {
+ /* base */
+ struct sde_hw_blk_reg_map hw;
+
+ /* intf */
+ enum sde_mdp idx;
+ const struct sde_mdp_cfg *cap;
+
+ /* ops */
+ struct sde_hw_mdp_ops ops;
+};
+
+/**
+ * sde_hw_intf_init - initializes the intf driver for the passed interface idx
+ * @idx: Interface index for which driver object is required
+ * @addr: Mapped register io address of MDP
+ * @m: Pointer to mdss catalog data
+ */
+struct sde_hw_mdp *sde_hw_mdptop_init(enum sde_mdp idx,
+ void __iomem *addr,
+ const struct sde_mdss_cfg *m);
+
+void sde_hw_mdp_destroy(struct sde_hw_mdp *mdp);
+
+#endif /*_SDE_HW_MDP_TOP_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index 9a3d25423b8a..8180078ac950 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -414,7 +414,7 @@ static void sde_hw_sspp_setup_sourceaddress(struct sde_hw_pipe *ctx,
return;
for (i = 0; i < cfg->src.num_planes; i++)
- SDE_REG_WRITE(c, SSPP_SRC0_ADDR + idx + i*0x4,
+ SDE_REG_WRITE(c, SSPP_SRC0_ADDR + idx + i*0x4,
cfg->addr.plane[i]);
}