This series adds binding and driver support for Display Engine 2.0 variant found in the Allwinner D1.
So far it has only been tested with HDMI. I will be sending the HDMI support series separately, because the hardware comes with a brand new custom HDMI PHY, which requires some refactoring to support cleanly.
This series was tested on A33, D1 and H3.
Changes in v3: - Drop redundant minItems and maxItems
Changes in v2: - New patch: I/O helper portability - Use Jernej's patches for mixer mode setting. - Use an enumeration for the ccsc value.
Jernej Skrabec (3): sun4i/drm: engine: Add mode_set callback sun4i/drm: backend: use mode_set engine callback sun4i/drm: sun8i: use mode_set engine callback
Samuel Holland (11): dt-bindings: display: Separate clock item lists by compatible dt-bindings: display: Add D1 display engine compatibles drm/sun4i: Remove obsolete references to PHYS_OFFSET drm/sun4i: hdmi: Use more portable I/O helpers drm/sun4i: Allow building the driver on RISC-V drm/sun4i: Allow VI layers to be primary planes drm/sun4i: csc: Add support for the new MMIO layout drm/sun4i: Add support for D1 mixers drm/sun4i: Add support for D1 TCON TOP drm/sun4i: Add support for D1 TCONs drm/sun4i: Add compatible for D1 display engine
.../allwinner,sun4i-a10-display-engine.yaml | 1 + .../display/allwinner,sun4i-a10-tcon.yaml | 2 + .../allwinner,sun8i-a83t-de2-mixer.yaml | 2 + .../display/allwinner,sun8i-r40-tcon-top.yaml | 133 ++++++++++++------ drivers/gpu/drm/sun4i/Kconfig | 2 +- drivers/gpu/drm/sun4i/sun4i_backend.c | 40 +++--- drivers/gpu/drm/sun4i/sun4i_crtc.c | 1 + drivers/gpu/drm/sun4i/sun4i_drv.c | 1 + drivers/gpu/drm/sun4i/sun4i_frontend.c | 3 - drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c | 4 +- drivers/gpu/drm/sun4i/sun4i_tcon.c | 8 ++ drivers/gpu/drm/sun4i/sun8i_csc.c | 7 +- drivers/gpu/drm/sun4i/sun8i_csc.h | 1 + drivers/gpu/drm/sun4i/sun8i_mixer.c | 74 ++++++++-- drivers/gpu/drm/sun4i/sun8i_mixer.h | 14 +- drivers/gpu/drm/sun4i/sun8i_tcon_top.c | 15 +- drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 30 ---- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 6 +- drivers/gpu/drm/sun4i/sunxi_engine.h | 27 ++++ 19 files changed, 251 insertions(+), 120 deletions(-)
So far, the binding and driver have relied on the fact that the H6 clocks are both a prefix and a subset of the R40 clocks. This allows them to share the clocks/clock-names items and the clock-output-names order between the hardware variants.
However, the D1 hardware has TCON TV0 and DSI, but no TCON TV1. This cannot be supported by the existing scheme because it puts a gap in the middle of the item lists. To prepare for adding D1 support, use separate lists for variants with different combinations of clocks.
Reviewed-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Signed-off-by: Samuel Holland samuel@sholland.org ---
Changes in v3: - Drop redundant minItems and maxItems
.../display/allwinner,sun8i-r40-tcon-top.yaml | 105 ++++++++++-------- 1 file changed, 61 insertions(+), 44 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml b/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml index 61ef7b337218..449fa99aa51b 100644 --- a/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml +++ b/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml @@ -48,31 +48,15 @@ properties:
clocks: minItems: 2 - items: - - description: The TCON TOP interface clock - - description: The TCON TOP TV0 clock - - description: The TCON TOP TVE0 clock - - description: The TCON TOP TV1 clock - - description: The TCON TOP TVE1 clock - - description: The TCON TOP MIPI DSI clock + maxItems: 6
clock-names: minItems: 2 - items: - - const: bus - - const: tcon-tv0 - - const: tve0 - - const: tcon-tv1 - - const: tve1 - - const: dsi + maxItems: 6
clock-output-names: minItems: 1 maxItems: 3 - description: > - The first item is the name of the clock created for the TV0 - channel, the second item is the name of the TCON TV1 channel - clock and the third one is the name of the DSI channel clock.
resets: maxItems: 1 @@ -129,32 +113,65 @@ required:
additionalProperties: false
-if: - properties: - compatible: - contains: - const: allwinner,sun50i-h6-tcon-top - -then: - properties: - clocks: - maxItems: 2 - - clock-output-names: - maxItems: 1 - -else: - properties: - clocks: - minItems: 6 - - clock-output-names: - minItems: 3 - - ports: - required: - - port@2 - - port@3 +allOf: + - if: + properties: + compatible: + contains: + const: allwinner,sun8i-r40-tcon-top + + then: + properties: + clocks: + items: + - description: The TCON TOP interface clock + - description: The TCON TOP TV0 clock + - description: The TCON TOP TVE0 clock + - description: The TCON TOP TV1 clock + - description: The TCON TOP TVE1 clock + - description: The TCON TOP MIPI DSI clock + + clock-names: + items: + - const: bus + - const: tcon-tv0 + - const: tve0 + - const: tcon-tv1 + - const: tve1 + - const: dsi + + clock-output-names: + items: + - description: TCON TV0 output clock name + - description: TCON TV1 output clock name + - description: DSI output clock name + + ports: + required: + - port@2 + - port@3 + + - if: + properties: + compatible: + contains: + const: allwinner,sun50i-h6-tcon-top + + then: + properties: + clocks: + items: + - description: The TCON TOP interface clock + - description: The TCON TOP TV0 clock + + clock-names: + items: + - const: bus + - const: tcon-tv0 + + clock-output-names: + items: + - description: TCON TV0 output clock name
examples: - |
On Sun, 24 Apr 2022 11:26:19 -0500, Samuel Holland wrote:
So far, the binding and driver have relied on the fact that the H6 clocks are both a prefix and a subset of the R40 clocks. This allows them to share the clocks/clock-names items and the clock-output-names order between the hardware variants.
However, the D1 hardware has TCON TV0 and DSI, but no TCON TV1. This cannot be supported by the existing scheme because it puts a gap in the middle of the item lists. To prepare for adding D1 support, use separate lists for variants with different combinations of clocks.
[...]
Applied to drm/drm-misc (drm-misc-next).
Thanks! Maxime
Allwinner D1 contains a display engine 2.0. It features two mixers, a TCON TOP (with DSI and HDMI), one TCON LCD, and one TCON TV.
Reviewed-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Signed-off-by: Samuel Holland samuel@sholland.org ---
Changes in v3: - Drop redundant minItems and maxItems
.../allwinner,sun4i-a10-display-engine.yaml | 1 + .../display/allwinner,sun4i-a10-tcon.yaml | 2 ++ .../allwinner,sun8i-a83t-de2-mixer.yaml | 2 ++ .../display/allwinner,sun8i-r40-tcon-top.yaml | 28 +++++++++++++++++++ 4 files changed, 33 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-display-engine.yaml b/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-display-engine.yaml index d4412aea7b73..c388ae5da1e4 100644 --- a/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-display-engine.yaml +++ b/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-display-engine.yaml @@ -62,6 +62,7 @@ properties: - allwinner,sun8i-r40-display-engine - allwinner,sun8i-v3s-display-engine - allwinner,sun9i-a80-display-engine + - allwinner,sun20i-d1-display-engine - allwinner,sun50i-a64-display-engine - allwinner,sun50i-h6-display-engine
diff --git a/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml b/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml index 3a7d5d731712..4a92a4c7dcd7 100644 --- a/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml +++ b/Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml @@ -33,6 +33,8 @@ properties: - const: allwinner,sun8i-v3s-tcon - const: allwinner,sun9i-a80-tcon-lcd - const: allwinner,sun9i-a80-tcon-tv + - const: allwinner,sun20i-d1-tcon-lcd + - const: allwinner,sun20i-d1-tcon-tv
- items: - enum: diff --git a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml index 4f91eec26de9..cb243bc58ef7 100644 --- a/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml +++ b/Documentation/devicetree/bindings/display/allwinner,sun8i-a83t-de2-mixer.yaml @@ -19,6 +19,8 @@ properties: - allwinner,sun8i-r40-de2-mixer-0 - allwinner,sun8i-r40-de2-mixer-1 - allwinner,sun8i-v3s-de2-mixer + - allwinner,sun20i-d1-de2-mixer-0 + - allwinner,sun20i-d1-de2-mixer-1 - allwinner,sun50i-a64-de2-mixer-0 - allwinner,sun50i-a64-de2-mixer-1 - allwinner,sun50i-h6-de3-mixer-0 diff --git a/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml b/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml index 449fa99aa51b..845e226d7aff 100644 --- a/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml +++ b/Documentation/devicetree/bindings/display/allwinner,sun8i-r40-tcon-top.yaml @@ -41,6 +41,7 @@ properties: compatible: enum: - allwinner,sun8i-r40-tcon-top + - allwinner,sun20i-d1-tcon-top - allwinner,sun50i-h6-tcon-top
reg: @@ -151,6 +152,33 @@ allOf: - port@2 - port@3
+ - if: + properties: + compatible: + contains: + const: allwinner,sun20i-d1-tcon-top + + then: + properties: + clocks: + items: + - description: The TCON TOP interface clock + - description: The TCON TOP TV0 clock + - description: The TCON TOP TVE0 clock + - description: The TCON TOP MIPI DSI clock + + clock-names: + items: + - const: bus + - const: tcon-tv0 + - const: tve0 + - const: dsi + + clock-output-names: + items: + - description: TCON TV0 output clock name + - description: DSI output clock name + - if: properties: compatible:
On Sun, 24 Apr 2022 11:26:20 -0500, Samuel Holland wrote:
Allwinner D1 contains a display engine 2.0. It features two mixers, a TCON TOP (with DSI and HDMI), one TCON LCD, and one TCON TV.
Applied to drm/drm-misc (drm-misc-next).
Thanks! Maxime
commit b4bdc4fbf8d0 ("soc: sunxi: Deal with the MBUS DMA offsets in a central place") added a platform device notifier that sets the DMA offset for all of the display engine frontend and backend devices.
The code applying the offset to DMA buffer physical addresses was then removed from the backend driver in commit 756668ba682e ("drm/sun4i: backend: Remove the MBUS quirks"), but the code subtracting PHYS_OFFSET was left in the frontend driver.
As a result, the offset was applied twice in the frontend driver. This likely went unnoticed because it only affects specific configurations (scaling or certain pixel formats) where the frontend is used, on boards with both one of these older SoCs and more than 1 GB of DRAM.
In addition, the references to PHYS_OFFSET prevent compiling the driver on architectures where PHYS_OFFSET is not defined.
Fixes: b4bdc4fbf8d0 ("soc: sunxi: Deal with the MBUS DMA offsets in a central place") Reviewed-by: Jernej Skrabec jernej.skrabec@gmail.com Signed-off-by: Samuel Holland samuel@sholland.org ---
(no changes since v1)
drivers/gpu/drm/sun4i/sun4i_frontend.c | 3 --- 1 file changed, 3 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index 56ae38389db0..462fae73eae9 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -222,13 +222,11 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
/* Set the physical address of the buffer in memory */ paddr = drm_fb_cma_get_gem_addr(fb, state, 0); - paddr -= PHYS_OFFSET; DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &paddr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr);
if (fb->format->num_planes > 1) { paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 2 : 1); - paddr -= PHYS_OFFSET; DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", &paddr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG, paddr); @@ -236,7 +234,6 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
if (fb->format->num_planes > 2) { paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 1 : 2); - paddr -= PHYS_OFFSET; DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n", &paddr); regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR2_REG, paddr);
On Sun, 24 Apr 2022 11:26:21 -0500, Samuel Holland wrote:
commit b4bdc4fbf8d0 ("soc: sunxi: Deal with the MBUS DMA offsets in a central place") added a platform device notifier that sets the DMA offset for all of the display engine frontend and backend devices.
The code applying the offset to DMA buffer physical addresses was then removed from the backend driver in commit 756668ba682e ("drm/sun4i: backend: Remove the MBUS quirks"), but the code subtracting PHYS_OFFSET was left in the frontend driver.
[...]
Applied to drm/drm-misc (drm-misc-fixes).
Thanks! Maxime
readsb/writesb are unavailable on some architectures. In preparation for removing the Kconfig architecture dependency, switch to the equivalent but more portable ioread/write8_rep helpers.
Reported-by: kernel test robot lkp@intel.com Signed-off-by: Samuel Holland samuel@sholland.org ---
(no changes since v2)
Changes in v2: - New patch: I/O helper portability
drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c index b66fa27fe6ea..c7d7e9fff91c 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c @@ -56,9 +56,9 @@ static int fifo_transfer(struct sun4i_hdmi *hdmi, u8 *buf, int len, bool read) return -EIO;
if (read) - readsb(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len); + ioread8_rep(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len); else - writesb(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len); + iowrite8_rep(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len);
/* Clear FIFO request bit by forcing a write to that bit */ regmap_field_force_write(hdmi->field_ddc_int_status,
Dne nedelja, 24. april 2022 ob 18:26:22 CEST je Samuel Holland napisal(a):
readsb/writesb are unavailable on some architectures. In preparation for removing the Kconfig architecture dependency, switch to the equivalent but more portable ioread/write8_rep helpers.
Reported-by: kernel test robot lkp@intel.com Signed-off-by: Samuel Holland samuel@sholland.org
Reviewed-by: Jernej Skrabec jernej.skrabec@gmail.com
Best regards, Jernej Skrabec
(no changes since v2)
Changes in v2:
- New patch: I/O helper portability
drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c b/drivers/gpu/drm/sun4i/
sun4i_hdmi_i2c.c
index b66fa27fe6ea..c7d7e9fff91c 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c @@ -56,9 +56,9 @@ static int fifo_transfer(struct sun4i_hdmi *hdmi, u8 *buf,
int len, bool read)
return -EIO;
if (read)
readsb(hdmi->base + hdmi->variant->ddc_fifo_reg, buf,
len);
ioread8_rep(hdmi->base + hdmi->variant->ddc_fifo_reg,
buf, len);
else
writesb(hdmi->base + hdmi->variant->ddc_fifo_reg, buf,
len);
iowrite8_rep(hdmi->base + hdmi->variant->ddc_fifo_reg,
buf, len);
/* Clear FIFO request bit by forcing a write to that bit */ regmap_field_force_write(hdmi->field_ddc_int_status, -- 2.35.1
On Sun, 24 Apr 2022 11:26:22 -0500, Samuel Holland wrote:
readsb/writesb are unavailable on some architectures. In preparation for removing the Kconfig architecture dependency, switch to the equivalent but more portable ioread/write8_rep helpers.
Applied to drm/drm-misc (drm-misc-next).
Thanks! Maxime
Allwinner D1 is a RISC-V SoC which contains a DE 2.0 engine. Let's remove the dependency on a specific CPU architecture, so the driver can be built wherever ARCH_SUNXI is selected.
Acked-by: Jernej Skrabec jernej.skrabec@gmail.com Signed-off-by: Samuel Holland samuel@sholland.org ---
(no changes since v1)
drivers/gpu/drm/sun4i/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig index befc5a80222d..3a43c436c74a 100644 --- a/drivers/gpu/drm/sun4i/Kconfig +++ b/drivers/gpu/drm/sun4i/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config DRM_SUN4I tristate "DRM Support for Allwinner A10 Display Engine" - depends on DRM && (ARM || ARM64) && COMMON_CLK + depends on DRM && COMMON_CLK depends on ARCH_SUNXI || COMPILE_TEST select DRM_GEM_CMA_HELPER select DRM_KMS_HELPER
On Sun, 24 Apr 2022 11:26:23 -0500, Samuel Holland wrote:
Allwinner D1 is a RISC-V SoC which contains a DE 2.0 engine. Let's remove the dependency on a specific CPU architecture, so the driver can be built wherever ARCH_SUNXI is selected.
Applied to drm/drm-misc (drm-misc-next).
Thanks! Maxime
From: Jernej Skrabec jernej.skrabec@gmail.com
This optional callback is useful for setting properties which depends only on current mode. Such properties are width, height and interlaced output.
These properties are currently set in update layer callback for primary plane which is less than ideal. More about that in follow up patches, which will migrate that code to this newly defined callback.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com Signed-off-by: Samuel Holland samuel@sholland.org ---
(no changes since v2)
Changes in v2: - Use Jernej's patches for mixer mode setting.
drivers/gpu/drm/sun4i/sun4i_crtc.c | 1 + drivers/gpu/drm/sun4i/sunxi_engine.h | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 45d9eb552d86..c06d7cd45388 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -146,6 +146,7 @@ static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc) struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
sun4i_tcon_mode_set(scrtc->tcon, encoder, mode); + sunxi_engine_mode_set(scrtc->engine, mode); }
static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = { diff --git a/drivers/gpu/drm/sun4i/sunxi_engine.h b/drivers/gpu/drm/sun4i/sunxi_engine.h index 548710a936d5..ec8cf9b2bda4 100644 --- a/drivers/gpu/drm/sun4i/sunxi_engine.h +++ b/drivers/gpu/drm/sun4i/sunxi_engine.h @@ -9,6 +9,7 @@ struct drm_plane; struct drm_device; struct drm_crtc_state; +struct drm_display_mode;
struct sunxi_engine;
@@ -108,6 +109,17 @@ struct sunxi_engine_ops { * This function is optional. */ void (*vblank_quirk)(struct sunxi_engine *engine); + + /** + * @mode_set + * + * This callback is used to set mode related parameters + * like interlacing, screen size, etc. once per mode set. + * + * This function is optional. + */ + void (*mode_set)(struct sunxi_engine *engine, + const struct drm_display_mode *mode); };
/** @@ -181,4 +193,19 @@ sunxi_engine_disable_color_correction(struct sunxi_engine *engine) if (engine->ops && engine->ops->disable_color_correction) engine->ops->disable_color_correction(engine); } + +/** + * sunxi_engine_mode_set - Inform engine of a new mode + * @engine: pointer to the engine + * @mode: new mode + * + * Engine can use this functionality to set specifics once per mode change. + */ +static inline void +sunxi_engine_mode_set(struct sunxi_engine *engine, + const struct drm_display_mode *mode) +{ + if (engine->ops && engine->ops->mode_set) + engine->ops->mode_set(engine, mode); +} #endif /* _SUNXI_ENGINE_H_ */
On Sun, 24 Apr 2022 11:26:24 -0500, Samuel Holland wrote:
From: Jernej Skrabec jernej.skrabec@gmail.com
This optional callback is useful for setting properties which depends only on current mode. Such properties are width, height and interlaced output.
These properties are currently set in update layer callback for primary plane which is less than ideal. More about that in follow up patches, which will migrate that code to this newly defined callback.
[...]
Applied to drm/drm-misc (drm-misc-next).
Thanks! Maxime
From: Jernej Skrabec jernej.skrabec@gmail.com
Newly introduced mode_set callback in engine structure is a much better place for setting backend output size and interlace mode for following reasons: 1. Aforementioned properties change only when mode changes, so it's enough to be set only once per mode set. Currently it's done whenever properties of primary plane are changed. 2. It's assumed that primary plane will always cover whole screen. While this is true most of the time, it's not always. Planes are universal. There is no reason to add artificial limitation to primary plane.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com [Samuel: drop unused 'interlaced' variable] Signed-off-by: Samuel Holland samuel@sholland.org ---
(no changes since v2)
Changes in v2: - Use Jernej's patches for mixer mode setting.
drivers/gpu/drm/sun4i/sun4i_backend.c | 40 +++++++++++++-------------- 1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index f52ff4e6c662..decd95ad519d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -172,14 +172,6 @@ int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
- if (plane->type == DRM_PLANE_TYPE_PRIMARY) { - DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n", - state->crtc_w, state->crtc_h); - regmap_write(backend->engine.regs, SUN4I_BACKEND_DISSIZE_REG, - SUN4I_BACKEND_DISSIZE(state->crtc_w, - state->crtc_h)); - } - /* Set height and width */ DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n", state->crtc_w, state->crtc_h); @@ -259,7 +251,6 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, { struct drm_plane_state *state = plane->state; struct drm_framebuffer *fb = state->fb; - bool interlaced = false; u32 val; int ret;
@@ -267,17 +258,6 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_ATTCTL_REG0(layer), SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN, 0);
- if (plane->state->crtc) - interlaced = plane->state->crtc->state->adjusted_mode.flags - & DRM_MODE_FLAG_INTERLACE; - - regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG, - SUN4I_BACKEND_MODCTL_ITLMOD_EN, - interlaced ? SUN4I_BACKEND_MODCTL_ITLMOD_EN : 0); - - DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n", - interlaced ? "on" : "off"); - val = SUN4I_BACKEND_ATTCTL_REG0_LAY_GLBALPHA(state->alpha >> 8); if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) val |= SUN4I_BACKEND_ATTCTL_REG0_LAY_GLBALPHA_EN; @@ -654,6 +634,25 @@ static void sun4i_backend_vblank_quirk(struct sunxi_engine *engine) spin_unlock(&backend->frontend_lock); };
+static void sun4i_backend_mode_set(struct sunxi_engine *engine, + const struct drm_display_mode *mode) +{ + bool interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); + + DRM_DEBUG_DRIVER("Updating global size W: %u H: %u\n", + mode->hdisplay, mode->vdisplay); + + regmap_write(engine->regs, SUN4I_BACKEND_DISSIZE_REG, + SUN4I_BACKEND_DISSIZE(mode->hdisplay, mode->vdisplay)); + + regmap_update_bits(engine->regs, SUN4I_BACKEND_MODCTL_REG, + SUN4I_BACKEND_MODCTL_ITLMOD_EN, + interlaced ? SUN4I_BACKEND_MODCTL_ITLMOD_EN : 0); + + DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n", + interlaced ? "on" : "off"); +} + static int sun4i_backend_init_sat(struct device *dev) { struct sun4i_backend *backend = dev_get_drvdata(dev); int ret; @@ -765,6 +764,7 @@ static const struct sunxi_engine_ops sun4i_backend_engine_ops = { .apply_color_correction = sun4i_backend_apply_color_correction, .disable_color_correction = sun4i_backend_disable_color_correction, .vblank_quirk = sun4i_backend_vblank_quirk, + .mode_set = sun4i_backend_mode_set, };
static const struct regmap_config sun4i_backend_regmap_config = {
On Sun, 24 Apr 2022 11:26:25 -0500, Samuel Holland wrote:
From: Jernej Skrabec jernej.skrabec@gmail.com
Newly introduced mode_set callback in engine structure is a much better place for setting backend output size and interlace mode for following reasons:
- Aforementioned properties change only when mode changes, so it's enough to be set only once per mode set. Currently it's done whenever properties of primary plane are changed.
- It's assumed that primary plane will always cover whole screen. While this is true most of the time, it's not always. Planes are universal. There is no reason to add artificial limitation to primary plane.
[...]
Applied to drm/drm-misc (drm-misc-next).
Thanks! Maxime
From: Jernej Skrabec jernej.skrabec@gmail.com
Newly introduced mode_set callback in engine structure is a much better place for setting mixer output size and interlace mode for the following reasons: 1. Aforementioned properties change only when mode changes, so it's enough to be set only once per mode set. Currently it's done whenever properties of primary plane are changed. 2. It's assumed that primary plane will always cover whole screen. While this is true most of the time, it's not always. DE2/3 planes are universal and mostly equal in functionality. There is no reason to add artificial limitation to primary planes. 3. The current code only works for UI layers, but some mixers do not have any UI layers.
Signed-off-by: Jernej Skrabec jernej.skrabec@gmail.com [Samuel: update commit message] Signed-off-by: Samuel Holland samuel@sholland.org ---
(no changes since v2)
Changes in v2: - Use Jernej's patches for mixer mode setting.
drivers/gpu/drm/sun4i/sun8i_mixer.c | 30 ++++++++++++++++++++++++++ drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 30 -------------------------- 2 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index f5e8aeaa3cdf..6b1711a9a71f 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -298,9 +298,39 @@ static struct drm_plane **sun8i_layers_init(struct drm_device *drm, return planes; }
+static void sun8i_mixer_mode_set(struct sunxi_engine *engine, + const struct drm_display_mode *mode) +{ + struct sun8i_mixer *mixer = engine_to_sun8i_mixer(engine); + u32 bld_base, size, val; + bool interlaced; + + bld_base = sun8i_blender_base(mixer); + interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); + size = SUN8I_MIXER_SIZE(mode->hdisplay, mode->vdisplay); + + DRM_DEBUG_DRIVER("Updating global size W: %u H: %u\n", + mode->hdisplay, mode->vdisplay); + + regmap_write(engine->regs, SUN8I_MIXER_GLOBAL_SIZE, size); + regmap_write(engine->regs, SUN8I_MIXER_BLEND_OUTSIZE(bld_base), size); + + if (interlaced) + val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED; + else + val = 0; + + regmap_update_bits(engine->regs, SUN8I_MIXER_BLEND_OUTCTL(bld_base), + SUN8I_MIXER_BLEND_OUTCTL_INTERLACED, val); + + DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n", + interlaced ? "on" : "off"); +} + static const struct sunxi_engine_ops sun8i_engine_ops = { .commit = sun8i_mixer_commit, .layers_init = sun8i_layers_init, + .mode_set = sun8i_mixer_mode_set, };
static const struct regmap_config sun8i_mixer_regmap_config = { diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index 7845c2a53a7f..4632dea2dc1e 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -120,36 +120,6 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel, insize = SUN8I_MIXER_SIZE(src_w, src_h); outsize = SUN8I_MIXER_SIZE(dst_w, dst_h);
- if (plane->type == DRM_PLANE_TYPE_PRIMARY) { - bool interlaced = false; - u32 val; - - DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n", - dst_w, dst_h); - regmap_write(mixer->engine.regs, - SUN8I_MIXER_GLOBAL_SIZE, - outsize); - regmap_write(mixer->engine.regs, - SUN8I_MIXER_BLEND_OUTSIZE(bld_base), outsize); - - if (state->crtc) - interlaced = state->crtc->state->adjusted_mode.flags - & DRM_MODE_FLAG_INTERLACE; - - if (interlaced) - val = SUN8I_MIXER_BLEND_OUTCTL_INTERLACED; - else - val = 0; - - regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_BLEND_OUTCTL(bld_base), - SUN8I_MIXER_BLEND_OUTCTL_INTERLACED, - val); - - DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n", - interlaced ? "on" : "off"); - } - /* Set height and width */ DRM_DEBUG_DRIVER("Layer source offset X: %d Y: %d\n", state->src.x1 >> 16, state->src.y1 >> 16);
On Sun, 24 Apr 2022 11:26:26 -0500, Samuel Holland wrote:
From: Jernej Skrabec jernej.skrabec@gmail.com
Newly introduced mode_set callback in engine structure is a much better place for setting mixer output size and interlace mode for the following reasons:
- Aforementioned properties change only when mode changes, so it's enough to be set only once per mode set. Currently it's done whenever properties of primary plane are changed.
- It's assumed that primary plane will always cover whole screen. While this is true most of the time, it's not always. DE2/3 planes are universal and mostly equal in functionality. There is no reason to add artificial limitation to primary planes.
- The current code only works for UI layers, but some mixers do not have any UI layers.
[...]
Applied to drm/drm-misc (drm-misc-next).
Thanks! Maxime
D1's mixer 1 has no UI layers, only a single VI layer. That means the mixer can only be used if the primary plane comes from this VI layer. Add the code to handle this case.
Signed-off-by: Samuel Holland samuel@sholland.org ---
(no changes since v2)
Changes in v2: - Use Jernej's patches for mixer mode setting.
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index bb7c43036dfa..f7d0b082d634 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -542,6 +542,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, struct sun8i_mixer *mixer, int index) { + enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY; u32 supported_encodings, supported_ranges; unsigned int plane_cnt, format_count; struct sun8i_vi_layer *layer; @@ -560,12 +561,15 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, format_count = ARRAY_SIZE(sun8i_vi_layer_formats); }
+ if (!mixer->cfg->ui_num && index == 0) + type = DRM_PLANE_TYPE_PRIMARY; + /* possible crtcs are set later */ ret = drm_universal_plane_init(drm, &layer->plane, 0, &sun8i_vi_layer_funcs, formats, format_count, sun8i_layer_modifiers, - DRM_PLANE_TYPE_OVERLAY, NULL); + type, NULL); if (ret) { dev_err(drm->dev, "Couldn't initialize layer\n"); return ERR_PTR(ret);
Dne nedelja, 24. april 2022 ob 18:26:27 CEST je Samuel Holland napisal(a):
D1's mixer 1 has no UI layers, only a single VI layer. That means the mixer can only be used if the primary plane comes from this VI layer. Add the code to handle this case.
Signed-off-by: Samuel Holland samuel@sholland.org
Reviewed-by: Jernej Skrabec jernej.skrabec@gmail.com
Best regards, Jernej Skrabec
(no changes since v2)
Changes in v2:
- Use Jernej's patches for mixer mode setting.
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/
sun8i_vi_layer.c
index bb7c43036dfa..f7d0b082d634 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -542,6 +542,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct
drm_device *drm,
struct
sun8i_mixer *mixer,
int index)
{
- enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY; u32 supported_encodings, supported_ranges; unsigned int plane_cnt, format_count; struct sun8i_vi_layer *layer;
@@ -560,12 +561,15 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct
drm_device *drm,
format_count = ARRAY_SIZE(sun8i_vi_layer_formats);
}
- if (!mixer->cfg->ui_num && index == 0)
type = DRM_PLANE_TYPE_PRIMARY;
- /* possible crtcs are set later */ ret = drm_universal_plane_init(drm, &layer->plane, 0, &sun8i_vi_layer_funcs, formats, format_count, sun8i_layer_modifiers,
DRM_PLANE_TYPE_OVERLAY,
NULL);
if (ret) { dev_err(drm->dev, "Couldn't initialize layer\n"); return ERR_PTR(ret);type, NULL);
-- 2.35.1
On Sun, 24 Apr 2022 11:26:27 -0500, Samuel Holland wrote:
D1's mixer 1 has no UI layers, only a single VI layer. That means the mixer can only be used if the primary plane comes from this VI layer. Add the code to handle this case.
Applied to drm/drm-misc (drm-misc-next).
Thanks! Maxime
D1 changes the MMIO offsets for the CSC blocks in the first mixer. The mixers' ccsc property is used as an index into the ccsc_base array. Use an enumeration to describe this index, and add the new set of offsets.
Signed-off-by: Samuel Holland samuel@sholland.org ---
(no changes since v2)
Changes in v2: - Use an enumeration for the ccsc value.
drivers/gpu/drm/sun4i/sun8i_csc.c | 7 ++++--- drivers/gpu/drm/sun4i/sun8i_csc.h | 1 + drivers/gpu/drm/sun4i/sun8i_mixer.c | 18 +++++++++--------- drivers/gpu/drm/sun4i/sun8i_mixer.h | 14 ++++++++++---- 4 files changed, 24 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c index 9bd62de0c288..58480d8e4f70 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.c +++ b/drivers/gpu/drm/sun4i/sun8i_csc.c @@ -8,9 +8,10 @@ #include "sun8i_csc.h" #include "sun8i_mixer.h"
-static const u32 ccsc_base[2][2] = { - {CCSC00_OFFSET, CCSC01_OFFSET}, - {CCSC10_OFFSET, CCSC11_OFFSET}, +static const u32 ccsc_base[][2] = { + [CCSC_MIXER0_LAYOUT] = {CCSC00_OFFSET, CCSC01_OFFSET}, + [CCSC_MIXER1_LAYOUT] = {CCSC10_OFFSET, CCSC11_OFFSET}, + [CCSC_D1_MIXER0_LAYOUT] = {CCSC00_OFFSET, CCSC01_D1_OFFSET}, };
/* diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h index 022cafa6c06c..828b86fd0cab 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.h +++ b/drivers/gpu/drm/sun4i/sun8i_csc.h @@ -13,6 +13,7 @@ struct sun8i_mixer; /* VI channel CSC units offsets */ #define CCSC00_OFFSET 0xAA050 #define CCSC01_OFFSET 0xFA050 +#define CCSC01_D1_OFFSET 0xFA000 #define CCSC10_OFFSET 0xA0000 #define CCSC11_OFFSET 0xF0000
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 6b1711a9a71f..4ce593c99807 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -564,7 +564,7 @@ static int sun8i_mixer_remove(struct platform_device *pdev) }
static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = { - .ccsc = 0, + .ccsc = CCSC_MIXER0_LAYOUT, .scaler_mask = 0xf, .scanline_yuv = 2048, .ui_num = 3, @@ -572,7 +572,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = { };
static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = { - .ccsc = 1, + .ccsc = CCSC_MIXER1_LAYOUT, .scaler_mask = 0x3, .scanline_yuv = 2048, .ui_num = 1, @@ -580,7 +580,7 @@ static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = { };
static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = { - .ccsc = 0, + .ccsc = CCSC_MIXER0_LAYOUT, .mod_rate = 432000000, .scaler_mask = 0xf, .scanline_yuv = 2048, @@ -589,7 +589,7 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = { };
static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = { - .ccsc = 0, + .ccsc = CCSC_MIXER0_LAYOUT, .mod_rate = 297000000, .scaler_mask = 0xf, .scanline_yuv = 2048, @@ -598,7 +598,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = { };
static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = { - .ccsc = 1, + .ccsc = CCSC_MIXER1_LAYOUT, .mod_rate = 297000000, .scaler_mask = 0x3, .scanline_yuv = 2048, @@ -611,12 +611,12 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { .ui_num = 1, .scaler_mask = 0x3, .scanline_yuv = 2048, - .ccsc = 0, + .ccsc = CCSC_MIXER0_LAYOUT, .mod_rate = 150000000, };
static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = { - .ccsc = 0, + .ccsc = CCSC_MIXER0_LAYOUT, .mod_rate = 297000000, .scaler_mask = 0xf, .scanline_yuv = 4096, @@ -625,7 +625,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = { };
static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = { - .ccsc = 1, + .ccsc = CCSC_MIXER1_LAYOUT, .mod_rate = 297000000, .scaler_mask = 0x3, .scanline_yuv = 2048, @@ -634,7 +634,7 @@ static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = { };
static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = { - .ccsc = 0, + .ccsc = CCSC_MIXER0_LAYOUT, .is_de3 = true, .mod_rate = 600000000, .scaler_mask = 0xf, diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h index 5b3fbee18671..85c94884fb9a 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h @@ -141,6 +141,15 @@ #define SUN50I_MIXER_CDC0_EN 0xd0000 #define SUN50I_MIXER_CDC1_EN 0xd8000
+enum { + /* First mixer or second mixer with VEP support. */ + CCSC_MIXER0_LAYOUT, + /* Second mixer without VEP support. */ + CCSC_MIXER1_LAYOUT, + /* First mixer with the MMIO layout found in the D1 SoC. */ + CCSC_D1_MIXER0_LAYOUT, +}; + /** * struct sun8i_mixer_cfg - mixer HW configuration * @vi_num: number of VI channels @@ -149,10 +158,7 @@ * First, scaler supports for VI channels is defined and after that, scaler * support for UI channels. For example, if mixer has 2 VI channels without * scaler and 2 UI channels with scaler, bitmask would be 0xC. - * @ccsc: select set of CCSC base addresses - * Set value to 0 if this is first mixer or second mixer with VEP support. - * Set value to 1 if this is second mixer without VEP support. Other values - * are invalid. + * @ccsc: select set of CCSC base addresses from the enumeration above. * @mod_rate: module clock rate that needs to be set in order to have * a functional block. * @is_de3: true, if this is next gen display engine 3.0, false otherwise.
Dne nedelja, 24. april 2022 ob 18:26:28 CEST je Samuel Holland napisal(a):
D1 changes the MMIO offsets for the CSC blocks in the first mixer. The mixers' ccsc property is used as an index into the ccsc_base array. Use an enumeration to describe this index, and add the new set of offsets.
Signed-off-by: Samuel Holland samuel@sholland.org
Reviewed-by: Jernej Skrabec jernej.skrabec@gmail.com
Best regards, Jernej Skrabec
(no changes since v2)
Changes in v2:
- Use an enumeration for the ccsc value.
drivers/gpu/drm/sun4i/sun8i_csc.c | 7 ++++--- drivers/gpu/drm/sun4i/sun8i_csc.h | 1 + drivers/gpu/drm/sun4i/sun8i_mixer.c | 18 +++++++++--------- drivers/gpu/drm/sun4i/sun8i_mixer.h | 14 ++++++++++---- 4 files changed, 24 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/
sun8i_csc.c
index 9bd62de0c288..58480d8e4f70 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.c +++ b/drivers/gpu/drm/sun4i/sun8i_csc.c @@ -8,9 +8,10 @@ #include "sun8i_csc.h" #include "sun8i_mixer.h"
-static const u32 ccsc_base[2][2] = {
- {CCSC00_OFFSET, CCSC01_OFFSET},
- {CCSC10_OFFSET, CCSC11_OFFSET},
+static const u32 ccsc_base[][2] = {
- [CCSC_MIXER0_LAYOUT] = {CCSC00_OFFSET, CCSC01_OFFSET},
- [CCSC_MIXER1_LAYOUT] = {CCSC10_OFFSET, CCSC11_OFFSET},
- [CCSC_D1_MIXER0_LAYOUT] = {CCSC00_OFFSET,
CCSC01_D1_OFFSET},
};
/* diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/
sun8i_csc.h
index 022cafa6c06c..828b86fd0cab 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.h +++ b/drivers/gpu/drm/sun4i/sun8i_csc.h @@ -13,6 +13,7 @@ struct sun8i_mixer; /* VI channel CSC units offsets */ #define CCSC00_OFFSET 0xAA050 #define CCSC01_OFFSET 0xFA050 +#define CCSC01_D1_OFFSET 0xFA000 #define CCSC10_OFFSET 0xA0000 #define CCSC11_OFFSET 0xF0000
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/
sun8i_mixer.c
index 6b1711a9a71f..4ce593c99807 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -564,7 +564,7 @@ static int sun8i_mixer_remove(struct platform_device
*pdev)
}
static const struct sun8i_mixer_cfg sun8i_a83t_mixer0_cfg = {
- .ccsc = 0,
- .ccsc = CCSC_MIXER0_LAYOUT, .scaler_mask = 0xf, .scanline_yuv = 2048, .ui_num = 3,
@@ -572,7 +572,7 @@ static const struct sun8i_mixer_cfg
sun8i_a83t_mixer0_cfg = {
};
static const struct sun8i_mixer_cfg sun8i_a83t_mixer1_cfg = {
- .ccsc = 1,
- .ccsc = CCSC_MIXER1_LAYOUT, .scaler_mask = 0x3, .scanline_yuv = 2048, .ui_num = 1,
@@ -580,7 +580,7 @@ static const struct sun8i_mixer_cfg
sun8i_a83t_mixer1_cfg = {
};
static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
- .ccsc = 0,
- .ccsc = CCSC_MIXER0_LAYOUT, .mod_rate = 432000000, .scaler_mask = 0xf, .scanline_yuv = 2048,
@@ -589,7 +589,7 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg
= {
};
static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
- .ccsc = 0,
- .ccsc = CCSC_MIXER0_LAYOUT, .mod_rate = 297000000, .scaler_mask = 0xf, .scanline_yuv = 2048,
@@ -598,7 +598,7 @@ static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg
= {
};
static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = {
- .ccsc = 1,
- .ccsc = CCSC_MIXER1_LAYOUT, .mod_rate = 297000000, .scaler_mask = 0x3, .scanline_yuv = 2048,
@@ -611,12 +611,12 @@ static const struct sun8i_mixer_cfg
sun8i_v3s_mixer_cfg = {
.ui_num = 1, .scaler_mask = 0x3, .scanline_yuv = 2048,
- .ccsc = 0,
- .ccsc = CCSC_MIXER0_LAYOUT, .mod_rate = 150000000,
};
static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = {
- .ccsc = 0,
- .ccsc = CCSC_MIXER0_LAYOUT, .mod_rate = 297000000, .scaler_mask = 0xf, .scanline_yuv = 4096,
@@ -625,7 +625,7 @@ static const struct sun8i_mixer_cfg
sun50i_a64_mixer0_cfg = {
};
static const struct sun8i_mixer_cfg sun50i_a64_mixer1_cfg = {
- .ccsc = 1,
- .ccsc = CCSC_MIXER1_LAYOUT, .mod_rate = 297000000, .scaler_mask = 0x3, .scanline_yuv = 2048,
@@ -634,7 +634,7 @@ static const struct sun8i_mixer_cfg
sun50i_a64_mixer1_cfg = {
};
static const struct sun8i_mixer_cfg sun50i_h6_mixer0_cfg = {
- .ccsc = 0,
- .ccsc = CCSC_MIXER0_LAYOUT, .is_de3 = true, .mod_rate = 600000000, .scaler_mask = 0xf,
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/
sun8i_mixer.h
index 5b3fbee18671..85c94884fb9a 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h @@ -141,6 +141,15 @@ #define SUN50I_MIXER_CDC0_EN 0xd0000 #define SUN50I_MIXER_CDC1_EN 0xd8000
+enum {
- /* First mixer or second mixer with VEP support. */
- CCSC_MIXER0_LAYOUT,
- /* Second mixer without VEP support. */
- CCSC_MIXER1_LAYOUT,
- /* First mixer with the MMIO layout found in the D1 SoC. */
- CCSC_D1_MIXER0_LAYOUT,
+};
/**
- struct sun8i_mixer_cfg - mixer HW configuration
- @vi_num: number of VI channels
@@ -149,10 +158,7 @@
- First, scaler supports for VI channels is defined and after that,
scaler
- support for UI channels. For example, if mixer has 2 VI channels
without
- scaler and 2 UI channels with scaler, bitmask would be 0xC.
- @ccsc: select set of CCSC base addresses
- Set value to 0 if this is first mixer or second mixer with VEP
support.
- Set value to 1 if this is second mixer without VEP support. Other
values
- are invalid.
- @ccsc: select set of CCSC base addresses from the enumeration above.
- @mod_rate: module clock rate that needs to be set in order to have
- a functional block.
- @is_de3: true, if this is next gen display engine 3.0, false otherwise.
-- 2.35.1
On Sun, 24 Apr 2022 11:26:28 -0500, Samuel Holland wrote:
D1 changes the MMIO offsets for the CSC blocks in the first mixer. The mixers' ccsc property is used as an index into the ccsc_base array. Use an enumeration to describe this index, and add the new set of offsets.
Applied to drm/drm-misc (drm-misc-next).
Thanks! Maxime
D1 has a display engine with the usual pair of mixers, albeit with relatively few layers. In fact, D1 appears to be the first SoC to have a mixer without any UI layers. Add support for these new variants.
Acked-by: Jernej Skrabec jernej.skrabec@gmail.com Signed-off-by: Samuel Holland samuel@sholland.org ---
(no changes since v1)
drivers/gpu/drm/sun4i/sun8i_mixer.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 4ce593c99807..875a1156c04e 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -615,6 +615,24 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = { .mod_rate = 150000000, };
+static const struct sun8i_mixer_cfg sun20i_d1_mixer0_cfg = { + .ccsc = CCSC_D1_MIXER0_LAYOUT, + .mod_rate = 297000000, + .scaler_mask = 0x3, + .scanline_yuv = 2048, + .ui_num = 1, + .vi_num = 1, +}; + +static const struct sun8i_mixer_cfg sun20i_d1_mixer1_cfg = { + .ccsc = CCSC_MIXER1_LAYOUT, + .mod_rate = 297000000, + .scaler_mask = 0x1, + .scanline_yuv = 1024, + .ui_num = 0, + .vi_num = 1, +}; + static const struct sun8i_mixer_cfg sun50i_a64_mixer0_cfg = { .ccsc = CCSC_MIXER0_LAYOUT, .mod_rate = 297000000, @@ -668,6 +686,14 @@ static const struct of_device_id sun8i_mixer_of_table[] = { .compatible = "allwinner,sun8i-v3s-de2-mixer", .data = &sun8i_v3s_mixer_cfg, }, + { + .compatible = "allwinner,sun20i-d1-de2-mixer-0", + .data = &sun20i_d1_mixer0_cfg, + }, + { + .compatible = "allwinner,sun20i-d1-de2-mixer-1", + .data = &sun20i_d1_mixer1_cfg, + }, { .compatible = "allwinner,sun50i-a64-de2-mixer-0", .data = &sun50i_a64_mixer0_cfg,
On Sun, 24 Apr 2022 11:26:29 -0500, Samuel Holland wrote:
D1 has a display engine with the usual pair of mixers, albeit with relatively few layers. In fact, D1 appears to be the first SoC to have a mixer without any UI layers. Add support for these new variants.
Applied to drm/drm-misc (drm-misc-next).
Thanks! Maxime
D1 has a TCON TOP with TCON TV0 and DSI, but no TCON TV1. This puts the DSI clock name at index 1 in clock-output-names. Support this by only incrementing the index for clocks that are actually supported.
Signed-off-by: Samuel Holland samuel@sholland.org ---
(no changes since v1)
drivers/gpu/drm/sun4i/sun8i_tcon_top.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c index 1b9b8b48f4a7..da97682b6835 100644 --- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c +++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c @@ -189,22 +189,23 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master, * if TVE is active on each TCON TV. If it is, mux should be switched * to TVE clock parent. */ + i = 0; clk_data->hws[CLK_TCON_TOP_TV0] = sun8i_tcon_top_register_gate(dev, "tcon-tv0", regs, &tcon_top->reg_lock, - TCON_TOP_TCON_TV0_GATE, 0); + TCON_TOP_TCON_TV0_GATE, i++);
if (quirks->has_tcon_tv1) clk_data->hws[CLK_TCON_TOP_TV1] = sun8i_tcon_top_register_gate(dev, "tcon-tv1", regs, &tcon_top->reg_lock, - TCON_TOP_TCON_TV1_GATE, 1); + TCON_TOP_TCON_TV1_GATE, i++);
if (quirks->has_dsi) clk_data->hws[CLK_TCON_TOP_DSI] = sun8i_tcon_top_register_gate(dev, "dsi", regs, &tcon_top->reg_lock, - TCON_TOP_TCON_DSI_GATE, 2); + TCON_TOP_TCON_DSI_GATE, i++);
for (i = 0; i < CLK_NUM; i++) if (IS_ERR(clk_data->hws[i])) { @@ -272,6 +273,10 @@ static const struct sun8i_tcon_top_quirks sun8i_r40_tcon_top_quirks = { .has_dsi = true, };
+static const struct sun8i_tcon_top_quirks sun20i_d1_tcon_top_quirks = { + .has_dsi = true, +}; + static const struct sun8i_tcon_top_quirks sun50i_h6_tcon_top_quirks = { /* Nothing special */ }; @@ -282,6 +287,10 @@ const struct of_device_id sun8i_tcon_top_of_table[] = { .compatible = "allwinner,sun8i-r40-tcon-top", .data = &sun8i_r40_tcon_top_quirks }, + { + .compatible = "allwinner,sun20i-d1-tcon-top", + .data = &sun20i_d1_tcon_top_quirks + }, { .compatible = "allwinner,sun50i-h6-tcon-top", .data = &sun50i_h6_tcon_top_quirks
Dne nedelja, 24. april 2022 ob 18:26:30 CEST je Samuel Holland napisal(a):
D1 has a TCON TOP with TCON TV0 and DSI, but no TCON TV1. This puts the DSI clock name at index 1 in clock-output-names. Support this by only incrementing the index for clocks that are actually supported.
Signed-off-by: Samuel Holland samuel@sholland.org
Reviewed-by: Jernej Skrabec jernej.skrabec@gmail.com
Best regards, Jernej Skrabec
(no changes since v1)
drivers/gpu/drm/sun4i/sun8i_tcon_top.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c b/drivers/gpu/drm/sun4i/
sun8i_tcon_top.c
index 1b9b8b48f4a7..da97682b6835 100644 --- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c +++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c @@ -189,22 +189,23 @@ static int sun8i_tcon_top_bind(struct device *dev,
struct device *master,
* if TVE is active on each TCON TV. If it is, mux should be
switched
* to TVE clock parent. */
- i = 0; clk_data->hws[CLK_TCON_TOP_TV0] = sun8i_tcon_top_register_gate(dev, "tcon-tv0", regs, &tcon_top-
reg_lock,
TCON_TOP_TCON_TV0_GATE, 0);
TCON_TOP_TCON_TV0_GATE, i++);
if (quirks->has_tcon_tv1) clk_data->hws[CLK_TCON_TOP_TV1] = sun8i_tcon_top_register_gate(dev, "tcon-
tv1", regs,
&tcon_top->reg_lock,
TCON_TOP_TCON_TV1_GATE, 1);
TCON_TOP_TCON_TV1_GATE, i++);
if (quirks->has_dsi) clk_data->hws[CLK_TCON_TOP_DSI] = sun8i_tcon_top_register_gate(dev, "dsi",
regs,
&tcon_top->reg_lock,
TCON_TOP_TCON_DSI_GATE, 2);
TCON_TOP_TCON_DSI_GATE, i++);
for (i = 0; i < CLK_NUM; i++) if (IS_ERR(clk_data->hws[i])) { @@ -272,6 +273,10 @@ static const struct sun8i_tcon_top_quirks
sun8i_r40_tcon_top_quirks = {
.has_dsi = true, };
+static const struct sun8i_tcon_top_quirks sun20i_d1_tcon_top_quirks = {
- .has_dsi = true,
+};
static const struct sun8i_tcon_top_quirks sun50i_h6_tcon_top_quirks = { /* Nothing special */ }; @@ -282,6 +287,10 @@ const struct of_device_id sun8i_tcon_top_of_table[] = { .compatible = "allwinner,sun8i-r40-tcon-top", .data = &sun8i_r40_tcon_top_quirks },
- {
.compatible = "allwinner,sun20i-d1-tcon-top",
.data = &sun20i_d1_tcon_top_quirks
- }, { .compatible = "allwinner,sun50i-h6-tcon-top", .data = &sun50i_h6_tcon_top_quirks
-- 2.35.1
On Sun, 24 Apr 2022 11:26:30 -0500, Samuel Holland wrote:
D1 has a TCON TOP with TCON TV0 and DSI, but no TCON TV1. This puts the DSI clock name at index 1 in clock-output-names. Support this by only incrementing the index for clocks that are actually supported.
Applied to drm/drm-misc (drm-misc-next).
Thanks! Maxime
D1 has a TCON TOP, so its quirks are similar to those for the R40 TCONs. While there are some register changes, the part of the TCON TV supported by the driver matches the R40 quirks, so that quirks structure can be reused. D1 has the first supported TCON LCD with a TCON TOP, so the TCON LCD needs a new quirks structure.
D1's TCON LCD hardware supports LVDS; in fact it provides dual-link LVDS from a single TCON. However, it comes with a brand new LVDS PHY. Since this PHY has not been tested, leave out LVDS driver support for now.
Signed-off-by: Samuel Holland samuel@sholland.org ---
(no changes since v1)
drivers/gpu/drm/sun4i/sun4i_tcon.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 88db2d2a9336..2ee158aaeb9e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -1542,6 +1542,12 @@ static const struct sun4i_tcon_quirks sun9i_a80_tcon_tv_quirks = { .needs_edp_reset = true, };
+static const struct sun4i_tcon_quirks sun20i_d1_lcd_quirks = { + .has_channel_0 = true, + .dclk_min_div = 1, + .set_mux = sun8i_r40_tcon_tv_set_mux, +}; + /* sun4i_drv uses this list to check if a device node is a TCON */ const struct of_device_id sun4i_tcon_of_table[] = { { .compatible = "allwinner,sun4i-a10-tcon", .data = &sun4i_a10_quirks }, @@ -1559,6 +1565,8 @@ const struct of_device_id sun4i_tcon_of_table[] = { { .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks }, { .compatible = "allwinner,sun9i-a80-tcon-lcd", .data = &sun9i_a80_tcon_lcd_quirks }, { .compatible = "allwinner,sun9i-a80-tcon-tv", .data = &sun9i_a80_tcon_tv_quirks }, + { .compatible = "allwinner,sun20i-d1-tcon-lcd", .data = &sun20i_d1_lcd_quirks }, + { .compatible = "allwinner,sun20i-d1-tcon-tv", .data = &sun8i_r40_tv_quirks }, { } }; MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
Dne nedelja, 24. april 2022 ob 18:26:31 CEST je Samuel Holland napisal(a):
D1 has a TCON TOP, so its quirks are similar to those for the R40 TCONs. While there are some register changes, the part of the TCON TV supported by the driver matches the R40 quirks, so that quirks structure can be reused. D1 has the first supported TCON LCD with a TCON TOP, so the TCON LCD needs a new quirks structure.
D1's TCON LCD hardware supports LVDS; in fact it provides dual-link LVDS from a single TCON. However, it comes with a brand new LVDS PHY. Since this PHY has not been tested, leave out LVDS driver support for now.
Signed-off-by: Samuel Holland samuel@sholland.org
Reviewed-by: Jernej Skrabec jernej.skrabec@gmail.com
Best regards, Jernej Skrabec
(no changes since v1)
drivers/gpu/drm/sun4i/sun4i_tcon.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/
sun4i_tcon.c
index 88db2d2a9336..2ee158aaeb9e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -1542,6 +1542,12 @@ static const struct sun4i_tcon_quirks
sun9i_a80_tcon_tv_quirks = {
.needs_edp_reset = true, };
+static const struct sun4i_tcon_quirks sun20i_d1_lcd_quirks = {
- .has_channel_0 = true,
- .dclk_min_div = 1,
- .set_mux = sun8i_r40_tcon_tv_set_mux,
+};
/* sun4i_drv uses this list to check if a device node is a TCON */ const struct of_device_id sun4i_tcon_of_table[] = { { .compatible = "allwinner,sun4i-a10-tcon", .data =
&sun4i_a10_quirks },
@@ -1559,6 +1565,8 @@ const struct of_device_id sun4i_tcon_of_table[] = { { .compatible = "allwinner,sun8i-v3s-tcon", .data =
&sun8i_v3s_quirks },
{ .compatible = "allwinner,sun9i-a80-tcon-lcd", .data =
&sun9i_a80_tcon_lcd_quirks },
{ .compatible = "allwinner,sun9i-a80-tcon-tv", .data =
&sun9i_a80_tcon_tv_quirks },
- { .compatible = "allwinner,sun20i-d1-tcon-lcd", .data =
&sun20i_d1_lcd_quirks },
- { .compatible = "allwinner,sun20i-d1-tcon-tv", .data =
&sun8i_r40_tv_quirks },
{ } }; MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table); -- 2.35.1
On Sun, 24 Apr 2022 11:26:31 -0500, Samuel Holland wrote:
D1 has a TCON TOP, so its quirks are similar to those for the R40 TCONs. While there are some register changes, the part of the TCON TV supported by the driver matches the R40 quirks, so that quirks structure can be reused. D1 has the first supported TCON LCD with a TCON TOP, so the TCON LCD needs a new quirks structure.
D1's TCON LCD hardware supports LVDS; in fact it provides dual-link LVDS from a single TCON. However, it comes with a brand new LVDS PHY. Since this PHY has not been tested, leave out LVDS driver support for now.
[...]
Applied to drm/drm-misc (drm-misc-next).
Thanks! Maxime
Now that the various blocks in the D1 display engine pipeline are supported, we can enable the overall engine.
Acked-by: Jernej Skrabec jernej.skrabec@gmail.com Signed-off-by: Samuel Holland samuel@sholland.org ---
(no changes since v1)
drivers/gpu/drm/sun4i/sun4i_drv.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 6a9ba8a77c77..275f7e4a03ae 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -418,6 +418,7 @@ static const struct of_device_id sun4i_drv_of_table[] = { { .compatible = "allwinner,sun8i-r40-display-engine" }, { .compatible = "allwinner,sun8i-v3s-display-engine" }, { .compatible = "allwinner,sun9i-a80-display-engine" }, + { .compatible = "allwinner,sun20i-d1-display-engine" }, { .compatible = "allwinner,sun50i-a64-display-engine" }, { .compatible = "allwinner,sun50i-h6-display-engine" }, { }
On Sun, 24 Apr 2022 11:26:32 -0500, Samuel Holland wrote:
Now that the various blocks in the D1 display engine pipeline are supported, we can enable the overall engine.
Applied to drm/drm-misc (drm-misc-next).
Thanks! Maxime
dri-devel@lists.freedesktop.org