summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/sun4i
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/sun4i')
-rw-r--r--drivers/gpu/drm/sun4i/Kconfig2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c40
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_crtc.c1
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.c1
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_frontend.c3
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_hdmi.h1
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c6
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c4
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c8
-rw-r--r--drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c7
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_csc.c7
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_csc.h1
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_mixer.c74
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_mixer.h14
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_tcon_top.c15
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_ui_layer.c30
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_vi_layer.c6
-rw-r--r--drivers/gpu/drm/sun4i/sunxi_engine.h27
19 files changed, 164 insertions, 85 deletions
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index befc5a80222d5..3a43c436c74a7 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
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index f52ff4e6c6626..decd95ad519de 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 = {
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 45d9eb552d869..c06d7cd453889 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/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 6a9ba8a77c778..275f7e4a03ae8 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" },
{ }
diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c
index 56ae38389db0b..462fae73eae98 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);
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi.h b/drivers/gpu/drm/sun4i/sun4i_hdmi.h
index 00ca35f07ba5b..65c801cd6f35d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi.h
@@ -285,7 +285,6 @@ struct sun4i_hdmi {
struct sun4i_drv *drv;
- bool hdmi_monitor;
struct cec_adapter *cec_adap;
const struct sun4i_hdmi_variant *variant;
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 3799a745b7dd9..d8b71710e8f66 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -99,6 +99,7 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder)
{
struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
+ struct drm_display_info *display = &hdmi->connector.display_info;
u32 val = 0;
DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
@@ -111,7 +112,7 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder)
writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
val = SUN4I_HDMI_VID_CTRL_ENABLE;
- if (hdmi->hdmi_monitor)
+ if (display->is_hdmi)
val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE;
writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
@@ -215,9 +216,8 @@ static int sun4i_hdmi_get_modes(struct drm_connector *connector)
if (!edid)
return 0;
- hdmi->hdmi_monitor = drm_detect_hdmi_monitor(edid);
DRM_DEBUG_DRIVER("Monitor is %s monitor\n",
- hdmi->hdmi_monitor ? "an HDMI" : "a DVI");
+ connector->display_info.is_hdmi ? "an HDMI" : "a DVI");
drm_connector_update_edid_property(connector, edid);
cec_s_phys_addr_from_edid(hdmi->cec_adap, edid);
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c
index b66fa27fe6ea8..c7d7e9fff91c4 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,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 88db2d2a93368..2ee158aaeb9e9 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);
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 527c7b2474dae..b4dfa166eccdf 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -1193,8 +1193,8 @@ err_remove_dsi_host:
err_unprotect_clk:
clk_rate_exclusive_put(dsi->mod_clk);
err_attach_clk:
- if (!IS_ERR(dsi->bus_clk))
- regmap_mmio_detach_clk(dsi->regs);
+ regmap_mmio_detach_clk(dsi->regs);
+
return ret;
}
@@ -1207,8 +1207,7 @@ static int sun6i_dsi_remove(struct platform_device *pdev)
mipi_dsi_host_unregister(&dsi->host);
clk_rate_exclusive_put(dsi->mod_clk);
- if (!IS_ERR(dsi->bus_clk))
- regmap_mmio_detach_clk(dsi->regs);
+ regmap_mmio_detach_clk(dsi->regs);
return 0;
}
diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c
index 9bd62de0c288c..58480d8e4f704 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 022cafa6c06cb..828b86fd0cabb 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_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 5e2b0175df36f..2860e6bff8b77 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -135,7 +135,7 @@ static int sun8i_hdmi_phy_config_a83t(struct dw_hdmi *hdmi,
dw_hdmi_phy_gen2_txpwron(hdmi, 0);
dw_hdmi_phy_gen2_pddq(hdmi, 1);
- dw_hdmi_phy_reset(hdmi);
+ dw_hdmi_phy_gen2_reset(hdmi);
dw_hdmi_phy_gen2_pddq(hdmi, 0);
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index f5e8aeaa3cdf8..875a1156c04ea 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 = {
@@ -534,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,
@@ -542,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,
@@ -550,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,
@@ -559,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,
@@ -568,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,
@@ -581,12 +611,30 @@ 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 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 = 0,
+ .ccsc = CCSC_MIXER0_LAYOUT,
.mod_rate = 297000000,
.scaler_mask = 0xf,
.scanline_yuv = 4096,
@@ -595,7 +643,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,
@@ -604,7 +652,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,
@@ -639,6 +687,14 @@ static const struct of_device_id sun8i_mixer_of_table[] = {
.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,
},
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 5b3fbee186713..85c94884fb9a4 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.
diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
index 1b9b8b48f4a70..da97682b68351 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 */
};
@@ -283,6 +288,10 @@ const struct of_device_id sun8i_tcon_top_of_table[] = {
.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
},
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index 7845c2a53a7fb..4632dea2dc1e7 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);
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index bb7c43036dfa4..f7d0b082d6349 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);
diff --git a/drivers/gpu/drm/sun4i/sunxi_engine.h b/drivers/gpu/drm/sun4i/sunxi_engine.h
index 548710a936d5f..ec8cf9b2bda41 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_ */