This patchset aims to add support for the following HDMI2.0 4k60 modes:
- 594Mhz TMDS frequency needing TMDS Scramling and 1/40 rate for RGB/YUV4:4:4
- 297MHz TMDS frequency with YUV4:2:0 encoding
The first mode uses the SCDC helpers introduced by intel to :
- discover where the monitor support SCDC
- setup the SCDC parameters
This is implemented in the dw-hdmi bridge driver by handling scrambling
support during the bridge setup and by exporting an helper for the PHY
setup to setup the SCDC configuration for the 1/40 TMDS rate.
This code will only be active if the encoder support a TMDS rate > 340MHz.
This patch could eventually break support on different SoC when connected
on a 4k60 monitor with SCDC :
- i.MX correctly discards pixel clocks > 216MHz
- R-CAR discards discards pixel clocks > 297MHz since [1]
- Rockchip discards invalid pixel clocks not in the rockchip_mpll_cfg table
- sun8i correctly discards pixel clocks > 297MHz on a83t
- sun8i discards discards pixel clocks > 594Mhz on h6, which is already broken
First patch should fix support for Allwinner H6.
The second mode is implemented by added the missing 4:2:0 bypass handling
in the dw-hdmi bridge driver and adding a "mtmdsclock" separating the
pixel clock from the tmds clock in the mode setup phase.
We also enable support for these modes in the connector only if the platform
glue code explicits the support.
Only the meson DRM dw_hdmi glue allows ycbcr420 modes, so no breakage
is expected here.
The remaining patches adds support for :
- 1/40 TMDS rate aka DIV40 in the dw-hdmi meson PHY setup
- 4:2:0 output and clock setup
The dw-hdmi support re-uses the support done by Rockchip engineers on the
Linux 4.4 BSP kernel.
These modes has been validated using a MuxLab HDMI Signal Analyser in
addition to different UHD TVs supporting full 4k60 or the 4:2:0 variant.
Changes since v1 at [2]:
- Rebased on drm-misc-next and fixed drm_hdmi_avi_infoframe_from_display_mode
API change
Changes since RFC v1 at [2]:
- Fix all comments from Laurent :
- Add define for HDMI 1.4 max tmds clock and SCDC supported version
- Call dw_hdmi_set_high_tmds_clock_ratio() in dw_hdmi_phy_enable_powerdown()
to unbreak Allwinner H6
- Pass in_t(u8, bytes, SCDC_MIN_SOURCE_VERSION) as SCDC version
- Finally add comments for SCDC and Scrambling process
[1] https://patchwork.freedesktop.org/patch/263616/
[2] https://patchwork.freedesktop.org/series/52950/
Neil Armstrong (7):
drm/bridge: dw-hdmi: Add SCDC and TMDS Scrambling support
drm/meson: add HDMI div40 TMDS mode
drm/meson: add support for HDMI2.0 2160p modes
drm/bridge: dw-hdmi: add support for YUV420 output
drm/bridge: dw-hdmi: allow ycbcr420 modes for >= 0x200a
drm/meson: Add YUV420 output support
drm/meson: Output in YUV444 if sink supports it
Zheng Yang (1):
drm/bridge: dw-hdmi: support dynamically get input/out color info
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 176 ++++++++++++++++++++++++++----
drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 +
drivers/gpu/drm/meson/meson_dw_hdmi.c | 128 +++++++++++++++++++---
drivers/gpu/drm/meson/meson_vclk.c | 93 ++++++++++++----
drivers/gpu/drm/meson/meson_vclk.h | 7 +-
drivers/gpu/drm/meson/meson_venc.c | 8 +-
drivers/gpu/drm/meson/meson_venc.h | 11 ++
drivers/gpu/drm/meson/meson_venc_cvbs.c | 3 +-
include/drm/bridge/dw_hdmi.h | 7 ++
9 files changed, 369 insertions(+), 65 deletions(-)
--
2.7.4
Now the DW-HDMI Controller supports the HDMI2.0 modes, enable support
for these modes in the connector if the platform supports them.
We limit these modes to DW-HDMI IP version >= 0x200a which
are designed to support HDMI2.0 display modes.
Signed-off-by: Neil Armstrong <[email protected]>
Tested-by: Heiko Stuebner <[email protected]>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 6 ++++++
include/drm/bridge/dw_hdmi.h | 1 +
2 files changed, 7 insertions(+)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 3634bbd..f1b352d 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2609,6 +2609,12 @@ __dw_hdmi_probe(struct platform_device *pdev,
if (hdmi->phy.ops->setup_hpd)
hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data);
+ if (hdmi->version >= 0x200a)
+ hdmi->connector.ycbcr_420_allowed =
+ hdmi->plat_data->ycbcr_420_allowed;
+ else
+ hdmi->connector.ycbcr_420_allowed = false;
+
memset(&pdevinfo, 0, sizeof(pdevinfo));
pdevinfo.parent = dev;
pdevinfo.id = PLATFORM_DEVID_AUTO;
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index d506df2..ede8bff 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -130,6 +130,7 @@ struct dw_hdmi_plat_data {
const struct drm_display_mode *mode);
unsigned long input_bus_format;
unsigned long input_bus_encoding;
+ bool ycbcr_420_allowed;
/* Vendor PHY support */
const struct dw_hdmi_phy_ops *phy_ops;
--
2.7.4
This patch adds support for the YUV420 output from the Amlogic Meson SoCs
Video Processing Unit to the HDMI Controller.
The YUV420 is obtained by generating a YUV444 pixel stream like
the classic HDMI display modes, but then the Video Encoder output
can be configured to down-sample the YUV444 pixel stream to a YUV420
stream.
In addition if pixel stream down-sampling, the Y Cb Cr components must
also be mapped differently to align with the HDMI2.0 specifications.
This mode needs a different clock generation scheme since the TMDS PHY
clock must match the 10x ration with the YUV420 pixel clock, but
the video encoder must run at 2x the pixel clock.
This patch adds the TMDS PHY clock value in all the video clock setup
in order to better support these specific uses cases and switch
to the Common Clock framework for clocks handling in the future.
Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_dw_hdmi.c | 110 ++++++++++++++++++++++++++------
drivers/gpu/drm/meson/meson_vclk.c | 93 ++++++++++++++++++++-------
drivers/gpu/drm/meson/meson_vclk.h | 7 +-
drivers/gpu/drm/meson/meson_venc.c | 6 +-
drivers/gpu/drm/meson/meson_venc.h | 11 ++++
drivers/gpu/drm/meson/meson_venc_cvbs.c | 3 +-
6 files changed, 184 insertions(+), 46 deletions(-)
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
index e28814f..540971a 100644
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
@@ -141,6 +141,8 @@ struct meson_dw_hdmi {
struct regulator *hdmi_supply;
u32 irq_stat;
struct dw_hdmi *hdmi;
+ unsigned long input_bus_format;
+ unsigned long output_bus_format;
};
#define encoder_to_meson_dw_hdmi(x) \
container_of(x, struct meson_dw_hdmi, encoder)
@@ -323,25 +325,36 @@ static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
{
struct meson_drm *priv = dw_hdmi->priv;
int vic = drm_match_cea_mode(mode);
+ unsigned int phy_freq;
unsigned int vclk_freq;
unsigned int venc_freq;
unsigned int hdmi_freq;
vclk_freq = mode->clock;
+ /* For 420, pixel clock is half unlike venc clock */
+ if (dw_hdmi->input_bus_format == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
+ vclk_freq /= 2;
+
+ /* TMDS clock is pixel_clock * 10 */
+ phy_freq = vclk_freq * 10;
+
if (!vic) {
- meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, vclk_freq,
- vclk_freq, vclk_freq, false);
+ meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, phy_freq,
+ vclk_freq, vclk_freq, vclk_freq, false);
return;
}
+ /* 480i/576i needs global pixel doubling */
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
vclk_freq *= 2;
venc_freq = vclk_freq;
hdmi_freq = vclk_freq;
- if (meson_venc_hdmi_venc_repeat(vic))
+ /* VENC double pixels for 1080i, 720p and YUV420 modes */
+ if (meson_venc_hdmi_venc_repeat(vic) ||
+ dw_hdmi->input_bus_format == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
venc_freq *= 2;
vclk_freq = max(venc_freq, hdmi_freq);
@@ -349,11 +362,11 @@ static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
venc_freq /= 2;
- DRM_DEBUG_DRIVER("vclk:%d venc=%d hdmi=%d enci=%d\n",
- vclk_freq, venc_freq, hdmi_freq,
+ DRM_DEBUG_DRIVER("vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n",
+ phy_freq, vclk_freq, venc_freq, hdmi_freq,
priv->venc.hdmi_use_enci);
- meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, vclk_freq,
+ meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, phy_freq, vclk_freq,
venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
}
@@ -386,8 +399,9 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
/* Enable normal output to PHY */
dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
- /* TMDS pattern setup (TOFIX Handle the YUV420 case) */
- if (mode->clock > 340000) {
+ /* TMDS pattern setup */
+ if (mode->clock > 340000 &&
+ dw_hdmi->input_bus_format == MEDIA_BUS_FMT_YUV8_1X24) {
dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 0);
dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
0x03ff03ff);
@@ -560,6 +574,8 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
const struct drm_display_mode *mode)
{
struct meson_drm *priv = connector->dev->dev_private;
+ bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
+ unsigned int phy_freq;
unsigned int vclk_freq;
unsigned int venc_freq;
unsigned int hdmi_freq;
@@ -568,8 +584,10 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
- /* If sink max TMDS clock, we reject the mode */
- if (mode->clock > connector->display_info.max_tmds_clock)
+ /* If sink does not support 540MHz, reject the non-420 HDMI2 modes */
+ if (mode->clock > connector->display_info.max_tmds_clock &&
+ !drm_mode_is_420_only(&connector->display_info, mode) &&
+ !drm_mode_is_420_also(&connector->display_info, mode))
return MODE_BAD;
/* Check against non-VIC supported modes */
@@ -585,6 +603,15 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
vclk_freq = mode->clock;
+ /* For 420, pixel clock is half unlike venc clock */
+ if (drm_mode_is_420_only(&connector->display_info, mode) ||
+ (!is_hdmi2_sink &&
+ drm_mode_is_420_also(&connector->display_info, mode)))
+ vclk_freq /= 2;
+
+ /* TMDS clock is pixel_clock * 10 */
+ phy_freq = vclk_freq * 10;
+
/* 480i/576i needs global pixel doubling */
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
vclk_freq *= 2;
@@ -592,8 +619,11 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
venc_freq = vclk_freq;
hdmi_freq = vclk_freq;
- /* VENC double pixels for 1080i and 720p modes */
- if (meson_venc_hdmi_venc_repeat(vic))
+ /* VENC double pixels for 1080i, 720p and YUV420 modes */
+ if (meson_venc_hdmi_venc_repeat(vic) ||
+ drm_mode_is_420_only(&connector->display_info, mode) ||
+ (!is_hdmi2_sink &&
+ drm_mode_is_420_also(&connector->display_info, mode)))
venc_freq *= 2;
vclk_freq = max(venc_freq, hdmi_freq);
@@ -601,10 +631,10 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
venc_freq /= 2;
- dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__,
- vclk_freq, venc_freq, hdmi_freq);
+ dev_dbg(connector->dev->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n",
+ __func__, phy_freq, vclk_freq, venc_freq, hdmi_freq);
- return meson_vclk_vic_supported_freq(vclk_freq);
+ return meson_vclk_vic_supported_freq(phy_freq, vclk_freq);
}
/* Encoder */
@@ -622,6 +652,21 @@ static int meson_venc_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
+ struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
+ struct drm_display_info *info = &conn_state->connector->display_info;
+ struct drm_display_mode *mode = &crtc_state->mode;
+ bool is_hdmi2_sink =
+ conn_state->connector->display_info.hdmi.scdc.supported;
+
+ if (drm_mode_is_420_only(info, mode) ||
+ (!is_hdmi2_sink && drm_mode_is_420_also(info, mode))) {
+ dw_hdmi->input_bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
+ dw_hdmi->output_bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
+ } else {
+ dw_hdmi->input_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
+ dw_hdmi->output_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+ }
+
return 0;
}
@@ -659,17 +704,29 @@ static void meson_venc_hdmi_encoder_mode_set(struct drm_encoder *encoder,
struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
struct meson_drm *priv = dw_hdmi->priv;
int vic = drm_match_cea_mode(mode);
+ unsigned int ycrcb_map = MESON_VENC_MAP_CB_Y_CR;
+ bool yuv420_mode = false;
DRM_DEBUG_DRIVER("\"%s\" vic %d\n", mode->name, vic);
+ if (dw_hdmi->input_bus_format == MEDIA_BUS_FMT_UYYVYY8_0_5X24) {
+ ycrcb_map = MESON_VENC_MAP_CR_Y_CB;
+ yuv420_mode = true;
+ }
+
/* VENC + VENC-DVI Mode setup */
- meson_venc_hdmi_mode_set(priv, vic, mode);
+ meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode);
/* VCLK Set clock */
dw_hdmi_set_vclk(dw_hdmi, mode);
- /* Setup YUV444 to HDMI-TX, no 10bit diphering */
- writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
+ if (dw_hdmi->input_bus_format == 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
+ /* Setup YUV444 to HDMI-TX, no 10bit diphering */
+ writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
}
static const struct drm_encoder_helper_funcs
@@ -708,6 +765,20 @@ static const struct regmap_config meson_dw_hdmi_regmap_config = {
.fast_io = true,
};
+static unsigned long meson_dw_hdmi_get_in_bus_format(void *data)
+{
+ struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
+
+ return dw_hdmi->input_bus_format;
+}
+
+static unsigned long meson_dw_hdmi_get_out_bus_format(void *data)
+{
+ struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
+
+ return dw_hdmi->output_bus_format;
+}
+
static bool meson_hdmi_connector_is_available(struct device *dev)
{
struct device_node *ep, *remote;
@@ -884,6 +955,9 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
dw_plat_data->phy_data = meson_dw_hdmi;
dw_plat_data->input_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;
+ dw_plat_data->get_input_bus_format = meson_dw_hdmi_get_in_bus_format;
+ dw_plat_data->get_output_bus_format = meson_dw_hdmi_get_out_bus_format;
+ dw_plat_data->ycbcr_420_allowed = true;
platform_set_drvdata(pdev, meson_dw_hdmi);
diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
index f6ba35a..27c9c5e 100644
--- a/drivers/gpu/drm/meson/meson_vclk.c
+++ b/drivers/gpu/drm/meson/meson_vclk.c
@@ -337,12 +337,17 @@ enum {
/* 2970 /1 /1 /1 /5 /2 => /1 /1 */
MESON_VCLK_HDMI_297000,
/* 5940 /1 /1 /2 /5 /1 => /1 /1 */
- MESON_VCLK_HDMI_594000
+ MESON_VCLK_HDMI_594000,
+/* 2970 /1 /1 /1 /5 /1 => /1 /2 */
+ MESON_VCLK_HDMI_594000_YUV420,
};
struct meson_vclk_params {
+ unsigned int pll_freq;
+ unsigned int phy_freq;
+ unsigned int vclk_freq;
+ unsigned int venc_freq;
unsigned int pixel_freq;
- unsigned int pll_base_freq;
unsigned int pll_od1;
unsigned int pll_od2;
unsigned int pll_od3;
@@ -350,8 +355,11 @@ struct meson_vclk_params {
unsigned int vclk_div;
} params[] = {
[MESON_VCLK_HDMI_ENCI_54000] = {
+ .pll_freq = 4320000,
+ .phy_freq = 270000,
+ .vclk_freq = 54000,
+ .venc_freq = 54000,
.pixel_freq = 54000,
- .pll_base_freq = 4320000,
.pll_od1 = 4,
.pll_od2 = 4,
.pll_od3 = 1,
@@ -359,8 +367,11 @@ struct meson_vclk_params {
.vclk_div = 1,
},
[MESON_VCLK_HDMI_DDR_54000] = {
- .pixel_freq = 54000,
- .pll_base_freq = 4320000,
+ .pll_freq = 4320000,
+ .phy_freq = 270000,
+ .vclk_freq = 54000,
+ .venc_freq = 54000,
+ .pixel_freq = 27000,
.pll_od1 = 4,
.pll_od2 = 4,
.pll_od3 = 1,
@@ -368,8 +379,11 @@ struct meson_vclk_params {
.vclk_div = 1,
},
[MESON_VCLK_HDMI_DDR_148500] = {
- .pixel_freq = 148500,
- .pll_base_freq = 2970000,
+ .pll_freq = 2970000,
+ .phy_freq = 742500,
+ .vclk_freq = 148500,
+ .venc_freq = 148500,
+ .pixel_freq = 74250,
.pll_od1 = 4,
.pll_od2 = 1,
.pll_od3 = 1,
@@ -377,8 +391,11 @@ struct meson_vclk_params {
.vclk_div = 1,
},
[MESON_VCLK_HDMI_74250] = {
+ .pll_freq = 2970000,
+ .phy_freq = 742500,
+ .vclk_freq = 74250,
+ .venc_freq = 74250,
.pixel_freq = 74250,
- .pll_base_freq = 2970000,
.pll_od1 = 2,
.pll_od2 = 2,
.pll_od3 = 2,
@@ -386,8 +403,11 @@ struct meson_vclk_params {
.vclk_div = 1,
},
[MESON_VCLK_HDMI_148500] = {
+ .pll_freq = 2970000,
+ .phy_freq = 1485000,
+ .vclk_freq = 148500,
+ .venc_freq = 148500,
.pixel_freq = 148500,
- .pll_base_freq = 2970000,
.pll_od1 = 1,
.pll_od2 = 2,
.pll_od3 = 2,
@@ -395,8 +415,11 @@ struct meson_vclk_params {
.vclk_div = 1,
},
[MESON_VCLK_HDMI_297000] = {
+ .pll_freq = 2970000,
+ .phy_freq = 2970000,
+ .venc_freq = 297000,
+ .vclk_freq = 297000,
.pixel_freq = 297000,
- .pll_base_freq = 2970000,
.pll_od1 = 1,
.pll_od2 = 1,
.pll_od3 = 1,
@@ -404,14 +427,29 @@ struct meson_vclk_params {
.vclk_div = 2,
},
[MESON_VCLK_HDMI_594000] = {
+ .pll_freq = 5940000,
+ .phy_freq = 5940000,
+ .venc_freq = 594000,
+ .vclk_freq = 594000,
.pixel_freq = 594000,
- .pll_base_freq = 5940000,
.pll_od1 = 1,
.pll_od2 = 1,
.pll_od3 = 2,
.vid_pll_div = VID_PLL_DIV_5,
.vclk_div = 1,
},
+ [MESON_VCLK_HDMI_594000_YUV420] = {
+ .pll_freq = 2970000,
+ .phy_freq = 2970000,
+ .venc_freq = 594000,
+ .vclk_freq = 594000,
+ .pixel_freq = 297000,
+ .pll_od1 = 1,
+ .pll_od2 = 1,
+ .pll_od3 = 1,
+ .vid_pll_div = VID_PLL_DIV_5,
+ .vclk_div = 1,
+ },
{ /* sentinel */ },
};
@@ -616,6 +654,7 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
unsigned int od, m, frac, od1, od2, od3;
if (meson_hdmi_pll_find_params(priv, pll_freq, &m, &frac, &od)) {
+ /* OD2 goes to the PHY, and needs to be *10, so keep OD3=1 */
od3 = 1;
if (od < 4) {
od1 = 2;
@@ -638,21 +677,28 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
}
enum drm_mode_status
-meson_vclk_vic_supported_freq(unsigned int freq)
+meson_vclk_vic_supported_freq(unsigned int phy_freq,
+ unsigned int vclk_freq)
{
int i;
- DRM_DEBUG_DRIVER("freq = %d\n", freq);
+ DRM_DEBUG_DRIVER("phy_freq = %d vclk_freq = %d\n",
+ phy_freq, vclk_freq);
for (i = 0 ; params[i].pixel_freq ; ++i) {
DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n",
i, params[i].pixel_freq,
FREQ_1000_1001(params[i].pixel_freq));
+ DRM_DEBUG_DRIVER("i = %d phy_freq = %d alt = %d\n",
+ i, params[i].phy_freq,
+ FREQ_1000_1001(params[i].phy_freq/10)*10);
/* Match strict frequency */
- if (freq == params[i].pixel_freq)
+ if (phy_freq == params[i].phy_freq &&
+ vclk_freq == params[i].vclk_freq)
return MODE_OK;
/* Match 1000/1001 variant */
- if (freq == FREQ_1000_1001(params[i].pixel_freq))
+ if (phy_freq == (FREQ_1000_1001(params[i].phy_freq/10)*10) &&
+ vclk_freq == FREQ_1000_1001(params[i].vclk_freq))
return MODE_OK;
}
@@ -863,8 +909,9 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
}
void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
- unsigned int vclk_freq, unsigned int venc_freq,
- unsigned int dac_freq, bool hdmi_use_enci)
+ unsigned int phy_freq, unsigned int vclk_freq,
+ unsigned int venc_freq, unsigned int dac_freq,
+ bool hdmi_use_enci)
{
bool vic_alternate_clock = false;
unsigned int freq;
@@ -883,7 +930,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
* - venc_div = 1
* - encp encoder
*/
- meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
+ meson_vclk_set(priv, phy_freq, 0, 0, 0,
VID_PLL_DIV_5, 2, 1, 1, false, false);
return;
}
@@ -905,9 +952,11 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
}
for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
- if (vclk_freq == params[freq].pixel_freq ||
- vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) {
- if (vclk_freq != params[freq].pixel_freq)
+ if ((phy_freq == params[freq].phy_freq ||
+ phy_freq == FREQ_1000_1001(params[freq].phy_freq/10)*10) &&
+ (vclk_freq == params[freq].vclk_freq ||
+ vclk_freq == FREQ_1000_1001(params[freq].vclk_freq))) {
+ if (vclk_freq != params[freq].vclk_freq)
vic_alternate_clock = true;
else
vic_alternate_clock = false;
@@ -936,7 +985,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
return;
}
- meson_vclk_set(priv, params[freq].pll_base_freq,
+ meson_vclk_set(priv, params[freq].pll_freq,
params[freq].pll_od1, params[freq].pll_od2,
params[freq].pll_od3, params[freq].vid_pll_div,
params[freq].vclk_div, hdmi_tx_div, venc_div,
diff --git a/drivers/gpu/drm/meson/meson_vclk.h b/drivers/gpu/drm/meson/meson_vclk.h
index 4bd8752..c4d19dd 100644
--- a/drivers/gpu/drm/meson/meson_vclk.h
+++ b/drivers/gpu/drm/meson/meson_vclk.h
@@ -33,10 +33,11 @@ enum {
enum drm_mode_status
meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq);
enum drm_mode_status
-meson_vclk_vic_supported_freq(unsigned int freq);
+meson_vclk_vic_supported_freq(unsigned int phy_freq, unsigned int vclk_freq);
void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
- unsigned int vclk_freq, unsigned int venc_freq,
- unsigned int dac_freq, bool hdmi_use_enci);
+ unsigned int phy_freq, unsigned int vclk_freq,
+ unsigned int venc_freq, unsigned int dac_freq,
+ bool hdmi_use_enci);
#endif /* __MESON_VCLK_H */
diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
index 66d73a9..04956e3 100644
--- a/drivers/gpu/drm/meson/meson_venc.c
+++ b/drivers/gpu/drm/meson/meson_venc.c
@@ -956,6 +956,8 @@ bool meson_venc_hdmi_venc_repeat(int vic)
EXPORT_SYMBOL_GPL(meson_venc_hdmi_venc_repeat);
void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
+ unsigned int ycrcb_map,
+ bool yuv420_mode,
struct drm_display_mode *mode)
{
union meson_hdmi_venc_mode *vmode = NULL;
@@ -1506,8 +1508,8 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
writel_relaxed((use_enci ? 1 : 2) |
(mode->flags & DRM_MODE_FLAG_PHSYNC ? 1 << 2 : 0) |
(mode->flags & DRM_MODE_FLAG_PVSYNC ? 1 << 3 : 0) |
- 4 << 5 |
- (venc_repeat ? 1 << 8 : 0) |
+ (ycrcb_map << 5) |
+ (venc_repeat || yuv420_mode ? 1 << 8 : 0) |
(hdmi_repeat ? 1 << 12 : 0),
priv->io_base + _REG(VPU_HDMI_SETTING));
diff --git a/drivers/gpu/drm/meson/meson_venc.h b/drivers/gpu/drm/meson/meson_venc.h
index 97eaebb..5580bf3 100644
--- a/drivers/gpu/drm/meson/meson_venc.h
+++ b/drivers/gpu/drm/meson/meson_venc.h
@@ -33,6 +33,15 @@ enum {
MESON_VENC_MODE_HDMI,
};
+enum {
+ MESON_VENC_MAP_CR_Y_CB = 0,
+ MESON_VENC_MAP_Y_CB_CR,
+ MESON_VENC_MAP_Y_CR_CB,
+ MESON_VENC_MAP_CB_CR_Y,
+ MESON_VENC_MAP_CB_Y_CR,
+ MESON_VENC_MAP_CR_CB_Y,
+};
+
struct meson_cvbs_enci_mode {
unsigned int mode_tag;
unsigned int hso_begin; /* HSO begin position */
@@ -70,6 +79,8 @@ extern struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc;
void meson_venci_cvbs_mode_set(struct meson_drm *priv,
struct meson_cvbs_enci_mode *mode);
void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
+ unsigned int ycrcb_map,
+ bool yuv420_mode,
struct drm_display_mode *mode);
unsigned int meson_venci_get_field(struct meson_drm *priv);
diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c
index d622d81..3c36df2 100644
--- a/drivers/gpu/drm/meson/meson_venc_cvbs.c
+++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c
@@ -207,7 +207,8 @@ static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,
/* Setup 27MHz vclk2 for ENCI and VDAC */
meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
MESON_VCLK_CVBS, MESON_VCLK_CVBS,
- MESON_VCLK_CVBS, true);
+ MESON_VCLK_CVBS, MESON_VCLK_CVBS,
+ true);
break;
}
}
--
2.7.4
Add support for TMDS Clock > 3.4GHz for HDMI2.0 display modes.
Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_dw_hdmi.c | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
index 83585b3..e28814f 100644
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
@@ -365,7 +365,8 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
unsigned int wr_clk =
readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING));
- DRM_DEBUG_DRIVER("\"%s\"\n", mode->name);
+ DRM_DEBUG_DRIVER("\"%s\" div%d\n", mode->name,
+ mode->clock > 340000 ? 40 : 10);
/* Enable clocks */
regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
@@ -385,9 +386,17 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
/* Enable normal output to PHY */
dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
- /* TMDS pattern setup (TOFIX pattern for 4k2k scrambling) */
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 0x001f001f);
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23, 0x001f001f);
+ /* TMDS pattern setup (TOFIX Handle the YUV420 case) */
+ if (mode->clock > 340000) {
+ dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 0);
+ dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
+ 0x03ff03ff);
+ } else {
+ dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
+ 0x001f001f);
+ dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
+ 0x001f001f);
+ }
/* Load TMDS pattern */
dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
@@ -413,6 +422,8 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
/* Disable clock, fifo, fifo_wr */
regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0);
+ dw_hdmi_set_high_tmds_clock_ratio(hdmi);
+
msleep(100);
/* Reset PHY 3 times in a row */
@@ -557,6 +568,10 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
+ /* If sink max TMDS clock, we reject the mode */
+ if (mode->clock > connector->display_info.max_tmds_clock)
+ return MODE_BAD;
+
/* Check against non-VIC supported modes */
if (!vic) {
status = meson_venc_hdmi_supported_mode(mode);
--
2.7.4
From: Zheng Yang <[email protected]>
To get input/output bus_format/enc_format dynamically, this patch
introduce following functions in plat_data:
- get_input_bus_format
- get_output_bus_format
- get_enc_in_encoding
- get_enc_out_encoding
Signed-off-by: Zheng Yang <[email protected]>
Signed-off-by: Neil Armstrong <[email protected]>
Tested-by: Heiko Stuebner <[email protected]>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 28 +++++++++++++++++++++-------
include/drm/bridge/dw_hdmi.h | 5 +++++
2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index a63e5f0..3634bbd 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1807,6 +1807,7 @@ static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi)
static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
{
int ret;
+ void *data = hdmi->plat_data->phy_data;
hdmi_disable_overflow_interrupts(hdmi);
@@ -1818,10 +1819,13 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic);
}
- if ((hdmi->vic == 6) || (hdmi->vic == 7) ||
- (hdmi->vic == 21) || (hdmi->vic == 22) ||
- (hdmi->vic == 2) || (hdmi->vic == 3) ||
- (hdmi->vic == 17) || (hdmi->vic == 18))
+ if (hdmi->plat_data->get_enc_out_encoding)
+ hdmi->hdmi_data.enc_out_encoding =
+ hdmi->plat_data->get_enc_out_encoding(data);
+ else if ((hdmi->vic == 6) || (hdmi->vic == 7) ||
+ (hdmi->vic == 21) || (hdmi->vic == 22) ||
+ (hdmi->vic == 2) || (hdmi->vic == 3) ||
+ (hdmi->vic == 17) || (hdmi->vic == 18))
hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_601;
else
hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_709;
@@ -1830,21 +1834,31 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
/* TOFIX: Get input format from plat data or fallback to RGB888 */
- if (hdmi->plat_data->input_bus_format)
+ if (hdmi->plat_data->get_input_bus_format)
+ hdmi->hdmi_data.enc_in_bus_format =
+ hdmi->plat_data->get_input_bus_format(data);
+ else if (hdmi->plat_data->input_bus_format)
hdmi->hdmi_data.enc_in_bus_format =
hdmi->plat_data->input_bus_format;
else
hdmi->hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
/* TOFIX: Get input encoding from plat data or fallback to none */
- if (hdmi->plat_data->input_bus_encoding)
+ if (hdmi->plat_data->get_enc_in_encoding)
+ hdmi->hdmi_data.enc_in_encoding =
+ hdmi->plat_data->get_enc_in_encoding(data);
+ else if (hdmi->plat_data->input_bus_encoding)
hdmi->hdmi_data.enc_in_encoding =
hdmi->plat_data->input_bus_encoding;
else
hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT;
/* TOFIX: Default to RGB888 output format */
- hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+ if (hdmi->plat_data->get_output_bus_format)
+ hdmi->hdmi_data.enc_out_bus_format =
+ hdmi->plat_data->get_output_bus_format(data);
+ else
+ hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
hdmi->hdmi_data.pix_repet_factor = 0;
hdmi->hdmi_data.hdcp_enable = 0;
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 66e7077..d506df2 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -144,6 +144,11 @@ struct dw_hdmi_plat_data {
int (*configure_phy)(struct dw_hdmi *hdmi,
const struct dw_hdmi_plat_data *pdata,
unsigned long mpixelclock);
+
+ unsigned long (*get_input_bus_format)(void *data);
+ unsigned long (*get_output_bus_format)(void *data);
+ unsigned long (*get_enc_in_encoding)(void *data);
+ unsigned long (*get_enc_out_encoding)(void *data);
};
struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
--
2.7.4
In order to support the HDMI2.0 YUV420 display modes, this patch
adds support for the YUV420 TMDS Clock divided by 2 and the controller
passthrough mode.
YUV420 Synopsys PHY support will need some specific configuration table
to support theses modes.
This patch is based on work from Zheng Yang <[email protected]> in
the Rockchip Linux 4.4 BSP at [1]
[1] https://github.com/rockchip-linux/kernel/tree/release-4.4
Cc: Zheng Yang <[email protected]>
Signed-off-by: Neil Armstrong <[email protected]>
Tested-by: Heiko Stuebner <[email protected]>
Reviewed-by: Andrzej Hajda <[email protected]>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 65 ++++++++++++++++++++++++-------
1 file changed, 51 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 6d5a2e9..a63e5f0 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -99,6 +99,7 @@ struct hdmi_vmode {
unsigned int mpixelclock;
unsigned int mpixelrepetitioninput;
unsigned int mpixelrepetitionoutput;
+ unsigned int mtmdsclock;
};
struct hdmi_data_info {
@@ -543,7 +544,7 @@ static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
{
mutex_lock(&hdmi->audio_mutex);
- hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
+ hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mtmdsclock,
hdmi->sample_rate);
mutex_unlock(&hdmi->audio_mutex);
}
@@ -552,7 +553,7 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
{
mutex_lock(&hdmi->audio_mutex);
hdmi->sample_rate = rate;
- hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
+ hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mtmdsclock,
hdmi->sample_rate);
mutex_unlock(&hdmi->audio_mutex);
}
@@ -653,6 +654,20 @@ static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
}
}
+static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
+{
+ switch (bus_format) {
+ case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+ case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+ case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
+ case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
{
switch (bus_format) {
@@ -882,7 +897,8 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
u8 val, vp_conf;
if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) ||
- hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format)) {
+ hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format) ||
+ hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) {
switch (hdmi_bus_fmt_color_depth(
hdmi->hdmi_data.enc_out_bus_format)) {
case 8:
@@ -1036,7 +1052,7 @@ EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);
*/
void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi)
{
- unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mpixelclock;
+ unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mtmdsclock;
/* Control for TMDS Bit Period/TMDS Clock-Period Ratio */
if (hdmi->connector.display_info.hdmi.scdc.supported) {
@@ -1198,6 +1214,8 @@ static int hdmi_phy_configure_dwc_hdmi_3d_tx(struct dw_hdmi *hdmi,
const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
+ /* TOFIX Will need 420 specific PHY configuration tables */
+
/* PLL/MPLL Cfg - always match on final entry */
for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
if (mpixelclock <= mpll_config->mpixelclock)
@@ -1245,6 +1263,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
const struct dw_hdmi_phy_data *phy = hdmi->phy.data;
const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
unsigned long mpixelclock = hdmi->hdmi_data.video_mode.mpixelclock;
+ unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mtmdsclock;
int ret;
dw_hdmi_phy_power_off(hdmi);
@@ -1273,7 +1292,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
}
/* Wait for resuming transmission of TMDS clock and data */
- if (mpixelclock > HDMI14_MAX_TMDSCLK)
+ if (mtmdsclock > HDMI14_MAX_TMDSCLK)
msleep(100);
return dw_hdmi_phy_power_on(hdmi);
@@ -1390,6 +1409,8 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
frame.colorspace = HDMI_COLORSPACE_YUV444;
else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
frame.colorspace = HDMI_COLORSPACE_YUV422;
+ else if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format))
+ frame.colorspace = HDMI_COLORSPACE_YUV420;
else
frame.colorspace = HDMI_COLORSPACE_RGB;
@@ -1547,15 +1568,18 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
struct drm_hdmi_info *hdmi_info = &hdmi->connector.display_info.hdmi;
struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
- unsigned int vdisplay;
+ unsigned int vdisplay, hdisplay;
- vmode->mpixelclock = mode->clock * 1000;
+ vmode->mtmdsclock = vmode->mpixelclock = mode->clock * 1000;
dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
+ if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format))
+ vmode->mtmdsclock /= 2;
+
/* Set up HDMI_FC_INVIDCONF */
inv_val = (hdmi->hdmi_data.hdcp_enable ||
- vmode->mpixelclock > HDMI14_MAX_TMDSCLK ||
+ vmode->mtmdsclock > HDMI14_MAX_TMDSCLK ||
hdmi_info->scdc.scrambling.low_rates ?
HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
@@ -1589,6 +1613,22 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF);
+ hdisplay = mode->hdisplay;
+ hblank = mode->htotal - mode->hdisplay;
+ h_de_hs = mode->hsync_start - mode->hdisplay;
+ hsync_len = mode->hsync_end - mode->hsync_start;
+
+ /*
+ * When we're setting a YCbCr420 mode, we need
+ * to adjust the horizontal timing to suit.
+ */
+ if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) {
+ hdisplay /= 2;
+ hblank /= 2;
+ h_de_hs /= 2;
+ hsync_len /= 2;
+ }
+
vdisplay = mode->vdisplay;
vblank = mode->vtotal - mode->vdisplay;
v_de_vs = mode->vsync_start - mode->vdisplay;
@@ -1607,7 +1647,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
/* Scrambling Control */
if (hdmi_info->scdc.supported) {
- if (vmode->mpixelclock > HDMI14_MAX_TMDSCLK ||
+ if (vmode->mtmdsclock > HDMI14_MAX_TMDSCLK ||
hdmi_info->scdc.scrambling.low_rates) {
/*
* HDMI2.0 Specifies the following procedure:
@@ -1645,15 +1685,14 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
}
/* Set up horizontal active pixel width */
- hdmi_writeb(hdmi, mode->hdisplay >> 8, HDMI_FC_INHACTV1);
- hdmi_writeb(hdmi, mode->hdisplay, HDMI_FC_INHACTV0);
+ hdmi_writeb(hdmi, hdisplay >> 8, HDMI_FC_INHACTV1);
+ hdmi_writeb(hdmi, hdisplay, HDMI_FC_INHACTV0);
/* Set up vertical active lines */
hdmi_writeb(hdmi, vdisplay >> 8, HDMI_FC_INVACTV1);
hdmi_writeb(hdmi, vdisplay, HDMI_FC_INVACTV0);
/* Set up horizontal blanking pixel region width */
- hblank = mode->htotal - mode->hdisplay;
hdmi_writeb(hdmi, hblank >> 8, HDMI_FC_INHBLANK1);
hdmi_writeb(hdmi, hblank, HDMI_FC_INHBLANK0);
@@ -1661,7 +1700,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
hdmi_writeb(hdmi, vblank, HDMI_FC_INVBLANK);
/* Set up HSYNC active edge delay width (in pixel clks) */
- h_de_hs = mode->hsync_start - mode->hdisplay;
hdmi_writeb(hdmi, h_de_hs >> 8, HDMI_FC_HSYNCINDELAY1);
hdmi_writeb(hdmi, h_de_hs, HDMI_FC_HSYNCINDELAY0);
@@ -1669,7 +1707,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
hdmi_writeb(hdmi, v_de_vs, HDMI_FC_VSYNCINDELAY);
/* Set up HSYNC active pulse width (in pixel clks) */
- hsync_len = mode->hsync_end - mode->hsync_start;
hdmi_writeb(hdmi, hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1);
hdmi_writeb(hdmi, hsync_len, HDMI_FC_HSYNCINWIDTH0);
--
2.7.4
With the YUV420 handling, we can dynamically setup the HDMI output
pixel format depending on the mode and connector info.
So now, we can output in YUV444, which is the native video pipeline
format, directly to the HDMI Sink if it's supported without
necessarily involving the HDMI Controller CSC.
Signed-off-by: Neil Armstrong <[email protected]>
---
drivers/gpu/drm/meson/meson_dw_hdmi.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
index 540971a..69f9b2a 100644
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
@@ -664,7 +664,10 @@ static int meson_venc_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
dw_hdmi->output_bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
} else {
dw_hdmi->input_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
- dw_hdmi->output_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+ if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
+ dw_hdmi->output_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
+ else
+ dw_hdmi->output_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
}
return 0;
--
2.7.4
Add support for SCDC Setup for TMDS Clock > 3.4GHz and enable TMDS
Scrambling when supported or mandatory.
This patch also adds an helper to setup the control bit to support
the high TMDS Bit Period/TMDS Clock-Period Ratio as required with
TMDS Clock > 3.4GHz for HDMI2.0 3840x2160@60/50 modes.
These changes were based on work done by Huicong Xu <[email protected]>
and Nickey Yang <[email protected]> to support HDMI2.0 modes
on the Rockchip 4.4 BSP kernel at [1]
[1] https://github.com/rockchip-linux/kernel/tree/release-4.4
Cc: Nickey Yang <[email protected]>
Cc: Huicong Xu <[email protected]>
Signed-off-by: Neil Armstrong <[email protected]>
Tested-by: Heiko Stuebner <[email protected]>
Reviewed-by: Andrzej Hajda <[email protected]>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 85 ++++++++++++++++++++++++++++++-
drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 +
include/drm/bridge/dw_hdmi.h | 1 +
3 files changed, 85 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 7aae726..6d5a2e9 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -27,6 +27,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_encoder_slave.h>
+#include <drm/drm_scdc_helper.h>
#include <drm/drm_probe_helper.h>
#include <drm/bridge/dw_hdmi.h>
@@ -43,6 +44,11 @@
#define HDMI_EDID_LEN 512
+/* DW-HDMI Controller >= 0x200a are at least compliant with SCDC version 1 */
+#define SCDC_MIN_SOURCE_VERSION 0x1
+
+#define HDMI14_MAX_TMDSCLK 340000000
+
enum hdmi_datamap {
RGB444_8B = 0x01,
RGB444_10B = 0x03,
@@ -1015,6 +1021,33 @@ void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
}
EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);
+/*
+ * HDMI2.0 Specifies the following procedure for High TMDS Bit Rates:
+ * - The Source shall suspend transmission of the TMDS clock and data
+ * - The Source shall write to the TMDS_Bit_Clock_Ratio bit to change it
+ * from a 0 to a 1 or from a 1 to a 0
+ * - The Source shall allow a minimum of 1 ms and a maximum of 100 ms from
+ * the time the TMDS_Bit_Clock_Ratio bit is written until resuming
+ * transmission of TMDS clock and data
+ *
+ * To respect the 100ms maximum delay, the dw_hdmi_set_high_tmds_clock_ratio()
+ * helper should called right before enabling the TMDS Clock and Data in
+ * the PHY configuration callback.
+ */
+void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi)
+{
+ unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mpixelclock;
+
+ /* Control for TMDS Bit Period/TMDS Clock-Period Ratio */
+ if (hdmi->connector.display_info.hdmi.scdc.supported) {
+ if (mtmdsclock > HDMI14_MAX_TMDSCLK)
+ drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 1);
+ else
+ drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 0);
+ }
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_set_high_tmds_clock_ratio);
+
static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable)
{
hdmi_mask_writeb(hdmi, !enable, HDMI_PHY_CONF0,
@@ -1216,6 +1249,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
dw_hdmi_phy_power_off(hdmi);
+ dw_hdmi_set_high_tmds_clock_ratio(hdmi);
+
/* Leave low power consumption mode by asserting SVSRET. */
if (phy->has_svsret)
dw_hdmi_phy_enable_svsret(hdmi, 1);
@@ -1237,6 +1272,10 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
return ret;
}
+ /* Wait for resuming transmission of TMDS clock and data */
+ if (mpixelclock > HDMI14_MAX_TMDSCLK)
+ msleep(100);
+
return dw_hdmi_phy_power_on(hdmi);
}
@@ -1504,7 +1543,8 @@ static void hdmi_config_vendor_specific_infoframe(struct dw_hdmi *hdmi,
static void hdmi_av_composer(struct dw_hdmi *hdmi,
const struct drm_display_mode *mode)
{
- u8 inv_val;
+ u8 inv_val, bytes;
+ struct drm_hdmi_info *hdmi_info = &hdmi->connector.display_info.hdmi;
struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
unsigned int vdisplay;
@@ -1514,7 +1554,9 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
/* Set up HDMI_FC_INVIDCONF */
- inv_val = (hdmi->hdmi_data.hdcp_enable ?
+ inv_val = (hdmi->hdmi_data.hdcp_enable ||
+ vmode->mpixelclock > HDMI14_MAX_TMDSCLK ||
+ hdmi_info->scdc.scrambling.low_rates ?
HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
@@ -1563,6 +1605,45 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
vsync_len /= 2;
}
+ /* Scrambling Control */
+ if (hdmi_info->scdc.supported) {
+ if (vmode->mpixelclock > HDMI14_MAX_TMDSCLK ||
+ hdmi_info->scdc.scrambling.low_rates) {
+ /*
+ * HDMI2.0 Specifies the following procedure:
+ * After the Source Device has determined that
+ * SCDC_Present is set (=1), the Source Device should
+ * write the accurate Version of the Source Device
+ * to the Source Version field in the SCDCS.
+ * Source Devices compliant shall set the
+ * Source Version = 1.
+ */
+ drm_scdc_readb(&hdmi->i2c->adap, SCDC_SINK_VERSION,
+ &bytes);
+ drm_scdc_writeb(&hdmi->i2c->adap, SCDC_SOURCE_VERSION,
+ min_t(u8, bytes, SCDC_MIN_SOURCE_VERSION));
+
+ /* Enabled Scrambling in the Sink */
+ drm_scdc_set_scrambling(&hdmi->i2c->adap, 1);
+
+ /*
+ * To activate the scrambler feature, you must ensure
+ * that the quasi-static configuration bit
+ * fc_invidconf.HDCP_keepout is set at configuration
+ * time, before the required mc_swrstzreq.tmdsswrst_req
+ * reset request is issued.
+ */
+ hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ,
+ HDMI_MC_SWRSTZ);
+ hdmi_writeb(hdmi, 1, HDMI_FC_SCRAMBLER_CTRL);
+ } else {
+ hdmi_writeb(hdmi, 0, HDMI_FC_SCRAMBLER_CTRL);
+ hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ,
+ HDMI_MC_SWRSTZ);
+ drm_scdc_set_scrambling(&hdmi->i2c->adap, 0);
+ }
+ }
+
/* Set up horizontal active pixel width */
hdmi_writeb(hdmi, mode->hdisplay >> 8, HDMI_FC_INHACTV1);
hdmi_writeb(hdmi, mode->hdisplay, HDMI_FC_INHACTV0);
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
index 9d90eb9..3f3c616 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
@@ -255,6 +255,7 @@
#define HDMI_FC_MASK2 0x10DA
#define HDMI_FC_POL2 0x10DB
#define HDMI_FC_PRCONF 0x10E0
+#define HDMI_FC_SCRAMBLER_CTRL 0x10E1
#define HDMI_FC_GMD_STAT 0x1100
#define HDMI_FC_GMD_EN 0x1101
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 9f93895..66e7077 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -159,6 +159,7 @@ void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense);
void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
+void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi);
/* PHY configuration */
void dw_hdmi_phy_i2c_set_addr(struct dw_hdmi *hdmi, u8 address);
--
2.7.4
Now we support the TMDS Clock > 3.4GHz and support the SCDC Control
operation in the DW-HDMI Controller, we can enable support for the
HDMI2.0 3840x2160@60/50 RGB444 display modes.
Signed-off-by: Neil Armstrong <[email protected]>
Reviewed-by: Andrzej Hajda <[email protected]>
---
drivers/gpu/drm/meson/meson_venc.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
index 0ba04f6..66d73a9 100644
--- a/drivers/gpu/drm/meson/meson_venc.c
+++ b/drivers/gpu/drm/meson/meson_venc.c
@@ -848,6 +848,8 @@ struct meson_hdmi_venc_vic_mode {
{ 93, &meson_hdmi_encp_mode_2160p24 },
{ 94, &meson_hdmi_encp_mode_2160p25 },
{ 95, &meson_hdmi_encp_mode_2160p30 },
+ { 96, &meson_hdmi_encp_mode_2160p25 },
+ { 97, &meson_hdmi_encp_mode_2160p30 },
{ 0, NULL}, /* sentinel */
};
--
2.7.4
On 01.02.2019 13:07, Neil Armstrong wrote:
> In order to support the HDMI2.0 YUV420 display modes, this patch
> adds support for the YUV420 TMDS Clock divided by 2 and the controller
> passthrough mode.
>
> YUV420 Synopsys PHY support will need some specific configuration table
> to support theses modes.
>
> This patch is based on work from Zheng Yang <[email protected]> in
> the Rockchip Linux 4.4 BSP at [1]
>
> [1] https://github.com/rockchip-linux/kernel/tree/release-4.4
>
> Cc: Zheng Yang <[email protected]>
> Signed-off-by: Neil Armstrong <[email protected]>
> Tested-by: Heiko Stuebner <[email protected]>
> Reviewed-by: Andrzej Hajda <[email protected]>
> ---
Patches 1-4 queued to drm-misc-next.
Regards
Andrzej
On Fri, Feb 1, 2019 at 6:08 AM Neil Armstrong <[email protected]> wrote:
>
> Add support for SCDC Setup for TMDS Clock > 3.4GHz and enable TMDS
> Scrambling when supported or mandatory.
>
> This patch also adds an helper to setup the control bit to support
> the high TMDS Bit Period/TMDS Clock-Period Ratio as required with
> TMDS Clock > 3.4GHz for HDMI2.0 3840x2160@60/50 modes.
>
> These changes were based on work done by Huicong Xu <[email protected]>
> and Nickey Yang <[email protected]> to support HDMI2.0 modes
> on the Rockchip 4.4 BSP kernel at [1]
>
> [1] https://github.com/rockchip-linux/kernel/tree/release-4.4
>
> Cc: Nickey Yang <[email protected]>
> Cc: Huicong Xu <[email protected]>
> Signed-off-by: Neil Armstrong <[email protected]>
> Tested-by: Heiko Stuebner <[email protected]>
> Reviewed-by: Andrzej Hajda <[email protected]>
> ---
> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 85 ++++++++++++++++++++++++++++++-
> drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 +
> include/drm/bridge/dw_hdmi.h | 1 +
> 3 files changed, 85 insertions(+), 2 deletions(-)
This commit in drm-misc-next is breaking booting on the Rock960. I
have FB and fbcon enabled. The boot hangs after this message:
[ 3.012334] [drm:rockchip_drm_fbdev_create] FB [1920x1080]-24
kvaddr=(____ptrval____) offset=0 size=8294400
Rob
Hi Rob,
On 08/03/2019 00:13, Rob Herring wrote:
> On Fri, Feb 1, 2019 at 6:08 AM Neil Armstrong <[email protected]> wrote:
>>
>> Add support for SCDC Setup for TMDS Clock > 3.4GHz and enable TMDS
>> Scrambling when supported or mandatory.
>>
>> This patch also adds an helper to setup the control bit to support
>> the high TMDS Bit Period/TMDS Clock-Period Ratio as required with
>> TMDS Clock > 3.4GHz for HDMI2.0 3840x2160@60/50 modes.
>>
>> These changes were based on work done by Huicong Xu <[email protected]>
>> and Nickey Yang <[email protected]> to support HDMI2.0 modes
>> on the Rockchip 4.4 BSP kernel at [1]
>>
>> [1] https://github.com/rockchip-linux/kernel/tree/release-4.4
>>
>> Cc: Nickey Yang <[email protected]>
>> Cc: Huicong Xu <[email protected]>
>> Signed-off-by: Neil Armstrong <[email protected]>
>> Tested-by: Heiko Stuebner <[email protected]>
>> Reviewed-by: Andrzej Hajda <[email protected]>
>> ---
>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 85 ++++++++++++++++++++++++++++++-
>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 +
>> include/drm/bridge/dw_hdmi.h | 1 +
>> 3 files changed, 85 insertions(+), 2 deletions(-)
>
> This commit in drm-misc-next is breaking booting on the Rock960. I
> have FB and fbcon enabled. The boot hangs after this message:
>
> [ 3.012334] [drm:rockchip_drm_fbdev_create] FB [1920x1080]-24
> kvaddr=(____ptrval____) offset=0 size=8294400
Could you give more details on the tree used ? did you bisect to find this commit ?
Neil
>
> Rob
>
On Fri, Mar 8, 2019 at 2:05 AM Neil Armstrong <[email protected]> wrote:
>
> Hi Rob,
>
> On 08/03/2019 00:13, Rob Herring wrote:
> > On Fri, Feb 1, 2019 at 6:08 AM Neil Armstrong <[email protected]> wrote:
> >>
> >> Add support for SCDC Setup for TMDS Clock > 3.4GHz and enable TMDS
> >> Scrambling when supported or mandatory.
> >>
> >> This patch also adds an helper to setup the control bit to support
> >> the high TMDS Bit Period/TMDS Clock-Period Ratio as required with
> >> TMDS Clock > 3.4GHz for HDMI2.0 3840x2160@60/50 modes.
> >>
> >> These changes were based on work done by Huicong Xu <[email protected]>
> >> and Nickey Yang <[email protected]> to support HDMI2.0 modes
> >> on the Rockchip 4.4 BSP kernel at [1]
> >>
> >> [1] https://github.com/rockchip-linux/kernel/tree/release-4.4
> >>
> >> Cc: Nickey Yang <[email protected]>
> >> Cc: Huicong Xu <[email protected]>
> >> Signed-off-by: Neil Armstrong <[email protected]>
> >> Tested-by: Heiko Stuebner <[email protected]>
> >> Reviewed-by: Andrzej Hajda <[email protected]>
> >> ---
> >> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 85 ++++++++++++++++++++++++++++++-
> >> drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 +
> >> include/drm/bridge/dw_hdmi.h | 1 +
> >> 3 files changed, 85 insertions(+), 2 deletions(-)
> >
> > This commit in drm-misc-next is breaking booting on the Rock960. I
> > have FB and fbcon enabled. The boot hangs after this message:
> >
> > [ 3.012334] [drm:rockchip_drm_fbdev_create] FB [1920x1080]-24
> > kvaddr=(____ptrval____) offset=0 size=8294400
>
> Could you give more details on the tree used ? did you bisect to find this commit ?
As I said above, drm-misc-next (from drm-misc tree) is the branch. I
bisected between it and v5.0. Reverting it fixes booting.
Rob
On 08/03/2019 15:54, Rob Herring wrote:
> On Fri, Mar 8, 2019 at 2:05 AM Neil Armstrong <[email protected]> wrote:
>>
>> Hi Rob,
>>
>> On 08/03/2019 00:13, Rob Herring wrote:
>>> On Fri, Feb 1, 2019 at 6:08 AM Neil Armstrong <[email protected]> wrote:
>>>>
>>>> Add support for SCDC Setup for TMDS Clock > 3.4GHz and enable TMDS
>>>> Scrambling when supported or mandatory.
>>>>
>>>> This patch also adds an helper to setup the control bit to support
>>>> the high TMDS Bit Period/TMDS Clock-Period Ratio as required with
>>>> TMDS Clock > 3.4GHz for HDMI2.0 3840x2160@60/50 modes.
>>>>
>>>> These changes were based on work done by Huicong Xu <[email protected]>
>>>> and Nickey Yang <[email protected]> to support HDMI2.0 modes
>>>> on the Rockchip 4.4 BSP kernel at [1]
>>>>
>>>> [1] https://github.com/rockchip-linux/kernel/tree/release-4.4
>>>>
>>>> Cc: Nickey Yang <[email protected]>
>>>> Cc: Huicong Xu <[email protected]>
>>>> Signed-off-by: Neil Armstrong <[email protected]>
>>>> Tested-by: Heiko Stuebner <[email protected]>
>>>> Reviewed-by: Andrzej Hajda <[email protected]>
>>>> ---
>>>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 85 ++++++++++++++++++++++++++++++-
>>>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 +
>>>> include/drm/bridge/dw_hdmi.h | 1 +
>>>> 3 files changed, 85 insertions(+), 2 deletions(-)
>>>
>>> This commit in drm-misc-next is breaking booting on the Rock960. I
>>> have FB and fbcon enabled. The boot hangs after this message:
>>>
>>> [ 3.012334] [drm:rockchip_drm_fbdev_create] FB [1920x1080]-24
>>> kvaddr=(____ptrval____) offset=0 size=8294400
>>
>> Could you give more details on the tree used ? did you bisect to find this commit ?
>
> As I said above, drm-misc-next (from drm-misc tree) is the branch. I
> bisected between it and v5.0. Reverting it fixes booting.
Thanks, could you give more details on the environment ? Did you test over the latest linux-next ?
Can you share the EDID of your monitor ?
Can you check this patch :
----><----------------------------------------------------------------------------------------
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index a63e5f0dae56..f33c2ac158c1 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1268,8 +1268,6 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
dw_hdmi_phy_power_off(hdmi);
- dw_hdmi_set_high_tmds_clock_ratio(hdmi);
-
/* Leave low power consumption mode by asserting SVSRET. */
if (phy->has_svsret)
dw_hdmi_phy_enable_svsret(hdmi, 1);
On Mon, Mar 11, 2019 at 3:53 AM Neil Armstrong <[email protected]> wrote:
>
> On 08/03/2019 15:54, Rob Herring wrote:
> > On Fri, Mar 8, 2019 at 2:05 AM Neil Armstrong <[email protected]> wrote:
> >>
> >> Hi Rob,
> >>
> >> On 08/03/2019 00:13, Rob Herring wrote:
> >>> On Fri, Feb 1, 2019 at 6:08 AM Neil Armstrong <[email protected]> wrote:
> >>>>
> >>>> Add support for SCDC Setup for TMDS Clock > 3.4GHz and enable TMDS
> >>>> Scrambling when supported or mandatory.
> >>>>
> >>>> This patch also adds an helper to setup the control bit to support
> >>>> the high TMDS Bit Period/TMDS Clock-Period Ratio as required with
> >>>> TMDS Clock > 3.4GHz for HDMI2.0 3840x2160@60/50 modes.
> >>>>
> >>>> These changes were based on work done by Huicong Xu <[email protected]>
> >>>> and Nickey Yang <[email protected]> to support HDMI2.0 modes
> >>>> on the Rockchip 4.4 BSP kernel at [1]
> >>>>
> >>>> [1] https://github.com/rockchip-linux/kernel/tree/release-4.4
> >>>>
> >>>> Cc: Nickey Yang <[email protected]>
> >>>> Cc: Huicong Xu <[email protected]>
> >>>> Signed-off-by: Neil Armstrong <[email protected]>
> >>>> Tested-by: Heiko Stuebner <[email protected]>
> >>>> Reviewed-by: Andrzej Hajda <[email protected]>
> >>>> ---
> >>>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 85 ++++++++++++++++++++++++++++++-
> >>>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 +
> >>>> include/drm/bridge/dw_hdmi.h | 1 +
> >>>> 3 files changed, 85 insertions(+), 2 deletions(-)
> >>>
> >>> This commit in drm-misc-next is breaking booting on the Rock960. I
> >>> have FB and fbcon enabled. The boot hangs after this message:
> >>>
> >>> [ 3.012334] [drm:rockchip_drm_fbdev_create] FB [1920x1080]-24
> >>> kvaddr=(____ptrval____) offset=0 size=8294400
> >>
> >> Could you give more details on the tree used ? did you bisect to find this commit ?
> >
> > As I said above, drm-misc-next (from drm-misc tree) is the branch. I
> > bisected between it and v5.0. Reverting it fixes booting.
>
> Thanks, could you give more details on the environment ? Did you test over the latest linux-next ?
Here's a log of the drm parts: https://pastebin.com/tFJ9Gs6h
linux-next also hangs.
> Can you share the EDID of your monitor ?
Maybe not mode related. I tried forcing to 1280x720 and it hangs too.
In any case, here's the parsed EDID:
256-byte EDID successfully retrieved from i2c bus 3
Looks like i2c was successful. Have a good day.
Checksum Correct
Section "Monitor"
Identifier "CYS-R101"
ModelName "CYS-R101"
VendorName "CYX"
# Monitor Manufactured week 28 of 2018
# EDID version 1.3
# Digital Display
DisplaySize 220 130
Gamma 2.20
Option "DPMS" "true"
Horizsync 30-102
VertRefresh 48-75
# Maximum pixel clock is 190MHz
#Not giving standard mode: 1920x1080, 60Hz
#Not giving standard mode: 1920x1080, 60Hz
#Not giving standard mode: 1920x1080, 60Hz
#Not giving standard mode: 1440x900, 60Hz
#Not giving standard mode: 1400x1050, 60Hz
#Not giving standard mode: 1280x1024, 60Hz
#Not giving standard mode: 1280x960, 60Hz
#Not giving standard mode: 1280x720, 60Hz
#Extension block found. Parsing...
Modeline "Mode 5" 54.00 2560 2608 2640 2720 1440 1443 1448 1481 +hsync +vsync
Modeline "Mode 0" 267.81 2560 2608 2640 2720 1600 1603 1608 1641 +hsync +vsync
Modeline "Mode 1" 148.500 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync
Modeline "Mode 2" 74.250 1920 2008 2052 2200 1080 1082 1087 1125
+hsync +vsync interlace
Modeline "Mode 3" 74.250 1280 1390 1420 1650 720 725 730 750 +hsync +vsync
Modeline "Mode 4" 148.500 1920 2448 2492 2640 1080 1084 1089 1125 +hsync +vsync
Option "PreferredMode" "Mode 5"
EndSection
> Can you check this patch :
Still hangs with it.
>
> ----><----------------------------------------------------------------------------------------
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index a63e5f0dae56..f33c2ac158c1 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -1268,8 +1268,6 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
>
> dw_hdmi_phy_power_off(hdmi);
>
> - dw_hdmi_set_high_tmds_clock_ratio(hdmi);
> -
> /* Leave low power consumption mode by asserting SVSRET. */
> if (phy->has_svsret)
> dw_hdmi_phy_enable_svsret(hdmi, 1);
>
>
Hi Rob,
Le 14/03/2019 19:55, Rob Herring a écrit :
> On Mon, Mar 11, 2019 at 3:53 AM Neil Armstrong <[email protected]> wrote:
>>
>> On 08/03/2019 15:54, Rob Herring wrote:
>>> On Fri, Mar 8, 2019 at 2:05 AM Neil Armstrong <[email protected]> wrote:
>>>>
>>>> Hi Rob,
>>>>
>>>> On 08/03/2019 00:13, Rob Herring wrote:
>>>>> On Fri, Feb 1, 2019 at 6:08 AM Neil Armstrong <[email protected]> wrote:
>>>>>>
>>>>>> Add support for SCDC Setup for TMDS Clock > 3.4GHz and enable TMDS
>>>>>> Scrambling when supported or mandatory.
>>>>>>
>>>>>> This patch also adds an helper to setup the control bit to support
>>>>>> the high TMDS Bit Period/TMDS Clock-Period Ratio as required with
>>>>>> TMDS Clock > 3.4GHz for HDMI2.0 3840x2160@60/50 modes.
>>>>>>
>>>>>> These changes were based on work done by Huicong Xu <[email protected]>
>>>>>> and Nickey Yang <[email protected]> to support HDMI2.0 modes
>>>>>> on the Rockchip 4.4 BSP kernel at [1]
>>>>>>
>>>>>> [1] https://github.com/rockchip-linux/kernel/tree/release-4.4
>>>>>>
>>>>>> Cc: Nickey Yang <[email protected]>
>>>>>> Cc: Huicong Xu <[email protected]>
>>>>>> Signed-off-by: Neil Armstrong <[email protected]>
>>>>>> Tested-by: Heiko Stuebner <[email protected]>
>>>>>> Reviewed-by: Andrzej Hajda <[email protected]>
>>>>>> ---
>>>>>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 85 ++++++++++++++++++++++++++++++-
>>>>>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 +
>>>>>> include/drm/bridge/dw_hdmi.h | 1 +
>>>>>> 3 files changed, 85 insertions(+), 2 deletions(-)
>>>>>
>>>>> This commit in drm-misc-next is breaking booting on the Rock960. I
>>>>> have FB and fbcon enabled. The boot hangs after this message:
>>>>>
>>>>> [ 3.012334] [drm:rockchip_drm_fbdev_create] FB [1920x1080]-24
>>>>> kvaddr=(____ptrval____) offset=0 size=8294400
>>>>
>>>> Could you give more details on the tree used ? did you bisect to find this commit ?
>>>
>>> As I said above, drm-misc-next (from drm-misc tree) is the branch. I
>>> bisected between it and v5.0. Reverting it fixes booting.
>>
>> Thanks, could you give more details on the environment ? Did you test over the latest linux-next ?
>
> Here's a log of the drm parts: https://pastebin.com/tFJ9Gs6h
>
> linux-next also hangs.
>
>> Can you share the EDID of your monitor ?
>
> Maybe not mode related. I tried forcing to 1280x720 and it hangs too.
> In any case, here's the parsed EDID:
>
> 256-byte EDID successfully retrieved from i2c bus 3
> Looks like i2c was successful. Have a good day.
> Checksum Correct
>
> Section "Monitor"
> Identifier "CYS-R101"
> ModelName "CYS-R101"
> VendorName "CYX"
> # Monitor Manufactured week 28 of 2018
> # EDID version 1.3
> # Digital Display
> DisplaySize 220 130
> Gamma 2.20
> Option "DPMS" "true"
> Horizsync 30-102
> VertRefresh 48-75
> # Maximum pixel clock is 190MHz
> #Not giving standard mode: 1920x1080, 60Hz
> #Not giving standard mode: 1920x1080, 60Hz
> #Not giving standard mode: 1920x1080, 60Hz
> #Not giving standard mode: 1440x900, 60Hz
> #Not giving standard mode: 1400x1050, 60Hz
> #Not giving standard mode: 1280x1024, 60Hz
> #Not giving standard mode: 1280x960, 60Hz
> #Not giving standard mode: 1280x720, 60Hz
>
> #Extension block found. Parsing...
> Modeline "Mode 5" 54.00 2560 2608 2640 2720 1440 1443 1448 1481 +hsync +vsync
> Modeline "Mode 0" 267.81 2560 2608 2640 2720 1600 1603 1608 1641 +hsync +vsync
> Modeline "Mode 1" 148.500 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync
> Modeline "Mode 2" 74.250 1920 2008 2052 2200 1080 1082 1087 1125
> +hsync +vsync interlace
> Modeline "Mode 3" 74.250 1280 1390 1420 1650 720 725 730 750 +hsync +vsync
> Modeline "Mode 4" 148.500 1920 2448 2492 2640 1080 1084 1089 1125 +hsync +vsync
> Option "PreferredMode" "Mode 5"
> EndSection
>
>> Can you check this patch :
>
> Still hangs with it.
Thanks for testing, the only impact would be if hdmi_info->scdc.supported
and hdmi_info->scdc.scrambling.low_rate were true.
Honestly, hdmi_info->scdc.scrambling.low_rate wasn't really tested.
Could you dump the edid in binary format ? or parse it with https://github.com/rpavlik/edid-decode
supporting modern HDMI EDIDs.
Thanks,
Neil
>
>>
>> ----><----------------------------------------------------------------------------------------
>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> index a63e5f0dae56..f33c2ac158c1 100644
>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> @@ -1268,8 +1268,6 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi)
>>
>> dw_hdmi_phy_power_off(hdmi);
>>
>> - dw_hdmi_set_high_tmds_clock_ratio(hdmi);
>> -
>> /* Leave low power consumption mode by asserting SVSRET. */
>> if (phy->has_svsret)
>> dw_hdmi_phy_enable_svsret(hdmi, 1);
>>
>>
On Thu, Mar 14, 2019 at 3:07 PM Neil Armstrong <[email protected]> wrote:
>
> Hi Rob,
>
> Le 14/03/2019 19:55, Rob Herring a écrit :
> > On Mon, Mar 11, 2019 at 3:53 AM Neil Armstrong <[email protected]> wrote:
> >>
> >> On 08/03/2019 15:54, Rob Herring wrote:
> >>> On Fri, Mar 8, 2019 at 2:05 AM Neil Armstrong <[email protected]> wrote:
> >>>>
> >>>> Hi Rob,
> >>>>
> >>>> On 08/03/2019 00:13, Rob Herring wrote:
> >>>>> On Fri, Feb 1, 2019 at 6:08 AM Neil Armstrong <[email protected]> wrote:
> >>>>>>
> >>>>>> Add support for SCDC Setup for TMDS Clock > 3.4GHz and enable TMDS
> >>>>>> Scrambling when supported or mandatory.
> >>>>>>
> >>>>>> This patch also adds an helper to setup the control bit to support
> >>>>>> the high TMDS Bit Period/TMDS Clock-Period Ratio as required with
> >>>>>> TMDS Clock > 3.4GHz for HDMI2.0 3840x2160@60/50 modes.
> >>>>>>
> >>>>>> These changes were based on work done by Huicong Xu <[email protected]>
> >>>>>> and Nickey Yang <[email protected]> to support HDMI2.0 modes
> >>>>>> on the Rockchip 4.4 BSP kernel at [1]
> >>>>>>
> >>>>>> [1] https://github.com/rockchip-linux/kernel/tree/release-4.4
> >>>>>>
> >>>>>> Cc: Nickey Yang <[email protected]>
> >>>>>> Cc: Huicong Xu <[email protected]>
> >>>>>> Signed-off-by: Neil Armstrong <[email protected]>
> >>>>>> Tested-by: Heiko Stuebner <[email protected]>
> >>>>>> Reviewed-by: Andrzej Hajda <[email protected]>
> >>>>>> ---
> >>>>>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 85 ++++++++++++++++++++++++++++++-
> >>>>>> drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 +
> >>>>>> include/drm/bridge/dw_hdmi.h | 1 +
> >>>>>> 3 files changed, 85 insertions(+), 2 deletions(-)
> >>>>>
> >>>>> This commit in drm-misc-next is breaking booting on the Rock960. I
> >>>>> have FB and fbcon enabled. The boot hangs after this message:
> >>>>>
> >>>>> [ 3.012334] [drm:rockchip_drm_fbdev_create] FB [1920x1080]-24
> >>>>> kvaddr=(____ptrval____) offset=0 size=8294400
> >>>>
> >>>> Could you give more details on the tree used ? did you bisect to find this commit ?
> >>>
> >>> As I said above, drm-misc-next (from drm-misc tree) is the branch. I
> >>> bisected between it and v5.0. Reverting it fixes booting.
> >>
> >> Thanks, could you give more details on the environment ? Did you test over the latest linux-next ?
> >
> > Here's a log of the drm parts: https://pastebin.com/tFJ9Gs6h
> >
> > linux-next also hangs.
> >
> >> Can you share the EDID of your monitor ?
> >
> > Maybe not mode related. I tried forcing to 1280x720 and it hangs too.
> > In any case, here's the parsed EDID:
> >
> > 256-byte EDID successfully retrieved from i2c bus 3
> > Looks like i2c was successful. Have a good day.
> > Checksum Correct
> >
> > Section "Monitor"
> > Identifier "CYS-R101"
> > ModelName "CYS-R101"
> > VendorName "CYX"
> > # Monitor Manufactured week 28 of 2018
> > # EDID version 1.3
> > # Digital Display
> > DisplaySize 220 130
> > Gamma 2.20
> > Option "DPMS" "true"
> > Horizsync 30-102
> > VertRefresh 48-75
> > # Maximum pixel clock is 190MHz
> > #Not giving standard mode: 1920x1080, 60Hz
> > #Not giving standard mode: 1920x1080, 60Hz
> > #Not giving standard mode: 1920x1080, 60Hz
> > #Not giving standard mode: 1440x900, 60Hz
> > #Not giving standard mode: 1400x1050, 60Hz
> > #Not giving standard mode: 1280x1024, 60Hz
> > #Not giving standard mode: 1280x960, 60Hz
> > #Not giving standard mode: 1280x720, 60Hz
> >
> > #Extension block found. Parsing...
> > Modeline "Mode 5" 54.00 2560 2608 2640 2720 1440 1443 1448 1481 +hsync +vsync
> > Modeline "Mode 0" 267.81 2560 2608 2640 2720 1600 1603 1608 1641 +hsync +vsync
> > Modeline "Mode 1" 148.500 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync
> > Modeline "Mode 2" 74.250 1920 2008 2052 2200 1080 1082 1087 1125
> > +hsync +vsync interlace
> > Modeline "Mode 3" 74.250 1280 1390 1420 1650 720 725 730 750 +hsync +vsync
> > Modeline "Mode 4" 148.500 1920 2448 2492 2640 1080 1084 1089 1125 +hsync +vsync
> > Option "PreferredMode" "Mode 5"
> > EndSection
> >
> >> Can you check this patch :
> >
> > Still hangs with it.
>
>
> Thanks for testing, the only impact would be if hdmi_info->scdc.supported
> and hdmi_info->scdc.scrambling.low_rate were true.
> Honestly, hdmi_info->scdc.scrambling.low_rate wasn't really tested.
>
> Could you dump the edid in binary format ? or parse it with https://github.com/rpavlik/edid-decode
> supporting modern HDMI EDIDs.
Here's with edid-decode:
EDID version: 1.3
Manufacturer: CYX Model 101 Serial Number 16843009
Made in week 28 of 2018
Digital display
Maximum image size: 22 cm x 13 cm
Gamma: 2.20
DPMS levels: Off
Undefined display color type
Default (sRGB) color space is primary color space
First detailed timing is preferred timing
Display x,y Chromaticity:
Red: 0.6455, 0.3300
Green: 0.3095, 0.6171
Blue: 0.1523, 0.0732
White: 0.3134, 0.3291
Established timings supported:
640x480@60Hz 4:3 HorFreq: 31469 Hz Clock: 25.175 MHz
800x600@60Hz 4:3 HorFreq: 37900 Hz Clock: 40.000 MHz
1024x768@60Hz 4:3 HorFreq: 48400 Hz Clock: 65.000 MHz
Standard timings supported:
1920x1080@60Hz 16:9
1920x1080@60Hz 16:9
1920x1080@60Hz 16:9
1440x900@60Hz 16:10 HorFreq: 55500 Hz Clock: 88.750 MHz
1400x1050@60Hz 4:3 HorFreq: 64700 Hz Clock: 101.000 MHz
1280x1024@60Hz 5:4 HorFreq: 64000 Hz Clock: 108.000 MHz
1280x960@60Hz 4:3 HorFreq: 60000 Hz Clock: 108.000 MHz
1280x720@60Hz 16:9
Detailed mode: Clock 267.810 MHz, 220 mm x 130 mm
2560 2608 2640 2720 hborder 0
1600 1603 1608 1641 vborder 0
+hsync +vsync
VertFreq: 59 Hz, HorFreq: 98459 Hz
Monitor name: CYS-R101
Serial number:
Monitor ranges (bare limits): 48-75Hz V, 30-102kHz H, max dotclock 190MHz
Has 1 extension blocks
Checksum: 0x8b (valid)
CTA extension block
Extension version: 3
58 bytes of CTA data
Video data block
VIC 16 1920x1080@60Hz 16:9 HorFreq: 67500 Hz Clock: 148.500 MHz
VIC 5 1920x1080i@60Hz 16:9 HorFreq: 33750 Hz Clock: 74.250 MHz
VIC 4 1280x720@60Hz 16:9 HorFreq: 45000 Hz Clock: 74.250 MHz
VIC 31 1920x1080@50Hz 16:9 HorFreq: 56250 Hz Clock: 148.500 MHz
Audio data block
Linear PCM, max channels 2
Supported sample rates (kHz): 48 44.1 32
Supported sample sizes (bits): 24 20 16
Speaker allocation data block
Speaker map:
FL/FR - Front Left/Right
Vendor-specific data block, OUI 000c03 (HDMI)
Source physical address 1.0.0.0
DC_36bit
DC_30bit
DC_Y444
Maximum TMDS clock: 340MHz
Vendor-specific data block, OUI c45dd8 (HDMI Forum)
Version: 1
Maximum TMDS Character Rate: 340MHz
SCDC Present
Supports 10-bits/component Deep Color 4:2:0 Pixel Encoding
Vendor-specific data block, OUI 00001a
Extended tag: YCbCr 4:2:0 capability map data block
VSD Index 17
VSD Index 18
Extended tag: Colorimetry data block
BT2020YCC
BT2020RGB
Extended tag: Video capability data block
YCbCr quantization: Selectable (via AVI YQ) (1)
RGB quantization: Selectable (via AVI Q) (1)
PT scan behaviour: Support both over- and underscan (3)
IT scan behaviour: Support both over- and underscan (3)
CE scan behaviour: Support both over- and underscan (3)
Extended tag: HDR static metadata data block
Electro optical transfer functions:
Traditional gamma - SDR luminance range
SMPTE ST2084
Supported static metadata descriptors:
Static metadata type 1
Desired content max luminance: 89 (343.724 cd/m^2)
Desired content max frame-average luminance: 89 (343.724 cd/m^2)
Desired content min luminance: 73 (0.282 cd/m^2)
Underscans PC formats by default
Basic audio support
Supports YCbCr 4:4:4
Supports YCbCr 4:2:2
1 native detailed modes
Detailed mode: Clock 54.000 MHz, 220 mm x 130 mm
2560 2608 2640 2720 hborder 0
1440 1443 1448 1481 vborder 0
+hsync +vsync side by side interleaved
VertFreq: 13 Hz, HorFreq: 19852 Hz
Checksum: 0x3c (valid)
Hi Rob,
On 14/03/2019 21:14, Rob Herring wrote:
> On Thu, Mar 14, 2019 at 3:07 PM Neil Armstrong <[email protected]> wrote:
>>
[...]
>
> Here's with edid-decode:
>
> EDID version: 1.3
> Manufacturer: CYX Model 101 Serial Number 16843009
> Made in week 28 of 2018
> Digital display
> Maximum image size: 22 cm x 13 cm
> Gamma: 2.20
> DPMS levels: Off
> Undefined display color type
> Default (sRGB) color space is primary color space
> First detailed timing is preferred timing
> Display x,y Chromaticity:
> Red: 0.6455, 0.3300
> Green: 0.3095, 0.6171
> Blue: 0.1523, 0.0732
> White: 0.3134, 0.3291
> Established timings supported:
> 640x480@60Hz 4:3 HorFreq: 31469 Hz Clock: 25.175 MHz
> 800x600@60Hz 4:3 HorFreq: 37900 Hz Clock: 40.000 MHz
> 1024x768@60Hz 4:3 HorFreq: 48400 Hz Clock: 65.000 MHz
> Standard timings supported:
> 1920x1080@60Hz 16:9
> 1920x1080@60Hz 16:9
> 1920x1080@60Hz 16:9
> 1440x900@60Hz 16:10 HorFreq: 55500 Hz Clock: 88.750 MHz
> 1400x1050@60Hz 4:3 HorFreq: 64700 Hz Clock: 101.000 MHz
> 1280x1024@60Hz 5:4 HorFreq: 64000 Hz Clock: 108.000 MHz
> 1280x960@60Hz 4:3 HorFreq: 60000 Hz Clock: 108.000 MHz
> 1280x720@60Hz 16:9
> Detailed mode: Clock 267.810 MHz, 220 mm x 130 mm
> 2560 2608 2640 2720 hborder 0
> 1600 1603 1608 1641 vborder 0
> +hsync +vsync
> VertFreq: 59 Hz, HorFreq: 98459 Hz
> Monitor name: CYS-R101
> Serial number:
> Monitor ranges (bare limits): 48-75Hz V, 30-102kHz H, max dotclock 190MHz
> Has 1 extension blocks
> Checksum: 0x8b (valid)
>
> CTA extension block
> Extension version: 3
> 58 bytes of CTA data
> Video data block
> VIC 16 1920x1080@60Hz 16:9 HorFreq: 67500 Hz Clock: 148.500 MHz
> VIC 5 1920x1080i@60Hz 16:9 HorFreq: 33750 Hz Clock: 74.250 MHz
> VIC 4 1280x720@60Hz 16:9 HorFreq: 45000 Hz Clock: 74.250 MHz
> VIC 31 1920x1080@50Hz 16:9 HorFreq: 56250 Hz Clock: 148.500 MHz
> Audio data block
> Linear PCM, max channels 2
> Supported sample rates (kHz): 48 44.1 32
> Supported sample sizes (bits): 24 20 16
> Speaker allocation data block
> Speaker map:
> FL/FR - Front Left/Right
> Vendor-specific data block, OUI 000c03 (HDMI)
> Source physical address 1.0.0.0
> DC_36bit
> DC_30bit
> DC_Y444
> Maximum TMDS clock: 340MHz
> Vendor-specific data block, OUI c45dd8 (HDMI Forum)
> Version: 1
> Maximum TMDS Character Rate: 340MHz
> SCDC Present
> Supports 10-bits/component Deep Color 4:2:0 Pixel Encoding
> Vendor-specific data block, OUI 00001a
> Extended tag: YCbCr 4:2:0 capability map data block
> VSD Index 17
> VSD Index 18
> Extended tag: Colorimetry data block
> BT2020YCC
> BT2020RGB
> Extended tag: Video capability data block
> YCbCr quantization: Selectable (via AVI YQ) (1)
> RGB quantization: Selectable (via AVI Q) (1)
> PT scan behaviour: Support both over- and underscan (3)
> IT scan behaviour: Support both over- and underscan (3)
> CE scan behaviour: Support both over- and underscan (3)
> Extended tag: HDR static metadata data block
> Electro optical transfer functions:
> Traditional gamma - SDR luminance range
> SMPTE ST2084
> Supported static metadata descriptors:
> Static metadata type 1
> Desired content max luminance: 89 (343.724 cd/m^2)
> Desired content max frame-average luminance: 89 (343.724 cd/m^2)
> Desired content min luminance: 73 (0.282 cd/m^2)
> Underscans PC formats by default
> Basic audio support
> Supports YCbCr 4:4:4
> Supports YCbCr 4:2:2
> 1 native detailed modes
> Detailed mode: Clock 54.000 MHz, 220 mm x 130 mm
> 2560 2608 2640 2720 hborder 0
> 1440 1443 1448 1481 vborder 0
> +hsync +vsync side by side interleaved
> VertFreq: 13 Hz, HorFreq: 19852 Hz
> Checksum: 0x3c (valid)
>
Thanks for the parsed edid.
I think we have multiple issues :
- This EDID is severely broken, SCDC support doesn't make sense because
"Maximum TMDS Character Rate: 340MHz" and "Supports scrambling for <= 340 Mcsc" is not present
Same for 4:2:0, the IDs in the "YCbCr 4:2:0 capability map data block" refers
to invalid modes 17 & 18 in a mode table containing only 4 entries.
- DW-HDMI should not care if SCDC is present, Max TMDS <= 340MHz and low_rates is not present
- In any case, the SoC should not freeze in this situation, so either the
HDMI_FC_SCRAMBLER_CTRL or HDMI_MC_SWRSTZ writes makes the SoC freeze or
the drm_scdc_set_scrambling() containing i2c write fails, anyway this is
the root issue.
This will need 3 steps :
- an entry in the EDID quirk table to disable SCDC and 420 for this monitor
- a fix in dw-hdmi to ignore this SCDC setup
- an investigation to find why and where the SoC did freeze
Rob, could you give the Commercial name of the display for the EDID quirk table ?
Thanks,
Neil
Hi Neil,
On Fri, Feb 1, 2019 at 1:08 PM Neil Armstrong <[email protected]> wrote:
>
> This patch adds support for the YUV420 output from the Amlogic Meson SoCs
> Video Processing Unit to the HDMI Controller.
>
> The YUV420 is obtained by generating a YUV444 pixel stream like
> the classic HDMI display modes, but then the Video Encoder output
> can be configured to down-sample the YUV444 pixel stream to a YUV420
> stream.
> In addition if pixel stream down-sampling, the Y Cb Cr components must
> also be mapped differently to align with the HDMI2.0 specifications.
>
> This mode needs a different clock generation scheme since the TMDS PHY
> clock must match the 10x ration with the YUV420 pixel clock, but
> the video encoder must run at 2x the pixel clock.
>
> This patch adds the TMDS PHY clock value in all the video clock setup
> in order to better support these specific uses cases and switch
> to the Common Clock framework for clocks handling in the future.
>
> Signed-off-by: Neil Armstrong <[email protected]>
> ---
> drivers/gpu/drm/meson/meson_dw_hdmi.c | 110 ++++++++++++++++++++++++++------
> drivers/gpu/drm/meson/meson_vclk.c | 93 ++++++++++++++++++++-------
> drivers/gpu/drm/meson/meson_vclk.h | 7 +-
> drivers/gpu/drm/meson/meson_venc.c | 6 +-
> drivers/gpu/drm/meson/meson_venc.h | 11 ++++
> drivers/gpu/drm/meson/meson_venc_cvbs.c | 3 +-
> 6 files changed, 184 insertions(+), 46 deletions(-)
>
> diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
> index e28814f..540971a 100644
> --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
> +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
> @@ -141,6 +141,8 @@ struct meson_dw_hdmi {
> struct regulator *hdmi_supply;
> u32 irq_stat;
> struct dw_hdmi *hdmi;
> + unsigned long input_bus_format;
> + unsigned long output_bus_format;
> };
> #define encoder_to_meson_dw_hdmi(x) \
> container_of(x, struct meson_dw_hdmi, encoder)
> @@ -323,25 +325,36 @@ static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
> {
> struct meson_drm *priv = dw_hdmi->priv;
> int vic = drm_match_cea_mode(mode);
> + unsigned int phy_freq;
> unsigned int vclk_freq;
> unsigned int venc_freq;
> unsigned int hdmi_freq;
>
> vclk_freq = mode->clock;
>
> + /* For 420, pixel clock is half unlike venc clock */
> + if (dw_hdmi->input_bus_format == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
> + vclk_freq /= 2;
> +
> + /* TMDS clock is pixel_clock * 10 */
> + phy_freq = vclk_freq * 10;
> +
> if (!vic) {
> - meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, vclk_freq,
> - vclk_freq, vclk_freq, false);
> + meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, phy_freq,
> + vclk_freq, vclk_freq, vclk_freq, false);
> return;
> }
>
> + /* 480i/576i needs global pixel doubling */
> if (mode->flags & DRM_MODE_FLAG_DBLCLK)
> vclk_freq *= 2;
>
> venc_freq = vclk_freq;
> hdmi_freq = vclk_freq;
>
> - if (meson_venc_hdmi_venc_repeat(vic))
> + /* VENC double pixels for 1080i, 720p and YUV420 modes */
> + if (meson_venc_hdmi_venc_repeat(vic) ||
> + dw_hdmi->input_bus_format == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
> venc_freq *= 2;
>
> vclk_freq = max(venc_freq, hdmi_freq);
> @@ -349,11 +362,11 @@ static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
> if (mode->flags & DRM_MODE_FLAG_DBLCLK)
> venc_freq /= 2;
>
> - DRM_DEBUG_DRIVER("vclk:%d venc=%d hdmi=%d enci=%d\n",
> - vclk_freq, venc_freq, hdmi_freq,
> + DRM_DEBUG_DRIVER("vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n",
> + phy_freq, vclk_freq, venc_freq, hdmi_freq,
> priv->venc.hdmi_use_enci);
>
> - meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, vclk_freq,
> + meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, phy_freq, vclk_freq,
> venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
> }
>
> @@ -386,8 +399,9 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
> /* Enable normal output to PHY */
> dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
>
> - /* TMDS pattern setup (TOFIX Handle the YUV420 case) */
> - if (mode->clock > 340000) {
> + /* TMDS pattern setup */
> + if (mode->clock > 340000 &&
> + dw_hdmi->input_bus_format == MEDIA_BUS_FMT_YUV8_1X24) {
> dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 0);
> dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
> 0x03ff03ff);
> @@ -560,6 +574,8 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
> const struct drm_display_mode *mode)
> {
> struct meson_drm *priv = connector->dev->dev_private;
> + bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
> + unsigned int phy_freq;
> unsigned int vclk_freq;
> unsigned int venc_freq;
> unsigned int hdmi_freq;
> @@ -568,8 +584,10 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
>
> DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
>
> - /* If sink max TMDS clock, we reject the mode */
> - if (mode->clock > connector->display_info.max_tmds_clock)
> + /* If sink does not support 540MHz, reject the non-420 HDMI2 modes */
> + if (mode->clock > connector->display_info.max_tmds_clock &&
> + !drm_mode_is_420_only(&connector->display_info, mode) &&
> + !drm_mode_is_420_also(&connector->display_info, mode))
> return MODE_BAD;
>
This part makes all the modes identified as BAD on my TV, on G12A and
GXL, which in turn breaks HDMI output (no signal detected).
Here is the dmesg with drm debug: https://pastebin.com/t3XESC2w
Cheers,
Maxime
|snip]
On 19/03/2019 11:35, Maxime Jourdan wrote:
> Hi Neil,
>
> On Fri, Feb 1, 2019 at 1:08 PM Neil Armstrong <[email protected]> wrote:
>>
>> This patch adds support for the YUV420 output from the Amlogic Meson SoCs
>> Video Processing Unit to the HDMI Controller.
>>
>> The YUV420 is obtained by generating a YUV444 pixel stream like
>> the classic HDMI display modes, but then the Video Encoder output
>> can be configured to down-sample the YUV444 pixel stream to a YUV420
>> stream.
>> In addition if pixel stream down-sampling, the Y Cb Cr components must
>> also be mapped differently to align with the HDMI2.0 specifications.
>>
>> This mode needs a different clock generation scheme since the TMDS PHY
>> clock must match the 10x ration with the YUV420 pixel clock, but
>> the video encoder must run at 2x the pixel clock.
>>
>> This patch adds the TMDS PHY clock value in all the video clock setup
>> in order to better support these specific uses cases and switch
>> to the Common Clock framework for clocks handling in the future.
>>
>> Signed-off-by: Neil Armstrong <[email protected]>
>> ---
>> drivers/gpu/drm/meson/meson_dw_hdmi.c | 110 ++++++++++++++++++++++++++------
>> drivers/gpu/drm/meson/meson_vclk.c | 93 ++++++++++++++++++++-------
>> drivers/gpu/drm/meson/meson_vclk.h | 7 +-
>> drivers/gpu/drm/meson/meson_venc.c | 6 +-
>> drivers/gpu/drm/meson/meson_venc.h | 11 ++++
>> drivers/gpu/drm/meson/meson_venc_cvbs.c | 3 +-
>> 6 files changed, 184 insertions(+), 46 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
>> index e28814f..540971a 100644
>> --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
>> +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
>> @@ -141,6 +141,8 @@ struct meson_dw_hdmi {
>> struct regulator *hdmi_supply;
>> u32 irq_stat;
>> struct dw_hdmi *hdmi;
>> + unsigned long input_bus_format;
>> + unsigned long output_bus_format;
>> };
>> #define encoder_to_meson_dw_hdmi(x) \
>> container_of(x, struct meson_dw_hdmi, encoder)
>> @@ -323,25 +325,36 @@ static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
>> {
>> struct meson_drm *priv = dw_hdmi->priv;
>> int vic = drm_match_cea_mode(mode);
>> + unsigned int phy_freq;
>> unsigned int vclk_freq;
>> unsigned int venc_freq;
>> unsigned int hdmi_freq;
>>
>> vclk_freq = mode->clock;
>>
>> + /* For 420, pixel clock is half unlike venc clock */
>> + if (dw_hdmi->input_bus_format == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
>> + vclk_freq /= 2;
>> +
>> + /* TMDS clock is pixel_clock * 10 */
>> + phy_freq = vclk_freq * 10;
>> +
>> if (!vic) {
>> - meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, vclk_freq,
>> - vclk_freq, vclk_freq, false);
>> + meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, phy_freq,
>> + vclk_freq, vclk_freq, vclk_freq, false);
>> return;
>> }
>>
>> + /* 480i/576i needs global pixel doubling */
>> if (mode->flags & DRM_MODE_FLAG_DBLCLK)
>> vclk_freq *= 2;
>>
>> venc_freq = vclk_freq;
>> hdmi_freq = vclk_freq;
>>
>> - if (meson_venc_hdmi_venc_repeat(vic))
>> + /* VENC double pixels for 1080i, 720p and YUV420 modes */
>> + if (meson_venc_hdmi_venc_repeat(vic) ||
>> + dw_hdmi->input_bus_format == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
>> venc_freq *= 2;
>>
>> vclk_freq = max(venc_freq, hdmi_freq);
>> @@ -349,11 +362,11 @@ static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
>> if (mode->flags & DRM_MODE_FLAG_DBLCLK)
>> venc_freq /= 2;
>>
>> - DRM_DEBUG_DRIVER("vclk:%d venc=%d hdmi=%d enci=%d\n",
>> - vclk_freq, venc_freq, hdmi_freq,
>> + DRM_DEBUG_DRIVER("vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n",
>> + phy_freq, vclk_freq, venc_freq, hdmi_freq,
>> priv->venc.hdmi_use_enci);
>>
>> - meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, vclk_freq,
>> + meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, phy_freq, vclk_freq,
>> venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
>> }
>>
>> @@ -386,8 +399,9 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
>> /* Enable normal output to PHY */
>> dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
>>
>> - /* TMDS pattern setup (TOFIX Handle the YUV420 case) */
>> - if (mode->clock > 340000) {
>> + /* TMDS pattern setup */
>> + if (mode->clock > 340000 &&
>> + dw_hdmi->input_bus_format == MEDIA_BUS_FMT_YUV8_1X24) {
>> dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 0);
>> dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
>> 0x03ff03ff);
>> @@ -560,6 +574,8 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
>> const struct drm_display_mode *mode)
>> {
>> struct meson_drm *priv = connector->dev->dev_private;
>> + bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
>> + unsigned int phy_freq;
>> unsigned int vclk_freq;
>> unsigned int venc_freq;
>> unsigned int hdmi_freq;
>> @@ -568,8 +584,10 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
>>
>> DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
>>
>> - /* If sink max TMDS clock, we reject the mode */
>> - if (mode->clock > connector->display_info.max_tmds_clock)
>> + /* If sink does not support 540MHz, reject the non-420 HDMI2 modes */
>> + if (mode->clock > connector->display_info.max_tmds_clock &&
>> + !drm_mode_is_420_only(&connector->display_info, mode) &&
>> + !drm_mode_is_420_also(&connector->display_info, mode))
>> return MODE_BAD;
>>
Hi Maxime,
>
> This part makes all the modes identified as BAD on my TV, on G12A and
> GXL, which in turn breaks HDMI output (no signal detected).
In fact, the issue comes from patch 2.
+ if (mode->clock > connector->display_info.max_tmds_clock)
+ return MODE_BAD;
is wrong if max_tmds_clock is 0, as reported from a DMT monitor.
The original :
+ /* If sink max TMDS clock < 340MHz, we reject the HDMI2.0 modes */
+ if (mode->clock > 340000 &&
+ connector->display_info.max_tmds_clock < 340000)
+ return MODE_BAD;
was correct, and I was asked to simplify it.
I will submit a fix reverting to the later.
Neil
>
> Here is the dmesg with drm debug: https://pastebin.com/t3XESC2w
>
> Cheers,
> Maxime
>
> |snip]
>