diff options
author | He Yangxuan <yangxuan8282@gmail.com> | 2018-12-12 04:18:06 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2018-12-20 14:35:09 +0000 |
commit | 468ce5d3db5bea1bfc4d0b21ce0460bbc508c0ff (patch) | |
tree | eed21d01ea548aec8278a37ccf3a67357c56ed13 /testing/linux-amlogic/0017-drm-bridge-dw-hdmi-add-support-for-YUV420-output.patch | |
parent | 27ddcaeab2051aaf617a81eeddfa34fb6557e64a (diff) | |
download | aports-468ce5d3db5bea1bfc4d0b21ce0460bbc508c0ff.tar.bz2 aports-468ce5d3db5bea1bfc4d0b21ce0460bbc508c0ff.tar.xz |
testing/linux-amlogic: upgrade to 4.19.8
Diffstat (limited to 'testing/linux-amlogic/0017-drm-bridge-dw-hdmi-add-support-for-YUV420-output.patch')
-rw-r--r-- | testing/linux-amlogic/0017-drm-bridge-dw-hdmi-add-support-for-YUV420-output.patch | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/testing/linux-amlogic/0017-drm-bridge-dw-hdmi-add-support-for-YUV420-output.patch b/testing/linux-amlogic/0017-drm-bridge-dw-hdmi-add-support-for-YUV420-output.patch new file mode 100644 index 0000000000..9c36ea2b48 --- /dev/null +++ b/testing/linux-amlogic/0017-drm-bridge-dw-hdmi-add-support-for-YUV420-output.patch @@ -0,0 +1,198 @@ +From 3e7f3ec3de8753faefdeb02ed6d00cc580e6ad52 Mon Sep 17 00:00:00 2001 +From: Neil Armstrong <narmstrong@baylibre.com> +Date: Wed, 14 Nov 2018 17:19:36 +0100 +Subject: [PATCH] drm/bridge: dw-hdmi: add support for YUV420 output + +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. + +This patch is based on work from Zheng Yang <zhengyang@rock-chips.com> in +the Rockchip Linux 4.4 BSP at [1] + +[1] https://github.com/rockchip-linux/kernel/tree/release-4.4 + +Cc: Zheng Yang <zhengyang@rock-chips.com> +Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> + +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 63 ++++++++++++++++++++++++------- + 1 file changed, 50 insertions(+), 13 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 2a30d83..c3e4ed1 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -94,6 +94,7 @@ struct hdmi_vmode { + unsigned int mpixelclock; + unsigned int mpixelrepetitioninput; + unsigned int mpixelrepetitionoutput; ++ unsigned int mtmdsclock; + }; + + struct hdmi_data_info { +@@ -549,7 +550,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); + } +@@ -558,7 +559,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); + } +@@ -659,6 +660,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) { +@@ -888,7 +903,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: +@@ -1029,7 +1045,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) { +@@ -1370,6 +1386,9 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) + struct hdmi_avi_infoframe frame; + u8 val; + ++ if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) ++ is_hdmi2_sink = true; ++ + /* Initialise info frame from DRM mode */ + drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, is_hdmi2_sink); + +@@ -1377,6 +1396,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; + +@@ -1534,15 +1555,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 > 340000000 || ++ vmode->mtmdsclock > 340000000 || + hdmi_info->scdc.scrambling.low_rates ? + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE : + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE); +@@ -1576,6 +1600,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; +@@ -1594,7 +1634,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, + + /* Scrambling Control */ + if (hdmi_info->scdc.supported) { +- if (vmode->mpixelclock > 340000000 || ++ if (vmode->mtmdsclock > 340000000 || + hdmi_info->scdc.scrambling.low_rates) { + drm_scdc_readb(&hdmi->i2c->adap, SCDC_SINK_VERSION, + &bytes); +@@ -1613,15 +1653,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); + +@@ -1629,7 +1668,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); + +@@ -1637,7 +1675,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); + |