Files
BPI-CM9-Linux/build/patch/kernel/archive/meson-6.12/0053-drm-meson-Update-the-HDMI-encoder-for-Meson8-8b-8m2.patch

145 lines
5.9 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Date: Wed, 6 Oct 2021 23:34:04 +0200
Subject: drm/meson: Update the HDMI encoder for Meson8/8b/8m2
Meson8/8b/8m2 uses VPU_HDMI_OUTPUT_YCBCR for YUV444 while newer SoCs use
VPU_HDMI_OUTPUT_CBYCR. Also the 32-bit SoCs use VPU_HDMI_OUTPUT_CRYCB
for RGB. These are the only two known mappings for the 32-bit SoCs.
The VPU_HDMI_FMT_CTRL register with it's YUV444 to YUV422/YUV420
converter is not present on these older SoCs. Avoid writing this
reserved register on these 32-bit SoCs.
MEDIA_BUS_FMT_RGB888_1X24 cannot be exposed as output format because the
RGB to YUV converter is always enabled in meson_plane_atomic_update()
(so there's currently no way to configure it).
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/gpu/drm/meson/meson_encoder_hdmi.c | 66 +++++++---
1 file changed, 49 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
index 111111111111..222222222222 100644
--- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
@@ -190,13 +190,13 @@ static void meson_encoder_hdmi_atomic_enable(struct drm_bridge *bridge,
{
struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
struct drm_atomic_state *state = bridge_state->base.state;
- unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR;
struct meson_drm *priv = encoder_hdmi->priv;
struct drm_connector_state *conn_state;
const struct drm_display_mode *mode;
struct drm_crtc_state *crtc_state;
struct drm_connector *connector;
bool yuv420_mode = false;
+ unsigned int ycrcb_map;
int vic;
connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
@@ -217,11 +217,21 @@ static void meson_encoder_hdmi_atomic_enable(struct drm_bridge *bridge,
dev_dbg(priv->dev, "\"%s\" vic %d\n", mode->name, vic);
- if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) {
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_M8) ||
+ meson_vpu_is_compatible(priv, VPU_COMPATIBLE_M8B) ||
+ meson_vpu_is_compatible(priv, VPU_COMPATIBLE_M8M2)) {
+ if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_RGB888_1X24)
+ ycrcb_map = VPU_HDMI_OUTPUT_YCBCR;
+ else
+ ycrcb_map = VPU_HDMI_OUTPUT_CRYCB;
+ } else if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) {
ycrcb_map = VPU_HDMI_OUTPUT_CRYCB;
yuv420_mode = true;
- } else if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYVY8_1X16)
+ } else if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYVY8_1X16) {
ycrcb_map = VPU_HDMI_OUTPUT_CRYCB;
+ } else {
+ ycrcb_map = VPU_HDMI_OUTPUT_CBYCR;
+ }
/* VENC + VENC-DVI Mode setup */
meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode);
@@ -229,17 +239,21 @@ static void meson_encoder_hdmi_atomic_enable(struct drm_bridge *bridge,
/* VCLK Set clock */
meson_encoder_hdmi_set_vclk(encoder_hdmi, mode);
- if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
- /* Setup YUV420 to HDMI-TX, no 10bit diphering */
- writel_relaxed(2 | (2 << 2),
- priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
- else if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYVY8_1X16)
- /* Setup YUV422 to HDMI-TX, no 10bit diphering */
- writel_relaxed(1 | (2 << 2),
- priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
- else
- /* Setup YUV444 to HDMI-TX, no 10bit diphering */
- writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
+ if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_M8) &&
+ !meson_vpu_is_compatible(priv, VPU_COMPATIBLE_M8B) &&
+ !meson_vpu_is_compatible(priv, VPU_COMPATIBLE_M8M2)) {
+ if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
+ /* Setup YUV420 to HDMI-TX, no 10bit diphering */
+ writel_relaxed(2 | (2 << 2),
+ priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
+ else if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYVY8_1X16)
+ /* Setup YUV422 to HDMI-TX, no 10bit diphering */
+ writel_relaxed(1 | (2 << 2),
+ priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
+ else
+ /* Setup YUV444 to HDMI-TX, no 10bit diphering */
+ writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
+ }
dev_dbg(priv->dev, "%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
@@ -262,7 +276,11 @@ static void meson_encoder_hdmi_atomic_disable(struct drm_bridge *bridge,
writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
}
-static const u32 meson_encoder_hdmi_out_bus_fmts[] = {
+static const u32 meson8_encoder_hdmi_out_bus_fmts[] = {
+ MEDIA_BUS_FMT_YUV8_1X24,
+};
+
+static const u32 meson_gx_encoder_hdmi_out_bus_fmts[] = {
MEDIA_BUS_FMT_YUV8_1X24,
MEDIA_BUS_FMT_UYVY8_1X16,
MEDIA_BUS_FMT_UYYVYY8_0_5X24,
@@ -276,13 +294,27 @@ meson_encoder_hdmi_get_inp_bus_fmts(struct drm_bridge *bridge,
u32 output_fmt,
unsigned int *num_input_fmts)
{
+ struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
+ struct meson_drm *priv = encoder_hdmi->priv;
+ unsigned int num_out_bus_fmts;
+ const u32 *out_bus_fmts;
u32 *input_fmts = NULL;
int i;
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_M8) ||
+ meson_vpu_is_compatible(priv, VPU_COMPATIBLE_M8B) ||
+ meson_vpu_is_compatible(priv, VPU_COMPATIBLE_M8M2)) {
+ num_out_bus_fmts = ARRAY_SIZE(meson8_encoder_hdmi_out_bus_fmts);
+ out_bus_fmts = meson8_encoder_hdmi_out_bus_fmts;
+ } else {
+ num_out_bus_fmts = ARRAY_SIZE(meson_gx_encoder_hdmi_out_bus_fmts);
+ out_bus_fmts = meson_gx_encoder_hdmi_out_bus_fmts;
+ }
+
*num_input_fmts = 0;
- for (i = 0 ; i < ARRAY_SIZE(meson_encoder_hdmi_out_bus_fmts) ; ++i) {
- if (output_fmt == meson_encoder_hdmi_out_bus_fmts[i]) {
+ for (i = 0 ; i < num_out_bus_fmts ; ++i) {
+ if (output_fmt == out_bus_fmts[i]) {
*num_input_fmts = 1;
input_fmts = kcalloc(*num_input_fmts,
sizeof(*input_fmts),
--
Armbian