diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-09-01 11:26:46 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-09-01 11:26:46 -0700 |
commit | 477f70cd2a67904e04c2c2b9bd0fa2e95222f2f6 (patch) | |
tree | 1897dd1de49e1ea24897163533e2d8ead5dad0ad /drivers/gpu/drm/xlnx/zynqmp_disp.c | |
parent | 835d31d319d9c8c4eb6cac074643360ba0ecab10 (diff) | |
parent | 8f0284f190e6a0aa09015090568c03f18288231a (diff) |
Merge tag 'drm-next-2021-08-31-1' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie:
"Highlights:
- i915 has seen a lot of refactoring and uAPI cleanups due to a
change in the upstream direction going forward
This has all been audited with known userspace, but there may be
some pitfalls that were missed.
- i915 now uses common TTM to enable discrete memory on DG1/2 GPUs
- i915 enables Jasper and Elkhart Lake by default and has preliminary
XeHP/DG2 support
- amdgpu adds support for Cyan Skillfish
- lots of implicit fencing rules documented and fixed up in drivers
- msm now uses the core scheduler
- the irq midlayer has been removed for non-legacy drivers
- the sysfb code now works on more than x86.
Otherwise the usual smattering of stuff everywhere, panels, bridges,
refactorings.
Detailed summary:
core:
- extract i915 eDP backlight into core
- DP aux bus support
- drm_device.irq_enabled removed
- port drivers to native irq interfaces
- export gem shadow plane handling for vgem
- print proper driver name in framebuffer registration
- driver fixes for implicit fencing rules
- ARM fixed rate compression modifier added
- updated fb damage handling
- rmfb ioctl logging/docs
- drop drm_gem_object_put_locked
- define DRM_FORMAT_MAX_PLANES
- add gem fb vmap/vunmap helpers
- add lockdep_assert(once) helpers
- mark drm irq midlayer as legacy
- use offset adjusted bo mapping conversion
vgaarb:
- cleanups
fbdev:
- extend efifb handling to all arches
- div by 0 fixes for multiple drivers
udmabuf:
- add hugepage mapping support
dma-buf:
- non-dynamic exporter fixups
- document implicit fencing rules
amdgpu:
- Initial Cyan Skillfish support
- switch virtual DCE over to vkms based atomic
- VCN/JPEG power down fixes
- NAVI PCIE link handling fixes
- AMD HDMI freesync fixes
- Yellow Carp + Beige Goby fixes
- Clockgating/S0ix/SMU/EEPROM fixes
- embed hw fence in job
- rework dma-resv handling
- ensure eviction to system ram
amdkfd:
- uapi: SVM address range query added
- sysfs leak fix
- GPUVM TLB optimizations
- vmfault/migration counters
i915:
- Enable JSL and EHL by default
- preliminary XeHP/DG2 support
- remove all CNL support (never shipped)
- move to TTM for discrete memory support
- allow mixed object mmap handling
- GEM uAPI spring cleaning
- add I915_MMAP_OBJECT_FIXED
- reinstate ADL-P mmap ioctls
- drop a bunch of unused by userspace features
- disable and remove GPU relocations
- revert some i915 misfeatures
- major refactoring of GuC for Gen11+
- execbuffer object locking separate step
- reject caching/set-domain on discrete
- Enable pipe DMC loading on XE-LPD and ADL-P
- add PSF GV point support
- Refactor and fix DDI buffer translations
- Clean up FBC CFB allocation code
- Finish INTEL_GEN() and friends macro conversions
nouveau:
- add eDP backlight support
- implicit fence fix
msm:
- a680/7c3 support
- drm/scheduler conversion
panfrost:
- rework GPU reset
virtio:
- fix fencing for planes
ast:
- add detect support
bochs:
- move to tiny GPU driver
vc4:
- use hotplug irqs
- HDMI codec support
vmwgfx:
- use internal vmware device headers
ingenic:
- demidlayering irq
rcar-du:
- shutdown fixes
- convert to bridge connector helpers
zynqmp-dsub:
- misc fixes
mgag200:
- convert PLL handling to atomic
mediatek:
- MT8133 AAL support
- gem mmap object support
- MT8167 support
etnaviv:
- NXP Layerscape LS1028A SoC support
- GEM mmap cleanups
tegra:
- new user API
exynos:
- missing unlock fix
- build warning fix
- use refcount_t"
* tag 'drm-next-2021-08-31-1' of git://anongit.freedesktop.org/drm/drm: (1318 commits)
drm/amd/display: Move AllowDRAMSelfRefreshOrDRAMClockChangeInVblank to bounding box
drm/amd/display: Remove duplicate dml init
drm/amd/display: Update bounding box states (v2)
drm/amd/display: Update number of DCN3 clock states
drm/amdgpu: disable GFX CGCG in aldebaran
drm/amdgpu: Clear RAS interrupt status on aldebaran
drm/amdgpu: Add support for RAS XGMI err query
drm/amdkfd: Account for SH/SE count when setting up cu masks.
drm/amdgpu: rename amdgpu_bo_get_preferred_pin_domain
drm/amdgpu: drop redundant cancel_delayed_work_sync call
drm/amdgpu: add missing cleanups for more ASICs on UVD/VCE suspend
drm/amdgpu: add missing cleanups for Polaris12 UVD/VCE on suspend
drm/amdkfd: map SVM range with correct access permission
drm/amdkfd: check access permisson to restore retry fault
drm/amdgpu: Update RAS XGMI Error Query
drm/amdgpu: Add driver infrastructure for MCA RAS
drm/amd/display: Add Logging for HDMI color depth information
drm/amd/amdgpu: consolidate PSP TA init shared buf functions
drm/amd/amdgpu: add name field back to ras_common_if
drm/amdgpu: Fix build with missing pm_suspend_target_state module export
...
Diffstat (limited to 'drivers/gpu/drm/xlnx/zynqmp_disp.c')
-rw-r--r-- | drivers/gpu/drm/xlnx/zynqmp_disp.c | 320 |
1 files changed, 159 insertions, 161 deletions
diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c index 109d627968ac..ff2b308d8651 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_disp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c @@ -91,7 +91,7 @@ struct zynqmp_disp_format { }; /** - * enum zynqmp_disp_id - Layer identifier + * enum zynqmp_disp_layer_id - Layer identifier * @ZYNQMP_DISP_LAYER_VID: Video layer * @ZYNQMP_DISP_LAYER_GFX: Graphics layer */ @@ -159,42 +159,16 @@ struct zynqmp_disp_layer { }; /** - * struct zynqmp_disp_blend - Blender - * @base: Registers I/O base address - */ -struct zynqmp_disp_blend { - void __iomem *base; -}; - -/** - * struct zynqmp_disp_avbuf - Audio/video buffer manager - * @base: Registers I/O base address - */ -struct zynqmp_disp_avbuf { - void __iomem *base; -}; - -/** - * struct zynqmp_disp_audio - Audio mixer - * @base: Registers I/O base address - * @clk: Audio clock - * @clk_from_ps: True of the audio clock comes from PS, false from PL - */ -struct zynqmp_disp_audio { - void __iomem *base; - struct clk *clk; - bool clk_from_ps; -}; - -/** * struct zynqmp_disp - Display controller * @dev: Device structure * @drm: DRM core * @dpsub: Display subsystem * @crtc: DRM CRTC - * @blend: Blender (video rendering pipeline) - * @avbuf: Audio/video buffer manager - * @audio: Audio mixer + * @blend.base: Register I/O base address for the blender + * @avbuf.base: Register I/O base address for the audio/video buffer manager + * @audio.base: Registers I/O base address for the audio mixer + * @audio.clk: Audio clock + * @audio.clk_from_ps: True of the audio clock comes from PS, false from PL * @layers: Layers (planes) * @event: Pending vblank event request * @pclk: Pixel clock @@ -207,9 +181,17 @@ struct zynqmp_disp { struct drm_crtc crtc; - struct zynqmp_disp_blend blend; - struct zynqmp_disp_avbuf avbuf; - struct zynqmp_disp_audio audio; + struct { + void __iomem *base; + } blend; + struct { + void __iomem *base; + } avbuf; + struct { + void __iomem *base; + struct clk *clk; + bool clk_from_ps; + } audio; struct zynqmp_disp_layer layers[ZYNQMP_DISP_NUM_LAYERS]; @@ -423,51 +405,60 @@ static const struct zynqmp_disp_format avbuf_gfx_fmts[] = { }, }; -static u32 zynqmp_disp_avbuf_read(struct zynqmp_disp_avbuf *avbuf, int reg) +static u32 zynqmp_disp_avbuf_read(struct zynqmp_disp *disp, int reg) { - return readl(avbuf->base + reg); + return readl(disp->avbuf.base + reg); } -static void zynqmp_disp_avbuf_write(struct zynqmp_disp_avbuf *avbuf, - int reg, u32 val) +static void zynqmp_disp_avbuf_write(struct zynqmp_disp *disp, int reg, u32 val) { - writel(val, avbuf->base + reg); + writel(val, disp->avbuf.base + reg); +} + +static bool zynqmp_disp_layer_is_gfx(const struct zynqmp_disp_layer *layer) +{ + return layer->id == ZYNQMP_DISP_LAYER_GFX; +} + +static bool zynqmp_disp_layer_is_video(const struct zynqmp_disp_layer *layer) +{ + return layer->id == ZYNQMP_DISP_LAYER_VID; } /** * zynqmp_disp_avbuf_set_format - Set the input format for a layer - * @avbuf: Audio/video buffer manager - * @layer: The layer ID + * @disp: Display controller + * @layer: The layer * @fmt: The format information * * Set the video buffer manager format for @layer to @fmt. */ -static void zynqmp_disp_avbuf_set_format(struct zynqmp_disp_avbuf *avbuf, - enum zynqmp_disp_layer_id layer, +static void zynqmp_disp_avbuf_set_format(struct zynqmp_disp *disp, + struct zynqmp_disp_layer *layer, const struct zynqmp_disp_format *fmt) { unsigned int i; u32 val; - val = zynqmp_disp_avbuf_read(avbuf, ZYNQMP_DISP_AV_BUF_FMT); - val &= layer == ZYNQMP_DISP_LAYER_VID + val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_FMT); + val &= zynqmp_disp_layer_is_video(layer) ? ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK : ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK; val |= fmt->buf_fmt; - zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_FMT, val); + zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_FMT, val); for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++) { - unsigned int reg = layer == ZYNQMP_DISP_LAYER_VID + unsigned int reg = zynqmp_disp_layer_is_video(layer) ? ZYNQMP_DISP_AV_BUF_VID_COMP_SF(i) : ZYNQMP_DISP_AV_BUF_GFX_COMP_SF(i); - zynqmp_disp_avbuf_write(avbuf, reg, fmt->sf[i]); + zynqmp_disp_avbuf_write(disp, reg, fmt->sf[i]); } } /** * zynqmp_disp_avbuf_set_clocks_sources - Set the clocks sources - * @avbuf: Audio/video buffer manager + * @disp: Display controller * @video_from_ps: True if the video clock originates from the PS * @audio_from_ps: True if the audio clock originates from the PS * @timings_internal: True if video timings are generated internally @@ -477,7 +468,7 @@ static void zynqmp_disp_avbuf_set_format(struct zynqmp_disp_avbuf *avbuf, * generated internally or externally. */ static void -zynqmp_disp_avbuf_set_clocks_sources(struct zynqmp_disp_avbuf *avbuf, +zynqmp_disp_avbuf_set_clocks_sources(struct zynqmp_disp *disp, bool video_from_ps, bool audio_from_ps, bool timings_internal) { @@ -490,16 +481,16 @@ zynqmp_disp_avbuf_set_clocks_sources(struct zynqmp_disp_avbuf *avbuf, if (timings_internal) val |= ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING; - zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_CLK_SRC, val); + zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_CLK_SRC, val); } /** * zynqmp_disp_avbuf_enable_channels - Enable buffer channels - * @avbuf: Audio/video buffer manager + * @disp: Display controller * * Enable all (video and audio) buffer channels. */ -static void zynqmp_disp_avbuf_enable_channels(struct zynqmp_disp_avbuf *avbuf) +static void zynqmp_disp_avbuf_enable_channels(struct zynqmp_disp *disp) { unsigned int i; u32 val; @@ -509,7 +500,7 @@ static void zynqmp_disp_avbuf_enable_channels(struct zynqmp_disp_avbuf *avbuf) ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT); for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS; i++) - zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_CHBUF(i), + zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_CHBUF(i), val); val = ZYNQMP_DISP_AV_BUF_CHBUF_EN | @@ -517,75 +508,75 @@ static void zynqmp_disp_avbuf_enable_channels(struct zynqmp_disp_avbuf *avbuf) ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT); for (; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++) - zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_CHBUF(i), + zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_CHBUF(i), val); } /** * zynqmp_disp_avbuf_disable_channels - Disable buffer channels - * @avbuf: Audio/video buffer manager + * @disp: Display controller * * Disable all (video and audio) buffer channels. */ -static void zynqmp_disp_avbuf_disable_channels(struct zynqmp_disp_avbuf *avbuf) +static void zynqmp_disp_avbuf_disable_channels(struct zynqmp_disp *disp) { unsigned int i; for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++) - zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_CHBUF(i), + zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_CHBUF(i), ZYNQMP_DISP_AV_BUF_CHBUF_FLUSH); } /** * zynqmp_disp_avbuf_enable_audio - Enable audio - * @avbuf: Audio/video buffer manager + * @disp: Display controller * * Enable all audio buffers with a non-live (memory) source. */ -static void zynqmp_disp_avbuf_enable_audio(struct zynqmp_disp_avbuf *avbuf) +static void zynqmp_disp_avbuf_enable_audio(struct zynqmp_disp *disp) { u32 val; - val = zynqmp_disp_avbuf_read(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT); + val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_OUTPUT); val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK; val |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM; val |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN; - zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT, val); + zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_OUTPUT, val); } /** * zynqmp_disp_avbuf_disable_audio - Disable audio - * @avbuf: Audio/video buffer manager + * @disp: Display controller * * Disable all audio buffers. */ -static void zynqmp_disp_avbuf_disable_audio(struct zynqmp_disp_avbuf *avbuf) +static void zynqmp_disp_avbuf_disable_audio(struct zynqmp_disp *disp) { u32 val; - val = zynqmp_disp_avbuf_read(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT); + val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_OUTPUT); val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK; val |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE; val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN; - zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT, val); + zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_OUTPUT, val); } /** * zynqmp_disp_avbuf_enable_video - Enable a video layer - * @avbuf: Audio/video buffer manager - * @layer: The layer ID + * @disp: Display controller + * @layer: The layer * @mode: Operating mode of layer * * Enable the video/graphics buffer for @layer. */ -static void zynqmp_disp_avbuf_enable_video(struct zynqmp_disp_avbuf *avbuf, - enum zynqmp_disp_layer_id layer, +static void zynqmp_disp_avbuf_enable_video(struct zynqmp_disp *disp, + struct zynqmp_disp_layer *layer, enum zynqmp_disp_layer_mode mode) { u32 val; - val = zynqmp_disp_avbuf_read(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT); - if (layer == ZYNQMP_DISP_LAYER_VID) { + val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_OUTPUT); + if (zynqmp_disp_layer_is_video(layer)) { val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK; if (mode == ZYNQMP_DISP_LAYER_NONLIVE) val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM; @@ -599,52 +590,52 @@ static void zynqmp_disp_avbuf_enable_video(struct zynqmp_disp_avbuf *avbuf, else val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE; } - zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT, val); + zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_OUTPUT, val); } /** * zynqmp_disp_avbuf_disable_video - Disable a video layer - * @avbuf: Audio/video buffer manager - * @layer: The layer ID + * @disp: Display controller + * @layer: The layer * * Disable the video/graphics buffer for @layer. */ -static void zynqmp_disp_avbuf_disable_video(struct zynqmp_disp_avbuf *avbuf, - enum zynqmp_disp_layer_id layer) +static void zynqmp_disp_avbuf_disable_video(struct zynqmp_disp *disp, + struct zynqmp_disp_layer *layer) { u32 val; - val = zynqmp_disp_avbuf_read(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT); - if (layer == ZYNQMP_DISP_LAYER_VID) { + val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_OUTPUT); + if (zynqmp_disp_layer_is_video(layer)) { val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK; val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE; } else { val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK; val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_DISABLE; } - zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT, val); + zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_OUTPUT, val); } /** * zynqmp_disp_avbuf_enable - Enable the video pipe - * @avbuf: Audio/video buffer manager + * @disp: Display controller * * De-assert the video pipe reset. */ -static void zynqmp_disp_avbuf_enable(struct zynqmp_disp_avbuf *avbuf) +static void zynqmp_disp_avbuf_enable(struct zynqmp_disp *disp) { - zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_SRST_REG, 0); + zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_SRST_REG, 0); } /** * zynqmp_disp_avbuf_disable - Disable the video pipe - * @avbuf: Audio/video buffer manager + * @disp: Display controller * * Assert the video pipe reset. */ -static void zynqmp_disp_avbuf_disable(struct zynqmp_disp_avbuf *avbuf) +static void zynqmp_disp_avbuf_disable(struct zynqmp_disp *disp) { - zynqmp_disp_avbuf_write(avbuf, ZYNQMP_DISP_AV_BUF_SRST_REG, + zynqmp_disp_avbuf_write(disp, ZYNQMP_DISP_AV_BUF_SRST_REG, ZYNQMP_DISP_AV_BUF_SRST_REG_VID_RST); } @@ -652,10 +643,9 @@ static void zynqmp_disp_avbuf_disable(struct zynqmp_disp_avbuf *avbuf) * Blender (Video Pipeline) */ -static void zynqmp_disp_blend_write(struct zynqmp_disp_blend *blend, - int reg, u32 val) +static void zynqmp_disp_blend_write(struct zynqmp_disp *disp, int reg, u32 val) { - writel(val, blend->base + reg); + writel(val, disp->blend.base + reg); } /* @@ -701,12 +691,12 @@ static const u32 csc_sdtv_to_rgb_offsets[] = { /** * zynqmp_disp_blend_set_output_format - Set the output format of the blender - * @blend: Blender object + * @disp: Display controller * @format: Output format * * Set the output format of the blender to @format. */ -static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp_blend *blend, +static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp *disp, enum zynqmp_dpsub_format format) { static const unsigned int blend_output_fmts[] = { @@ -722,7 +712,7 @@ static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp_blend *blend, const u32 *offsets; unsigned int i; - zynqmp_disp_blend_write(blend, ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT, fmt); + zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT, fmt); if (fmt == ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB) { coeffs = csc_identity_matrix; offsets = csc_zero_offsets; @@ -732,19 +722,19 @@ static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp_blend *blend, } for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i++) - zynqmp_disp_blend_write(blend, + zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF(i), coeffs[i]); for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++) - zynqmp_disp_blend_write(blend, + zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_OUTCSC_OFFSET(i), offsets[i]); } /** * zynqmp_disp_blend_set_bg_color - Set the background color - * @blend: Blender object + * @disp: Display controller * @rcr: Red/Cr color component * @gy: Green/Y color component * @bcb: Blue/Cb color component @@ -753,31 +743,31 @@ static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp_blend *blend, * B or Cr, Y and Cb components respectively depending on the selected output * format. */ -static void zynqmp_disp_blend_set_bg_color(struct zynqmp_disp_blend *blend, +static void zynqmp_disp_blend_set_bg_color(struct zynqmp_disp *disp, u32 rcr, u32 gy, u32 bcb) { - zynqmp_disp_blend_write(blend, ZYNQMP_DISP_V_BLEND_BG_CLR_0, rcr); - zynqmp_disp_blend_write(blend, ZYNQMP_DISP_V_BLEND_BG_CLR_1, gy); - zynqmp_disp_blend_write(blend, ZYNQMP_DISP_V_BLEND_BG_CLR_2, bcb); + zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_BG_CLR_0, rcr); + zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_BG_CLR_1, gy); + zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_BG_CLR_2, bcb); } /** * zynqmp_disp_blend_set_global_alpha - Configure global alpha blending - * @blend: Blender object + * @disp: Display controller * @enable: True to enable global alpha blending * @alpha: Global alpha value (ignored if @enabled is false) */ -static void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp_blend *blend, +static void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp *disp, bool enable, u32 alpha) { - zynqmp_disp_blend_write(blend, ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA, + zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA, ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_VALUE(alpha) | (enable ? ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_EN : 0)); } /** * zynqmp_disp_blend_layer_set_csc - Configure colorspace conversion for layer - * @blend: Blender object + * @disp: Display controller * @layer: The layer * @coeffs: Colorspace conversion matrix * @offsets: Colorspace conversion offsets @@ -786,7 +776,7 @@ static void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp_blend *blend, * Columns of the matrix are automatically swapped based on the input format to * handle RGB and YCrCb components permutations. */ -static void zynqmp_disp_blend_layer_set_csc(struct zynqmp_disp_blend *blend, +static void zynqmp_disp_blend_layer_set_csc(struct zynqmp_disp *disp, struct zynqmp_disp_layer *layer, const u16 *coeffs, const u32 *offsets) @@ -807,32 +797,32 @@ static void zynqmp_disp_blend_layer_set_csc(struct zynqmp_disp_blend *blend, } } - if (layer->id == ZYNQMP_DISP_LAYER_VID) + if (zynqmp_disp_layer_is_video(layer)) reg = ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF(0); else reg = ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF(0); for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i += 3, reg += 12) { - zynqmp_disp_blend_write(blend, reg + 0, coeffs[i + swap[0]]); - zynqmp_disp_blend_write(blend, reg + 4, coeffs[i + swap[1]]); - zynqmp_disp_blend_write(blend, reg + 8, coeffs[i + swap[2]]); + zynqmp_disp_blend_write(disp, reg + 0, coeffs[i + swap[0]]); + zynqmp_disp_blend_write(disp, reg + 4, coeffs[i + swap[1]]); + zynqmp_disp_blend_write(disp, reg + 8, coeffs[i + swap[2]]); } - if (layer->id == ZYNQMP_DISP_LAYER_VID) + if (zynqmp_disp_layer_is_video(layer)) reg = ZYNQMP_DISP_V_BLEND_IN1CSC_OFFSET(0); else reg = ZYNQMP_DISP_V_BLEND_IN2CSC_OFFSET(0); for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++) - zynqmp_disp_blend_write(blend, reg + i * 4, offsets[i]); + zynqmp_disp_blend_write(disp, reg + i * 4, offsets[i]); } /** * zynqmp_disp_blend_layer_enable - Enable a layer - * @blend: Blender object + * @disp: Display controller * @layer: The layer */ -static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend, +static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp *disp, struct zynqmp_disp_layer *layer) { const u16 *coeffs; @@ -844,7 +834,7 @@ static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend, (layer->drm_fmt->hsub > 1 ? ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_EN_US : 0); - zynqmp_disp_blend_write(blend, + zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_LAYER_CONTROL(layer->id), val); @@ -856,22 +846,22 @@ static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend, offsets = csc_zero_offsets; } - zynqmp_disp_blend_layer_set_csc(blend, layer, coeffs, offsets); + zynqmp_disp_blend_layer_set_csc(disp, layer, coeffs, offsets); } /** * zynqmp_disp_blend_layer_disable - Disable a layer - * @blend: Blender object + * @disp: Display controller * @layer: The layer */ -static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp_blend *blend, +static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp *disp, struct zynqmp_disp_layer *layer) { - zynqmp_disp_blend_write(blend, + zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_LAYER_CONTROL(layer->id), 0); - zynqmp_disp_blend_layer_set_csc(blend, layer, csc_zero_matrix, + zynqmp_disp_blend_layer_set_csc(disp, layer, csc_zero_matrix, csc_zero_offsets); } @@ -879,57 +869,55 @@ static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp_blend *blend, * Audio Mixer */ -static void zynqmp_disp_audio_write(struct zynqmp_disp_audio *audio, - int reg, u32 val) +static void zynqmp_disp_audio_write(struct zynqmp_disp *disp, int reg, u32 val) { - writel(val, audio->base + reg); + writel(val, disp->audio.base + reg); } /** * zynqmp_disp_audio_enable - Enable the audio mixer - * @audio: Audio mixer + * @disp: Display controller * * Enable the audio mixer by de-asserting the soft reset. The audio state is set to * default values by the reset, set the default mixer volume explicitly. */ -static void zynqmp_disp_audio_enable(struct zynqmp_disp_audio *audio) +static void zynqmp_disp_audio_enable(struct zynqmp_disp *disp) { /* Clear the audio soft reset register as it's an non-reset flop. */ - zynqmp_disp_audio_write(audio, ZYNQMP_DISP_AUD_SOFT_RESET, 0); - zynqmp_disp_audio_write(audio, ZYNQMP_DISP_AUD_MIXER_VOLUME, + zynqmp_disp_audio_write(disp, ZYNQMP_DISP_AUD_SOFT_RESET, 0); + zynqmp_disp_audio_write(disp, ZYNQMP_DISP_AUD_MIXER_VOLUME, ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE); } /** * zynqmp_disp_audio_disable - Disable the audio mixer - * @audio: Audio mixer + * @disp: Display controller * * Disable the audio mixer by asserting its soft reset. */ -static void zynqmp_disp_audio_disable(struct zynqmp_disp_audio *audio) +static void zynqmp_disp_audio_disable(struct zynqmp_disp *disp) { - zynqmp_disp_audio_write(audio, ZYNQMP_DISP_AUD_SOFT_RESET, + zynqmp_disp_audio_write(disp, ZYNQMP_DISP_AUD_SOFT_RESET, ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST); } -static void zynqmp_disp_audio_init(struct device *dev, - struct zynqmp_disp_audio *audio) +static void zynqmp_disp_audio_init(struct zynqmp_disp *disp) { /* Try the live PL audio clock. */ - audio->clk = devm_clk_get(dev, "dp_live_audio_aclk"); - if (!IS_ERR(audio->clk)) { - audio->clk_from_ps = false; + disp->audio.clk = devm_clk_get(disp->dev, "dp_live_audio_aclk"); + if (!IS_ERR(disp->audio.clk)) { + disp->audio.clk_from_ps = false; return; } /* If the live PL audio clock is not valid, fall back to PS clock. */ - audio->clk = devm_clk_get(dev, "dp_aud_clk"); - if (!IS_ERR(audio->clk)) { - audio->clk_from_ps = true; + disp->audio.clk = devm_clk_get(disp->dev, "dp_aud_clk"); + if (!IS_ERR(disp->audio.clk)) { + disp->audio.clk_from_ps = true; return; } - dev_err(dev, "audio disabled due to missing clock\n"); + dev_err(disp->dev, "audio disabled due to missing clock\n"); } /* ----------------------------------------------------------------------------- @@ -1025,9 +1013,9 @@ zynqmp_disp_layer_find_format(struct zynqmp_disp_layer *layer, */ static void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer) { - zynqmp_disp_avbuf_enable_video(&layer->disp->avbuf, layer->id, + zynqmp_disp_avbuf_enable_video(layer->disp, layer, ZYNQMP_DISP_LAYER_NONLIVE); - zynqmp_disp_blend_layer_enable(&layer->disp->blend, layer); + zynqmp_disp_blend_layer_enable(layer->disp, layer); layer->mode = ZYNQMP_DISP_LAYER_NONLIVE; } @@ -1046,8 +1034,8 @@ static void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer) for (i = 0; i < layer->drm_fmt->num_planes; i++) dmaengine_terminate_sync(layer->dmas[i].chan); - zynqmp_disp_avbuf_disable_video(&layer->disp->avbuf, layer->id); - zynqmp_disp_blend_layer_disable(&layer->disp->blend, layer); + zynqmp_disp_avbuf_disable_video(layer->disp, layer); + zynqmp_disp_blend_layer_disable(layer->disp, layer); } /** @@ -1067,8 +1055,7 @@ static void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer, layer->disp_fmt = zynqmp_disp_layer_find_format(layer, info->format); layer->drm_fmt = info; - zynqmp_disp_avbuf_set_format(&layer->disp->avbuf, layer->id, - layer->disp_fmt); + zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt); /* * Set slave_id for each DMA channel to indicate they're part of a @@ -1175,6 +1162,10 @@ zynqmp_disp_plane_atomic_disable(struct drm_plane *plane, return; zynqmp_disp_layer_disable(layer); + + if (zynqmp_disp_layer_is_gfx(layer)) + zynqmp_disp_blend_set_global_alpha(layer->disp, false, + plane->state->alpha >> 8); } static void @@ -1204,6 +1195,10 @@ zynqmp_disp_plane_atomic_update(struct drm_plane *plane, zynqmp_disp_layer_update(layer, new_state); + if (zynqmp_disp_layer_is_gfx(layer)) + zynqmp_disp_blend_set_global_alpha(layer->disp, true, + plane->state->alpha >> 8); + /* Enable or re-enable the plane is the format has changed. */ if (format_changed) zynqmp_disp_layer_enable(layer); @@ -1244,8 +1239,8 @@ static int zynqmp_disp_create_planes(struct zynqmp_disp *disp) drm_formats[j] = layer->info->formats[j].drm_fmt; /* Graphics layer is primary, and video layer is overlay. */ - type = i == ZYNQMP_DISP_LAYER_GFX - ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; + type = zynqmp_disp_layer_is_video(layer) + ? DRM_PLANE_TYPE_OVERLAY : DRM_PLANE_TYPE_PRIMARY; ret = drm_universal_plane_init(disp->drm, &layer->plane, 0, &zynqmp_disp_plane_funcs, drm_formats, @@ -1256,6 +1251,10 @@ static int zynqmp_disp_create_planes(struct zynqmp_disp *disp) drm_plane_helper_add(&layer->plane, &zynqmp_disp_plane_helper_funcs); + + drm_plane_create_zpos_immutable_property(&layer->plane, i); + if (zynqmp_disp_layer_is_gfx(layer)) + drm_plane_create_alpha_property(&layer->plane); } return 0; @@ -1387,14 +1386,14 @@ err: */ static void zynqmp_disp_enable(struct zynqmp_disp *disp) { - zynqmp_disp_avbuf_enable(&disp->avbuf); + zynqmp_disp_avbuf_enable(disp); /* Choose clock source based on the DT clock handle. */ - zynqmp_disp_avbuf_set_clocks_sources(&disp->avbuf, disp->pclk_from_ps, + zynqmp_disp_avbuf_set_clocks_sources(disp, disp->pclk_from_ps, disp->audio.clk_from_ps, true); - zynqmp_disp_avbuf_enable_channels(&disp->avbuf); - zynqmp_disp_avbuf_enable_audio(&disp->avbuf); + zynqmp_disp_avbuf_enable_channels(disp); + zynqmp_disp_avbuf_enable_audio(disp); - zynqmp_disp_audio_enable(&disp->audio); + zynqmp_disp_audio_enable(disp); } /** @@ -1403,11 +1402,11 @@ static void zynqmp_disp_enable(struct zynqmp_disp *disp) */ static void zynqmp_disp_disable(struct zynqmp_disp *disp) { - zynqmp_disp_audio_disable(&disp->audio); + zynqmp_disp_audio_disable(disp); - zynqmp_disp_avbuf_disable_audio(&disp->avbuf); - zynqmp_disp_avbuf_disable_channels(&disp->avbuf); - zynqmp_disp_avbuf_disable(&disp->avbuf); + zynqmp_disp_avbuf_disable_audio(disp); + zynqmp_disp_avbuf_disable_channels(disp); + zynqmp_disp_avbuf_disable(disp); } static inline struct zynqmp_disp *crtc_to_disp(struct drm_crtc *crtc) @@ -1452,9 +1451,10 @@ zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; int ret, vrefresh; + pm_runtime_get_sync(disp->dev); + zynqmp_disp_crtc_setup_clock(crtc, adjusted_mode); - pm_runtime_get_sync(disp->dev); ret = clk_prepare_enable(disp->pclk); if (ret) { dev_err(disp->dev, "failed to enable a pixel clock\n"); @@ -1462,10 +1462,8 @@ zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc, return; } - zynqmp_disp_blend_set_output_format(&disp->blend, - ZYNQMP_DPSUB_FORMAT_RGB); - zynqmp_disp_blend_set_bg_color(&disp->blend, 0, 0, 0); - zynqmp_disp_blend_set_global_alpha(&disp->blend, false, 0); + zynqmp_disp_blend_set_output_format(disp, ZYNQMP_DPSUB_FORMAT_RGB); + zynqmp_disp_blend_set_bg_color(disp, 0, 0, 0); zynqmp_disp_enable(disp); @@ -1674,7 +1672,7 @@ int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm) disp->pclk_from_ps = true; } - zynqmp_disp_audio_init(disp->dev, &disp->audio); + zynqmp_disp_audio_init(disp); ret = zynqmp_disp_create_layers(disp); if (ret) |