diff options
author | Dave Airlie <airlied@redhat.com> | 2019-05-28 00:25:46 +0200 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2019-05-28 00:59:11 +0200 |
commit | 88cd7a2c1b29f61a2a3fab76216a43f3b779e0cd (patch) | |
tree | b8a4311c8f7edfc92c1055b6a5a86b1a5552878e /drivers/gpu/drm/stm | |
parent | Linux 5.2-rc2 (diff) | |
parent | dt-bindings: fix up for vendor prefixes file conversion (diff) | |
download | linux-88cd7a2c1b29f61a2a3fab76216a43f3b779e0cd.tar.xz linux-88cd7a2c1b29f61a2a3fab76216a43f3b779e0cd.zip |
Merge tag 'drm-misc-next-2019-05-24' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for v5.3, try #2:
UAPI Changes:
- Add HDR source metadata property.
- Make drm.h compile on GNU/kFreeBSD by including stdint.h
- Clarify how the userspace reviewer has to review new kernel UAPI.
- Clarify that for using new UAPI, merging to drm-next or drm-misc-next should be enough.
Cross-subsystem Changes:
- video/hdmi: Add unpack function for DRM infoframes.
- Device tree bindings:
* Updating a property for Mali Midgard GPUs
* Updating a property for STM32 DSI panel
* Adding support for FriendlyELEC HD702E 800x1280 panel
* Adding support for Evervision VGG804821 800x480 5.0" WVGA TFT panel
* Adding support for the EDT ET035012DM6 3.5" 320x240 QVGA 24-bit RGB TFT.
* Adding support for Three Five displays TFC S9700RTWV43TR-01B 800x480 panel
with resistive touch found on TI's AM335X-EVM.
* Adding support for EDT ETM0430G0DH6 480x272 panel.
- Add OSD101T2587-53TS driver with DT bindings.
- Add Samsung S6E63M0 panel driver with DT bindings.
- Add VXT VL050-8048NT-C01 800x480 panel with DT bindings.
- Dma-buf:
- Make mmap callback actually optional.
- Documentation updates.
- Fix debugfs refcount inbalance.
- Remove unused sync_dump function.
- Fix device tree bindings in drm-misc-next after a botched merge.
Core Changes:
- Add support for HDR infoframes and related EDID parsing.
- Remove prime sg_table caching, now done inside dma-buf.
- Add shiny new drm_gem_vram helpers for simple VRAM drivers;
with some fixes to the new API on top.
- Small fix to job cleanup without timeout handler.
- Documentation fixes to drm_fourcc.
- Replace lookups of drm_format with struct drm_format_info;
remove functions that become obsolete by this conversion.
- Remove double include in bridge/panel.c and some drivers.
- Remove drmP.h include from drm/edid and drm/dp.
- Fix null pointer deref in drm_fb_helper_hotplug_event().
- Remove most members from drm_fb_helper_crtc, only mode_set is kept.
- Remove race of fb helpers with userspace; only restore mode
when userspace is not master.
- Move legacy setup from drm_file.c to drm_legacy_misc.c
- Rework scheduler job destruction.
- drm/bus was removed, remove from TODO.
- Add __drm_atomic_helper_crtc_reset() to subclass crtc_state,
and convert some drivers to use it (conversion is not complete yet).
- Bump vblank timeout wait to 100 ms for atomic.
- Docbook fix for drm_hdmi_infoframe_set_hdr_metadata.
Driver Changes:
- sun4i: Use DRM_GEM_CMA_VMAP_DRIVER_OPS instead of definining manually.
- v3d: Small cleanups, adding support for compute shaders,
reservation/synchronization fixes and job management refactoring,
fixes MMU and debugfs.
- lima: Fix null pointer in irq handler on startup, set default timeout for scheduled jobs.
- stm/ltdc: Assorted fixes and adding FB modifier support.
- amdgpu: Avoid hw reset if guilty job was already signaled.
- virtio: Add seqno to fences, add trace events, use correct flags for fence allocation.
- Convert AST, bochs, mgag200, vboxvideo, hisilicon to the new drm_gem_vram API.
- sun6i_mipi_dsi: Support DSI GENERIC_SHORT_WRITE_2 transfers.
- bochs: Small fix to use PTR_RET_OR_ZERO and driver unload.
- gma500: header fixes
- cirrus: Remove unused files.
- mediatek: Fix compiler warning after merging the HDR series.
- vc4: Rework binner bo handling.
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/052875a5-27ba-3832-60c2-193d950afdff@linux.intel.com
Diffstat (limited to 'drivers/gpu/drm/stm')
-rw-r--r-- | drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 60 | ||||
-rw-r--r-- | drivers/gpu/drm/stm/ltdc.c | 67 |
2 files changed, 96 insertions, 31 deletions
diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c index 1bef73e8c8fe..d8e4a146b320 100644 --- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c +++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c @@ -9,6 +9,7 @@ #include <linux/clk.h> #include <linux/iopoll.h> #include <linux/module.h> +#include <linux/regulator/consumer.h> #include <drm/drmP.h> #include <drm/drm_mipi_dsi.h> #include <drm/bridge/dw_mipi_dsi.h> @@ -76,6 +77,7 @@ struct dw_mipi_dsi_stm { u32 hw_version; int lane_min_kbps; int lane_max_kbps; + struct regulator *vdd_supply; }; static inline void dsi_write(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 val) @@ -314,21 +316,36 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dsi->base = devm_ioremap_resource(dev, res); if (IS_ERR(dsi->base)) { - DRM_ERROR("Unable to get dsi registers\n"); - return PTR_ERR(dsi->base); + ret = PTR_ERR(dsi->base); + DRM_ERROR("Unable to get dsi registers %d\n", ret); + return ret; + } + + dsi->vdd_supply = devm_regulator_get(dev, "phy-dsi"); + if (IS_ERR(dsi->vdd_supply)) { + ret = PTR_ERR(dsi->vdd_supply); + if (ret != -EPROBE_DEFER) + DRM_ERROR("Failed to request regulator: %d\n", ret); + return ret; + } + + ret = regulator_enable(dsi->vdd_supply); + if (ret) { + DRM_ERROR("Failed to enable regulator: %d\n", ret); + return ret; } dsi->pllref_clk = devm_clk_get(dev, "ref"); if (IS_ERR(dsi->pllref_clk)) { ret = PTR_ERR(dsi->pllref_clk); - dev_err(dev, "Unable to get pll reference clock: %d\n", ret); - return ret; + DRM_ERROR("Unable to get pll reference clock: %d\n", ret); + goto err_clk_get; } ret = clk_prepare_enable(dsi->pllref_clk); if (ret) { - dev_err(dev, "%s: Failed to enable pllref_clk\n", __func__); - return ret; + DRM_ERROR("Failed to enable pllref_clk: %d\n", ret); + goto err_clk_get; } dw_mipi_dsi_stm_plat_data.base = dsi->base; @@ -338,20 +355,28 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev) dsi->dsi = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data); if (IS_ERR(dsi->dsi)) { - DRM_ERROR("Failed to initialize mipi dsi host\n"); - clk_disable_unprepare(dsi->pllref_clk); - return PTR_ERR(dsi->dsi); + ret = PTR_ERR(dsi->dsi); + DRM_ERROR("Failed to initialize mipi dsi host: %d\n", ret); + goto err_dsi_probe; } return 0; + +err_dsi_probe: + clk_disable_unprepare(dsi->pllref_clk); +err_clk_get: + regulator_disable(dsi->vdd_supply); + + return ret; } static int dw_mipi_dsi_stm_remove(struct platform_device *pdev) { struct dw_mipi_dsi_stm *dsi = platform_get_drvdata(pdev); - clk_disable_unprepare(dsi->pllref_clk); dw_mipi_dsi_remove(dsi->dsi); + clk_disable_unprepare(dsi->pllref_clk); + regulator_disable(dsi->vdd_supply); return 0; } @@ -363,6 +388,7 @@ static int __maybe_unused dw_mipi_dsi_stm_suspend(struct device *dev) DRM_DEBUG_DRIVER("\n"); clk_disable_unprepare(dsi->pllref_clk); + regulator_disable(dsi->vdd_supply); return 0; } @@ -370,10 +396,22 @@ static int __maybe_unused dw_mipi_dsi_stm_suspend(struct device *dev) static int __maybe_unused dw_mipi_dsi_stm_resume(struct device *dev) { struct dw_mipi_dsi_stm *dsi = dw_mipi_dsi_stm_plat_data.priv_data; + int ret; DRM_DEBUG_DRIVER("\n"); - clk_prepare_enable(dsi->pllref_clk); + ret = regulator_enable(dsi->vdd_supply); + if (ret) { + DRM_ERROR("Failed to enable regulator: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(dsi->pllref_clk); + if (ret) { + regulator_disable(dsi->vdd_supply); + DRM_ERROR("Failed to enable pllref_clk: %d\n", ret); + return ret; + } return 0; } diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 32fd6a3b37fb..14eb8c40953b 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -232,6 +232,11 @@ static const enum ltdc_pix_fmt ltdc_pix_fmt_a1[NB_PF] = { PF_ARGB4444 /* 0x07 */ }; +static const u64 ltdc_format_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + static inline u32 reg_read(void __iomem *base, u32 reg) { return readl_relaxed(base + reg); @@ -426,8 +431,8 @@ static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc, /* Enable IRQ */ reg_set(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE); - /* Immediately commit the planes */ - reg_set(ldev->regs, LTDC_SRCR, SRCR_IMR); + /* Commit shadow registers = update planes at next vblank */ + reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR); /* Enable LTDC */ reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN); @@ -555,7 +560,7 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) if (vm.flags & DISPLAY_FLAGS_VSYNC_HIGH) val |= GCR_VSPOL; - if (vm.flags & DISPLAY_FLAGS_DE_HIGH) + if (vm.flags & DISPLAY_FLAGS_DE_LOW) val |= GCR_DEPOL; if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) @@ -779,7 +784,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, /* Configures the color frame buffer pitch in bytes & line length */ pitch_in_bytes = fb->pitches[0]; - line_length = drm_format_plane_cpp(fb->format->format, 0) * + line_length = fb->format->cpp[0] * (x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1; val = ((pitch_in_bytes << 16) | line_length); reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs, @@ -822,11 +827,11 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane, mutex_lock(&ldev->err_lock); if (ldev->error_status & ISR_FUIF) { - DRM_DEBUG_DRIVER("Fifo underrun\n"); + DRM_WARN("ltdc fifo underrun: please verify display mode\n"); ldev->error_status &= ~ISR_FUIF; } if (ldev->error_status & ISR_TERRIF) { - DRM_DEBUG_DRIVER("Transfer error\n"); + DRM_WARN("ltdc transfer error\n"); ldev->error_status &= ~ISR_TERRIF; } mutex_unlock(&ldev->err_lock); @@ -864,6 +869,16 @@ static void ltdc_plane_atomic_print_state(struct drm_printer *p, fpsi->counter = 0; } +static bool ltdc_plane_format_mod_supported(struct drm_plane *plane, + u32 format, + u64 modifier) +{ + if (modifier == DRM_FORMAT_MOD_LINEAR) + return true; + + return false; +} + static const struct drm_plane_funcs ltdc_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -872,6 +887,7 @@ static const struct drm_plane_funcs ltdc_plane_funcs = { .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, .atomic_print_state = ltdc_plane_atomic_print_state, + .format_mod_supported = ltdc_plane_format_mod_supported, }; static const struct drm_plane_helper_funcs ltdc_plane_helper_funcs = { @@ -890,6 +906,7 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev, unsigned int i, nb_fmt = 0; u32 formats[NB_PF * 2]; u32 drm_fmt, drm_fmt_no_alpha; + const u64 *modifiers = ltdc_format_modifiers; int ret; /* Get supported pixel formats */ @@ -918,7 +935,7 @@ static struct drm_plane *ltdc_plane_create(struct drm_device *ddev, ret = drm_universal_plane_init(ddev, plane, possible_crtcs, <dc_plane_funcs, formats, nb_fmt, - NULL, type, NULL); + modifiers, type, NULL); if (ret < 0) return NULL; @@ -1021,10 +1038,13 @@ static int ltdc_get_caps(struct drm_device *ddev) struct ltdc_device *ldev = ddev->dev_private; u32 bus_width_log2, lcr, gc2r; - /* at least 1 layer must be managed */ + /* + * at least 1 layer must be managed & the number of layers + * must not exceed LTDC_MAX_LAYER + */ lcr = reg_read(ldev->regs, LTDC_LCR); - ldev->caps.nb_layers = max_t(int, lcr, 1); + ldev->caps.nb_layers = clamp((int)lcr, 1, LTDC_MAX_LAYER); /* set data bus width */ gc2r = reg_read(ldev->regs, LTDC_GC2R); @@ -1125,8 +1145,9 @@ int ltdc_load(struct drm_device *ddev) ldev->pixel_clk = devm_clk_get(dev, "lcd"); if (IS_ERR(ldev->pixel_clk)) { - DRM_ERROR("Unable to get lcd clock\n"); - return -ENODEV; + if (PTR_ERR(ldev->pixel_clk) != -EPROBE_DEFER) + DRM_ERROR("Unable to get lcd clock\n"); + return PTR_ERR(ldev->pixel_clk); } if (clk_prepare_enable(ldev->pixel_clk)) { @@ -1134,6 +1155,12 @@ int ltdc_load(struct drm_device *ddev) return -ENODEV; } + if (!IS_ERR(rstc)) { + reset_control_assert(rstc); + usleep_range(10, 20); + reset_control_deassert(rstc); + } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ldev->regs = devm_ioremap_resource(dev, res); if (IS_ERR(ldev->regs)) { @@ -1142,8 +1169,15 @@ int ltdc_load(struct drm_device *ddev) goto err; } + /* Disable interrupts */ + reg_clear(ldev->regs, LTDC_IER, + IER_LIE | IER_RRIE | IER_FUIE | IER_TERRIE); + for (i = 0; i < MAX_IRQ; i++) { irq = platform_get_irq(pdev, i); + if (irq == -EPROBE_DEFER) + goto err; + if (irq < 0) continue; @@ -1156,15 +1190,6 @@ int ltdc_load(struct drm_device *ddev) } } - if (!IS_ERR(rstc)) { - reset_control_assert(rstc); - usleep_range(10, 20); - reset_control_deassert(rstc); - } - - /* Disable interrupts */ - reg_clear(ldev->regs, LTDC_IER, - IER_LIE | IER_RRIE | IER_FUIE | IER_TERRIE); ret = ltdc_get_caps(ddev); if (ret) { @@ -1203,6 +1228,8 @@ int ltdc_load(struct drm_device *ddev) goto err; } + ddev->mode_config.allow_fb_modifiers = true; + ret = ltdc_crtc_init(ddev, crtc); if (ret) { DRM_ERROR("Failed to init crtc\n"); |