summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/armada/armada_510.c130
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.c214
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.h21
-rw-r--r--drivers/gpu/drm/armada/armada_debugfs.c98
-rw-r--r--drivers/gpu/drm/armada/armada_drm.h1
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c38
-rw-r--r--drivers/gpu/drm/armada/armada_hw.h29
-rw-r--r--drivers/gpu/drm/armada/armada_overlay.c56
-rw-r--r--drivers/gpu/drm/armada/armada_plane.c124
-rw-r--r--drivers/gpu/drm/armada/armada_plane.h23
-rw-r--r--drivers/gpu/drm/bridge/ti-tfp410.c10
-rw-r--r--drivers/gpu/drm/exynos/Kconfig6
-rw-r--r--drivers/gpu/drm/exynos/exynos5433_drm_decon.c7
-rw-r--r--drivers/gpu/drm/exynos/exynos7_drm_decon.c8
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp.c13
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dma.c6
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dpi.c8
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h8
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c21
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c6
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c8
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c15
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c14
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c11
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c7
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gsc.c13
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.c3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_mic.c22
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_rotator.c10
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_scaler.c12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c9
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c41
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c31
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c24
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx.xml.h28
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_debugfs.c8
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c40
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_power.c76
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c70
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.h1
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c16
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.h2
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c20
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c8
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c176
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c14
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c5
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c110
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c46
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c57
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c6
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h22
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c4
-rw-r--r--drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c3
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c2
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c38
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c3
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c2
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.h7
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_cfg.c21
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_cfg.h1
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c19
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c149
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c6
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.h5
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c30
-rw-r--r--drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c106
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c34
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h1
-rw-r--r--drivers/gpu/drm/msm/msm_fb.c2
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c6
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h1
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c13
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c5
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.c2
-rw-r--r--drivers/gpu/drm/msm/msm_perf.c15
-rw-r--r--drivers/gpu/drm/msm/msm_rd.c16
-rw-r--r--drivers/gpu/vga/Kconfig1
85 files changed, 1393 insertions, 891 deletions
diff --git a/drivers/gpu/drm/armada/armada_510.c b/drivers/gpu/drm/armada/armada_510.c
index 0e91d27921bd..6f8ad8fb19f1 100644
--- a/drivers/gpu/drm/armada/armada_510.c
+++ b/drivers/gpu/drm/armada/armada_510.c
@@ -14,18 +14,62 @@
#include "armada_drm.h"
#include "armada_hw.h"
+struct armada510_variant_data {
+ struct clk *clks[4];
+ struct clk *sel_clk;
+};
+
static int armada510_crtc_init(struct armada_crtc *dcrtc, struct device *dev)
{
+ struct armada510_variant_data *v;
struct clk *clk;
+ int idx;
+
+ v = devm_kzalloc(dev, sizeof(*v), GFP_KERNEL);
+ if (!v)
+ return -ENOMEM;
+
+ dcrtc->variant_data = v;
+
+ if (dev->of_node) {
+ struct property *prop;
+ const char *s;
+
+ of_property_for_each_string(dev->of_node, "clock-names", prop,
+ s) {
+ if (!strcmp(s, "ext_ref_clk0"))
+ idx = 0;
+ else if (!strcmp(s, "ext_ref_clk1"))
+ idx = 1;
+ else if (!strcmp(s, "plldivider"))
+ idx = 2;
+ else if (!strcmp(s, "axibus"))
+ idx = 3;
+ else
+ continue;
+
+ clk = devm_clk_get(dev, s);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER :
+ PTR_ERR(clk);
+ v->clks[idx] = clk;
+ }
+ } else {
+ clk = devm_clk_get(dev, "ext_ref_clk1");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER :
+ PTR_ERR(clk);
+
+ v->clks[1] = clk;
+ }
- clk = devm_clk_get(dev, "ext_ref_clk1");
- if (IS_ERR(clk))
- return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER : PTR_ERR(clk);
-
- dcrtc->extclk[0] = clk;
-
- /* Lower the watermark so to eliminate jitter at higher bandwidths */
- armada_updatel(0x20, (1 << 11) | 0xff, dcrtc->base + LCD_CFG_RDREG4F);
+ /*
+ * Lower the watermark so to eliminate jitter at higher bandwidths.
+ * Disable SRAM read wait state to avoid system hang with external
+ * clock.
+ */
+ armada_updatel(CFG_DMA_WM(0x20), CFG_SRAM_WAIT | CFG_DMA_WM_MASK,
+ dcrtc->base + LCD_CFG_RDREG4F);
/* Initialise SPU register */
writel_relaxed(ADV_HWC32ENABLE | ADV_HWC32ARGB | ADV_HWC32BLEND,
@@ -34,65 +78,77 @@ static int armada510_crtc_init(struct armada_crtc *dcrtc, struct device *dev)
return 0;
}
+static const u32 armada510_clk_sels[] = {
+ SCLK_510_EXTCLK0,
+ SCLK_510_EXTCLK1,
+ SCLK_510_PLL,
+ SCLK_510_AXI,
+};
+
+static const struct armada_clocking_params armada510_clocking = {
+ /* HDMI requires -0.6%..+0.5% */
+ .permillage_min = 994,
+ .permillage_max = 1005,
+ .settable = BIT(0) | BIT(1),
+ .div_max = SCLK_510_INT_DIV_MASK,
+};
+
/*
* Armada510 specific SCLK register selection.
* This gets called with sclk = NULL to test whether the mode is
* supportable, and again with sclk != NULL to set the clocks up for
* that. The former can return an error, but the latter is expected
* not to.
- *
- * We currently are pretty rudimentary here, always selecting
- * EXT_REF_CLK_1 for LCD0 and erroring LCD1. This needs improvement!
*/
static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
const struct drm_display_mode *mode, uint32_t *sclk)
{
- struct clk *clk = dcrtc->extclk[0];
- int ret;
+ struct armada510_variant_data *v = dcrtc->variant_data;
+ unsigned long desired_khz = mode->crtc_clock;
+ struct armada_clk_result res;
+ int ret, idx;
- if (dcrtc->num == 1)
- return -EINVAL;
+ idx = armada_crtc_select_clock(dcrtc, &res, &armada510_clocking,
+ v->clks, ARRAY_SIZE(v->clks),
+ desired_khz);
+ if (idx < 0)
+ return idx;
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- if (dcrtc->clk != clk) {
- ret = clk_prepare_enable(clk);
- if (ret)
- return ret;
- dcrtc->clk = clk;
- }
+ ret = clk_prepare_enable(res.clk);
+ if (ret)
+ return ret;
if (sclk) {
- uint32_t rate, ref, div;
+ clk_set_rate(res.clk, res.desired_clk_hz);
- rate = mode->clock * 1000;
- ref = clk_round_rate(clk, rate);
- div = DIV_ROUND_UP(ref, rate);
- if (div < 1)
- div = 1;
+ *sclk = res.div | armada510_clk_sels[idx];
- clk_set_rate(clk, ref);
- *sclk = div | SCLK_510_EXTCLK1;
+ /* We are now using this clock */
+ v->sel_clk = res.clk;
+ swap(dcrtc->clk, res.clk);
}
+ clk_disable_unprepare(res.clk);
+
return 0;
}
static void armada510_crtc_disable(struct armada_crtc *dcrtc)
{
- if (!IS_ERR(dcrtc->clk)) {
+ if (dcrtc->clk) {
clk_disable_unprepare(dcrtc->clk);
- dcrtc->clk = ERR_PTR(-EINVAL);
+ dcrtc->clk = NULL;
}
}
static void armada510_crtc_enable(struct armada_crtc *dcrtc,
const struct drm_display_mode *mode)
{
- if (IS_ERR(dcrtc->clk)) {
- dcrtc->clk = dcrtc->extclk[0];
- WARN_ON(clk_prepare_enable(dcrtc->clk));
+ struct armada510_variant_data *v = dcrtc->variant_data;
+
+ if (!dcrtc->clk && v->sel_clk) {
+ if (!WARN_ON(clk_prepare_enable(v->sel_clk)))
+ dcrtc->clk = v->sel_clk;
}
}
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index ba4a3fab7745..2e17d7e72eeb 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -130,6 +130,70 @@ static void armada_drm_crtc_queue_state_event(struct drm_crtc *crtc)
}
}
+static void armada_drm_update_gamma(struct drm_crtc *crtc)
+{
+ struct drm_property_blob *blob = crtc->state->gamma_lut;
+ void __iomem *base = drm_to_armada_crtc(crtc)->base;
+ int i;
+
+ if (blob) {
+ struct drm_color_lut *lut = blob->data;
+
+ armada_updatel(CFG_CSB_256x8, CFG_CSB_256x8 | CFG_PDWN256x8,
+ base + LCD_SPU_SRAM_PARA1);
+
+ for (i = 0; i < 256; i++) {
+ writel_relaxed(drm_color_lut_extract(lut[i].red, 8),
+ base + LCD_SPU_SRAM_WRDAT);
+ writel_relaxed(i | SRAM_WRITE | SRAM_GAMMA_YR,
+ base + LCD_SPU_SRAM_CTRL);
+ readl_relaxed(base + LCD_SPU_HWC_OVSA_HPXL_VLN);
+ writel_relaxed(drm_color_lut_extract(lut[i].green, 8),
+ base + LCD_SPU_SRAM_WRDAT);
+ writel_relaxed(i | SRAM_WRITE | SRAM_GAMMA_UG,
+ base + LCD_SPU_SRAM_CTRL);
+ readl_relaxed(base + LCD_SPU_HWC_OVSA_HPXL_VLN);
+ writel_relaxed(drm_color_lut_extract(lut[i].blue, 8),
+ base + LCD_SPU_SRAM_WRDAT);
+ writel_relaxed(i | SRAM_WRITE | SRAM_GAMMA_VB,
+ base + LCD_SPU_SRAM_CTRL);
+ readl_relaxed(base + LCD_SPU_HWC_OVSA_HPXL_VLN);
+ }
+ armada_updatel(CFG_GAMMA_ENA, CFG_GAMMA_ENA,
+ base + LCD_SPU_DMA_CTRL0);
+ } else {
+ armada_updatel(0, CFG_GAMMA_ENA, base + LCD_SPU_DMA_CTRL0);
+ armada_updatel(CFG_PDWN256x8, CFG_CSB_256x8 | CFG_PDWN256x8,
+ base + LCD_SPU_SRAM_PARA1);
+ }
+}
+
+static enum drm_mode_status armada_drm_crtc_mode_valid(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode)
+{
+ struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+
+ if (mode->vscan > 1)
+ return MODE_NO_VSCAN;
+
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
+ if (mode->flags & DRM_MODE_FLAG_HSKEW)
+ return MODE_H_ILLEGAL;
+
+ /* We can't do interlaced modes if we don't have the SPU_ADV_REG */
+ if (!dcrtc->variant->has_spu_adv_reg &&
+ mode->flags & DRM_MODE_FLAG_INTERLACE)
+ return MODE_NO_INTERLACE;
+
+ if (mode->flags & (DRM_MODE_FLAG_BCAST | DRM_MODE_FLAG_PIXMUX |
+ DRM_MODE_FLAG_CLKDIV2))
+ return MODE_BAD;
+
+ return MODE_OK;
+}
+
/* The mode_config.mutex will be held for this call */
static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode, struct drm_display_mode *adj)
@@ -137,9 +201,18 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
int ret;
- /* We can't do interlaced modes if we don't have the SPU_ADV_REG */
- if (!dcrtc->variant->has_spu_adv_reg &&
- adj->flags & DRM_MODE_FLAG_INTERLACE)
+ /*
+ * Set CRTC modesetting parameters for the adjusted mode. This is
+ * applied after the connectors, bridges, and encoders have fixed up
+ * this mode, as described above drm_atomic_helper_check_modeset().
+ */
+ drm_mode_set_crtcinfo(adj, CRTC_INTERLACE_HALVE_V);
+
+ /*
+ * Validate the adjusted mode in case an encoder/bridge has set
+ * something we don't support.
+ */
+ if (armada_drm_crtc_mode_valid(crtc, adj) != MODE_OK)
return false;
/* Check whether the display mode is possible */
@@ -278,16 +351,9 @@ static void armada_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
armada_reg_queue_set(regs, i, sclk, LCD_CFG_SCLK_DIV);
- if (interlaced ^ dcrtc->interlaced) {
- if (adj->flags & DRM_MODE_FLAG_INTERLACE)
- drm_crtc_vblank_get(&dcrtc->crtc);
- else
- drm_crtc_vblank_put(&dcrtc->crtc);
- dcrtc->interlaced = interlaced;
- }
-
spin_lock_irqsave(&dcrtc->irq_lock, flags);
+ dcrtc->interlaced = interlaced;
/* Even interlaced/progressive frame */
dcrtc->v[1].spu_v_h_total = adj->crtc_vtotal << 16 |
adj->crtc_htotal;
@@ -345,6 +411,20 @@ static void armada_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
}
+static int armada_drm_crtc_atomic_check(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
+
+ if (state->gamma_lut && drm_color_lut_size(state->gamma_lut) != 256)
+ return -EINVAL;
+
+ if (state->color_mgmt_changed)
+ state->planes_changed = true;
+
+ return 0;
+}
+
static void armada_drm_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
@@ -352,6 +432,9 @@ static void armada_drm_crtc_atomic_begin(struct drm_crtc *crtc,
DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
+ if (crtc->state->color_mgmt_changed)
+ armada_drm_update_gamma(crtc);
+
dcrtc->regs_idx = 0;
dcrtc->regs = dcrtc->atomic_regs;
}
@@ -390,6 +473,9 @@ static void armada_drm_crtc_atomic_disable(struct drm_crtc *crtc,
DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
+ if (old_state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
+ drm_crtc_vblank_put(crtc);
+
drm_crtc_vblank_off(crtc);
armada_drm_crtc_update(dcrtc, false);
@@ -434,12 +520,17 @@ static void armada_drm_crtc_atomic_enable(struct drm_crtc *crtc,
armada_drm_crtc_update(dcrtc, true);
drm_crtc_vblank_on(crtc);
+ if (crtc->state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
+ WARN_ON(drm_crtc_vblank_get(crtc));
+
armada_drm_crtc_queue_state_event(crtc);
}
static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = {
+ .mode_valid = armada_drm_crtc_mode_valid,
.mode_fixup = armada_drm_crtc_mode_fixup,
.mode_set_nofb = armada_drm_crtc_mode_set_nofb,
+ .atomic_check = armada_drm_crtc_atomic_check,
.atomic_begin = armada_drm_crtc_atomic_begin,
.atomic_flush = armada_drm_crtc_atomic_flush,
.atomic_disable = armada_drm_crtc_atomic_disable,
@@ -460,6 +551,13 @@ static void armada_load_cursor_argb(void __iomem *base, uint32_t *pix,
for (x = 0; x < width; x++, p++) {
uint32_t val = *p;
+ /*
+ * In "ARGB888" (HWC32) mode, writing to the SRAM
+ * requires these bits to contain:
+ * 31:24 = alpha 23:16 = blue 15:8 = green 7:0 = red
+ * So, it's actually ABGR8888. This is independent
+ * of the SWAPRB bits in DMA control register 0.
+ */
val = (val & 0xff00ff00) |
(val & 0x000000ff) << 16 |
(val & 0x00ff0000) >> 16;
@@ -676,6 +774,14 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
kfree(dcrtc);
}
+static int armada_drm_crtc_late_register(struct drm_crtc *crtc)
+{
+ if (IS_ENABLED(CONFIG_DEBUG_FS))
+ armada_drm_crtc_debugfs_init(drm_to_armada_crtc(crtc));
+
+ return 0;
+}
+
/* These are called under the vbl_lock. */
static int armada_drm_crtc_enable_vblank(struct drm_crtc *crtc)
{
@@ -703,14 +809,93 @@ static const struct drm_crtc_funcs armada_crtc_funcs = {
.cursor_set = armada_drm_crtc_cursor_set,
.cursor_move = armada_drm_crtc_cursor_move,
.destroy = armada_drm_crtc_destroy,
+ .gamma_set = drm_atomic_helper_legacy_gamma_set,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+ .late_register = armada_drm_crtc_late_register,
.enable_vblank = armada_drm_crtc_enable_vblank,
.disable_vblank = armada_drm_crtc_disable_vblank,
};
+int armada_crtc_select_clock(struct armada_crtc *dcrtc,
+ struct armada_clk_result *res,
+ const struct armada_clocking_params *params,
+ struct clk *clks[], size_t num_clks,
+ unsigned long desired_khz)
+{
+ unsigned long desired_hz = desired_khz * 1000;
+ unsigned long desired_clk_hz; // requested clk input
+ unsigned long real_clk_hz; // actual clk input
+ unsigned long real_hz; // actual pixel clk
+ unsigned long permillage;
+ struct clk *clk;
+ u32 div;
+ int i;
+
+ DRM_DEBUG_KMS("[CRTC:%u:%s] desired clock=%luHz\n",
+ dcrtc->crtc.base.id, dcrtc->crtc.name, desired_hz);
+
+ for (i = 0; i < num_clks; i++) {
+ clk = clks[i];
+ if (!clk)
+ continue;
+
+ if (params->settable & BIT(i)) {
+ real_clk_hz = clk_round_rate(clk, desired_hz);
+ desired_clk_hz = desired_hz;
+ } else {
+ real_clk_hz = clk_get_rate(clk);
+ desired_clk_hz = real_clk_hz;
+ }
+
+ /* If the clock can do exactly the desired rate, we're done */
+ if (real_clk_hz == desired_hz) {
+ real_hz = real_clk_hz;
+ div = 1;
+ goto found;
+ }
+
+ /* Calculate the divider - if invalid, we can't do this rate */
+ div = DIV_ROUND_CLOSEST(real_clk_hz, desired_hz);
+ if (div == 0 || div > params->div_max)
+ continue;
+
+ /* Calculate the actual rate - HDMI requires -0.6%..+0.5% */
+ real_hz = DIV_ROUND_CLOSEST(real_clk_hz, div);
+
+ DRM_DEBUG_KMS("[CRTC:%u:%s] clk=%u %luHz div=%u real=%luHz\n",
+ dcrtc->crtc.base.id, dcrtc->crtc.name,
+ i, real_clk_hz, div, real_hz);
+
+ /* Avoid repeated division */
+ if (real_hz < desired_hz) {
+ permillage = real_hz / desired_khz;
+ if (permillage < params->permillage_min)
+ continue;
+ } else {
+ permillage = DIV_ROUND_UP(real_hz, desired_khz);
+ if (permillage > params->permillage_max)
+ continue;
+ }
+ goto found;
+ }
+
+ return -ERANGE;
+
+found:
+ DRM_DEBUG_KMS("[CRTC:%u:%s] selected clk=%u %luHz div=%u real=%luHz\n",
+ dcrtc->crtc.base.id, dcrtc->crtc.name,
+ i, real_clk_hz, div, real_hz);
+
+ res->desired_clk_hz = desired_clk_hz;
+ res->clk = clk;
+ res->div = div;
+
+ return i;
+}
+
static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
struct resource *res, int irq, const struct armada_variant *variant,
struct device_node *port)
@@ -737,7 +922,6 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
dcrtc->variant = variant;
dcrtc->base = base;
dcrtc->num = drm->mode_config.num_crtc;
- dcrtc->clk = ERR_PTR(-EINVAL);
dcrtc->cfg_dumb_ctrl = DUMB24_RGB888_0;
dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;
spin_lock_init(&dcrtc->irq_lock);
@@ -794,6 +978,12 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs);
+ ret = drm_mode_crtc_set_gamma_size(&dcrtc->crtc, 256);
+ if (ret)
+ return ret;
+
+ drm_crtc_enable_color_mgmt(&dcrtc->crtc, 0, false, 256);
+
return armada_overlay_plane_create(drm, 1 << dcrtc->num);
err_crtc_init:
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
index 08761ff01739..fb4aa48da60c 100644
--- a/drivers/gpu/drm/armada/armada_crtc.h
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -39,10 +39,10 @@ struct armada_variant;
struct armada_crtc {
struct drm_crtc crtc;
const struct armada_variant *variant;
+ void *variant_data;
unsigned num;
void __iomem *base;
struct clk *clk;
- struct clk *extclk[2];
struct {
uint32_t spu_v_h_total;
uint32_t spu_v_porch;
@@ -75,6 +75,25 @@ struct armada_crtc {
void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
+struct armada_clocking_params {
+ unsigned long permillage_min;
+ unsigned long permillage_max;
+ u32 settable;
+ u32 div_max;
+};
+
+struct armada_clk_result {
+ unsigned long desired_clk_hz;
+ struct clk *clk;
+ u32 div;
+};
+
+int armada_crtc_select_clock(struct armada_crtc *dcrtc,
+ struct armada_clk_result *res,
+ const struct armada_clocking_params *params,
+ struct clk *clks[], size_t num_clks,
+ unsigned long desired_khz);
+
extern struct platform_driver armada_lcd_platform_driver;
#endif
diff --git a/drivers/gpu/drm/armada/armada_debugfs.c b/drivers/gpu/drm/armada/armada_debugfs.c
index 6758c3a83de2..4dcce002ea2a 100644
--- a/drivers/gpu/drm/armada/armada_debugfs.c
+++ b/drivers/gpu/drm/armada/armada_debugfs.c
@@ -28,50 +28,33 @@ static int armada_debugfs_gem_linear_show(struct seq_file *m, void *data)
return 0;
}
-static int armada_debugfs_reg_show(struct seq_file *m, void *data)
+static int armada_debugfs_crtc_reg_show(struct seq_file *m, void *data)
{
- struct drm_device *dev = m->private;
- struct armada_private *priv = dev->dev_private;
- int n, i;
-
- if (priv) {
- for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
- struct armada_crtc *dcrtc = priv->dcrtc[n];
- if (!dcrtc)
- continue;
-
- for (i = 0x84; i <= 0x1c4; i += 4) {
- uint32_t v = readl_relaxed(dcrtc->base + i);
- seq_printf(m, "%u: 0x%04x: 0x%08x\n", n, i, v);
- }
- }
+ struct armada_crtc *dcrtc = m->private;
+ int i;
+
+ for (i = 0x84; i <= 0x1c4; i += 4) {
+ u32 v = readl_relaxed(dcrtc->base + i);
+ seq_printf(m, "0x%04x: 0x%08x\n", i, v);
}
return 0;
}
-static int armada_debugfs_reg_r_open(struct inode *inode, struct file *file)
+static int armada_debugfs_crtc_reg_open(struct inode *inode, struct file *file)
{
- return single_open(file, armada_debugfs_reg_show, inode->i_private);
+ return single_open(file, armada_debugfs_crtc_reg_show,
+ inode->i_private);
}
-static const struct file_operations fops_reg_r = {
- .owner = THIS_MODULE,
- .open = armada_debugfs_reg_r_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int armada_debugfs_write(struct file *file, const char __user *ptr,
- size_t len, loff_t *off)
+static int armada_debugfs_crtc_reg_write(struct file *file,
+ const char __user *ptr, size_t len, loff_t *off)
{
- struct drm_device *dev = file->private_data;
- struct armada_private *priv = dev->dev_private;
- struct armada_crtc *dcrtc = priv->dcrtc[0];
- char buf[32], *p;
- uint32_t reg, val;
+ struct armada_crtc *dcrtc;
+ unsigned long reg, mask, val;
+ char buf[32];
int ret;
+ u32 v;
if (*off != 0)
return 0;
@@ -84,24 +67,35 @@ static int armada_debugfs_write(struct file *file, const char __user *ptr,
return ret;
buf[len] = '\0';
- reg = simple_strtoul(buf, &p, 16);
- if (!isspace(*p))
+ if (sscanf(buf, "%lx %lx %lx", &reg, &mask, &val) != 3)
return -EINVAL;
- val = simple_strtoul(p + 1, NULL, 16);
+ if (reg < 0x84 || reg > 0x1c4 || reg & 3)
+ return -ERANGE;
- if (reg >= 0x84 && reg <= 0x1c4)
- writel(val, dcrtc->base + reg);
+ dcrtc = ((struct seq_file *)file->private_data)->private;
+ v = readl(dcrtc->base + reg);
+ v &= ~mask;
+ v |= val & mask;
+ writel(v, dcrtc->base + reg);
return len;
}
-static const struct file_operations fops_reg_w = {
+static const struct file_operations armada_debugfs_crtc_reg_fops = {
.owner = THIS_MODULE,
- .open = simple_open,
- .write = armada_debugfs_write,
- .llseek = noop_llseek,
+ .open = armada_debugfs_crtc_reg_open,
+ .read = seq_read,
+ .write = armada_debugfs_crtc_reg_write,
+ .llseek = seq_lseek,
+ .release = single_release,
};
+void armada_drm_crtc_debugfs_init(struct armada_crtc *dcrtc)
+{
+ debugfs_create_file("armada-regs", 0600, dcrtc->crtc.debugfs_entry,
+ dcrtc, &armada_debugfs_crtc_reg_fops);
+}
+
static struct drm_info_list armada_debugfs_list[] = {
{ "gem_linear", armada_debugfs_gem_linear_show, 0 },
};
@@ -109,24 +103,8 @@ static struct drm_info_list armada_debugfs_list[] = {
int armada_drm_debugfs_init(struct drm_minor *minor)
{
- struct dentry *de;
- int ret;
-
- ret = drm_debugfs_create_files(armada_debugfs_list,
- ARMADA_DEBUGFS_ENTRIES,
- minor->debugfs_root, minor);
- if (ret)
- return ret;
-
- de = debugfs_create_file("reg", S_IFREG | S_IRUSR,
- minor->debugfs_root, minor->dev, &fops_reg_r);
- if (!de)
- return -ENOMEM;
-
- de = debugfs_create_file("reg_wr", S_IFREG | S_IWUSR,
- minor->debugfs_root, minor->dev, &fops_reg_w);
- if (!de)
- return -ENOMEM;
+ drm_debugfs_create_files(armada_debugfs_list, ARMADA_DEBUGFS_ENTRIES,
+ minor->debugfs_root, minor);
return 0;
}
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index f09083ff15d3..b6307235f320 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -78,6 +78,7 @@ void armada_fbdev_fini(struct drm_device *);
int armada_overlay_plane_create(struct drm_device *, unsigned long);
+void armada_drm_crtc_debugfs_init(struct armada_crtc *dcrtc);
int armada_drm_debugfs_init(struct drm_minor *);
#endif
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index e660c5ca52ae..f1729398b1bd 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -100,6 +100,17 @@ static int armada_drm_bind(struct device *dev)
return ret;
}
+ /* Remove early framebuffers */
+ ret = drm_fb_helper_remove_conflicting_framebuffers(NULL,
+ "armada-drm-fb",
+ false);
+ if (ret) {
+ dev_err(dev, "[" DRM_NAME ":%s] can't kick out simple-fb: %d\n",
+ __func__, ret);
+ kfree(priv);
+ return ret;
+ }
+
priv->drm.dev_private = priv;
dev_set_drvdata(dev, &priv->drm);
@@ -171,6 +182,8 @@ static void armada_drm_unbind(struct device *dev)
drm_dev_unregister(&priv->drm);
+ drm_atomic_helper_shutdown(&priv->drm);
+
component_unbind_all(dev, &priv->drm);
drm_mode_config_cleanup(&priv->drm);
@@ -191,23 +204,15 @@ static int compare_dev_name(struct device *dev, void *data)
}
static void armada_add_endpoints(struct device *dev,
- struct component_match **match, struct device_node *port)
+ struct component_match **match, struct device_node *dev_node)
{
struct device_node *ep, *remote;
- for_each_child_of_node(port, ep) {
+ for_each_endpoint_of_node(dev_node, ep) {
remote = of_graph_get_remote_port_parent(ep);
- if (!remote || !of_device_is_available(remote)) {
- of_node_put(remote);
- continue;
- } else if (!of_device_is_available(remote->parent)) {
- dev_warn(dev, "parent device of %pOF is not available\n",
- remote);
- of_node_put(remote);
- continue;
- }
-
- drm_of_component_match_add(dev, match, compare_of, remote);
+ if (remote && of_device_is_available(remote))
+ drm_of_component_match_add(dev, match, compare_of,
+ remote);
of_node_put(remote);
}
}
@@ -229,7 +234,6 @@ static int armada_drm_probe(struct platform_device *pdev)
if (dev->platform_data) {
char **devices = dev->platform_data;
- struct device_node *port;
struct device *d;
int i;
@@ -245,10 +249,8 @@ static int armada_drm_probe(struct platform_device *pdev)
for (i = 0; devices[i]; i++) {
d = bus_find_device_by_name(&platform_bus_type, NULL,
devices[i]);
- if (d && d->of_node) {
- for_each_child_of_node(d->of_node, port)
- armada_add_endpoints(dev, &match, port);
- }
+ if (d && d->of_node)
+ armada_add_endpoints(dev, &match, d->of_node);
put_device(d);
}
}
diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h
index 277580b36758..5b1af0cc9f50 100644
--- a/drivers/gpu/drm/armada/armada_hw.h
+++ b/drivers/gpu/drm/armada/armada_hw.h
@@ -88,6 +88,16 @@ enum {
ADV_VSYNC_H_OFF = 0xfff << 0,
};
+/* LCD_CFG_RDREG4F - Armada 510 only */
+enum {
+ CFG_SRAM_WAIT = BIT(11),
+ CFG_SMPN_FASTTX = BIT(10),
+ CFG_DMA_ARB = BIT(9),
+ CFG_DMA_WM_EN = BIT(8),
+ CFG_DMA_WM_MASK = 0xff,
+#define CFG_DMA_WM(x) ((x) & CFG_DMA_WM_MASK)
+};
+
enum {
CFG_565 = 0,
CFG_1555 = 1,
@@ -169,6 +179,10 @@ enum {
SRAM_READ = 0 << 14,
SRAM_WRITE = 2 << 14,
SRAM_INIT = 3 << 14,
+ SRAM_GAMMA_YR = 0x0 << 8,
+ SRAM_GAMMA_UG = 0x1 << 8,
+ SRAM_GAMMA_VB = 0x2 << 8,
+ SRAM_PALETTE = 0x3 << 8,
SRAM_HWC32_RAM1 = 0xc << 8,
SRAM_HWC32_RAM2 = 0xd << 8,
SRAM_HWC32_RAMR = SRAM_HWC32_RAM1,
@@ -316,19 +330,4 @@ enum {
PWRDN_IRQ_LEVEL = 1 << 0,
};
-static inline u32 armada_rect_hw_fp(struct drm_rect *r)
-{
- return (drm_rect_height(r) & 0xffff0000) | drm_rect_width(r) >> 16;
-}
-
-static inline u32 armada_rect_hw(struct drm_rect *r)
-{
- return drm_rect_height(r) << 16 | (drm_rect_width(r) & 0x0000ffff);
-}
-
-static inline u32 armada_rect_yx(struct drm_rect *r)
-{
- return (r)->y1 << 16 | ((r)->x1 & 0x0000ffff);
-}
-
#endif
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 8d770641fcc4..a79d6e940435 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -27,7 +27,7 @@
#define DEFAULT_ENCODING DRM_COLOR_YCBCR_BT601
struct armada_overlay_state {
- struct drm_plane_state base;
+ struct armada_plane_state base;
u32 colorkey_yr;
u32 colorkey_ug;
u32 colorkey_vb;
@@ -38,7 +38,7 @@ struct armada_overlay_state {
u16 saturation;
};
#define drm_to_overlay_state(s) \
- container_of(s, struct armada_overlay_state, base)
+ container_of(s, struct armada_overlay_state, base.base)
static inline u32 armada_spu_contrast(struct drm_plane_state *state)
{
@@ -94,41 +94,39 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
armada_reg_queue_mod(regs, idx,
0, CFG_PDWN16x66 | CFG_PDWN32x66,
LCD_SPU_SRAM_PARA1);
- val = armada_rect_hw_fp(&state->src);
- if (armada_rect_hw_fp(&old_state->src) != val)
+ val = armada_src_hw(state);
+ if (armada_src_hw(old_state) != val)
armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_HPXL_VLN);
- val = armada_rect_yx(&state->dst);
- if (armada_rect_yx(&old_state->dst) != val)
+ val = armada_dst_yx(state);
+ if (armada_dst_yx(old_state) != val)
armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_OVSA_HPXL_VLN);
- val = armada_rect_hw(&state->dst);
- if (armada_rect_hw(&old_state->dst) != val)
+ val = armada_dst_hw(state);
+ if (armada_dst_hw(old_state) != val)
armada_reg_queue_set(regs, idx, val, LCD_SPU_DZM_HPXL_VLN);
/* FIXME: overlay on an interlaced display */
if (old_state->src.x1 != state->src.x1 ||
old_state->src.y1 != state->src.y1 ||
- old_state->fb != state->fb) {
+ old_state->fb != state->fb ||
+ state->crtc->state->mode_changed) {
const struct drm_format_info *format;
- u16 src_x, pitches[3];
- u32 addrs[2][3];
+ u16 src_x;
- armada_drm_plane_calc(state, addrs, pitches, false);
-
- armada_reg_queue_set(regs, idx, addrs[0][0],
+ armada_reg_queue_set(regs, idx, armada_addr(state, 0, 0),
LCD_SPU_DMA_START_ADDR_Y0);
- armada_reg_queue_set(regs, idx, addrs[0][1],
+ armada_reg_queue_set(regs, idx, armada_addr(state, 0, 1),
LCD_SPU_DMA_START_ADDR_U0);
- armada_reg_queue_set(regs, idx, addrs[0][2],
+ armada_reg_queue_set(regs, idx, armada_addr(state, 0, 2),
LCD_SPU_DMA_START_ADDR_V0);
- armada_reg_queue_set(regs, idx, addrs[1][0],
+ armada_reg_queue_set(regs, idx, armada_addr(state, 1, 0),
LCD_SPU_DMA_START_ADDR_Y1);
- armada_reg_queue_set(regs, idx, addrs[1][1],
+ armada_reg_queue_set(regs, idx, armada_addr(state, 1, 1),
LCD_SPU_DMA_START_ADDR_U1);
- armada_reg_queue_set(regs, idx, addrs[1][2],
+ armada_reg_queue_set(regs, idx, armada_addr(state, 1, 2),
LCD_SPU_DMA_START_ADDR_V1);
- val = pitches[0] << 16 | pitches[0];
+ val = armada_pitch(state, 0) << 16 | armada_pitch(state, 0);
armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_PITCH_YC);
- val = pitches[1] << 16 | pitches[2];
+ val = armada_pitch(state, 1) << 16 | armada_pitch(state, 2);
armada_reg_queue_set(regs, idx, val, LCD_SPU_DMA_PITCH_UV);
cfg = CFG_DMA_FMT(drm_fb_to_armada_fb(state->fb)->fmt) |
@@ -146,6 +144,8 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
src_x = state->src.x1 >> 16;
if (format->num_planes == 1 && src_x & (format->hsub - 1))
cfg ^= CFG_DMA_MOD(CFG_SWAPUV);
+ if (to_armada_plane_state(state)->interlace)
+ cfg |= CFG_DMA_FTOGGLE;
cfg_mask = CFG_CBSH_ENA | CFG_DMAFORMAT |
CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV |
CFG_SWAPYU | CFG_YUV2RGB) |
@@ -307,13 +307,10 @@ static void armada_overlay_reset(struct drm_plane *plane)
if (plane->state)
__drm_atomic_helper_plane_destroy_state(plane->state);
kfree(plane->state);
+ plane->state = NULL;
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (state) {
- state->base.plane = plane;
- state->base.color_encoding = DEFAULT_ENCODING;
- state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
- state->base.rotation = DRM_MODE_ROTATE_0;
state->colorkey_yr = 0xfefefe00;
state->colorkey_ug = 0x01010100;
state->colorkey_vb = 0x01010100;
@@ -323,8 +320,10 @@ static void armada_overlay_reset(struct drm_plane *plane)
state->brightness = DEFAULT_BRIGHTNESS;
state->contrast = DEFAULT_CONTRAST;
state->saturation = DEFAULT_SATURATION;
+ __drm_atomic_helper_plane_reset(plane, &state->base.base);
+ state->base.base.color_encoding = DEFAULT_ENCODING;
+ state->base.base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
}
- plane->state = &state->base;
}
struct drm_plane_state *
@@ -337,8 +336,9 @@ armada_overlay_duplicate_state(struct drm_plane *plane)
state = kmemdup(plane->state, sizeof(*state), GFP_KERNEL);
if (state)
- __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
- return &state->base;
+ __drm_atomic_helper_plane_duplicate_state(plane,
+ &state->base.base);
+ return &state->base.base;
}
static int armada_overlay_set_property(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/armada/armada_plane.c b/drivers/gpu/drm/armada/armada_plane.c
index 9f36423dd394..dbd4d52e8a32 100644
--- a/drivers/gpu/drm/armada/armada_plane.c
+++ b/drivers/gpu/drm/armada/armada_plane.c
@@ -79,23 +79,6 @@ void armada_drm_plane_calc(struct drm_plane_state *state, u32 addrs[2][3],
}
}
-static unsigned armada_drm_crtc_calc_fb(struct drm_plane_state *state,
- struct armada_regs *regs, bool interlaced)
-{
- u16 pitches[3];
- u32 addrs[2][3];
- unsigned i = 0;
-
- armada_drm_plane_calc(state, addrs, pitches, interlaced);
-
- /* write offset, base, and pitch */
- armada_reg_queue_set(regs, i, addrs[0][0], LCD_CFG_GRA_START_ADDR0);
- armada_reg_queue_set(regs, i, addrs[1][0], LCD_CFG_GRA_START_ADDR1);
- armada_reg_queue_mod(regs, i, pitches[0], 0xffff, LCD_CFG_GRA_PITCH);
-
- return i;
-}
-
int armada_drm_plane_prepare_fb(struct drm_plane *plane,
struct drm_plane_state *state)
{
@@ -126,20 +109,50 @@ void armada_drm_plane_cleanup_fb(struct drm_plane *plane,
int armada_drm_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
- if (state->fb && !WARN_ON(!state->crtc)) {
- struct drm_crtc *crtc = state->crtc;
- struct drm_crtc_state *crtc_state;
-
- if (state->state)
- crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
- else
- crtc_state = crtc->state;
- return drm_atomic_helper_check_plane_state(state, crtc_state,
- 0, INT_MAX,
- true, false);
- } else {
+ struct armada_plane_state *st = to_armada_plane_state(state);
+ struct drm_crtc *crtc = state->crtc;
+ struct drm_crtc_state *crtc_state;
+ bool interlace;
+ int ret;
+
+ if (!state->fb || WARN_ON(!state->crtc)) {
state->visible = false;
+ return 0;
+ }
+
+ if (state->state)
+ crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
+ else
+ crtc_state = crtc->state;
+
+ ret = drm_atomic_helper_check_plane_state(state, crtc_state, 0,
+ INT_MAX, true, false);
+ if (ret)
+ return ret;
+
+ interlace = crtc_state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE;
+ if (interlace) {
+ if ((state->dst.y1 | state->dst.y2) & 1)
+ return -EINVAL;
+ st->src_hw = drm_rect_height(&state->src) >> 17;
+ st->dst_yx = state->dst.y1 >> 1;
+ st->dst_hw = drm_rect_height(&state->dst) >> 1;
+ } else {
+ st->src_hw = drm_rect_height(&state->src) >> 16;
+ st->dst_yx = state->dst.y1;
+ st->dst_hw = drm_rect_height(&state->dst);
}
+
+ st->src_hw <<= 16;
+ st->src_hw |= drm_rect_width(&state->src) >> 16;
+ st->dst_yx <<= 16;
+ st->dst_yx |= state->dst.x1 & 0x0000ffff;
+ st->dst_hw <<= 16;
+ st->dst_hw |= drm_rect_width(&state->dst) & 0x0000ffff;
+
+ armada_drm_plane_calc(state, st->addrs, st->pitches, interlace);
+ st->interlace = interlace;
+
return 0;
}
@@ -173,21 +186,25 @@ static void armada_drm_primary_plane_atomic_update(struct drm_plane *plane,
val |= CFG_PDWN256x24;
armada_reg_queue_mod(regs, idx, 0, val, LCD_SPU_SRAM_PARA1);
}
- val = armada_rect_hw_fp(&state->src);
- if (armada_rect_hw_fp(&old_state->src) != val)
+ val = armada_src_hw(state);
+ if (armada_src_hw(old_state) != val)
armada_reg_queue_set(regs, idx, val, LCD_SPU_GRA_HPXL_VLN);
- val = armada_rect_yx(&state->dst);
- if (armada_rect_yx(&old_state->dst) != val)
+ val = armada_dst_yx(state);
+ if (armada_dst_yx(old_state) != val)
armada_reg_queue_set(regs, idx, val, LCD_SPU_GRA_OVSA_HPXL_VLN);
- val = armada_rect_hw(&state->dst);
- if (armada_rect_hw(&old_state->dst) != val)
+ val = armada_dst_hw(state);
+ if (armada_dst_hw(old_state) != val)
armada_reg_queue_set(regs, idx, val, LCD_SPU_GZM_HPXL_VLN);
if (old_state->src.x1 != state->src.x1 ||
old_state->src.y1 != state->src.y1 ||
old_state->fb != state->fb ||
state->crtc->state->mode_changed) {
- idx += armada_drm_crtc_calc_fb(state, regs + idx,
- dcrtc->interlaced);
+ armada_reg_queue_set(regs, idx, armada_addr(state, 0, 0),
+ LCD_CFG_GRA_START_ADDR0);
+ armada_reg_queue_set(regs, idx, armada_addr(state, 1, 0),
+ LCD_CFG_GRA_START_ADDR1);
+ armada_reg_queue_mod(regs, idx, armada_pitch(state, 0), 0xffff,
+ LCD_CFG_GRA_PITCH);
}
if (old_state->fb != state->fb ||
state->crtc->state->mode_changed) {
@@ -197,7 +214,7 @@ static void armada_drm_primary_plane_atomic_update(struct drm_plane *plane,
cfg |= CFG_PALETTE_ENA;
if (state->visible)
cfg |= CFG_GRA_ENA;
- if (dcrtc->interlaced)
+ if (to_armada_plane_state(state)->interlace)
cfg |= CFG_GRA_FTOGGLE;
cfg_mask = CFG_GRAFORMAT |
CFG_GRA_MOD(CFG_SWAPRB | CFG_SWAPUV |
@@ -248,7 +265,7 @@ static void armada_drm_primary_plane_atomic_disable(struct drm_plane *plane,
/* Disable plane and power down most RAMs and FIFOs */
armada_reg_queue_mod(regs, idx, 0, CFG_GRA_ENA, LCD_SPU_DMA_CTRL0);
armada_reg_queue_mod(regs, idx, CFG_PDWN256x32 | CFG_PDWN256x24 |
- CFG_PDWN256x8 | CFG_PDWN32x32 | CFG_PDWN64x66,
+ CFG_PDWN32x32 | CFG_PDWN64x66,
0, LCD_SPU_SRAM_PARA1);
dcrtc->regs_idx += idx;
@@ -262,12 +279,37 @@ static const struct drm_plane_helper_funcs armada_primary_plane_helper_funcs = {
.atomic_disable = armada_drm_primary_plane_atomic_disable,
};
+void armada_plane_reset(struct drm_plane *plane)
+{
+ struct armada_plane_state *st;
+ if (plane->state)
+ __drm_atomic_helper_plane_destroy_state(plane->state);
+ kfree(plane->state);
+ st = kzalloc(sizeof(*st), GFP_KERNEL);
+ if (st)
+ __drm_atomic_helper_plane_reset(plane, &st->base);
+}
+
+struct drm_plane_state *armada_plane_duplicate_state(struct drm_plane *plane)
+{
+ struct armada_plane_state *st;
+
+ if (WARN_ON(!plane->state))
+ return NULL;
+
+ st = kmemdup(plane->state, sizeof(*st), GFP_KERNEL);
+ if (st)
+ __drm_atomic_helper_plane_duplicate_state(plane, &st->base);
+
+ return &st->base;
+}
+
static const struct drm_plane_funcs armada_primary_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = drm_primary_helper_destroy,
- .reset = drm_atomic_helper_plane_reset,
- .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+ .reset = armada_plane_reset,
+ .atomic_duplicate_state = armada_plane_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
};
diff --git a/drivers/gpu/drm/armada/armada_plane.h b/drivers/gpu/drm/armada/armada_plane.h
index ff4281ba7fad..2707ec781941 100644
--- a/drivers/gpu/drm/armada/armada_plane.h
+++ b/drivers/gpu/drm/armada/armada_plane.h
@@ -1,6 +1,24 @@
#ifndef ARMADA_PLANE_H
#define ARMADA_PLANE_H
+struct armada_plane_state {
+ struct drm_plane_state base;
+ u32 src_hw;
+ u32 dst_yx;
+ u32 dst_hw;
+ u32 addrs[2][3];
+ u16 pitches[3];
+ bool interlace;
+};
+
+#define to_armada_plane_state(st) \
+ container_of(st, struct armada_plane_state, base)
+#define armada_src_hw(state) to_armada_plane_state(state)->src_hw
+#define armada_dst_yx(state) to_armada_plane_state(state)->dst_yx
+#define armada_dst_hw(state) to_armada_plane_state(state)->dst_hw
+#define armada_addr(state, f, p) to_armada_plane_state(state)->addrs[f][p]
+#define armada_pitch(state, n) to_armada_plane_state(state)->pitches[n]
+
void armada_drm_plane_calc(struct drm_plane_state *state, u32 addrs[2][3],
u16 pitches[3], bool interlaced);
int armada_drm_plane_prepare_fb(struct drm_plane *plane,
@@ -9,6 +27,11 @@ void armada_drm_plane_cleanup_fb(struct drm_plane *plane,
struct drm_plane_state *old_state);
int armada_drm_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state);
+void armada_plane_reset(struct drm_plane *plane);
+struct drm_plane_state *armada_plane_duplicate_state(struct drm_plane *plane);
+void armada_plane_destroy_state(struct drm_plane *plane,
+ struct drm_plane_state *state);
+
int armada_drm_primary_plane_init(struct drm_device *drm,
struct drm_plane *primary);
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index bfb21b5eefe1..4e76b2b27374 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -70,7 +70,12 @@ static int tfp410_get_modes(struct drm_connector *connector)
drm_connector_update_edid_property(connector, edid);
- return drm_add_edid_modes(connector, edid);
+ ret = drm_add_edid_modes(connector, edid);
+
+ kfree(edid);
+
+ return ret;
+
fallback:
/* No EDID, fallback on the XGA standard modes */
ret = drm_add_modes_noedid(connector, 1920, 1200);
@@ -376,7 +381,8 @@ static int tfp410_fini(struct device *dev)
{
struct tfp410 *dvi = dev_get_drvdata(dev);
- cancel_delayed_work_sync(&dvi->hpd_work);
+ if (dvi->hpd_irq >= 0)
+ cancel_delayed_work_sync(&dvi->hpd_work);
drm_bridge_remove(&dvi->bridge);
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index cbe58d307d1c..60ce4a8ad9e1 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_EXYNOS
tristate "DRM Support for Samsung SoC EXYNOS Series"
- depends on OF && DRM && (ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS || ARCH_MULTIPLATFORM)
+ depends on OF && DRM && (ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS || ARCH_MULTIPLATFORM || COMPILE_TEST)
select DRM_KMS_HELPER
select VIDEOMODE_HELPERS
select SND_SOC_HDMI_CODEC if SND_SOC
@@ -86,7 +86,7 @@ comment "Sub-drivers"
config DRM_EXYNOS_G2D
bool "G2D"
- depends on VIDEO_SAMSUNG_S5P_G2D=n
+ depends on VIDEO_SAMSUNG_S5P_G2D=n || COMPILE_TEST
select FRAME_VECTOR
help
Choose this option if you want to use Exynos G2D for DRM.
@@ -114,7 +114,7 @@ config DRM_EXYNOS_SCALER
config DRM_EXYNOS_GSC
bool "GScaler"
- depends on VIDEO_SAMSUNG_EXYNOS_GSC=n
+ depends on VIDEO_SAMSUNG_EXYNOS_GSC=n || COMPILE_TEST
select DRM_EXYNOS_IPP
help
Choose this option if you want to use Exynos GSC for DRM.
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 0650b619de24..2d5cbfda3ca7 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -7,7 +7,6 @@
* Hyungwon Hwang <human.hwang@samsung.com>
*/
-#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/iopoll.h>
@@ -15,11 +14,15 @@
#include <linux/mfd/syscon.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
-#include "exynos_drm_drv.h"
+#include <drm/drm_fourcc.h>
+#include <drm/drm_vblank.h>
+
#include "exynos_drm_crtc.h"
+#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_plane.h"
#include "regs-decon5433.h"
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 13509ca8aa35..f0640950bd46 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -6,8 +6,6 @@
* Akshu Agarwal <akshua@gmail.com>
* Ajay Kumar <ajaykumar.rs@samsung.com>
*/
-#include <drm/drmP.h>
-#include <drm/exynos_drm.h>
#include <linux/clk.h>
#include <linux/component.h>
@@ -21,10 +19,14 @@
#include <video/of_display_timing.h>
#include <video/of_videomode.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_vblank.h>
+#include <drm/exynos_drm.h>
+
#include "exynos_drm_crtc.h"
-#include "exynos_drm_plane.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
+#include "exynos_drm_plane.h"
#include "regs-decon7.h"
/*
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index c0653d007ca4..3a0f0ba8c63a 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -6,25 +6,24 @@
* Author: Jingoo Han <jg1.han@samsung.com>
*/
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
#include <linux/clk.h>
-#include <linux/of_graph.h>
#include <linux/component.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <video/of_display_timing.h>
#include <video/of_videomode.h>
#include <video/videomode.h>
-#include <drm/drmP.h>
+#include <drm/bridge/analogix_dp.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-
-#include <drm/bridge/analogix_dp.h>
#include <drm/exynos_drm.h>
#include "exynos_drm_crtc.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 98bec7418f01..77ce78986408 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -8,11 +8,11 @@
* Seung-Woo Kim <sw0312.kim@samsung.com>
*/
-#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_encoder.h>
#include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dma.c b/drivers/gpu/drm/exynos/exynos_drm_dma.c
index bef8bc3c8e00..9ebc02768847 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dma.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dma.c
@@ -4,11 +4,13 @@
// Author: Inki Dae <inki.dae@samsung.com>
// Author: Andrzej Hajda <a.hajda@samsung.com>
-#include <drm/drmP.h>
-#include <drm/exynos_drm.h>
#include <linux/dma-iommu.h>
#include <linux/dma-mapping.h>
#include <linux/iommu.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_print.h>
+#include <drm/exynos_drm.h>
#include "exynos_drm_drv.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
index 6ea92173db9f..87289db12868 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
@@ -10,14 +10,14 @@
* published by the Free Software Foundation.
*/
-#include <drm/drmP.h>
+#include <linux/of_graph.h>
+#include <linux/regulator/consumer.h>
+
#include <drm/drm_atomic_helper.h>
#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <linux/of_graph.h>
-#include <linux/regulator/consumer.h>
-
#include <video/of_videomode.h>
#include <video/videomode.h>
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index ba8932af9b43..58baf49d9926 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -7,25 +7,23 @@
* Seung-Woo Kim <sw0312.kim@samsung.com>
*/
+#include <linux/component.h>
#include <linux/pm_runtime.h>
-#include <drm/drmP.h>
+
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_probe_helper.h>
-
-#include <linux/component.h>
-
#include <drm/exynos_drm.h>
#include "exynos_drm_drv.h"
-#include "exynos_drm_fbdev.h"
#include "exynos_drm_fb.h"
+#include "exynos_drm_fbdev.h"
+#include "exynos_drm_g2d.h"
#include "exynos_drm_gem.h"
-#include "exynos_drm_plane.h"
#include "exynos_drm_ipp.h"
+#include "exynos_drm_plane.h"
#include "exynos_drm_vidi.h"
-#include "exynos_drm_g2d.h"
#define DRIVER_NAME "exynos"
#define DRIVER_DESC "Samsung SoC DRM"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 18b03b83f8a3..d4014ba592fd 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -11,15 +11,21 @@
#ifndef _EXYNOS_DRM_DRV_H_
#define _EXYNOS_DRM_DRV_H_
-#include <drm/drmP.h>
#include <linux/module.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
+#include <drm/drm_plane.h>
+
#define MAX_CRTC 3
#define MAX_PLANE 5
#define MAX_FB_BUFFER 4
#define DEFAULT_WIN 0
+struct drm_crtc_state;
+struct drm_display_mode;
+
#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc, base)
#define to_exynos_plane(x) container_of(x, struct exynos_drm_plane, base)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 63a4b5074a99..5f6f523821a2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -10,16 +10,9 @@
* published by the Free Software Foundation.
*/
-#include <asm/unaligned.h>
-
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_mipi_dsi.h>
-#include <drm/drm_panel.h>
-#include <drm/drm_probe_helper.h>
-
#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/component.h>
#include <linux/gpio/consumer.h>
#include <linux/irq.h>
#include <linux/of_device.h>
@@ -27,11 +20,19 @@
#include <linux/of_graph.h>
#include <linux/phy/phy.h>
#include <linux/regulator/consumer.h>
-#include <linux/component.h>
+
+#include <asm/unaligned.h>
#include <video/mipi_display.h>
#include <video/videomode.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+
#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index ea048905849a..64370b634cca 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -8,19 +8,19 @@
* Seung-Woo Kim <sw0312.kim@samsung.com>
*/
-#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_probe_helper.h>
-#include <uapi/drm/exynos_drm.h>
+#include <drm/exynos_drm.h>
+#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_fbdev.h"
-#include "exynos_drm_crtc.h"
static int check_fb_gem_memory_type(struct drm_device *drm_dev,
struct exynos_drm_gem *exynos_gem)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index 9dc33c6b6687..b0877b97291c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -8,14 +8,16 @@
* Seung-Woo Kim <sw0312.kim@samsung.com>
*/
-#include <drm/drmP.h>
+#include <linux/console.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_probe_helper.h>
#include <drm/exynos_drm.h>
-#include <linux/console.h>
-
#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_fbdev.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index 0db29690ede3..a594ab7be2c0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -6,21 +6,22 @@
* Jinyoung Jeon <jy0.jeon@samsung.com>
* Sangmin Lee <lsmin.lee@samsung.com>
*/
-#include <linux/kernel.h>
+
+#include <linux/clk.h>
#include <linux/component.h>
-#include <linux/platform_device.h>
+#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
-#include <linux/regmap.h>
-#include <linux/clk.h>
-#include <linux/pm_runtime.h>
#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
#include <linux/spinlock.h>
-#include <drm/drmP.h>
#include <drm/exynos_drm.h>
-#include "regs-fimc.h"
+
#include "exynos_drm_drv.h"
#include "exynos_drm_ipp.h"
+#include "regs-fimc.h"
/*
* FIMC stands for Fully Interactive Mobile Camera and
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index e9106b1f4a50..8d0a929104e5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -6,26 +6,28 @@
* Joonyoung Shim <jy0922.shim@samsung.com>
* Inki Dae <inki.dae@samsung.com>
*/
-#include <drm/drmP.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <linux/component.h>
-#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <video/of_display_timing.h>
#include <video/of_videomode.h>
#include <video/samsung_fimd.h>
+
+#include <drm/drm_fourcc.h>
+#include <drm/drm_vblank.h>
#include <drm/exynos_drm.h>
+#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
-#include "exynos_drm_crtc.h"
#include "exynos_drm_plane.h"
/*
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 2e4b9434245b..50904eee96f7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -4,21 +4,24 @@
* Authors: Joonyoung Shim <jy0922.shim@samsung.com>
*/
-#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/component.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
+#include <linux/uaccess.h>
#include <linux/workqueue.h>
-#include <linux/dma-mapping.h>
-#include <linux/of.h>
-#include <drm/drmP.h>
+#include <drm/drm_file.h>
#include <drm/exynos_drm.h>
+
#include "exynos_drm_drv.h"
#include "exynos_drm_g2d.h"
#include "exynos_drm_gem.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index d8f1fe9b68d8..d734d9d51762 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -5,12 +5,13 @@
* Author: Inki Dae <inki.dae@samsung.com>
*/
-#include <drm/drmP.h>
-#include <drm/drm_vma_manager.h>
-#include <linux/shmem_fs.h>
#include <linux/dma-buf.h>
#include <linux/pfn_t.h>
+#include <linux/shmem_fs.h>
+
+#include <drm/drm_prime.h>
+#include <drm/drm_vma_manager.h>
#include <drm/exynos_drm.h>
#include "exynos_drm_drv.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 05b0fe21b81e..1e4b21c49a06 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -6,20 +6,21 @@
* Jinyoung Jeon <jy0.jeon@samsung.com>
* Sangmin Lee <lsmin.lee@samsung.com>
*/
-#include <linux/kernel.h>
-#include <linux/component.h>
-#include <linux/platform_device.h>
+
#include <linux/clk.h>
-#include <linux/pm_runtime.h>
+#include <linux/component.h>
+#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
-#include <drm/drmP.h>
#include <drm/exynos_drm.h>
-#include "regs-gsc.h"
+
#include "exynos_drm_drv.h"
#include "exynos_drm_ipp.h"
+#include "regs-gsc.h"
/*
* GSC stands for General SCaler and
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index c862099723a0..d45bfab6fe40 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -16,10 +16,9 @@
* all copies or substantial portions of the Software.
*/
-
#include <drm/drmP.h>
#include <drm/drm_mode.h>
-#include <uapi/drm/exynos_drm.h>
+#include <drm/exynos_drm.h>
#include "exynos_drm_drv.h"
#include "exynos_drm_gem.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
index 8363cb40daed..b78e8c5ba553 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -5,23 +5,25 @@
* Hyungwon Hwang <human.hwang@samsung.com>
*/
-#include <linux/platform_device.h>
-#include <video/of_videomode.h>
-#include <linux/of_address.h>
-#include <video/videomode.h>
-#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/component.h>
#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/of_graph.h>
-#include <linux/clk.h>
-#include <linux/component.h>
+#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <drm/drmP.h>
-#include <drm/drm_encoder.h>
-#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+#include <drm/drm_encoder.h>
+#include <drm/drm_print.h>
+
#include "exynos_drm_drv.h"
/* Sysreg registers for MIC */
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 2f3c9b993acd..b29afced7374 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -4,14 +4,14 @@
* Authors: Joonyoung Shim <jy0922.shim@samsung.com>
*/
-#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/exynos_drm.h>
-#include "exynos_drm_drv.h"
+
#include "exynos_drm_crtc.h"
+#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_plane.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
index 85e30cb6c23f..8ebad2740ad5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -6,21 +6,21 @@
* Eunchul Kim <chulspro.kim@samsung.com>
*/
-#include <linux/kernel.h>
+#include <linux/clk.h>
#include <linux/component.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
+#include <linux/kernel.h>
#include <linux/of_device.h>
+#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <drm/drmP.h>
#include <drm/exynos_drm.h>
-#include "regs-rotator.h"
+
#include "exynos_drm_drv.h"
#include "exynos_drm_ipp.h"
+#include "regs-rotator.h"
/*
* Rotator supports image crop/rotator and input/output DMA operations.
diff --git a/drivers/gpu/drm/exynos/exynos_drm_scaler.c b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
index ec9c1b7d3103..9af096479e1c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_scaler.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
@@ -5,22 +5,22 @@
* Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
*/
-#include <linux/kernel.h>
+#include <linux/clk.h>
#include <linux/component.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
+#include <linux/kernel.h>
#include <linux/of_device.h>
+#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <drm/drmP.h>
#include <drm/exynos_drm.h>
-#include "regs-scaler.h"
-#include "exynos_drm_fb.h"
+
#include "exynos_drm_drv.h"
+#include "exynos_drm_fb.h"
#include "exynos_drm_ipp.h"
+#include "regs-scaler.h"
#define scaler_read(offset) readl(scaler->regs + (offset))
#define scaler_write(cfg, offset) writel(cfg, scaler->regs + (offset))
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index eb2667b4500c..65b891cb9c50 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -5,21 +5,20 @@
* Authors:
* Inki Dae <inki.dae@samsung.com>
*/
-#include <drm/drmP.h>
+#include <linux/component.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
-#include <linux/component.h>
#include <linux/timer.h>
-#include <drm/exynos_drm.h>
-
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
+#include <drm/exynos_drm.h>
-#include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h"
+#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_plane.h"
#include "exynos_drm_vidi.h"
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 894a99793633..bc1565f1822a 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -9,38 +9,37 @@
* Based on drivers/media/video/s5p-tv/hdmi_drv.c
*/
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_edid.h>
-#include <drm/drm_probe_helper.h>
-
-#include "regs-hdmi.h"
-
-#include <linux/kernel.h>
-#include <linux/wait.h>
-#include <linux/i2c.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <linux/pm_runtime.h>
+#include <drm/exynos_drm.h>
#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/delay.h>
#include <linux/gpio/consumer.h>
-#include <linux/regulator/consumer.h>
+#include <linux/hdmi.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_graph.h>
-#include <linux/hdmi.h>
-#include <linux/component.h>
-#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
-#include <sound/hdmi-codec.h>
-#include <drm/exynos_drm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/wait.h>
+#include <sound/hdmi-codec.h>
#include <media/cec-notifier.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+
#include "exynos_drm_crtc.h"
+#include "regs-hdmi.h"
#define HOTPLUG_DEBOUNCE_MS 1100
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index db0b698ea8ea..7b24338fad3c 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -9,33 +9,32 @@
* Based on drivers/media/video/s5p-tv/mixer_reg.c
*/
-#include <drm/drmP.h>
-
-#include "regs-mixer.h"
-#include "regs-vp.h"
-
-#include <linux/kernel.h>
-#include <linux/ktime.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/delay.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/delay.h>
-#include <linux/pm_runtime.h>
-#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
+#include <linux/kernel.h>
+#include <linux/ktime.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/component.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_vblank.h>
#include <drm/exynos_drm.h>
-#include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h"
+#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_plane.h"
+#include "regs-mixer.h"
+#include "regs-vp.h"
#define MIXER_WIN_NR 3
#define VP_DEFAULT_WIN 2
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index c3b4bc6e4155..13078c4975ff 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -395,19 +395,17 @@ static const unsigned int a3xx_registers[] = {
0x2200, 0x2212, 0x2214, 0x2217, 0x221a, 0x221a, 0x2240, 0x227e,
0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8,
0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7,
- 0x22ff, 0x22ff, 0x2340, 0x2343, 0x2348, 0x2349, 0x2350, 0x2356,
- 0x2360, 0x2360, 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d,
- 0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470, 0x2472, 0x2472,
- 0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3, 0x24e4, 0x24ef,
- 0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e, 0x2510, 0x2511,
- 0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea, 0x25ec, 0x25ed,
- 0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617, 0x261a, 0x261a,
- 0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0, 0x26c4, 0x26ce,
- 0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9, 0x26ec, 0x26ec,
- 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, 0x2748, 0x2749,
- 0x2750, 0x2756, 0x2760, 0x2760, 0x300c, 0x300e, 0x301c, 0x301d,
- 0x302a, 0x302a, 0x302c, 0x302d, 0x3030, 0x3031, 0x3034, 0x3036,
- 0x303c, 0x303c, 0x305e, 0x305f,
+ 0x22ff, 0x22ff, 0x2340, 0x2343, 0x2440, 0x2440, 0x2444, 0x2444,
+ 0x2448, 0x244d, 0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470,
+ 0x2472, 0x2472, 0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3,
+ 0x24e4, 0x24ef, 0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e,
+ 0x2510, 0x2511, 0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea,
+ 0x25ec, 0x25ed, 0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617,
+ 0x261a, 0x261a, 0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0,
+ 0x26c4, 0x26ce, 0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9,
+ 0x26ec, 0x26ec, 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743,
+ 0x300c, 0x300e, 0x301c, 0x301d, 0x302a, 0x302a, 0x302c, 0x302d,
+ 0x3030, 0x3031, 0x3034, 0x3036, 0x303c, 0x303c, 0x305e, 0x305f,
~0 /* sentinel */
};
diff --git a/drivers/gpu/drm/msm/adreno/a5xx.xml.h b/drivers/gpu/drm/msm/adreno/a5xx.xml.h
index cf4fe14ddd6e..4a61d4e72c98 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a5xx.xml.h
@@ -8,19 +8,19 @@ http://github.com/freedreno/envytools/
git clone https://github.com/freedreno/envytools.git
The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/envytools/rnndb/adreno.xml ( 501 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/a2xx.xml ( 42463 bytes, from 2018-11-19 13:44:03)
-- /home/robclark/src/envytools/rnndb/adreno/adreno_common.xml ( 14201 bytes, from 2018-12-02 17:29:54)
-- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 43052 bytes, from 2018-12-02 17:29:54)
-- /home/robclark/src/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/a4xx.xml ( 112086 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-12-02 17:29:54)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 140790 bytes, from 2018-12-02 17:29:54)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-09-14 13:03:07)
-- /home/robclark/src/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2018-07-03 19:37:13)
-
-Copyright (C) 2013-2018 by the following authors:
+- /home/ubuntu/envytools/envytools/rnndb/./adreno.xml ( 501 bytes, from 2019-05-29 01:28:15)
+- /home/ubuntu/envytools/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2019-05-29 01:28:15)
+- /home/ubuntu/envytools/envytools/rnndb/adreno/a2xx.xml ( 79608 bytes, from 2019-05-29 01:28:15)
+- /home/ubuntu/envytools/envytools/rnndb/adreno/adreno_common.xml ( 14239 bytes, from 2019-05-29 01:28:15)
+- /home/ubuntu/envytools/envytools/rnndb/adreno/adreno_pm4.xml ( 43155 bytes, from 2019-05-29 01:28:15)
+- /home/ubuntu/envytools/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2019-05-29 01:28:15)
+- /home/ubuntu/envytools/envytools/rnndb/adreno/a4xx.xml ( 112086 bytes, from 2019-05-29 01:28:15)
+- /home/ubuntu/envytools/envytools/rnndb/adreno/a5xx.xml ( 147291 bytes, from 2019-05-29 14:51:41)
+- /home/ubuntu/envytools/envytools/rnndb/adreno/a6xx.xml ( 148461 bytes, from 2019-05-29 01:28:15)
+- /home/ubuntu/envytools/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2019-05-29 01:28:15)
+- /home/ubuntu/envytools/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2019-05-29 01:28:15)
+
+Copyright (C) 2013-2019 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
- Ilia Mirkin <imirkin@alum.mit.edu> (imirkin)
@@ -2148,6 +2148,8 @@ static inline uint32_t A5XX_VSC_RESOLVE_CNTL_Y(uint32_t val)
#define REG_A5XX_HLSQ_TIMEOUT_THRESHOLD_1 0x00000e01
+#define REG_A5XX_HLSQ_DBG_ECO_CNTL 0x00000e04
+
#define REG_A5XX_HLSQ_ADDR_MODE_CNTL 0x00000e05
#define REG_A5XX_HLSQ_MODE_CNTL 0x00000e06
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
index 3041c500c5cd..9f2dd76bd67a 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
@@ -149,7 +149,6 @@ DEFINE_SIMPLE_ATTRIBUTE(reset_fops, NULL, reset_set, "%llx\n");
int a5xx_debugfs_init(struct msm_gpu *gpu, struct drm_minor *minor)
{
struct drm_device *dev;
- struct dentry *ent;
int ret;
if (!minor)
@@ -166,11 +165,8 @@ int a5xx_debugfs_init(struct msm_gpu *gpu, struct drm_minor *minor)
return ret;
}
- ent = debugfs_create_file("reset", S_IWUGO,
- minor->debugfs_root,
- dev, &reset_fops);
- if (!ent)
- return -ENOMEM;
+ debugfs_create_file("reset", S_IWUGO, minor->debugfs_root, dev,
+ &reset_fops);
return 0;
}
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index a3c778df23a8..1671db47aa57 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -309,12 +309,18 @@ static const struct {
void a5xx_set_hwcg(struct msm_gpu *gpu, bool state)
{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
unsigned int i;
for (i = 0; i < ARRAY_SIZE(a5xx_hwcg); i++)
gpu_write(gpu, a5xx_hwcg[i].offset,
state ? a5xx_hwcg[i].value : 0);
+ if (adreno_is_a540(adreno_gpu)) {
+ gpu_write(gpu, REG_A5XX_RBBM_CLOCK_DELAY_GPMU, state ? 0x00000770 : 0);
+ gpu_write(gpu, REG_A5XX_RBBM_CLOCK_HYST_GPMU, state ? 0x00000004 : 0);
+ }
+
gpu_write(gpu, REG_A5XX_RBBM_CLOCK_CNTL, state ? 0xAAA8AA00 : 0);
gpu_write(gpu, REG_A5XX_RBBM_ISDB_CNT, state ? 0x182 : 0x180);
}
@@ -498,6 +504,9 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
gpu_write(gpu, REG_A5XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
+ if (adreno_is_a540(adreno_gpu))
+ gpu_write(gpu, REG_A5XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000009);
+
/* Make all blocks contribute to the GPU BUSY perf counter */
gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xFFFFFFFF);
@@ -558,7 +567,10 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_HI, 0x00000000);
gpu_write(gpu, REG_A5XX_CP_MEQ_THRESHOLDS, 0x40);
- gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x40);
+ if (adreno_is_a530(adreno_gpu))
+ gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x40);
+ if (adreno_is_a540(adreno_gpu))
+ gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x400);
gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_2, 0x80000060);
gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_1, 0x40201B16);
@@ -583,6 +595,8 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
/* Set the highest bank bit */
gpu_write(gpu, REG_A5XX_TPL1_MODE_CNTL, 2 << 7);
gpu_write(gpu, REG_A5XX_RB_MODE_CNTL, 2 << 1);
+ if (adreno_is_a540(adreno_gpu))
+ gpu_write(gpu, REG_A5XX_UCHE_DBG_ECO_CNTL_2, 2);
/* Protect registers from the CP */
gpu_write(gpu, REG_A5XX_CP_PROTECT_CNTL, 0x00000007);
@@ -633,6 +647,30 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000);
gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000);
+ /* Put the GPU into 64 bit by default */
+ gpu_write(gpu, REG_A5XX_CP_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A5XX_VSC_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A5XX_GRAS_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A5XX_RB_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A5XX_PC_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A5XX_HLSQ_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A5XX_VFD_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A5XX_VPC_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A5XX_UCHE_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A5XX_SP_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A5XX_TPL1_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_ADDR_MODE_CNTL, 0x1);
+
+ /*
+ * VPC corner case with local memory load kill leads to corrupt
+ * internal state. Normal Disable does not work for all a5x chips.
+ * So do the following setting to disable it.
+ */
+ if (adreno_gpu->info->quirks & ADRENO_QUIRK_LMLOADKILL_DISABLE) {
+ gpu_rmw(gpu, REG_A5XX_VPC_DBG_ECO_CNTL, 0, BIT(23));
+ gpu_rmw(gpu, REG_A5XX_HLSQ_DBG_ECO_CNTL, BIT(18), 0);
+ }
+
ret = adreno_hw_init(gpu);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c b/drivers/gpu/drm/msm/adreno/a5xx_power.c
index 0ebfe2bb5707..a3a06db675ba 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_power.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c
@@ -23,6 +23,18 @@
#define AGC_POWER_CONFIG_PRODUCTION_ID 1
#define AGC_INIT_MSG_VALUE 0xBABEFACE
+/* AGC_LM_CONFIG (A540+) */
+#define AGC_LM_CONFIG (136/4)
+#define AGC_LM_CONFIG_GPU_VERSION_SHIFT 17
+#define AGC_LM_CONFIG_ENABLE_GPMU_ADAPTIVE 1
+#define AGC_LM_CONFIG_THROTTLE_DISABLE (2 << 8)
+#define AGC_LM_CONFIG_ISENSE_ENABLE (1 << 4)
+#define AGC_LM_CONFIG_ENABLE_ERROR (3 << 4)
+#define AGC_LM_CONFIG_LLM_ENABLED (1 << 16)
+#define AGC_LM_CONFIG_BCL_DISABLED (1 << 24)
+
+#define AGC_LEVEL_CONFIG (140/4)
+
static struct {
uint32_t reg;
uint32_t value;
@@ -107,7 +119,7 @@ static inline uint32_t _get_mvolts(struct msm_gpu *gpu, uint32_t freq)
}
/* Setup thermal limit management */
-static void a5xx_lm_setup(struct msm_gpu *gpu)
+static void a530_lm_setup(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
@@ -156,6 +168,45 @@ static void a5xx_lm_setup(struct msm_gpu *gpu)
gpu_write(gpu, AGC_INIT_MSG_MAGIC, AGC_INIT_MSG_VALUE);
}
+#define PAYLOAD_SIZE(_size) ((_size) * sizeof(u32))
+#define LM_DCVS_LIMIT 1
+#define LEVEL_CONFIG ~(0x303)
+
+static void a540_lm_setup(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ u32 config;
+
+ /* The battery current limiter isn't enabled for A540 */
+ config = AGC_LM_CONFIG_BCL_DISABLED;
+ config |= adreno_gpu->rev.patchid << AGC_LM_CONFIG_GPU_VERSION_SHIFT;
+
+ /* For now disable GPMU side throttling */
+ config |= AGC_LM_CONFIG_THROTTLE_DISABLE;
+
+ /* Until we get clock scaling 0 is always the active power level */
+ gpu_write(gpu, REG_A5XX_GPMU_GPMU_VOLTAGE, 0x80000000 | 0);
+
+ /* Fixed at 6000 for now */
+ gpu_write(gpu, REG_A5XX_GPMU_GPMU_PWR_THRESHOLD, 0x80000000 | 6000);
+
+ gpu_write(gpu, AGC_MSG_STATE, 0x80000001);
+ gpu_write(gpu, AGC_MSG_COMMAND, AGC_POWER_CONFIG_PRODUCTION_ID);
+
+ gpu_write(gpu, AGC_MSG_PAYLOAD(0), 5448);
+ gpu_write(gpu, AGC_MSG_PAYLOAD(1), 1);
+
+ gpu_write(gpu, AGC_MSG_PAYLOAD(2), _get_mvolts(gpu, gpu->fast_rate));
+ gpu_write(gpu, AGC_MSG_PAYLOAD(3), gpu->fast_rate / 1000000);
+
+ gpu_write(gpu, AGC_MSG_PAYLOAD(AGC_LM_CONFIG), config);
+ gpu_write(gpu, AGC_MSG_PAYLOAD(AGC_LEVEL_CONFIG), LEVEL_CONFIG);
+ gpu_write(gpu, AGC_MSG_PAYLOAD_SIZE,
+ PAYLOAD_SIZE(AGC_LEVEL_CONFIG + 1));
+
+ gpu_write(gpu, AGC_INIT_MSG_MAGIC, AGC_INIT_MSG_VALUE);
+}
+
/* Enable SP/TP cpower collapse */
static void a5xx_pc_init(struct msm_gpu *gpu)
{
@@ -197,7 +248,8 @@ static int a5xx_gpmu_init(struct msm_gpu *gpu)
return -EINVAL;
}
- gpu_write(gpu, REG_A5XX_GPMU_WFI_CONFIG, 0x4014);
+ if (adreno_is_a530(adreno_gpu))
+ gpu_write(gpu, REG_A5XX_GPMU_WFI_CONFIG, 0x4014);
/* Kick off the GPMU */
gpu_write(gpu, REG_A5XX_GPMU_CM3_SYSRESET, 0x0);
@@ -211,12 +263,26 @@ static int a5xx_gpmu_init(struct msm_gpu *gpu)
DRM_ERROR("%s: GPMU firmware initialization timed out\n",
gpu->name);
+ if (!adreno_is_a530(adreno_gpu)) {
+ u32 val = gpu_read(gpu, REG_A5XX_GPMU_GENERAL_1);
+
+ if (val)
+ DRM_ERROR("%s: GPMU firmware initialization failed: %d\n",
+ gpu->name, val);
+ }
+
return 0;
}
/* Enable limits management */
static void a5xx_lm_enable(struct msm_gpu *gpu)
{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+
+ /* This init sequence only applies to A530 */
+ if (!adreno_is_a530(adreno_gpu))
+ return;
+
gpu_write(gpu, REG_A5XX_GDPM_INT_MASK, 0x0);
gpu_write(gpu, REG_A5XX_GDPM_INT_EN, 0x0A);
gpu_write(gpu, REG_A5XX_GPMU_GPMU_VOLTAGE_INTR_EN_MASK, 0x01);
@@ -228,10 +294,14 @@ static void a5xx_lm_enable(struct msm_gpu *gpu)
int a5xx_power_init(struct msm_gpu *gpu)
{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
int ret;
/* Set up the limits management */
- a5xx_lm_setup(gpu);
+ if (adreno_is_a530(adreno_gpu))
+ a530_lm_setup(gpu);
+ else
+ a540_lm_setup(gpu);
/* Set up SP/TP power collpase */
a5xx_pc_init(gpu);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 38e2cfa9cec7..2ca470eb5cb8 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -74,7 +74,7 @@ bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu)
u32 val;
/* This can be called from gpu state code so make sure GMU is valid */
- if (IS_ERR_OR_NULL(gmu->mmio))
+ if (!gmu->initialized)
return false;
val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
@@ -90,7 +90,7 @@ bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
u32 val;
/* This can be called from gpu state code so make sure GMU is valid */
- if (IS_ERR_OR_NULL(gmu->mmio))
+ if (!gmu->initialized)
return false;
val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
@@ -504,8 +504,10 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
wmb();
err:
- devm_iounmap(gmu->dev, pdcptr);
- devm_iounmap(gmu->dev, seqptr);
+ if (!IS_ERR_OR_NULL(pdcptr))
+ iounmap(pdcptr);
+ if (!IS_ERR_OR_NULL(seqptr))
+ iounmap(seqptr);
}
/*
@@ -695,7 +697,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
int status, ret;
- if (WARN(!gmu->mmio, "The GMU is not set up yet\n"))
+ if (WARN(!gmu->initialized, "The GMU is not set up yet\n"))
return 0;
gmu->hung = false;
@@ -765,7 +767,7 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu)
{
u32 reg;
- if (!gmu->mmio)
+ if (!gmu->initialized)
return true;
reg = gmu_read(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS);
@@ -1195,7 +1197,7 @@ static void __iomem *a6xx_gmu_get_mmio(struct platform_device *pdev,
return ERR_PTR(-EINVAL);
}
- ret = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ ret = ioremap(res->start, resource_size(res));
if (!ret) {
DRM_DEV_ERROR(&pdev->dev, "Unable to map the %s registers\n", name);
return ERR_PTR(-EINVAL);
@@ -1211,10 +1213,10 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev,
irq = platform_get_irq_byname(pdev, name);
- ret = devm_request_irq(&pdev->dev, irq, handler, IRQF_TRIGGER_HIGH,
- name, gmu);
+ ret = request_irq(irq, handler, IRQF_TRIGGER_HIGH, name, gmu);
if (ret) {
- DRM_DEV_ERROR(&pdev->dev, "Unable to get interrupt %s\n", name);
+ DRM_DEV_ERROR(&pdev->dev, "Unable to get interrupt %s %d\n",
+ name, ret);
return ret;
}
@@ -1227,27 +1229,35 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
{
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
- if (IS_ERR_OR_NULL(gmu->mmio))
+ if (!gmu->initialized)
return;
- a6xx_gmu_stop(a6xx_gpu);
-
- pm_runtime_disable(gmu->dev);
+ pm_runtime_force_suspend(gmu->dev);
if (!IS_ERR_OR_NULL(gmu->gxpd)) {
pm_runtime_disable(gmu->gxpd);
dev_pm_domain_detach(gmu->gxpd, false);
}
- a6xx_gmu_irq_disable(gmu);
+ iounmap(gmu->mmio);
+ gmu->mmio = NULL;
+
a6xx_gmu_memory_free(gmu, gmu->hfi);
iommu_detach_device(gmu->domain, gmu->dev);
iommu_domain_free(gmu->domain);
+
+ free_irq(gmu->gmu_irq, gmu);
+ free_irq(gmu->hfi_irq, gmu);
+
+ /* Drop reference taken in of_find_device_by_node */
+ put_device(gmu->dev);
+
+ gmu->initialized = false;
}
-int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
+int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
{
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
struct platform_device *pdev = of_find_device_by_node(node);
@@ -1268,34 +1278,34 @@ int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
/* Get the list of clocks */
ret = a6xx_gmu_clocks_probe(gmu);
if (ret)
- return ret;
+ goto err_put_device;
/* Set up the IOMMU context bank */
ret = a6xx_gmu_memory_probe(gmu);
if (ret)
- return ret;
+ goto err_put_device;
/* Allocate memory for for the HFI queues */
gmu->hfi = a6xx_gmu_memory_alloc(gmu, SZ_16K);
if (IS_ERR(gmu->hfi))
- goto err;
+ goto err_memory;
/* Allocate memory for the GMU debug region */
gmu->debug = a6xx_gmu_memory_alloc(gmu, SZ_16K);
if (IS_ERR(gmu->debug))
- goto err;
+ goto err_memory;
/* Map the GMU registers */
gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");
if (IS_ERR(gmu->mmio))
- goto err;
+ goto err_memory;
/* Get the HFI and GMU interrupts */
gmu->hfi_irq = a6xx_gmu_get_irq(gmu, pdev, "hfi", a6xx_hfi_irq);
gmu->gmu_irq = a6xx_gmu_get_irq(gmu, pdev, "gmu", a6xx_gmu_irq);
if (gmu->hfi_irq < 0 || gmu->gmu_irq < 0)
- goto err;
+ goto err_mmio;
/*
* Get a link to the GX power domain to reset the GPU in case of GMU
@@ -1309,8 +1319,15 @@ int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
/* Set up the HFI queues */
a6xx_hfi_init(gmu);
+ gmu->initialized = true;
+
return 0;
-err:
+
+err_mmio:
+ iounmap(gmu->mmio);
+ free_irq(gmu->gmu_irq, gmu);
+ free_irq(gmu->hfi_irq, gmu);
+err_memory:
a6xx_gmu_memory_free(gmu, gmu->hfi);
if (gmu->domain) {
@@ -1318,6 +1335,11 @@ err:
iommu_domain_free(gmu->domain);
}
+ ret = -ENODEV;
- return -ENODEV;
+err_put_device:
+ /* Drop reference taken in of_find_device_by_node */
+ put_device(gmu->dev);
+
+ return ret;
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index bedd8e6a63aa..39a26dd63674 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -75,6 +75,7 @@ struct a6xx_gmu {
struct a6xx_hfi_queue queues[2];
+ bool initialized;
bool hung;
};
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index e74dce474250..be39cf01e51e 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -391,6 +391,20 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
REG_A6XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000);
gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000);
+ /* Turn on 64 bit addressing for all blocks */
+ gpu_write(gpu, REG_A6XX_CP_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A6XX_VSC_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A6XX_GRAS_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A6XX_RB_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A6XX_PC_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A6XX_HLSQ_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A6XX_VFD_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A6XX_VPC_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A6XX_UCHE_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A6XX_SP_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A6XX_TPL1_ADDR_MODE_CNTL, 0x1);
+ gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_ADDR_MODE_CNTL, 0x1);
+
/* enable hardware clockgating */
a6xx_set_hwcg(gpu, true);
@@ -854,7 +868,7 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
/* FIXME: How do we gracefully handle this? */
BUG_ON(!node);
- ret = a6xx_gmu_probe(a6xx_gpu, node);
+ ret = a6xx_gmu_init(a6xx_gpu, node);
if (ret) {
a6xx_destroy(&(a6xx_gpu->base.base));
return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index b46279eb18c5..64399554f2dd 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -53,7 +53,7 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu);
int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
-int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
+int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu);
void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index b907245d3d96..5bcc169c1189 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -145,6 +145,24 @@ static const struct adreno_info gpulist[] = {
.init = a5xx_gpu_init,
.zapfw = "a530_zap.mdt",
}, {
+ .rev = ADRENO_REV(5, 4, 0, 2),
+ .revn = 540,
+ .name = "A540",
+ .fw = {
+ [ADRENO_FW_PM4] = "a530_pm4.fw",
+ [ADRENO_FW_PFP] = "a530_pfp.fw",
+ [ADRENO_FW_GPMU] = "a540_gpmu.fw2",
+ },
+ .gmem = SZ_1M,
+ /*
+ * Increase inactive period to 250 to avoid bouncing
+ * the GDSC which appears to make it grumpy
+ */
+ .inactive_period = 250,
+ .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE,
+ .init = a5xx_gpu_init,
+ .zapfw = "a540_zap.mdt",
+ }, {
.rev = ADRENO_REV(6, 3, 0, ANY_ID),
.revn = 630,
.name = "A630",
@@ -351,7 +369,7 @@ static void adreno_unbind(struct device *dev, struct device *master,
{
struct msm_gpu *gpu = dev_get_drvdata(dev);
- gpu->funcs->pm_suspend(gpu);
+ pm_runtime_force_suspend(dev);
gpu->funcs->destroy(gpu);
set_gpu_pdev(dev_get_drvdata(master), NULL);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 6f7f4114afcf..3db8e499d4c5 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -67,7 +67,6 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname,
return ret;
mem_phys = r.start;
- mem_size = resource_size(&r);
/* Request the MDT file for the firmware */
fw = adreno_request_fw(to_adreno_gpu(gpu), fwname);
@@ -83,6 +82,13 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname,
goto out;
}
+ if (mem_size > resource_size(&r)) {
+ DRM_DEV_ERROR(dev,
+ "memory region is too small to load the MDT\n");
+ ret = -E2BIG;
+ goto out;
+ }
+
/* Allocate memory for the firmware image */
mem_region = memremap(mem_phys, mem_size, MEMREMAP_WC);
if (!mem_region) {
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 0925606ec9b5..d67c1a69c49a 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -61,6 +61,7 @@ enum {
enum adreno_quirks {
ADRENO_QUIRK_TWO_PASS_USE_WFI = 1,
ADRENO_QUIRK_FAULT_DETECT_MASK = 2,
+ ADRENO_QUIRK_LMLOADKILL_DISABLE = 3,
};
struct adreno_rev {
@@ -221,6 +222,11 @@ static inline int adreno_is_a530(struct adreno_gpu *gpu)
return gpu->revn == 530;
}
+static inline int adreno_is_a540(struct adreno_gpu *gpu)
+{
+ return gpu->revn == 540;
+}
+
int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value);
const struct firmware *adreno_request_fw(struct adreno_gpu *adreno_gpu,
const char *fwname);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
index cd6bde12029e..5cda96875e03 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
@@ -69,7 +69,6 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms,
struct dpu_core_perf_params *perf)
{
struct dpu_crtc_state *dpu_cstate;
- int i;
if (!kms || !kms->catalog || !crtc || !state || !perf) {
DPU_ERROR("invalid parameters\n");
@@ -80,35 +79,24 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms,
memset(perf, 0, sizeof(struct dpu_core_perf_params));
if (!dpu_cstate->bw_control) {
- for (i = 0; i < DPU_CORE_PERF_DATA_BUS_ID_MAX; i++) {
- perf->bw_ctl[i] = kms->catalog->perf.max_bw_high *
+ perf->bw_ctl = kms->catalog->perf.max_bw_high *
1000ULL;
- perf->max_per_pipe_ib[i] = perf->bw_ctl[i];
- }
+ perf->max_per_pipe_ib = perf->bw_ctl;
perf->core_clk_rate = kms->perf.max_core_clk_rate;
} else if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) {
- for (i = 0; i < DPU_CORE_PERF_DATA_BUS_ID_MAX; i++) {
- perf->bw_ctl[i] = 0;
- perf->max_per_pipe_ib[i] = 0;
- }
+ perf->bw_ctl = 0;
+ perf->max_per_pipe_ib = 0;
perf->core_clk_rate = 0;
} else if (kms->perf.perf_tune.mode == DPU_PERF_MODE_FIXED) {
- for (i = 0; i < DPU_CORE_PERF_DATA_BUS_ID_MAX; i++) {
- perf->bw_ctl[i] = kms->perf.fix_core_ab_vote;
- perf->max_per_pipe_ib[i] = kms->perf.fix_core_ib_vote;
- }
+ perf->bw_ctl = kms->perf.fix_core_ab_vote;
+ perf->max_per_pipe_ib = kms->perf.fix_core_ib_vote;
perf->core_clk_rate = kms->perf.fix_core_clk_rate;
}
DPU_DEBUG(
- "crtc=%d clk_rate=%llu core_ib=%llu core_ab=%llu llcc_ib=%llu llcc_ab=%llu mem_ib=%llu mem_ab=%llu\n",
+ "crtc=%d clk_rate=%llu core_ib=%llu core_ab=%llu\n",
crtc->base.id, perf->core_clk_rate,
- perf->max_per_pipe_ib[DPU_CORE_PERF_DATA_BUS_ID_MNOC],
- perf->bw_ctl[DPU_CORE_PERF_DATA_BUS_ID_MNOC],
- perf->max_per_pipe_ib[DPU_CORE_PERF_DATA_BUS_ID_LLCC],
- perf->bw_ctl[DPU_CORE_PERF_DATA_BUS_ID_LLCC],
- perf->max_per_pipe_ib[DPU_CORE_PERF_DATA_BUS_ID_EBI],
- perf->bw_ctl[DPU_CORE_PERF_DATA_BUS_ID_EBI]);
+ perf->max_per_pipe_ib, perf->bw_ctl);
}
int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
@@ -121,7 +109,6 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
struct dpu_crtc_state *dpu_cstate;
struct drm_crtc *tmp_crtc;
struct dpu_kms *kms;
- int i;
if (!crtc || !state) {
DPU_ERROR("invalid crtc\n");
@@ -143,31 +130,25 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
/* obtain new values */
_dpu_core_perf_calc_crtc(kms, crtc, state, &dpu_cstate->new_perf);
- for (i = DPU_CORE_PERF_DATA_BUS_ID_MNOC;
- i < DPU_CORE_PERF_DATA_BUS_ID_MAX; i++) {
- bw_sum_of_intfs = dpu_cstate->new_perf.bw_ctl[i];
- curr_client_type = dpu_crtc_get_client_type(crtc);
+ bw_sum_of_intfs = dpu_cstate->new_perf.bw_ctl;
+ curr_client_type = dpu_crtc_get_client_type(crtc);
- drm_for_each_crtc(tmp_crtc, crtc->dev) {
- if (tmp_crtc->enabled &&
- (dpu_crtc_get_client_type(tmp_crtc) ==
- curr_client_type) &&
- (tmp_crtc != crtc)) {
- struct dpu_crtc_state *tmp_cstate =
- to_dpu_crtc_state(tmp_crtc->state);
-
- DPU_DEBUG("crtc:%d bw:%llu ctrl:%d\n",
- tmp_crtc->base.id,
- tmp_cstate->new_perf.bw_ctl[i],
- tmp_cstate->bw_control);
- /*
- * For bw check only use the bw if the
- * atomic property has been already set
- */
- if (tmp_cstate->bw_control)
- bw_sum_of_intfs +=
- tmp_cstate->new_perf.bw_ctl[i];
- }
+ drm_for_each_crtc(tmp_crtc, crtc->dev) {
+ if (tmp_crtc->enabled &&
+ (dpu_crtc_get_client_type(tmp_crtc) ==
+ curr_client_type) && (tmp_crtc != crtc)) {
+ struct dpu_crtc_state *tmp_cstate =
+ to_dpu_crtc_state(tmp_crtc->state);
+
+ DPU_DEBUG("crtc:%d bw:%llu ctrl:%d\n",
+ tmp_crtc->base.id, tmp_cstate->new_perf.bw_ctl,
+ tmp_cstate->bw_control);
+ /*
+ * For bw check only use the bw if the
+ * atomic property has been already set
+ */
+ if (tmp_cstate->bw_control)
+ bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl;
}
/* convert bandwidth to kb */
@@ -198,9 +179,9 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
}
static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms,
- struct drm_crtc *crtc, u32 bus_id)
+ struct drm_crtc *crtc)
{
- struct dpu_core_perf_params perf = { { 0 } };
+ struct dpu_core_perf_params perf = { 0 };
enum dpu_crtc_client_type curr_client_type
= dpu_crtc_get_client_type(crtc);
struct drm_crtc *tmp_crtc;
@@ -213,13 +194,11 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms,
dpu_crtc_get_client_type(tmp_crtc)) {
dpu_cstate = to_dpu_crtc_state(tmp_crtc->state);
- perf.max_per_pipe_ib[bus_id] =
- max(perf.max_per_pipe_ib[bus_id],
- dpu_cstate->new_perf.max_per_pipe_ib[bus_id]);
+ perf.max_per_pipe_ib = max(perf.max_per_pipe_ib,
+ dpu_cstate->new_perf.max_per_pipe_ib);
- DPU_DEBUG("crtc=%d bus_id=%d bw=%llu\n",
- tmp_crtc->base.id, bus_id,
- dpu_cstate->new_perf.bw_ctl[bus_id]);
+ DPU_DEBUG("crtc=%d bw=%llu\n", tmp_crtc->base.id,
+ dpu_cstate->new_perf.bw_ctl);
}
}
return ret;
@@ -239,7 +218,6 @@ void dpu_core_perf_crtc_release_bw(struct drm_crtc *crtc)
struct dpu_crtc *dpu_crtc;
struct dpu_crtc_state *dpu_cstate;
struct dpu_kms *kms;
- int i;
if (!crtc) {
DPU_ERROR("invalid crtc\n");
@@ -275,10 +253,8 @@ void dpu_core_perf_crtc_release_bw(struct drm_crtc *crtc)
if (kms->perf.enable_bw_release) {
trace_dpu_cmd_release_bw(crtc->base.id);
DPU_DEBUG("Release BW crtc=%d\n", crtc->base.id);
- for (i = 0; i < DPU_CORE_PERF_DATA_BUS_ID_MAX; i++) {
- dpu_crtc->cur_perf.bw_ctl[i] = 0;
- _dpu_core_perf_crtc_update_bus(kms, crtc, i);
- }
+ dpu_crtc->cur_perf.bw_ctl = 0;
+ _dpu_core_perf_crtc_update_bus(kms, crtc);
}
}
@@ -321,11 +297,10 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc,
int params_changed, bool stop_req)
{
struct dpu_core_perf_params *new, *old;
- int update_bus = 0, update_clk = 0;
+ bool update_bus = false, update_clk = false;
u64 clk_rate = 0;
struct dpu_crtc *dpu_crtc;
struct dpu_crtc_state *dpu_cstate;
- int i;
struct msm_drm_private *priv;
struct dpu_kms *kms;
int ret;
@@ -352,62 +327,49 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc,
new = &dpu_cstate->new_perf;
if (crtc->enabled && !stop_req) {
- for (i = 0; i < DPU_CORE_PERF_DATA_BUS_ID_MAX; i++) {
- /*
- * cases for bus bandwidth update.
- * 1. new bandwidth vote - "ab or ib vote" is higher
- * than current vote for update request.
- * 2. new bandwidth vote - "ab or ib vote" is lower
- * than current vote at end of commit or stop.
- */
- if ((params_changed && ((new->bw_ctl[i] >
- old->bw_ctl[i]) ||
- (new->max_per_pipe_ib[i] >
- old->max_per_pipe_ib[i]))) ||
- (!params_changed && ((new->bw_ctl[i] <
- old->bw_ctl[i]) ||
- (new->max_per_pipe_ib[i] <
- old->max_per_pipe_ib[i])))) {
- DPU_DEBUG(
- "crtc=%d p=%d new_bw=%llu,old_bw=%llu\n",
- crtc->base.id, params_changed,
- new->bw_ctl[i], old->bw_ctl[i]);
- old->bw_ctl[i] = new->bw_ctl[i];
- old->max_per_pipe_ib[i] =
- new->max_per_pipe_ib[i];
- update_bus |= BIT(i);
- }
+ /*
+ * cases for bus bandwidth update.
+ * 1. new bandwidth vote - "ab or ib vote" is higher
+ * than current vote for update request.
+ * 2. new bandwidth vote - "ab or ib vote" is lower
+ * than current vote at end of commit or stop.
+ */
+ if ((params_changed && ((new->bw_ctl > old->bw_ctl) ||
+ (new->max_per_pipe_ib > old->max_per_pipe_ib))) ||
+ (!params_changed && ((new->bw_ctl < old->bw_ctl) ||
+ (new->max_per_pipe_ib < old->max_per_pipe_ib)))) {
+ DPU_DEBUG("crtc=%d p=%d new_bw=%llu,old_bw=%llu\n",
+ crtc->base.id, params_changed,
+ new->bw_ctl, old->bw_ctl);
+ old->bw_ctl = new->bw_ctl;
+ old->max_per_pipe_ib = new->max_per_pipe_ib;
+ update_bus = true;
}
if ((params_changed &&
- (new->core_clk_rate > old->core_clk_rate)) ||
- (!params_changed &&
- (new->core_clk_rate < old->core_clk_rate))) {
+ (new->core_clk_rate > old->core_clk_rate)) ||
+ (!params_changed &&
+ (new->core_clk_rate < old->core_clk_rate))) {
old->core_clk_rate = new->core_clk_rate;
- update_clk = 1;
+ update_clk = true;
}
} else {
DPU_DEBUG("crtc=%d disable\n", crtc->base.id);
memset(old, 0, sizeof(*old));
memset(new, 0, sizeof(*new));
- update_bus = ~0;
- update_clk = 1;
+ update_bus = true;
+ update_clk = true;
}
- trace_dpu_perf_crtc_update(crtc->base.id,
- new->bw_ctl[DPU_CORE_PERF_DATA_BUS_ID_MNOC],
- new->bw_ctl[DPU_CORE_PERF_DATA_BUS_ID_LLCC],
- new->bw_ctl[DPU_CORE_PERF_DATA_BUS_ID_EBI],
- new->core_clk_rate, stop_req,
- update_bus, update_clk);
-
- for (i = 0; i < DPU_CORE_PERF_DATA_BUS_ID_MAX; i++) {
- if (update_bus & BIT(i)) {
- ret = _dpu_core_perf_crtc_update_bus(kms, crtc, i);
- if (ret) {
- DPU_ERROR("crtc-%d: failed to update bw vote for bus-%d\n",
- crtc->base.id, i);
- return ret;
- }
+
+ trace_dpu_perf_crtc_update(crtc->base.id, new->bw_ctl,
+ new->core_clk_rate, stop_req, update_bus, update_clk);
+
+ if (update_bus) {
+ ret = _dpu_core_perf_crtc_update_bus(kms, crtc);
+ if (ret) {
+ DPU_ERROR("crtc-%d: failed to update bus bw vote\n",
+ crtc->base.id);
+ return ret;
}
}
@@ -498,8 +460,6 @@ int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, struct dentry *parent)
struct dentry *entry;
entry = debugfs_create_dir("core_perf", parent);
- if (IS_ERR_OR_NULL(entry))
- return -EINVAL;
debugfs_create_u64("max_core_clk_rate", 0600, entry,
&perf->max_core_clk_rate);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
index 6f0f1710023b..cf4b9b5964c6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
@@ -34,8 +34,8 @@ enum dpu_core_perf_data_bus_id {
* @core_clk_rate: core clock rate request
*/
struct dpu_core_perf_params {
- u64 max_per_pipe_ib[DPU_CORE_PERF_DATA_BUS_ID_MAX];
- u64 bw_ctl[DPU_CORE_PERF_DATA_BUS_ID_MAX];
+ u64 max_per_pipe_ib;
+ u64 bw_ctl;
u64 core_clk_rate;
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 3772f745589d..40ea6286eac1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1233,19 +1233,14 @@ static int dpu_crtc_debugfs_state_show(struct seq_file *s, void *v)
{
struct drm_crtc *crtc = (struct drm_crtc *) s->private;
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
- int i;
seq_printf(s, "client type: %d\n", dpu_crtc_get_client_type(crtc));
seq_printf(s, "intf_mode: %d\n", dpu_crtc_get_intf_mode(crtc));
seq_printf(s, "core_clk_rate: %llu\n",
dpu_crtc->cur_perf.core_clk_rate);
- for (i = DPU_CORE_PERF_DATA_BUS_ID_MNOC;
- i < DPU_CORE_PERF_DATA_BUS_ID_MAX; i++) {
- seq_printf(s, "bw_ctl[%d]: %llu\n", i,
- dpu_crtc->cur_perf.bw_ctl[i]);
- seq_printf(s, "max_per_pipe_ib[%d]: %llu\n", i,
- dpu_crtc->cur_perf.max_per_pipe_ib[i]);
- }
+ seq_printf(s, "bw_ctl: %llu\n", dpu_crtc->cur_perf.bw_ctl);
+ seq_printf(s, "max_per_pipe_ib: %llu\n",
+ dpu_crtc->cur_perf.max_per_pipe_ib);
return 0;
}
@@ -1264,10 +1259,7 @@ static int _dpu_crtc_init_debugfs(struct drm_crtc *crtc)
dpu_crtc->debugfs_root = debugfs_create_dir(dpu_crtc->name,
crtc->dev->primary->debugfs_root);
- if (!dpu_crtc->debugfs_root)
- return -ENOMEM;
- /* don't error check these */
debugfs_create_file("status", 0400,
dpu_crtc->debugfs_root,
dpu_crtc, &debugfs_status_fops);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 82bf16d61a45..1cf4e306fccf 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -622,9 +622,6 @@ static int dpu_encoder_virt_atomic_check(
}
}
- if (!ret)
- drm_mode_set_crtcinfo(adj_mode, 0);
-
trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags,
adj_mode->private_flags);
@@ -1985,8 +1982,6 @@ static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc)
/* create overall sub-directory for the encoder */
dpu_enc->debugfs_root = debugfs_create_dir(name,
drm_enc->dev->primary->debugfs_root);
- if (!dpu_enc->debugfs_root)
- return -ENOMEM;
/* don't error check these */
debugfs_create_file("status", 0600,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
index 2307c431a894..24ab6249083a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
@@ -471,90 +471,6 @@ static const struct dpu_format dpu_format_map[] = {
};
/*
- * A5x tile formats tables:
- * These tables hold the A5x tile formats supported.
- */
-static const struct dpu_format dpu_format_map_tile[] = {
- INTERLEAVED_RGB_FMT_TILED(BGR565,
- 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
- C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
- false, 2, 0,
- DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
-
- INTERLEAVED_RGB_FMT_TILED(ARGB8888,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
- true, 4, 0,
- DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
-
- INTERLEAVED_RGB_FMT_TILED(ABGR8888,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
- true, 4, 0,
- DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
-
- INTERLEAVED_RGB_FMT_TILED(XBGR8888,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
- false, 4, 0,
- DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
-
- INTERLEAVED_RGB_FMT_TILED(RGBA8888,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
- true, 4, 0,
- DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
-
- INTERLEAVED_RGB_FMT_TILED(BGRA8888,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
- true, 4, 0,
- DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
-
- INTERLEAVED_RGB_FMT_TILED(BGRX8888,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
- false, 4, 0,
- DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
-
- INTERLEAVED_RGB_FMT_TILED(XRGB8888,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
- false, 4, 0,
- DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
-
- INTERLEAVED_RGB_FMT_TILED(RGBX8888,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
- false, 4, 0,
- DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
-
- INTERLEAVED_RGB_FMT_TILED(ABGR2101010,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
- true, 4, DPU_FORMAT_FLAG_DX,
- DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
-
- INTERLEAVED_RGB_FMT_TILED(XBGR2101010,
- COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
- true, 4, DPU_FORMAT_FLAG_DX,
- DPU_FETCH_UBWC, 1, DPU_TILE_HEIGHT_TILED),
-
- PSEUDO_YUV_FMT_TILED(NV12,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C2_R_Cr,
- DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
- DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_NV12),
-
- PSEUDO_YUV_FMT_TILED(NV21,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C1_B_Cb,
- DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV,
- DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_NV12),
-};
-
-/*
* UBWC formats table:
* This table holds the UBWC formats supported.
* If a compression ratio needs to be used for this or any other format,
@@ -599,32 +515,6 @@ static const struct dpu_format dpu_format_map_ubwc[] = {
DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12),
};
-static const struct dpu_format dpu_format_map_p010[] = {
- PSEUDO_YUV_FMT_LOOSE(NV12,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C2_R_Cr,
- DPU_CHROMA_420, (DPU_FORMAT_FLAG_YUV | DPU_FORMAT_FLAG_DX),
- DPU_FETCH_LINEAR, 2),
-};
-
-static const struct dpu_format dpu_format_map_p010_ubwc[] = {
- PSEUDO_YUV_FMT_LOOSE_TILED(NV12,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C2_R_Cr,
- DPU_CHROMA_420, (DPU_FORMAT_FLAG_YUV | DPU_FORMAT_FLAG_DX |
- DPU_FORMAT_FLAG_COMPRESSED),
- DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12),
-};
-
-static const struct dpu_format dpu_format_map_tp10_ubwc[] = {
- PSEUDO_YUV_FMT_TILED(NV12,
- 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C2_R_Cr,
- DPU_CHROMA_420, (DPU_FORMAT_FLAG_YUV | DPU_FORMAT_FLAG_DX |
- DPU_FORMAT_FLAG_COMPRESSED),
- DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12),
-};
-
/* _dpu_get_v_h_subsample_rate - Get subsample rates for all formats we support
* Note: Not using the drm_format_*_subsampling since we have formats
*/
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c
index 95cfd106e1a7..71b6987bff1e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c
@@ -106,9 +106,9 @@ int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable)
rc = -EPERM;
}
- if (rc) {
- msm_dss_enable_clk(&clk_arry[i],
- i, false);
+ if (rc && i) {
+ msm_dss_enable_clk(&clk_arry[i - 1],
+ i - 1, false);
break;
}
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 885bf88afa3e..435b846f9f52 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -56,7 +56,7 @@ static const char * const iommu_ports[] = {
#define DPU_DEBUGFS_HWMASKNAME "hw_log_mask"
static int dpu_kms_hw_init(struct msm_kms *kms);
-static int _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms);
+static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms);
static unsigned long dpu_iomap_size(struct platform_device *pdev,
const char *name)
@@ -142,8 +142,6 @@ static void dpu_debugfs_danger_init(struct dpu_kms *dpu_kms,
struct dentry *parent)
{
struct dentry *entry = debugfs_create_dir("danger", parent);
- if (IS_ERR_OR_NULL(entry))
- return;
debugfs_create_file("danger_status", 0600, entry,
dpu_kms, &dpu_debugfs_danger_stats_fops);
@@ -218,32 +216,29 @@ void dpu_debugfs_setup_regset32(struct dpu_debugfs_regset32 *regset,
}
}
-void *dpu_debugfs_create_regset32(const char *name, umode_t mode,
+void dpu_debugfs_create_regset32(const char *name, umode_t mode,
void *parent, struct dpu_debugfs_regset32 *regset)
{
if (!name || !regset || !regset->dpu_kms || !regset->blk_len)
- return NULL;
+ return;
/* make sure offset is a multiple of 4 */
regset->offset = round_down(regset->offset, 4);
- return debugfs_create_file(name, mode, parent,
- regset, &dpu_fops_regset32);
+ debugfs_create_file(name, mode, parent, regset, &dpu_fops_regset32);
}
-static int _dpu_debugfs_init(struct dpu_kms *dpu_kms)
+static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor)
{
+ struct dpu_kms *dpu_kms = to_dpu_kms(kms);
void *p = dpu_hw_util_get_log_mask_ptr();
struct dentry *entry;
if (!p)
return -EINVAL;
- entry = debugfs_create_dir("debug", dpu_kms->dev->primary->debugfs_root);
- if (IS_ERR_OR_NULL(entry))
- return -ENODEV;
+ entry = debugfs_create_dir("debug", minor->debugfs_root);
- /* allow root to be NULL */
debugfs_create_x32(DPU_DEBUGFS_HWMASKNAME, 0600, entry, p);
dpu_debugfs_danger_init(dpu_kms, entry);
@@ -578,13 +573,6 @@ fail:
return ret;
}
-#ifdef CONFIG_DEBUG_FS
-static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor)
-{
- return _dpu_debugfs_init(to_dpu_kms(kms));
-}
-#endif
-
static long dpu_kms_round_pixclk(struct msm_kms *kms, unsigned long rate,
struct drm_encoder *encoder)
{
@@ -725,17 +713,20 @@ static const struct msm_kms_funcs kms_funcs = {
#endif
};
-static int _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms)
+static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms)
{
struct msm_mmu *mmu;
+ if (!dpu_kms->base.aspace)
+ return;
+
mmu = dpu_kms->base.aspace->mmu;
mmu->funcs->detach(mmu, (const char **)iommu_ports,
ARRAY_SIZE(iommu_ports));
msm_gem_address_space_put(dpu_kms->base.aspace);
- return 0;
+ dpu_kms->base.aspace = NULL;
}
static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms)
@@ -754,25 +745,20 @@ static int _dpu_kms_mmu_init(struct dpu_kms *dpu_kms)
aspace = msm_gem_address_space_create(dpu_kms->dev->dev,
domain, "dpu1");
if (IS_ERR(aspace)) {
- ret = PTR_ERR(aspace);
- goto fail;
+ iommu_domain_free(domain);
+ return PTR_ERR(aspace);
}
- dpu_kms->base.aspace = aspace;
-
ret = aspace->mmu->funcs->attach(aspace->mmu, iommu_ports,
ARRAY_SIZE(iommu_ports));
if (ret) {
DPU_ERROR("failed to attach iommu %d\n", ret);
msm_gem_address_space_put(aspace);
- goto fail;
+ return ret;
}
+ dpu_kms->base.aspace = aspace;
return 0;
-fail:
- _dpu_kms_mmu_destroy(dpu_kms);
-
- return ret;
}
static struct dss_clk *_dpu_kms_get_clk(struct dpu_kms *dpu_kms,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 31e9ef96ca5d..e9f998344838 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -197,12 +197,8 @@ void dpu_debugfs_setup_regset32(struct dpu_debugfs_regset32 *regset,
* @mode: File mode within debugfs
* @parent: Parent directory entry within debugfs, can be NULL
* @regset: Pointer to persistent register block definition
- *
- * Return: dentry pointer for newly created file, use either debugfs_remove()
- * or debugfs_remove_recursive() (on a parent directory) to remove the
- * file
*/
-void *dpu_debugfs_create_regset32(const char *name, umode_t mode,
+void dpu_debugfs_create_regset32(const char *name, umode_t mode,
void *parent, struct dpu_debugfs_regset32 *regset);
/**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
index 7316b4ab1b85..986915bbbc02 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
@@ -4,11 +4,15 @@
*/
#include "dpu_kms.h"
+#include <linux/interconnect.h>
#define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
#define HW_INTR_STATUS 0x0010
+/* Max BW defined in KBps */
+#define MAX_BW 6800000
+
struct dpu_irq_controller {
unsigned long enabled_mask;
struct irq_domain *domain;
@@ -21,8 +25,40 @@ struct dpu_mdss {
u32 hwversion;
struct dss_module_power mp;
struct dpu_irq_controller irq_controller;
+ struct icc_path *path[2];
+ u32 num_paths;
};
+static int dpu_mdss_parse_data_bus_icc_path(struct drm_device *dev,
+ struct dpu_mdss *dpu_mdss)
+{
+ struct icc_path *path0 = of_icc_get(dev->dev, "mdp0-mem");
+ struct icc_path *path1 = of_icc_get(dev->dev, "mdp1-mem");
+
+ if (IS_ERR_OR_NULL(path0))
+ return PTR_ERR_OR_ZERO(path0);
+
+ dpu_mdss->path[0] = path0;
+ dpu_mdss->num_paths = 1;
+
+ if (!IS_ERR_OR_NULL(path1)) {
+ dpu_mdss->path[1] = path1;
+ dpu_mdss->num_paths++;
+ }
+
+ return 0;
+}
+
+static void dpu_mdss_icc_request_bw(struct msm_mdss *mdss)
+{
+ struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
+ int i;
+ u64 avg_bw = dpu_mdss->num_paths ? MAX_BW / dpu_mdss->num_paths : 0;
+
+ for (i = 0; i < dpu_mdss->num_paths; i++)
+ icc_set_bw(dpu_mdss->path[i], avg_bw, kBps_to_icc(MAX_BW));
+}
+
static void dpu_mdss_irq(struct irq_desc *desc)
{
struct dpu_mdss *dpu_mdss = irq_desc_get_handler_data(desc);
@@ -136,6 +172,8 @@ static int dpu_mdss_enable(struct msm_mdss *mdss)
struct dss_module_power *mp = &dpu_mdss->mp;
int ret;
+ dpu_mdss_icc_request_bw(mdss);
+
ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
if (ret)
DPU_ERROR("clock enable failed, ret:%d\n", ret);
@@ -147,12 +185,15 @@ static int dpu_mdss_disable(struct msm_mdss *mdss)
{
struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
struct dss_module_power *mp = &dpu_mdss->mp;
- int ret;
+ int ret, i;
ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, false);
if (ret)
DPU_ERROR("clock disable failed, ret:%d\n", ret);
+ for (i = 0; i < dpu_mdss->num_paths; i++)
+ icc_set_bw(dpu_mdss->path[i], 0, 0);
+
return ret;
}
@@ -163,6 +204,7 @@ static void dpu_mdss_destroy(struct drm_device *dev)
struct dpu_mdss *dpu_mdss = to_dpu_mdss(priv->mdss);
struct dss_module_power *mp = &dpu_mdss->mp;
int irq;
+ int i;
pm_runtime_suspend(dev->dev);
pm_runtime_disable(dev->dev);
@@ -172,6 +214,9 @@ static void dpu_mdss_destroy(struct drm_device *dev)
msm_dss_put_clk(mp->clk_config, mp->num_clk);
devm_kfree(&pdev->dev, mp->clk_config);
+ for (i = 0; i < dpu_mdss->num_paths; i++)
+ icc_put(dpu_mdss->path[i]);
+
if (dpu_mdss->mmio)
devm_iounmap(&pdev->dev, dpu_mdss->mmio);
dpu_mdss->mmio = NULL;
@@ -211,6 +256,10 @@ int dpu_mdss_init(struct drm_device *dev)
}
dpu_mdss->mmio_len = resource_size(res);
+ ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss);
+ if (ret)
+ return ret;
+
mp = &dpu_mdss->mp;
ret = msm_dss_parse_clock(pdev, mp);
if (ret) {
@@ -232,14 +281,16 @@ int dpu_mdss_init(struct drm_device *dev)
irq_set_chained_handler_and_data(irq, dpu_mdss_irq,
dpu_mdss);
+ priv->mdss = &dpu_mdss->base;
+
pm_runtime_enable(dev->dev);
+ dpu_mdss_icc_request_bw(priv->mdss);
+
pm_runtime_get_sync(dev->dev);
dpu_mdss->hwversion = readl_relaxed(dpu_mdss->mmio);
pm_runtime_put_sync(dev->dev);
- priv->mdss = &dpu_mdss->base;
-
return ret;
irq_error:
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index d831cedb55ec..1858b40b18d8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -21,6 +21,7 @@
#include <linux/debugfs.h>
#include <linux/dma-buf.h>
+#include <drm/drm_damage_helper.h>
#include <drm/drm_atomic_uapi.h>
#include "msm_drv.h"
@@ -1324,9 +1325,6 @@ static int _dpu_plane_init_debugfs(struct drm_plane *plane)
debugfs_create_dir(pdpu->pipe_name,
plane->dev->primary->debugfs_root);
- if (!pdpu->debugfs_root)
- return -ENOMEM;
-
/* don't error check these */
debugfs_create_x32("features", 0600,
pdpu->debugfs_root, &pdpu->features);
@@ -1535,6 +1533,8 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
if (ret)
DPU_ERROR("failed to install zpos property, rc = %d\n", ret);
+ drm_plane_enable_fb_damage_clips(plane);
+
/* success! finalize initialization */
drm_plane_helper_add(plane, &dpu_plane_helper_funcs);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
index 7dac604b268d..765484437d11 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
@@ -138,16 +138,12 @@ TRACE_EVENT(dpu_trace_counter,
)
TRACE_EVENT(dpu_perf_crtc_update,
- TP_PROTO(u32 crtc, u64 bw_ctl_mnoc, u64 bw_ctl_llcc,
- u64 bw_ctl_ebi, u32 core_clk_rate,
- bool stop_req, u32 update_bus, u32 update_clk),
- TP_ARGS(crtc, bw_ctl_mnoc, bw_ctl_llcc, bw_ctl_ebi, core_clk_rate,
- stop_req, update_bus, update_clk),
+ TP_PROTO(u32 crtc, u64 bw_ctl, u32 core_clk_rate,
+ bool stop_req, bool update_bus, bool update_clk),
+ TP_ARGS(crtc, bw_ctl, core_clk_rate, stop_req, update_bus, update_clk),
TP_STRUCT__entry(
__field(u32, crtc)
- __field(u64, bw_ctl_mnoc)
- __field(u64, bw_ctl_llcc)
- __field(u64, bw_ctl_ebi)
+ __field(u64, bw_ctl)
__field(u32, core_clk_rate)
__field(bool, stop_req)
__field(u32, update_bus)
@@ -155,20 +151,16 @@ TRACE_EVENT(dpu_perf_crtc_update,
),
TP_fast_assign(
__entry->crtc = crtc;
- __entry->bw_ctl_mnoc = bw_ctl_mnoc;
- __entry->bw_ctl_llcc = bw_ctl_llcc;
- __entry->bw_ctl_ebi = bw_ctl_ebi;
+ __entry->bw_ctl = bw_ctl;
__entry->core_clk_rate = core_clk_rate;
__entry->stop_req = stop_req;
__entry->update_bus = update_bus;
__entry->update_clk = update_clk;
),
TP_printk(
- "crtc=%d bw_mnoc=%llu bw_llcc=%llu bw_ebi=%llu clk_rate=%u stop_req=%d u_bus=%d u_clk=%d",
+ "crtc=%d bw_ctl=%llu clk_rate=%u stop_req=%d u_bus=%d u_clk=%d",
__entry->crtc,
- __entry->bw_ctl_mnoc,
- __entry->bw_ctl_llcc,
- __entry->bw_ctl_ebi,
+ __entry->bw_ctl,
__entry->core_clk_rate,
__entry->stop_req,
__entry->update_bus,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c
index 3c9236bb291c..8bc3aea7cd86 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c
@@ -310,8 +310,6 @@ void dpu_debugfs_vbif_init(struct dpu_kms *dpu_kms, struct dentry *debugfs_root)
int i, j;
entry = debugfs_create_dir("vbif", debugfs_root);
- if (IS_ERR_OR_NULL(entry))
- return;
for (i = 0; i < dpu_kms->catalog->vbif_count; i++) {
struct dpu_vbif_cfg *vbif = &dpu_kms->catalog->vbif[i];
@@ -319,8 +317,6 @@ void dpu_debugfs_vbif_init(struct dpu_kms *dpu_kms, struct dentry *debugfs_root)
snprintf(vbif_name, sizeof(vbif_name), "%d", vbif->id);
debugfs_vbif = debugfs_create_dir(vbif_name, entry);
- if (IS_ERR_OR_NULL(debugfs_vbif))
- continue;
debugfs_create_u32("features", 0600, debugfs_vbif,
(u32 *)&vbif->features);
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
index 005066f7154d..2d46d1126283 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
@@ -15,6 +15,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <drm/drm_damage_helper.h>
#include "mdp4_kms.h"
#define DOWN_SCALE_MAX 8
@@ -391,6 +392,8 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
mdp4_plane_install_properties(plane, &plane->base);
+ drm_plane_enable_fb_damage_clips(plane);
+
return plane;
fail:
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
index f86351b16e0f..dd1daf0e305a 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
@@ -713,7 +713,7 @@ fail:
if (cfg_handler)
mdp5_cfg_destroy(cfg_handler);
- return NULL;
+ return ERR_PTR(ret);
}
static struct mdp5_cfg_platform *mdp5_get_config(struct platform_device *dev)
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 97179bec8902..1c55401956c4 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -16,6 +16,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/interconnect.h>
#include <linux/of_irq.h>
#include "msm_drv.h"
@@ -1048,9 +1049,46 @@ static const struct component_ops mdp5_ops = {
.unbind = mdp5_unbind,
};
+static int mdp5_setup_interconnect(struct platform_device *pdev)
+{
+ struct icc_path *path0 = of_icc_get(&pdev->dev, "mdp0-mem");
+ struct icc_path *path1 = of_icc_get(&pdev->dev, "mdp1-mem");
+ struct icc_path *path_rot = of_icc_get(&pdev->dev, "rotator-mem");
+
+ if (IS_ERR(path0))
+ return PTR_ERR(path0);
+
+ if (!path0) {
+ /* no interconnect support is not necessarily a fatal
+ * condition, the platform may simply not have an
+ * interconnect driver yet. But warn about it in case
+ * bootloader didn't setup bus clocks high enough for
+ * scanout.
+ */
+ dev_warn(&pdev->dev, "No interconnect support may cause display underflows!\n");
+ return 0;
+ }
+
+ icc_set_bw(path0, 0, MBps_to_icc(6400));
+
+ if (!IS_ERR_OR_NULL(path1))
+ icc_set_bw(path1, 0, MBps_to_icc(6400));
+ if (!IS_ERR_OR_NULL(path_rot))
+ icc_set_bw(path_rot, 0, MBps_to_icc(6400));
+
+ return 0;
+}
+
static int mdp5_dev_probe(struct platform_device *pdev)
{
+ int ret;
+
DBG("");
+
+ ret = mdp5_setup_interconnect(pdev);
+ if (ret)
+ return ret;
+
return component_add(&pdev->dev, &mdp5_ops);
}
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
index 1105c2433f14..91609bde033a 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
@@ -16,6 +16,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <drm/drm_damage_helper.h>
#include <drm/drm_print.h>
#include "mdp5_kms.h"
@@ -1099,6 +1100,8 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
mdp5_plane_install_properties(plane, &plane->base);
+ drm_plane_enable_fb_damage_clips(plane);
+
return plane;
fail:
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index ada942498b4e..55ea4bc2ee9c 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -242,6 +242,8 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
goto fail;
}
+ msm_dsi_manager_setup_encoder(msm_dsi->id);
+
priv->bridges[priv->num_bridges++] = msm_dsi->bridge;
priv->connectors[priv->num_connectors++] = msm_dsi->connector;
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 20a5d3cb0cab..0da8a4e428ad 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -71,7 +71,6 @@ struct msm_dsi {
*/
struct drm_panel *panel;
struct drm_bridge *external_bridge;
- unsigned long device_flags;
struct device *phy_dev;
bool phy_enabled;
@@ -89,7 +88,7 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id);
struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id);
int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg);
bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len);
-void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags);
+void msm_dsi_manager_setup_encoder(int id);
int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
bool msm_dsi_manager_validate_current_config(u8 id);
@@ -161,8 +160,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host,
int msm_dsi_host_power_off(struct mipi_dsi_host *host);
int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
const struct drm_display_mode *mode);
-struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
- unsigned long *panel_flags);
+struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host);
+unsigned long msm_dsi_host_get_mode_flags(struct mipi_dsi_host *host);
struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host);
int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer);
void msm_dsi_host_unregister(struct mipi_dsi_host *host);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
index 9ddf16380289..b7b7c1a9164a 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -110,6 +110,25 @@ static const struct msm_dsi_config msm8996_dsi_cfg = {
.num_dsi = 2,
};
+static const char * const dsi_msm8998_bus_clk_names[] = {
+ "iface", "bus", "core",
+};
+
+static const struct msm_dsi_config msm8998_dsi_cfg = {
+ .io_offset = DSI_6G_REG_SHIFT,
+ .reg_cfg = {
+ .num = 2,
+ .regs = {
+ {"vdd", 367000, 16 }, /* 0.9 V */
+ {"vdda", 62800, 2 }, /* 1.2 V */
+ },
+ },
+ .bus_clk_names = dsi_msm8998_bus_clk_names,
+ .num_bus_clks = ARRAY_SIZE(dsi_msm8998_bus_clk_names),
+ .io_start = { 0xc994000, 0xc996000 },
+ .num_dsi = 2,
+};
+
static const char * const dsi_sdm845_bus_clk_names[] = {
"iface", "bus",
};
@@ -178,6 +197,8 @@ static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
&msm8916_dsi_cfg, &msm_dsi_6g_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_4_1,
&msm8996_dsi_cfg, &msm_dsi_6g_host_ops},
+ {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_2_0,
+ &msm8998_dsi_cfg, &msm_dsi_6g_v2_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_2_1,
&sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops},
};
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
index a6a3d2bad263..e2b7a7dfbe49 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
@@ -17,6 +17,7 @@
#define MSM_DSI_6G_VER_MINOR_V1_3 0x10030000
#define MSM_DSI_6G_VER_MINOR_V1_3_1 0x10030001
#define MSM_DSI_6G_VER_MINOR_V1_4_1 0x10040001
+#define MSM_DSI_6G_VER_MINOR_V2_2_0 0x20000000
#define MSM_DSI_6G_VER_MINOR_V2_2_1 0x20020001
#define MSM_DSI_V2_VER_MINOR_8064 0x0
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index dbf490176c2c..aa35d18ab43c 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1041,7 +1041,7 @@ static void dsi_wait4video_done(struct msm_dsi_host *msm_host)
ret = wait_for_completion_timeout(&msm_host->video_comp,
msecs_to_jiffies(70));
- if (ret <= 0)
+ if (ret == 0)
DRM_DEV_ERROR(dev, "wait for video done timed out\n");
dsi_intr_ctrl(msm_host, DSI_IRQ_MASK_VIDEO_DONE, 0);
@@ -1590,8 +1590,6 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
msm_host->format = dsi->format;
msm_host->mode_flags = dsi->mode_flags;
- msm_dsi_manager_attach_dsi_device(msm_host->id, dsi->mode_flags);
-
/* Some gpios defined in panel DT need to be controlled by host */
ret = dsi_host_init_panel_gpios(msm_host, &dsi->dev);
if (ret)
@@ -2434,17 +2432,14 @@ int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
return 0;
}
-struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
- unsigned long *panel_flags)
+struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host)
{
- struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
- struct drm_panel *panel;
-
- panel = of_drm_find_panel(msm_host->device_node);
- if (panel_flags)
- *panel_flags = msm_host->mode_flags;
+ return of_drm_find_panel(to_msm_dsi_host(host)->device_node);
+}
- return panel;
+unsigned long msm_dsi_host_get_mode_flags(struct mipi_dsi_host *host)
+{
+ return to_msm_dsi_host(host)->mode_flags;
}
struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host)
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index ec6cb0f7f206..271aa7bbca92 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -225,64 +225,80 @@ static int dsi_mgr_bridge_get_id(struct drm_bridge *bridge)
return dsi_bridge->id;
}
-static enum drm_connector_status dsi_mgr_connector_detect(
- struct drm_connector *connector, bool force)
+static bool dsi_mgr_is_cmd_mode(struct msm_dsi *msm_dsi)
+{
+ unsigned long host_flags = msm_dsi_host_get_mode_flags(msm_dsi->host);
+ return !(host_flags & MIPI_DSI_MODE_VIDEO);
+}
+
+void msm_dsi_manager_setup_encoder(int id)
{
- int id = dsi_mgr_connector_get_id(connector);
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
- struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
- struct msm_drm_private *priv = connector->dev->dev_private;
+ struct msm_drm_private *priv = msm_dsi->dev->dev_private;
struct msm_kms *kms = priv->kms;
+ struct drm_encoder *encoder = msm_dsi_get_encoder(msm_dsi);
- DBG("id=%d", id);
- if (!msm_dsi->panel) {
- msm_dsi->panel = msm_dsi_host_get_panel(msm_dsi->host,
- &msm_dsi->device_flags);
-
- /* There is only 1 panel in the global panel list
- * for dual DSI mode. Therefore slave dsi should get
- * the drm_panel instance from master dsi, and
- * keep using the panel flags got from the current DSI link.
- */
- if (!msm_dsi->panel && IS_DUAL_DSI() &&
- !IS_MASTER_DSI_LINK(id) && other_dsi)
- msm_dsi->panel = msm_dsi_host_get_panel(
- other_dsi->host, NULL);
+ if (encoder && kms->funcs->set_encoder_mode)
+ kms->funcs->set_encoder_mode(kms, encoder,
+ dsi_mgr_is_cmd_mode(msm_dsi));
+}
+static int msm_dsi_manager_panel_init(struct drm_connector *conn, u8 id)
+{
+ struct msm_drm_private *priv = conn->dev->dev_private;
+ struct msm_kms *kms = priv->kms;
+ struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+ struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
+ struct msm_dsi *master_dsi, *slave_dsi;
+ struct drm_panel *panel;
- if (msm_dsi->panel && kms->funcs->set_encoder_mode) {
- bool cmd_mode = !(msm_dsi->device_flags &
- MIPI_DSI_MODE_VIDEO);
- struct drm_encoder *encoder =
- msm_dsi_get_encoder(msm_dsi);
+ if (IS_DUAL_DSI() && !IS_MASTER_DSI_LINK(id)) {
+ master_dsi = other_dsi;
+ slave_dsi = msm_dsi;
+ } else {
+ master_dsi = msm_dsi;
+ slave_dsi = other_dsi;
+ }
- kms->funcs->set_encoder_mode(kms, encoder, cmd_mode);
- }
+ /*
+ * There is only 1 panel in the global panel list for dual DSI mode.
+ * Therefore slave dsi should get the drm_panel instance from master
+ * dsi.
+ */
+ panel = msm_dsi_host_get_panel(master_dsi->host);
+ if (IS_ERR(panel)) {
+ DRM_ERROR("Could not find panel for %u (%ld)\n", msm_dsi->id,
+ PTR_ERR(panel));
+ return PTR_ERR(panel);
+ }
- if (msm_dsi->panel && IS_DUAL_DSI())
- drm_object_attach_property(&connector->base,
- connector->dev->mode_config.tile_property, 0);
+ if (!panel || !IS_DUAL_DSI())
+ goto out;
- /* Set split display info to kms once dual DSI panel is
- * connected to both hosts.
- */
- if (msm_dsi->panel && IS_DUAL_DSI() &&
- other_dsi && other_dsi->panel) {
- bool cmd_mode = !(msm_dsi->device_flags &
- MIPI_DSI_MODE_VIDEO);
- struct drm_encoder *encoder = msm_dsi_get_encoder(
- dsi_mgr_get_dsi(DSI_ENCODER_MASTER));
- struct drm_encoder *slave_enc = msm_dsi_get_encoder(
- dsi_mgr_get_dsi(DSI_ENCODER_SLAVE));
-
- if (kms->funcs->set_split_display)
- kms->funcs->set_split_display(kms, encoder,
- slave_enc, cmd_mode);
- else
- pr_err("mdp does not support dual DSI\n");
- }
+ drm_object_attach_property(&conn->base,
+ conn->dev->mode_config.tile_property, 0);
+
+ /*
+ * Set split display info to kms once dual DSI panel is connected to
+ * both hosts.
+ */
+ if (other_dsi && other_dsi->panel && kms->funcs->set_split_display) {
+ kms->funcs->set_split_display(kms, master_dsi->encoder,
+ slave_dsi->encoder,
+ dsi_mgr_is_cmd_mode(msm_dsi));
}
+out:
+ msm_dsi->panel = panel;
+ return 0;
+}
+
+static enum drm_connector_status dsi_mgr_connector_detect(
+ struct drm_connector *connector, bool force)
+{
+ int id = dsi_mgr_connector_get_id(connector);
+ struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+
return msm_dsi->panel ? connector_status_connected :
connector_status_disconnected;
}
@@ -595,7 +611,17 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
drm_connector_attach_encoder(connector, msm_dsi->encoder);
+ ret = msm_dsi_manager_panel_init(connector, id);
+ if (ret) {
+ DRM_DEV_ERROR(msm_dsi->dev->dev, "init panel failed %d\n", ret);
+ goto fail;
+ }
+
return connector;
+
+fail:
+ connector->funcs->destroy(msm_dsi->connector);
+ return ERR_PTR(ret);
}
bool msm_dsi_manager_validate_current_config(u8 id)
@@ -751,35 +777,6 @@ bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len)
return true;
}
-void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags)
-{
- struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
- struct drm_device *dev = msm_dsi->dev;
- struct msm_drm_private *priv;
- struct msm_kms *kms;
- struct drm_encoder *encoder;
- bool cmd_mode;
-
- /*
- * drm_device pointer is assigned to msm_dsi only in the modeset_init
- * path. If mipi_dsi_attach() happens in DSI driver's probe path
- * (generally the case when we're connected to a drm_panel of the type
- * mipi_dsi_device), this would be NULL. In such cases, try to set the
- * encoder mode in the DSI connector's detect() op.
- */
- if (!dev)
- return;
-
- priv = dev->dev_private;
- kms = priv->kms;
- encoder = msm_dsi_get_encoder(msm_dsi);
- cmd_mode = !(device_flags &
- MIPI_DSI_MODE_VIDEO);
-
- if (encoder && kms->funcs->set_encoder_mode)
- kms->funcs->set_encoder_mode(kms, encoder, cmd_mode);
-}
-
int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
{
struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index bc6f64b202f3..4097eca1b3ef 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -499,6 +499,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
#ifdef CONFIG_DRM_MSM_DSI_10NM_PHY
{ .compatible = "qcom,dsi-phy-10nm",
.data = &dsi_phy_10nm_cfgs },
+ { .compatible = "qcom,dsi-phy-10nm-8998",
+ .data = &dsi_phy_10nm_8998_cfgs },
#endif
{}
};
@@ -608,10 +610,12 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
goto fail;
phy->pll = msm_dsi_pll_init(pdev, phy->cfg->type, phy->id);
- if (IS_ERR_OR_NULL(phy->pll))
+ if (IS_ERR_OR_NULL(phy->pll)) {
DRM_DEV_INFO(dev,
"%s: pll init failed: %ld, need separate pll clk driver\n",
__func__, PTR_ERR(phy->pll));
+ phy->pll = NULL;
+ }
dsi_phy_disable_resource(phy);
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 86322c88b98e..c4069ce6afe6 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -13,6 +13,9 @@
#define dsi_phy_read(offset) msm_readl((offset))
#define dsi_phy_write(offset, data) msm_writel((data), (offset))
+/* v3.0.0 10nm implementation that requires the old timings settings */
+#define V3_0_0_10NM_OLD_TIMINGS_QUIRK BIT(0)
+
struct msm_dsi_phy_ops {
int (*init) (struct msm_dsi_phy *phy);
int (*enable)(struct msm_dsi_phy *phy, int src_pll_id,
@@ -33,6 +36,7 @@ struct msm_dsi_phy_cfg {
bool src_pll_truthtable[DSI_MAX][DSI_MAX];
const resource_size_t io_start[DSI_MAX];
const int num_dsi_phy;
+ const int quirks;
};
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs;
@@ -41,6 +45,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_10nm_8998_cfgs;
struct msm_dsi_dphy_timing {
u32 clk_pre;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
index 44959e79ce28..47403d4f2d28 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c
@@ -42,6 +42,9 @@ static void dsi_phy_hw_v3_0_lane_settings(struct msm_dsi_phy *phy)
u8 tx_dctrl[] = { 0x00, 0x00, 0x00, 0x04, 0x01 };
void __iomem *lane_base = phy->lane_base;
+ if (phy->cfg->quirks & V3_0_0_10NM_OLD_TIMINGS_QUIRK)
+ tx_dctrl[3] = 0x02;
+
/* Strength ctrl settings */
for (i = 0; i < 5; i++) {
dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_LPTX_STR_CTRL(i),
@@ -74,9 +77,11 @@ static void dsi_phy_hw_v3_0_lane_settings(struct msm_dsi_phy *phy)
tx_dctrl[i]);
}
- /* Toggle BIT 0 to release freeze I/0 */
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(3), 0x05);
- dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(3), 0x04);
+ if (!(phy->cfg->quirks & V3_0_0_10NM_OLD_TIMINGS_QUIRK)) {
+ /* Toggle BIT 0 to release freeze I/0 */
+ dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(3), 0x05);
+ dsi_phy_write(lane_base + REG_DSI_10nm_PHY_LN_TX_DCTRL(3), 0x04);
+ }
}
static int dsi_10nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
@@ -221,3 +226,22 @@ const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs = {
.io_start = { 0xae94400, 0xae96400 },
.num_dsi_phy = 2,
};
+
+const struct msm_dsi_phy_cfg dsi_phy_10nm_8998_cfgs = {
+ .type = MSM_DSI_PHY_10NM,
+ .src_pll_truthtable = { {false, false}, {true, false} },
+ .reg_cfg = {
+ .num = 1,
+ .regs = {
+ {"vdds", 36000, 32},
+ },
+ },
+ .ops = {
+ .enable = dsi_10nm_phy_enable,
+ .disable = dsi_10nm_phy_disable,
+ .init = dsi_10nm_phy_init,
+ },
+ .io_start = { 0xc994400, 0xc996400 },
+ .num_dsi_phy = 2,
+ .quirks = V3_0_0_10NM_OLD_TIMINGS_QUIRK,
+};
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c
index aabab6311043..8f6100db90ed 100644
--- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c
@@ -104,8 +104,13 @@ struct dsi_pll_10nm {
struct dsi_pll_regs reg_setup;
/* private clocks: */
- struct clk_hw *hws[NUM_DSI_CLOCKS_MAX];
- u32 num_hws;
+ struct clk_hw *out_div_clk_hw;
+ struct clk_hw *bit_clk_hw;
+ struct clk_hw *byte_clk_hw;
+ struct clk_hw *by_2_bit_clk_hw;
+ struct clk_hw *post_out_div_clk_hw;
+ struct clk_hw *pclk_mux_hw;
+ struct clk_hw *out_dsiclk_hw;
/* clock-provider: */
struct clk_hw_onecell_data *hw_data;
@@ -617,8 +622,19 @@ static int dsi_pll_10nm_get_provider(struct msm_dsi_pll *pll,
static void dsi_pll_10nm_destroy(struct msm_dsi_pll *pll)
{
struct dsi_pll_10nm *pll_10nm = to_pll_10nm(pll);
+ struct device *dev = &pll_10nm->pdev->dev;
DBG("DSI PLL%d", pll_10nm->id);
+ of_clk_del_provider(dev->of_node);
+
+ clk_hw_unregister_divider(pll_10nm->out_dsiclk_hw);
+ clk_hw_unregister_mux(pll_10nm->pclk_mux_hw);
+ clk_hw_unregister_fixed_factor(pll_10nm->post_out_div_clk_hw);
+ clk_hw_unregister_fixed_factor(pll_10nm->by_2_bit_clk_hw);
+ clk_hw_unregister_fixed_factor(pll_10nm->byte_clk_hw);
+ clk_hw_unregister_divider(pll_10nm->bit_clk_hw);
+ clk_hw_unregister_divider(pll_10nm->out_div_clk_hw);
+ clk_hw_unregister(&pll_10nm->base.clk_hw);
}
/*
@@ -639,10 +655,8 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)
.ops = &clk_ops_dsi_pll_10nm_vco,
};
struct device *dev = &pll_10nm->pdev->dev;
- struct clk_hw **hws = pll_10nm->hws;
struct clk_hw_onecell_data *hw_data;
struct clk_hw *hw;
- int num = 0;
int ret;
DBG("DSI%d", pll_10nm->id);
@@ -660,8 +674,6 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)
if (ret)
return ret;
- hws[num++] = &pll_10nm->base.clk_hw;
-
snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);
snprintf(parent, 32, "dsi%dvco_clk", pll_10nm->id);
@@ -670,10 +682,12 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)
pll_10nm->mmio +
REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE,
0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
+ goto err_base_clk_hw;
+ }
- hws[num++] = hw;
+ pll_10nm->out_div_clk_hw = hw;
snprintf(clk_name, 32, "dsi%d_pll_bit_clk", pll_10nm->id);
snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);
@@ -685,10 +699,12 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)
REG_DSI_10nm_PHY_CMN_CLK_CFG0,
0, 4, CLK_DIVIDER_ONE_BASED,
&pll_10nm->postdiv_lock);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
+ goto err_out_div_clk_hw;
+ }
- hws[num++] = hw;
+ pll_10nm->bit_clk_hw = hw;
snprintf(clk_name, 32, "dsi%d_phy_pll_out_byteclk", pll_10nm->id);
snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);
@@ -696,10 +712,12 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)
/* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */
hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
CLK_SET_RATE_PARENT, 1, 8);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
+ goto err_bit_clk_hw;
+ }
- hws[num++] = hw;
+ pll_10nm->byte_clk_hw = hw;
hw_data->hws[DSI_BYTE_PLL_CLK] = hw;
snprintf(clk_name, 32, "dsi%d_pll_by_2_bit_clk", pll_10nm->id);
@@ -707,20 +725,24 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)
hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
0, 1, 2);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
+ goto err_byte_clk_hw;
+ }
- hws[num++] = hw;
+ pll_10nm->by_2_bit_clk_hw = hw;
snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_10nm->id);
snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_10nm->id);
hw = clk_hw_register_fixed_factor(dev, clk_name, parent,
0, 1, 4);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
+ goto err_by_2_bit_clk_hw;
+ }
- hws[num++] = hw;
+ pll_10nm->post_out_div_clk_hw = hw;
snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_10nm->id);
snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_10nm->id);
@@ -734,10 +756,12 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)
}, 4, 0, pll_10nm->phy_cmn_mmio +
REG_DSI_10nm_PHY_CMN_CLK_CFG1,
0, 2, 0, NULL);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
+ goto err_post_out_div_clk_hw;
+ }
- hws[num++] = hw;
+ pll_10nm->pclk_mux_hw = hw;
snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_10nm->id);
snprintf(parent, 32, "dsi%d_pclk_mux", pll_10nm->id);
@@ -748,14 +772,14 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)
REG_DSI_10nm_PHY_CMN_CLK_CFG0,
4, 4, CLK_DIVIDER_ONE_BASED,
&pll_10nm->postdiv_lock);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
+ goto err_pclk_mux_hw;
+ }
- hws[num++] = hw;
+ pll_10nm->out_dsiclk_hw = hw;
hw_data->hws[DSI_PIXEL_PLL_CLK] = hw;
- pll_10nm->num_hws = num;
-
hw_data->num = NUM_PROVIDED_CLKS;
pll_10nm->hw_data = hw_data;
@@ -763,10 +787,29 @@ static int pll_10nm_register(struct dsi_pll_10nm *pll_10nm)
pll_10nm->hw_data);
if (ret) {
DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret);
- return ret;
+ goto err_dsiclk_hw;
}
return 0;
+
+err_dsiclk_hw:
+ clk_hw_unregister_divider(pll_10nm->out_dsiclk_hw);
+err_pclk_mux_hw:
+ clk_hw_unregister_mux(pll_10nm->pclk_mux_hw);
+err_post_out_div_clk_hw:
+ clk_hw_unregister_fixed_factor(pll_10nm->post_out_div_clk_hw);
+err_by_2_bit_clk_hw:
+ clk_hw_unregister_fixed_factor(pll_10nm->by_2_bit_clk_hw);
+err_byte_clk_hw:
+ clk_hw_unregister_fixed_factor(pll_10nm->byte_clk_hw);
+err_bit_clk_hw:
+ clk_hw_unregister_divider(pll_10nm->bit_clk_hw);
+err_out_div_clk_hw:
+ clk_hw_unregister_divider(pll_10nm->out_div_clk_hw);
+err_base_clk_hw:
+ clk_hw_unregister(&pll_10nm->base.clk_hw);
+
+ return ret;
}
struct msm_dsi_pll *msm_dsi_pll_10nm_init(struct platform_device *pdev, int id)
@@ -775,9 +818,6 @@ struct msm_dsi_pll *msm_dsi_pll_10nm_init(struct platform_device *pdev, int id)
struct msm_dsi_pll *pll;
int ret;
- if (!pdev)
- return ERR_PTR(-ENODEV);
-
pll_10nm = devm_kzalloc(&pdev->dev, sizeof(*pll_10nm), GFP_KERNEL);
if (!pll_10nm)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 31deb87abfc6..229d49740677 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -259,13 +259,24 @@ static int msm_drm_uninit(struct device *dev)
struct msm_mdss *mdss = priv->mdss;
int i;
+ /*
+ * Shutdown the hw if we're far enough along where things might be on.
+ * If we run this too early, we'll end up panicking in any variety of
+ * places. Since we don't register the drm device until late in
+ * msm_drm_init, drm_dev->registered is used as an indicator that the
+ * shutdown will be successful.
+ */
+ if (ddev->registered) {
+ drm_dev_unregister(ddev);
+ drm_atomic_helper_shutdown(ddev);
+ }
+
/* We must cancel and cleanup any pending vblank enable/disable
* work before drm_irq_uninstall() to avoid work re-enabling an
* irq after uninstall has disabled it.
*/
flush_workqueue(priv->wq);
- destroy_workqueue(priv->wq);
/* clean up event worker threads */
for (i = 0; i < priv->num_crtcs; i++) {
@@ -279,8 +290,6 @@ static int msm_drm_uninit(struct device *dev)
drm_kms_helper_poll_fini(ddev);
- drm_dev_unregister(ddev);
-
msm_perf_debugfs_cleanup(priv);
msm_rd_debugfs_cleanup(priv);
@@ -288,7 +297,7 @@ static int msm_drm_uninit(struct device *dev)
if (fbdev && priv->fbdev)
msm_fbdev_free(ddev);
#endif
- drm_atomic_helper_shutdown(ddev);
+
drm_mode_config_cleanup(ddev);
pm_runtime_get_sync(dev);
@@ -313,6 +322,7 @@ static int msm_drm_uninit(struct device *dev)
ddev->dev_private = NULL;
drm_dev_put(ddev);
+ destroy_workqueue(priv->wq);
kfree(priv);
return 0;
@@ -611,6 +621,7 @@ static void load_gpu(struct drm_device *dev)
static int context_init(struct drm_device *dev, struct drm_file *file)
{
+ struct msm_drm_private *priv = dev->dev_private;
struct msm_file_private *ctx;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
@@ -619,6 +630,7 @@ static int context_init(struct drm_device *dev, struct drm_file *file)
msm_submitqueue_init(dev, ctx);
+ ctx->aspace = priv->gpu->aspace;
file->driver_priv = ctx;
return 0;
@@ -1317,16 +1329,24 @@ static int msm_pdev_probe(struct platform_device *pdev)
ret = add_gpu_components(&pdev->dev, &match);
if (ret)
- return ret;
+ goto fail;
/* on all devices that I am aware of, iommu's which can map
* any address the cpu can see are used:
*/
ret = dma_set_mask_and_coherent(&pdev->dev, ~0);
if (ret)
- return ret;
+ goto fail;
+
+ ret = component_master_add_with_match(&pdev->dev, &msm_drm_ops, match);
+ if (ret)
+ goto fail;
- return component_master_add_with_match(&pdev->dev, &msm_drm_ops, match);
+ return 0;
+
+fail:
+ of_platform_depopulate(&pdev->dev);
+ return ret;
}
static int msm_pdev_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index e20e6b429804..d9aa7bad454d 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -68,6 +68,7 @@ struct msm_file_private {
rwlock_t queuelock;
struct list_head submitqueues;
int queueid;
+ struct msm_gem_address_space *aspace;
};
enum msm_mdp_plane_property {
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index 68fa2c8f61e6..a816ceb58716 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -16,6 +16,7 @@
*/
#include <drm/drm_crtc.h>
+#include <drm/drm_damage_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_probe_helper.h>
@@ -35,6 +36,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
static const struct drm_framebuffer_funcs msm_framebuffer_funcs = {
.create_handle = drm_gem_fb_create_handle,
.destroy = drm_gem_fb_destroy,
+ .dirty = drm_atomic_helper_dirtyfb,
};
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 35f55dd25994..d31d9f927887 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -352,8 +352,10 @@ put_iova(struct drm_gem_object *obj)
WARN_ON(!mutex_is_locked(&msm_obj->lock));
list_for_each_entry_safe(vma, tmp, &msm_obj->vmas, list) {
- msm_gem_purge_vma(vma->aspace, vma);
- msm_gem_close_vma(vma->aspace, vma);
+ if (vma->aspace) {
+ msm_gem_purge_vma(vma->aspace, vma);
+ msm_gem_close_vma(vma->aspace, vma);
+ }
del_vma(vma);
}
}
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 812d1b1369a5..36aeb58c132b 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -141,6 +141,7 @@ void msm_gem_free_work(struct work_struct *work);
struct msm_gem_submit {
struct drm_device *dev;
struct msm_gpu *gpu;
+ struct msm_gem_address_space *aspace;
struct list_head node; /* node in ring submit list */
struct list_head bo_list;
struct ww_acquire_ctx ticket;
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 1b681306aca3..d3801bfa4407 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -32,8 +32,9 @@
#define BO_PINNED 0x2000
static struct msm_gem_submit *submit_create(struct drm_device *dev,
- struct msm_gpu *gpu, struct msm_gpu_submitqueue *queue,
- uint32_t nr_bos, uint32_t nr_cmds)
+ struct msm_gpu *gpu, struct msm_gem_address_space *aspace,
+ struct msm_gpu_submitqueue *queue, uint32_t nr_bos,
+ uint32_t nr_cmds)
{
struct msm_gem_submit *submit;
uint64_t sz = sizeof(*submit) + ((u64)nr_bos * sizeof(submit->bos[0])) +
@@ -47,6 +48,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
return NULL;
submit->dev = dev;
+ submit->aspace = aspace;
submit->gpu = gpu;
submit->fence = NULL;
submit->cmd = (void *)&submit->bos[nr_bos];
@@ -160,7 +162,7 @@ static void submit_unlock_unpin_bo(struct msm_gem_submit *submit,
struct msm_gem_object *msm_obj = submit->bos[i].obj;
if (submit->bos[i].flags & BO_PINNED)
- msm_gem_unpin_iova(&msm_obj->base, submit->gpu->aspace);
+ msm_gem_unpin_iova(&msm_obj->base, submit->aspace);
if (submit->bos[i].flags & BO_LOCKED)
ww_mutex_unlock(&msm_obj->base.resv->lock);
@@ -264,7 +266,7 @@ static int submit_pin_objects(struct msm_gem_submit *submit)
/* if locking succeeded, pin bo: */
ret = msm_gem_get_and_pin_iova(&msm_obj->base,
- submit->gpu->aspace, &iova);
+ submit->aspace, &iova);
if (ret)
break;
@@ -477,7 +479,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
}
}
- submit = submit_create(dev, gpu, queue, args->nr_bos, args->nr_cmds);
+ submit = submit_create(dev, gpu, ctx->aspace, queue, args->nr_bos,
+ args->nr_cmds);
if (!submit) {
ret = -ENOMEM;
goto out_unlock;
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index bf4ee2766431..0a4c77fb3d94 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -684,7 +684,7 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
struct msm_gem_object *msm_obj = submit->bos[i].obj;
/* move to inactive: */
msm_gem_move_to_inactive(&msm_obj->base);
- msm_gem_unpin_iova(&msm_obj->base, gpu->aspace);
+ msm_gem_unpin_iova(&msm_obj->base, submit->aspace);
drm_gem_object_put(&msm_obj->base);
}
@@ -768,8 +768,7 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
/* submit takes a reference to the bo and iova until retired: */
drm_gem_object_get(&msm_obj->base);
- msm_gem_get_and_pin_iova(&msm_obj->base,
- submit->gpu->aspace, &iova);
+ msm_gem_get_and_pin_iova(&msm_obj->base, submit->aspace, &iova);
if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index 12bb54cefd46..19263290b9b7 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -30,7 +30,7 @@ static int msm_fault_handler(struct iommu_domain *domain, struct device *dev,
struct msm_iommu *iommu = arg;
if (iommu->base.handler)
return iommu->base.handler(iommu->base.arg, iova, flags);
- pr_warn_ratelimited("*** fault: iova=%08lx, flags=%d\n", iova, flags);
+ pr_warn_ratelimited("*** fault: iova=%16lx, flags=%d\n", iova, flags);
return 0;
}
diff --git a/drivers/gpu/drm/msm/msm_perf.c b/drivers/gpu/drm/msm/msm_perf.c
index 5ab21bd2decb..95948cfe7a12 100644
--- a/drivers/gpu/drm/msm/msm_perf.c
+++ b/drivers/gpu/drm/msm/msm_perf.c
@@ -205,7 +205,6 @@ int msm_perf_debugfs_init(struct drm_minor *minor)
{
struct msm_drm_private *priv = minor->dev->dev_private;
struct msm_perf_state *perf;
- struct dentry *ent;
/* only create on first minor: */
if (priv->perf)
@@ -220,19 +219,9 @@ int msm_perf_debugfs_init(struct drm_minor *minor)
mutex_init(&perf->read_lock);
priv->perf = perf;
- ent = debugfs_create_file("perf", S_IFREG | S_IRUGO,
- minor->debugfs_root, perf, &perf_debugfs_fops);
- if (!ent) {
- DRM_ERROR("Cannot create /sys/kernel/debug/dri/%pd/perf\n",
- minor->debugfs_root);
- goto fail;
- }
-
+ debugfs_create_file("perf", S_IFREG | S_IRUGO, minor->debugfs_root,
+ perf, &perf_debugfs_fops);
return 0;
-
-fail:
- msm_perf_debugfs_cleanup(priv);
- return -1;
}
void msm_perf_debugfs_cleanup(struct msm_drm_private *priv)
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c
index d21172933d92..480d810037ce 100644
--- a/drivers/gpu/drm/msm/msm_rd.c
+++ b/drivers/gpu/drm/msm/msm_rd.c
@@ -244,8 +244,6 @@ static void rd_cleanup(struct msm_rd_state *rd)
static struct msm_rd_state *rd_init(struct drm_minor *minor, const char *name)
{
struct msm_rd_state *rd;
- struct dentry *ent;
- int ret = 0;
rd = kzalloc(sizeof(*rd), GFP_KERNEL);
if (!rd)
@@ -258,20 +256,10 @@ static struct msm_rd_state *rd_init(struct drm_minor *minor, const char *name)
init_waitqueue_head(&rd->fifo_event);
- ent = debugfs_create_file(name, S_IFREG | S_IRUGO,
- minor->debugfs_root, rd, &rd_debugfs_fops);
- if (!ent) {
- DRM_ERROR("Cannot create /sys/kernel/debug/dri/%pd/%s\n",
- minor->debugfs_root, name);
- ret = -ENOMEM;
- goto fail;
- }
+ debugfs_create_file(name, S_IFREG | S_IRUGO, minor->debugfs_root, rd,
+ &rd_debugfs_fops);
return rd;
-
-fail:
- rd_cleanup(rd);
- return ERR_PTR(ret);
}
int msm_rd_debugfs_init(struct drm_minor *minor)
diff --git a/drivers/gpu/vga/Kconfig b/drivers/gpu/vga/Kconfig
index 84ab482d0db6..c8c770b05ed9 100644
--- a/drivers/gpu/vga/Kconfig
+++ b/drivers/gpu/vga/Kconfig
@@ -23,6 +23,7 @@ config VGA_SWITCHEROO
depends on X86
depends on ACPI
depends on PCI
+ depends on (FRAMEBUFFER_CONSOLE=n || FB=y)
select VGA_ARB
help
Many laptops released in 2008/9/10 have two GPUs with a multiplexer
OpenPOWER on IntegriCloud