145 lines
5.9 KiB
Diff
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
|
|
|