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]); }