Commit cb22f12f authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-xilinx-dpsub-20210809' of git://linuxtv.org/pinchartl/media into drm-next

- Miscellaneous fixes in ZynqMP DPSUB driver
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/YRCSRZZV1HZYPvaG@pendragon.ideasonboard.com
parents 25fed6b3 6ebfd22c
...@@ -3,6 +3,8 @@ config DRM_ZYNQMP_DPSUB ...@@ -3,6 +3,8 @@ config DRM_ZYNQMP_DPSUB
depends on ARCH_ZYNQMP || COMPILE_TEST depends on ARCH_ZYNQMP || COMPILE_TEST
depends on COMMON_CLK && DRM && OF depends on COMMON_CLK && DRM && OF
depends on DMADEVICES depends on DMADEVICES
depends on PHY_XILINX_ZYNQMP
depends on XILINX_ZYNQMP_DPDMA
select DMA_ENGINE select DMA_ENGINE
select DRM_GEM_CMA_HELPER select DRM_GEM_CMA_HELPER
select DRM_KMS_CMA_HELPER select DRM_KMS_CMA_HELPER
......
...@@ -91,7 +91,7 @@ struct zynqmp_disp_format { ...@@ -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_VID: Video layer
* @ZYNQMP_DISP_LAYER_GFX: Graphics layer * @ZYNQMP_DISP_LAYER_GFX: Graphics layer
*/ */
...@@ -158,43 +158,17 @@ struct zynqmp_disp_layer { ...@@ -158,43 +158,17 @@ struct zynqmp_disp_layer {
enum zynqmp_disp_layer_mode mode; enum zynqmp_disp_layer_mode mode;
}; };
/**
* 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 * struct zynqmp_disp - Display controller
* @dev: Device structure * @dev: Device structure
* @drm: DRM core * @drm: DRM core
* @dpsub: Display subsystem * @dpsub: Display subsystem
* @crtc: DRM CRTC * @crtc: DRM CRTC
* @blend: Blender (video rendering pipeline) * @blend.base: Register I/O base address for the blender
* @avbuf: Audio/video buffer manager * @avbuf.base: Register I/O base address for the audio/video buffer manager
* @audio: Audio mixer * @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) * @layers: Layers (planes)
* @event: Pending vblank event request * @event: Pending vblank event request
* @pclk: Pixel clock * @pclk: Pixel clock
...@@ -207,9 +181,17 @@ struct zynqmp_disp { ...@@ -207,9 +181,17 @@ struct zynqmp_disp {
struct drm_crtc crtc; struct drm_crtc crtc;
struct zynqmp_disp_blend blend; struct {
struct zynqmp_disp_avbuf avbuf; void __iomem *base;
struct zynqmp_disp_audio audio; } 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]; struct zynqmp_disp_layer layers[ZYNQMP_DISP_NUM_LAYERS];
...@@ -423,51 +405,60 @@ static const struct zynqmp_disp_format avbuf_gfx_fmts[] = { ...@@ -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, static void zynqmp_disp_avbuf_write(struct zynqmp_disp *disp, int reg, u32 val)
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 * zynqmp_disp_avbuf_set_format - Set the input format for a layer
* @avbuf: Audio/video buffer manager * @disp: Display controller
* @layer: The layer ID * @layer: The layer
* @fmt: The format information * @fmt: The format information
* *
* Set the video buffer manager format for @layer to @fmt. * Set the video buffer manager format for @layer to @fmt.
*/ */
static void zynqmp_disp_avbuf_set_format(struct zynqmp_disp_avbuf *avbuf, static void zynqmp_disp_avbuf_set_format(struct zynqmp_disp *disp,
enum zynqmp_disp_layer_id layer, struct zynqmp_disp_layer *layer,
const struct zynqmp_disp_format *fmt) const struct zynqmp_disp_format *fmt)
{ {
unsigned int i; unsigned int i;
u32 val; u32 val;
val = zynqmp_disp_avbuf_read(avbuf, ZYNQMP_DISP_AV_BUF_FMT); val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_FMT);
val &= layer == ZYNQMP_DISP_LAYER_VID val &= zynqmp_disp_layer_is_video(layer)
? ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK ? ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK
: ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK; : ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK;
val |= fmt->buf_fmt; 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++) { 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_VID_COMP_SF(i)
: ZYNQMP_DISP_AV_BUF_GFX_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 * 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 * @video_from_ps: True if the video clock originates from the PS
* @audio_from_ps: True if the audio 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 * @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, ...@@ -477,7 +468,7 @@ static void zynqmp_disp_avbuf_set_format(struct zynqmp_disp_avbuf *avbuf,
* generated internally or externally. * generated internally or externally.
*/ */
static void 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 video_from_ps, bool audio_from_ps,
bool timings_internal) bool timings_internal)
{ {
...@@ -490,16 +481,16 @@ zynqmp_disp_avbuf_set_clocks_sources(struct zynqmp_disp_avbuf *avbuf, ...@@ -490,16 +481,16 @@ zynqmp_disp_avbuf_set_clocks_sources(struct zynqmp_disp_avbuf *avbuf,
if (timings_internal) if (timings_internal)
val |= ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING; 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 * zynqmp_disp_avbuf_enable_channels - Enable buffer channels
* @avbuf: Audio/video buffer manager * @disp: Display controller
* *
* Enable all (video and audio) buffer channels. * 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; unsigned int i;
u32 val; u32 val;
...@@ -509,7 +500,7 @@ static void zynqmp_disp_avbuf_enable_channels(struct zynqmp_disp_avbuf *avbuf) ...@@ -509,7 +500,7 @@ static void zynqmp_disp_avbuf_enable_channels(struct zynqmp_disp_avbuf *avbuf)
ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT); ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT);
for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS; i++) 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);
val = ZYNQMP_DISP_AV_BUF_CHBUF_EN | val = ZYNQMP_DISP_AV_BUF_CHBUF_EN |
...@@ -517,75 +508,75 @@ static void zynqmp_disp_avbuf_enable_channels(struct zynqmp_disp_avbuf *avbuf) ...@@ -517,75 +508,75 @@ static void zynqmp_disp_avbuf_enable_channels(struct zynqmp_disp_avbuf *avbuf)
ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT); ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT);
for (; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++) 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); val);
} }
/** /**
* zynqmp_disp_avbuf_disable_channels - Disable buffer channels * zynqmp_disp_avbuf_disable_channels - Disable buffer channels
* @avbuf: Audio/video buffer manager * @disp: Display controller
* *
* Disable all (video and audio) buffer channels. * 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; unsigned int i;
for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; 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_AV_BUF_CHBUF_FLUSH);
} }
/** /**
* zynqmp_disp_avbuf_enable_audio - Enable audio * 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. * 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; 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_MASK;
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM; val |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM;
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN; 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 * zynqmp_disp_avbuf_disable_audio - Disable audio
* @avbuf: Audio/video buffer manager * @disp: Display controller
* *
* Disable all audio buffers. * 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; 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_MASK;
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE; val |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE;
val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN; 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 * zynqmp_disp_avbuf_enable_video - Enable a video layer
* @avbuf: Audio/video buffer manager * @disp: Display controller
* @layer: The layer ID * @layer: The layer
* @mode: Operating mode of layer * @mode: Operating mode of layer
* *
* Enable the video/graphics buffer for @layer. * Enable the video/graphics buffer for @layer.
*/ */
static void zynqmp_disp_avbuf_enable_video(struct zynqmp_disp_avbuf *avbuf, static void zynqmp_disp_avbuf_enable_video(struct zynqmp_disp *disp,
enum zynqmp_disp_layer_id layer, struct zynqmp_disp_layer *layer,
enum zynqmp_disp_layer_mode mode) enum zynqmp_disp_layer_mode mode)
{ {
u32 val; u32 val;
val = zynqmp_disp_avbuf_read(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT); val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_OUTPUT);
if (layer == ZYNQMP_DISP_LAYER_VID) { if (zynqmp_disp_layer_is_video(layer)) {
val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK; val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
if (mode == ZYNQMP_DISP_LAYER_NONLIVE) if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM; val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM;
...@@ -599,52 +590,52 @@ static void zynqmp_disp_avbuf_enable_video(struct zynqmp_disp_avbuf *avbuf, ...@@ -599,52 +590,52 @@ static void zynqmp_disp_avbuf_enable_video(struct zynqmp_disp_avbuf *avbuf,
else else
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE; 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 * zynqmp_disp_avbuf_disable_video - Disable a video layer
* @avbuf: Audio/video buffer manager * @disp: Display controller
* @layer: The layer ID * @layer: The layer
* *
* Disable the video/graphics buffer for @layer. * Disable the video/graphics buffer for @layer.
*/ */
static void zynqmp_disp_avbuf_disable_video(struct zynqmp_disp_avbuf *avbuf, static void zynqmp_disp_avbuf_disable_video(struct zynqmp_disp *disp,
enum zynqmp_disp_layer_id layer) struct zynqmp_disp_layer *layer)
{ {
u32 val; u32 val;
val = zynqmp_disp_avbuf_read(avbuf, ZYNQMP_DISP_AV_BUF_OUTPUT); val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_OUTPUT);
if (layer == ZYNQMP_DISP_LAYER_VID) { if (zynqmp_disp_layer_is_video(layer)) {
val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK; val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE; val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE;
} else { } else {
val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK; val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK;
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_DISABLE; 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 * zynqmp_disp_avbuf_enable - Enable the video pipe
* @avbuf: Audio/video buffer manager * @disp: Display controller
* *
* De-assert the video pipe reset. * 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 * zynqmp_disp_avbuf_disable - Disable the video pipe
* @avbuf: Audio/video buffer manager * @disp: Display controller
* *
* Assert the video pipe reset. * 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); ZYNQMP_DISP_AV_BUF_SRST_REG_VID_RST);
} }
...@@ -652,10 +643,9 @@ static void zynqmp_disp_avbuf_disable(struct zynqmp_disp_avbuf *avbuf) ...@@ -652,10 +643,9 @@ static void zynqmp_disp_avbuf_disable(struct zynqmp_disp_avbuf *avbuf)
* Blender (Video Pipeline) * Blender (Video Pipeline)
*/ */
static void zynqmp_disp_blend_write(struct zynqmp_disp_blend *blend, static void zynqmp_disp_blend_write(struct zynqmp_disp *disp, int reg, u32 val)
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[] = { ...@@ -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 * zynqmp_disp_blend_set_output_format - Set the output format of the blender
* @blend: Blender object * @disp: Display controller
* @format: Output format * @format: Output format
* *
* Set the output format of the blender to @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) enum zynqmp_dpsub_format format)
{ {
static const unsigned int blend_output_fmts[] = { static const unsigned int blend_output_fmts[] = {
...@@ -722,7 +712,7 @@ static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp_blend *blend, ...@@ -722,7 +712,7 @@ static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp_blend *blend,
const u32 *offsets; const u32 *offsets;
unsigned int i; 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) { if (fmt == ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB) {
coeffs = csc_identity_matrix; coeffs = csc_identity_matrix;
offsets = csc_zero_offsets; offsets = csc_zero_offsets;
...@@ -732,19 +722,19 @@ static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp_blend *blend, ...@@ -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++) 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), ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF(i),
coeffs[i]); coeffs[i]);
for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; 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), ZYNQMP_DISP_V_BLEND_OUTCSC_OFFSET(i),
offsets[i]); offsets[i]);
} }
/** /**
* zynqmp_disp_blend_set_bg_color - Set the background color * zynqmp_disp_blend_set_bg_color - Set the background color
* @blend: Blender object * @disp: Display controller
* @rcr: Red/Cr color component * @rcr: Red/Cr color component
* @gy: Green/Y color component * @gy: Green/Y color component
* @bcb: Blue/Cb color component * @bcb: Blue/Cb color component
...@@ -753,31 +743,31 @@ static void zynqmp_disp_blend_set_output_format(struct zynqmp_disp_blend *blend, ...@@ -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 * B or Cr, Y and Cb components respectively depending on the selected output
* format. * 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) u32 rcr, u32 gy, u32 bcb)
{ {
zynqmp_disp_blend_write(blend, ZYNQMP_DISP_V_BLEND_BG_CLR_0, rcr); zynqmp_disp_blend_write(disp, 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(disp, 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_2, bcb);
} }
/** /**
* zynqmp_disp_blend_set_global_alpha - Configure global alpha blending * zynqmp_disp_blend_set_global_alpha - Configure global alpha blending
* @blend: Blender object * @disp: Display controller
* @enable: True to enable global alpha blending * @enable: True to enable global alpha blending
* @alpha: Global alpha value (ignored if @enabled is false) * @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) 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) | ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_VALUE(alpha) |
(enable ? ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_EN : 0)); (enable ? ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_EN : 0));
} }
/** /**
* zynqmp_disp_blend_layer_set_csc - Configure colorspace conversion for layer * zynqmp_disp_blend_layer_set_csc - Configure colorspace conversion for layer
* @blend: Blender object * @disp: Display controller
* @layer: The layer * @layer: The layer
* @coeffs: Colorspace conversion matrix * @coeffs: Colorspace conversion matrix
* @offsets: Colorspace conversion offsets * @offsets: Colorspace conversion offsets
...@@ -786,7 +776,7 @@ static void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp_blend *blend, ...@@ -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 * Columns of the matrix are automatically swapped based on the input format to
* handle RGB and YCrCb components permutations. * 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, struct zynqmp_disp_layer *layer,
const u16 *coeffs, const u16 *coeffs,
const u32 *offsets) const u32 *offsets)
...@@ -807,32 +797,32 @@ static void zynqmp_disp_blend_layer_set_csc(struct zynqmp_disp_blend *blend, ...@@ -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); reg = ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF(0);
else else
reg = ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF(0); reg = ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF(0);
for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i += 3, reg += 12) { 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(disp, reg + 0, coeffs[i + swap[0]]);
zynqmp_disp_blend_write(blend, reg + 4, coeffs[i + swap[1]]); zynqmp_disp_blend_write(disp, reg + 4, coeffs[i + swap[1]]);
zynqmp_disp_blend_write(blend, reg + 8, coeffs[i + swap[2]]); 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); reg = ZYNQMP_DISP_V_BLEND_IN1CSC_OFFSET(0);
else else
reg = ZYNQMP_DISP_V_BLEND_IN2CSC_OFFSET(0); reg = ZYNQMP_DISP_V_BLEND_IN2CSC_OFFSET(0);
for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++) 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 * zynqmp_disp_blend_layer_enable - Enable a layer
* @blend: Blender object * @disp: Display controller
* @layer: The layer * @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) struct zynqmp_disp_layer *layer)
{ {
const u16 *coeffs; const u16 *coeffs;
...@@ -844,7 +834,7 @@ static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend, ...@@ -844,7 +834,7 @@ static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend,
(layer->drm_fmt->hsub > 1 ? (layer->drm_fmt->hsub > 1 ?
ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_EN_US : 0); 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), ZYNQMP_DISP_V_BLEND_LAYER_CONTROL(layer->id),
val); val);
...@@ -856,22 +846,22 @@ static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend, ...@@ -856,22 +846,22 @@ static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend,
offsets = csc_zero_offsets; 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 * zynqmp_disp_blend_layer_disable - Disable a layer
* @blend: Blender object * @disp: Display controller
* @layer: The layer * @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) struct zynqmp_disp_layer *layer)
{ {
zynqmp_disp_blend_write(blend, zynqmp_disp_blend_write(disp,
ZYNQMP_DISP_V_BLEND_LAYER_CONTROL(layer->id), ZYNQMP_DISP_V_BLEND_LAYER_CONTROL(layer->id),
0); 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); csc_zero_offsets);
} }
...@@ -879,57 +869,55 @@ static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp_blend *blend, ...@@ -879,57 +869,55 @@ static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp_blend *blend,
* Audio Mixer * Audio Mixer
*/ */
static void zynqmp_disp_audio_write(struct zynqmp_disp_audio *audio, static void zynqmp_disp_audio_write(struct zynqmp_disp *disp, int reg, u32 val)
int reg, u32 val)
{ {
writel(val, audio->base + reg); writel(val, disp->audio.base + reg);
} }
/** /**
* zynqmp_disp_audio_enable - Enable the audio mixer * 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 * 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. * 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. */ /* 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(disp, ZYNQMP_DISP_AUD_SOFT_RESET, 0);
zynqmp_disp_audio_write(audio, ZYNQMP_DISP_AUD_MIXER_VOLUME, zynqmp_disp_audio_write(disp, ZYNQMP_DISP_AUD_MIXER_VOLUME,
ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE); ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE);
} }
/** /**
* zynqmp_disp_audio_disable - Disable the audio mixer * zynqmp_disp_audio_disable - Disable the audio mixer
* @audio: Audio mixer * @disp: Display controller
* *
* Disable the audio mixer by asserting its soft reset. * 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); ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST);
} }
static void zynqmp_disp_audio_init(struct device *dev, static void zynqmp_disp_audio_init(struct zynqmp_disp *disp)
struct zynqmp_disp_audio *audio)
{ {
/* Try the live PL audio clock. */ /* Try the live PL audio clock. */
audio->clk = devm_clk_get(dev, "dp_live_audio_aclk"); disp->audio.clk = devm_clk_get(disp->dev, "dp_live_audio_aclk");
if (!IS_ERR(audio->clk)) { if (!IS_ERR(disp->audio.clk)) {
audio->clk_from_ps = false; disp->audio.clk_from_ps = false;
return; return;
} }
/* If the live PL audio clock is not valid, fall back to PS clock. */ /* If the live PL audio clock is not valid, fall back to PS clock. */
audio->clk = devm_clk_get(dev, "dp_aud_clk"); disp->audio.clk = devm_clk_get(disp->dev, "dp_aud_clk");
if (!IS_ERR(audio->clk)) { if (!IS_ERR(disp->audio.clk)) {
audio->clk_from_ps = true; disp->audio.clk_from_ps = true;
return; 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, ...@@ -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) 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_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; layer->mode = ZYNQMP_DISP_LAYER_NONLIVE;
} }
...@@ -1046,8 +1034,8 @@ static void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer) ...@@ -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++) for (i = 0; i < layer->drm_fmt->num_planes; i++)
dmaengine_terminate_sync(layer->dmas[i].chan); dmaengine_terminate_sync(layer->dmas[i].chan);
zynqmp_disp_avbuf_disable_video(&layer->disp->avbuf, layer->id); zynqmp_disp_avbuf_disable_video(layer->disp, layer);
zynqmp_disp_blend_layer_disable(&layer->disp->blend, 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, ...@@ -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->disp_fmt = zynqmp_disp_layer_find_format(layer, info->format);
layer->drm_fmt = info; layer->drm_fmt = info;
zynqmp_disp_avbuf_set_format(&layer->disp->avbuf, layer->id, zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt);
layer->disp_fmt);
/* /*
* Set slave_id for each DMA channel to indicate they're part of a * 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, ...@@ -1175,6 +1162,10 @@ zynqmp_disp_plane_atomic_disable(struct drm_plane *plane,
return; return;
zynqmp_disp_layer_disable(layer); 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 static void
...@@ -1204,6 +1195,10 @@ zynqmp_disp_plane_atomic_update(struct drm_plane *plane, ...@@ -1204,6 +1195,10 @@ zynqmp_disp_plane_atomic_update(struct drm_plane *plane,
zynqmp_disp_layer_update(layer, new_state); 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. */ /* Enable or re-enable the plane is the format has changed. */
if (format_changed) if (format_changed)
zynqmp_disp_layer_enable(layer); zynqmp_disp_layer_enable(layer);
...@@ -1244,8 +1239,8 @@ static int zynqmp_disp_create_planes(struct zynqmp_disp *disp) ...@@ -1244,8 +1239,8 @@ static int zynqmp_disp_create_planes(struct zynqmp_disp *disp)
drm_formats[j] = layer->info->formats[j].drm_fmt; drm_formats[j] = layer->info->formats[j].drm_fmt;
/* Graphics layer is primary, and video layer is overlay. */ /* Graphics layer is primary, and video layer is overlay. */
type = i == ZYNQMP_DISP_LAYER_GFX type = zynqmp_disp_layer_is_video(layer)
? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; ? DRM_PLANE_TYPE_OVERLAY : DRM_PLANE_TYPE_PRIMARY;
ret = drm_universal_plane_init(disp->drm, &layer->plane, 0, ret = drm_universal_plane_init(disp->drm, &layer->plane, 0,
&zynqmp_disp_plane_funcs, &zynqmp_disp_plane_funcs,
drm_formats, drm_formats,
...@@ -1256,6 +1251,10 @@ static int zynqmp_disp_create_planes(struct zynqmp_disp *disp) ...@@ -1256,6 +1251,10 @@ static int zynqmp_disp_create_planes(struct zynqmp_disp *disp)
drm_plane_helper_add(&layer->plane, drm_plane_helper_add(&layer->plane,
&zynqmp_disp_plane_helper_funcs); &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; return 0;
...@@ -1387,14 +1386,14 @@ static int zynqmp_disp_create_layers(struct zynqmp_disp *disp) ...@@ -1387,14 +1386,14 @@ static int zynqmp_disp_create_layers(struct zynqmp_disp *disp)
*/ */
static void zynqmp_disp_enable(struct zynqmp_disp *disp) 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. */ /* 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); disp->audio.clk_from_ps, true);
zynqmp_disp_avbuf_enable_channels(&disp->avbuf); zynqmp_disp_avbuf_enable_channels(disp);
zynqmp_disp_avbuf_enable_audio(&disp->avbuf); 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) ...@@ -1403,11 +1402,11 @@ static void zynqmp_disp_enable(struct zynqmp_disp *disp)
*/ */
static void zynqmp_disp_disable(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_audio(disp);
zynqmp_disp_avbuf_disable_channels(&disp->avbuf); zynqmp_disp_avbuf_disable_channels(disp);
zynqmp_disp_avbuf_disable(&disp->avbuf); zynqmp_disp_avbuf_disable(disp);
} }
static inline struct zynqmp_disp *crtc_to_disp(struct drm_crtc *crtc) 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, ...@@ -1452,9 +1451,10 @@ zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
int ret, vrefresh; int ret, vrefresh;
pm_runtime_get_sync(disp->dev);
zynqmp_disp_crtc_setup_clock(crtc, adjusted_mode); zynqmp_disp_crtc_setup_clock(crtc, adjusted_mode);
pm_runtime_get_sync(disp->dev);
ret = clk_prepare_enable(disp->pclk); ret = clk_prepare_enable(disp->pclk);
if (ret) { if (ret) {
dev_err(disp->dev, "failed to enable a pixel clock\n"); dev_err(disp->dev, "failed to enable a pixel clock\n");
...@@ -1462,10 +1462,8 @@ zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc, ...@@ -1462,10 +1462,8 @@ zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc,
return; return;
} }
zynqmp_disp_blend_set_output_format(&disp->blend, zynqmp_disp_blend_set_output_format(disp, ZYNQMP_DPSUB_FORMAT_RGB);
ZYNQMP_DPSUB_FORMAT_RGB); zynqmp_disp_blend_set_bg_color(disp, 0, 0, 0);
zynqmp_disp_blend_set_bg_color(&disp->blend, 0, 0, 0);
zynqmp_disp_blend_set_global_alpha(&disp->blend, false, 0);
zynqmp_disp_enable(disp); zynqmp_disp_enable(disp);
...@@ -1674,7 +1672,7 @@ int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm) ...@@ -1674,7 +1672,7 @@ int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
disp->pclk_from_ps = true; disp->pclk_from_ps = true;
} }
zynqmp_disp_audio_init(disp->dev, &disp->audio); zynqmp_disp_audio_init(disp);
ret = zynqmp_disp_create_layers(disp); ret = zynqmp_disp_create_layers(disp);
if (ret) if (ret)
......
...@@ -402,10 +402,6 @@ static int zynqmp_dp_phy_init(struct zynqmp_dp *dp) ...@@ -402,10 +402,6 @@ static int zynqmp_dp_phy_init(struct zynqmp_dp *dp)
} }
} }
ret = zynqmp_dp_reset(dp, false);
if (ret < 0)
return ret;
zynqmp_dp_clr(dp, ZYNQMP_DP_PHY_RESET, ZYNQMP_DP_PHY_RESET_ALL_RESET); zynqmp_dp_clr(dp, ZYNQMP_DP_PHY_RESET, ZYNQMP_DP_PHY_RESET_ALL_RESET);
/* /*
...@@ -441,8 +437,6 @@ static void zynqmp_dp_phy_exit(struct zynqmp_dp *dp) ...@@ -441,8 +437,6 @@ static void zynqmp_dp_phy_exit(struct zynqmp_dp *dp)
ret); ret);
} }
zynqmp_dp_reset(dp, true);
for (i = 0; i < dp->num_lanes; i++) { for (i = 0; i < dp->num_lanes; i++) {
ret = phy_exit(dp->phy[i]); ret = phy_exit(dp->phy[i]);
if (ret) if (ret)
...@@ -1683,9 +1677,13 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm) ...@@ -1683,9 +1677,13 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
return PTR_ERR(dp->reset); return PTR_ERR(dp->reset);
} }
ret = zynqmp_dp_reset(dp, false);
if (ret < 0)
return ret;
ret = zynqmp_dp_phy_probe(dp); ret = zynqmp_dp_phy_probe(dp);
if (ret) if (ret)
return ret; goto err_reset;
/* Initialize the hardware. */ /* Initialize the hardware. */
zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN, zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN,
...@@ -1697,7 +1695,7 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm) ...@@ -1697,7 +1695,7 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
ret = zynqmp_dp_phy_init(dp); ret = zynqmp_dp_phy_init(dp);
if (ret) if (ret)
return ret; goto err_reset;
zynqmp_dp_write(dp, ZYNQMP_DP_TRANSMITTER_ENABLE, 1); zynqmp_dp_write(dp, ZYNQMP_DP_TRANSMITTER_ENABLE, 1);
...@@ -1709,15 +1707,18 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm) ...@@ -1709,15 +1707,18 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
zynqmp_dp_irq_handler, IRQF_ONESHOT, zynqmp_dp_irq_handler, IRQF_ONESHOT,
dev_name(dp->dev), dp); dev_name(dp->dev), dp);
if (ret < 0) if (ret < 0)
goto error; goto err_phy_exit;
dev_dbg(dp->dev, "ZynqMP DisplayPort Tx probed with %u lanes\n", dev_dbg(dp->dev, "ZynqMP DisplayPort Tx probed with %u lanes\n",
dp->num_lanes); dp->num_lanes);
return 0; return 0;
error: err_phy_exit:
zynqmp_dp_phy_exit(dp); zynqmp_dp_phy_exit(dp);
err_reset:
zynqmp_dp_reset(dp, true);
return ret; return ret;
} }
...@@ -1735,4 +1736,5 @@ void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub) ...@@ -1735,4 +1736,5 @@ void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub)
zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, 0xffffffff); zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, 0xffffffff);
zynqmp_dp_phy_exit(dp); zynqmp_dp_phy_exit(dp);
zynqmp_dp_reset(dp, true);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment