diff options
87 files changed, 1404 insertions, 891 deletions
diff --git a/Documentation/devicetree/bindings/display/msm/dpu.txt b/Documentation/devicetree/bindings/display/msm/dpu.txt index ad2e8830324e..a61dd40f3792 100644 --- a/Documentation/devicetree/bindings/display/msm/dpu.txt +++ b/Documentation/devicetree/bindings/display/msm/dpu.txt @@ -28,6 +28,11 @@ Required properties: - #address-cells: number of address cells for the MDSS children. Should be 1. - #size-cells: Should be 1. - ranges: parent bus address space is the same as the child bus address space. +- interconnects : interconnect path specifier for MDSS according to + Documentation/devicetree/bindings/interconnect/interconnect.txt. Should be + 2 paths corresponding to 2 AXI ports. +- interconnect-names : MDSS will have 2 port names to differentiate between the + 2 interconnect paths defined with interconnect specifier. Optional properties: - assigned-clocks: list of clock specifiers for clocks needing rate assignment @@ -86,6 +91,11 @@ Example: interrupt-controller; #interrupt-cells = <1>; + interconnects = <&rsc_hlos MASTER_MDP0 &rsc_hlos SLAVE_EBI1>, + <&rsc_hlos MASTER_MDP1 &rsc_hlos SLAVE_EBI1>; + + interconnect-names = "mdp0-mem", "mdp1-mem"; + iommus = <&apps_iommu 0>; #address-cells = <2>; diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt index 9ae946942720..af95586c898f 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi.txt +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt @@ -88,6 +88,7 @@ Required properties: * "qcom,dsi-phy-28nm-8960" * "qcom,dsi-phy-14nm" * "qcom,dsi-phy-10nm" + * "qcom,dsi-phy-10nm-8998" - reg: Physical base address and length of the registers of PLL, PHY. Some revisions require the PHY regulator base address, whereas others require the PHY lane base address. See below for each PHY revision. 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", ®, &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 |