Skip to content

Commit

Permalink
drm/meson: add cursor plane using OSD2
Browse files Browse the repository at this point in the history
Tested on A311D using modetest, Weston & Sway, should work on SM1 & G12A.

Cursor doesn't move with Xorg, this would need some debugging.

Non tested on GXBB, GXL & GXM SoCs.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
  • Loading branch information
superna9999 committed Feb 1, 2023
1 parent 6d796c5 commit e7d277e
Show file tree
Hide file tree
Showing 8 changed files with 424 additions and 22 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/meson/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
meson-drm-y := meson_drv.o meson_plane.o meson_crtc.o meson_encoder_cvbs.o
meson-drm-y := meson_drv.o meson_plane.o meson_cursor.o meson_crtc.o meson_encoder_cvbs.o
meson-drm-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_overlay.o
meson-drm-y += meson_rdma.o meson_osd_afbcd.o
meson-drm-y += meson_encoder_hdmi.o
Expand Down
89 changes: 81 additions & 8 deletions drivers/gpu/drm/meson/meson_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct meson_crtc {
struct drm_pending_vblank_event *event;
struct meson_drm *priv;
void (*enable_osd1)(struct meson_drm *priv);
void (*enable_osd2)(struct meson_drm *priv);
void (*enable_vd1)(struct meson_drm *priv);
void (*enable_osd1_afbc)(struct meson_drm *priv);
void (*disable_osd1_afbc)(struct meson_drm *priv);
Expand Down Expand Up @@ -110,6 +111,20 @@ static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc,
writel_relaxed(0 << 16 |
(crtc_state->mode.vdisplay - 1),
priv->io_base + _REG(VPP_OSD1_BLD_V_SCOPE));
writel_relaxed(0 << 16 |
(crtc_state->mode.hdisplay - 1),
priv->io_base + _REG(VPP_OSD2_BLD_H_SCOPE));
writel_relaxed(0 << 16 |
(crtc_state->mode.vdisplay - 1),
priv->io_base + _REG(VPP_OSD2_BLD_V_SCOPE));
writel_relaxed(crtc_state->mode.hdisplay |
crtc_state->mode.vdisplay << 16,
priv->io_base +
_REG(VIU_OSD_BLEND_BLEND0_SIZE));
writel_relaxed(crtc_state->mode.hdisplay |
crtc_state->mode.vdisplay << 16,
priv->io_base +
_REG(VIU_OSD_BLEND_BLEND1_SIZE));
writel_relaxed(crtc_state->mode.hdisplay << 16 |
crtc_state->mode.vdisplay,
priv->io_base + _REG(VPP_OUT_H_V_SIZE));
Expand Down Expand Up @@ -158,6 +173,9 @@ static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc,
priv->viu.osd1_enabled = false;
priv->viu.osd1_commit = false;

priv->viu.osd2_enabled = false;
priv->viu.osd2_commit = false;

priv->viu.vd1_enabled = false;
priv->viu.vd1_commit = false;

Expand All @@ -183,11 +201,14 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
priv->viu.osd1_enabled = false;
priv->viu.osd1_commit = false;

priv->viu.osd2_enabled = false;
priv->viu.osd2_commit = false;

priv->viu.vd1_enabled = false;
priv->viu.vd1_commit = false;

/* Disable VPP Postblend */
writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_VD1_POSTBLEND |
writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND | VPP_VD1_POSTBLEND |
VPP_VD1_PREBLEND | VPP_POSTBLEND_ENABLE, 0,
priv->io_base + _REG(VPP_MISC));

Expand Down Expand Up @@ -223,6 +244,7 @@ static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
struct meson_drm *priv = meson_crtc->priv;

priv->viu.osd1_commit = true;
priv->viu.osd2_commit = true;
priv->viu.vd1_commit = true;
}

Expand All @@ -246,6 +268,12 @@ static void meson_crtc_enable_osd1(struct meson_drm *priv)
priv->io_base + _REG(VPP_MISC));
}

static void meson_crtc_enable_osd2(struct meson_drm *priv)
{
writel_bits_relaxed(VPP_OSD2_POSTBLEND, VPP_OSD2_POSTBLEND,
priv->io_base + _REG(VPP_MISC));
}

static void meson_crtc_g12a_enable_osd1_afbc(struct meson_drm *priv)
{
writel_relaxed(priv->viu.osd1_blk2_cfg4,
Expand Down Expand Up @@ -274,14 +302,20 @@ static void meson_g12a_crtc_enable_osd1(struct meson_drm *priv)
writel_relaxed(priv->viu.osd_blend_din0_scope_v,
priv->io_base +
_REG(VIU_OSD_BLEND_DIN0_SCOPE_V));
writel_relaxed(priv->viu.osb_blend0_size,
writel_bits_relaxed(OSD_BLEND_POSTBLD_SRC_OSD1, OSD_BLEND_POSTBLD_SRC_OSD1,
priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
}

static void meson_g12a_crtc_enable_osd2(struct meson_drm *priv)
{
writel_relaxed(priv->viu.osd_blend_din3_scope_h,
priv->io_base +
_REG(VIU_OSD_BLEND_BLEND0_SIZE));
writel_relaxed(priv->viu.osb_blend1_size,
_REG(VIU_OSD_BLEND_DIN1_SCOPE_H));
writel_relaxed(priv->viu.osd_blend_din3_scope_v,
priv->io_base +
_REG(VIU_OSD_BLEND_BLEND1_SIZE));
writel_bits_relaxed(3 << 8, 3 << 8,
priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
_REG(VIU_OSD_BLEND_DIN1_SCOPE_V));
writel_bits_relaxed(OSD_BLEND_POSTBLD_SRC_OSD2, OSD_BLEND_POSTBLD_SRC_OSD2,
priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
}

static void meson_crtc_enable_vd1(struct meson_drm *priv)
Expand Down Expand Up @@ -388,6 +422,43 @@ void meson_crtc_irq(struct meson_drm *priv)
priv->viu.osd1_commit = false;
}

if (priv->viu.osd2_enabled && priv->viu.osd2_commit) {
writel_relaxed(priv->viu.osd2_ctrl_stat,
priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
writel_relaxed(priv->viu.osd2_ctrl_stat2,
priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
writel_relaxed(priv->viu.osd2_blk0_cfg[0],
priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W0));
writel_relaxed(priv->viu.osd2_blk0_cfg[1],
priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W1));
writel_relaxed(priv->viu.osd2_blk0_cfg[2],
priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W2));
writel_relaxed(priv->viu.osd2_blk0_cfg[3],
priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W3));
writel_relaxed(priv->viu.osd2_blk0_cfg[4],
priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W4));

/* vsync forced to update INTERLACE_SEL_ODD in interlace mode */
meson_crtc->vsync_forced = priv->viu.osd2_interlace;

meson_canvas_config(priv->canvas, priv->canvas_id_osd2,
priv->viu.osd2_addr,
priv->viu.osd2_stride,
priv->viu.osd2_height,
MESON_CANVAS_WRAP_NONE,
MESON_CANVAS_BLKMODE_LINEAR, 0);

/* Enable OSD2 */
if (meson_crtc->enable_osd2)
meson_crtc->enable_osd2(priv);

priv->viu.osd2_commit = false;
} else if (priv->viu.osd2_enabled && priv->viu.osd2_interlace) {
u32 reg = readl_relaxed(priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W0)) & ~BIT(0);
writel_relaxed(reg | meson_venci_get_field(priv) ? 1 : 0,
priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W0));
}

/* Update the VD1 registers */
if (priv->viu.vd1_enabled && priv->viu.vd1_commit) {

Expand Down Expand Up @@ -685,7 +756,7 @@ int meson_crtc_create(struct meson_drm *priv)
meson_crtc->priv = priv;
crtc = &meson_crtc->base;
ret = drm_crtc_init_with_planes(priv->drm, crtc,
priv->primary_plane, NULL,
priv->primary_plane, priv->cursor_plane,
&meson_crtc_funcs, "meson_crtc");
if (ret) {
dev_err(priv->drm->dev, "Failed to init CRTC\n");
Expand All @@ -694,6 +765,7 @@ int meson_crtc_create(struct meson_drm *priv)

if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
meson_crtc->enable_osd1 = meson_g12a_crtc_enable_osd1;
meson_crtc->enable_osd2 = meson_g12a_crtc_enable_osd2;
meson_crtc->enable_vd1 = meson_g12a_crtc_enable_vd1;
meson_crtc->viu_offset = MESON_G12A_VIU_OFFSET;
meson_crtc->enable_osd1_afbc =
Expand All @@ -703,6 +775,7 @@ int meson_crtc_create(struct meson_drm *priv)
drm_crtc_helper_add(crtc, &meson_g12a_crtc_helper_funcs);
} else {
meson_crtc->enable_osd1 = meson_crtc_enable_osd1;
meson_crtc->enable_osd2 = meson_crtc_enable_osd2;
meson_crtc->enable_vd1 = meson_crtc_enable_vd1;
if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
meson_crtc->enable_osd1_afbc =
Expand Down

0 comments on commit e7d277e

Please sign in to comment.