armbian_build/patch/kernel/meson64-current/1-0003-drm-bridge-dw-hdmi-Add-support-for-dynamic-output-fo.patch
Igor Pečovnik 150ac0c2af
Remove K<4, change branches, new features (#1586)
AR-1 - Adding support category for distributions
AR-4 - Remove Allwinner legacy
AR-5 - Drop Udoo family and move Udoo board into newly created imx6 family
AR-9 - Rename sunxi-next to sunxi-legacy
AR-10 - Rename sunxi-dev to sunxi-current
AR-11 - Adding Radxa Rockpi S support
AR-13 - Rename rockchip64-default to rockchip64-legacy
AR-14 - Add rockchip64-current as mainline source
AR-15 - Drop Rockchip 4.19.y NEXT, current become 5.3.y
AR-16 - Rename RK3399 default to legacy
AR-17 - Rename Odroid XU4 next and default to legacy 4.14.y, add DEV 5.4.y
AR-18 - Add Odroid N2 current mainline
AR-19 - Move Odroid C1 to meson family
AR-20 - Rename mvebu64-default to mvebu64-legacy
AR-21 - Rename mvebu-default to mvebu-legacy
AR-22 - Rename mvebu-next to mvebu-current
AR-23 - Drop meson64 default and next, current becomes former DEV 5.3.y
AR-24 - Drop cubox family and move Cubox/Hummingboard boards under imx6
AR-26 - Adjust motd
AR-27 - Enabling distribution release status
AR-28 - Added new GCC compilers
AR-29 - Implementing Ubuntu Eoan
AR-30 - Add desktop packages per board or family
AR-31 - Remove (Ubuntu/Debian) distribution name from image filename
AR-32 - Move arch configs from configuration.sh to separate arm64 and armhf config files
AR-33 - Revision numbers for beta builds changed to day_in_the_year
AR-34 - Patches support linked patches
AR-35 - Break meson64 family into gxbb and gxl
AR-36 - Add Nanopineo2 Black
AR-38 - Upgrade option from old branches to new one via armbian-config
AR-41 - Show full timezone info
AR-43 - Merge Odroid N2 to meson64
AR-44 - Enable FORCE_BOOTSCRIPT_UPDATE for all builds
2019-11-19 23:25:39 +01:00

210 lines
6.8 KiB
Diff

From e42e927075a310f92aa5b2d7861c5ddde84a704a Mon Sep 17 00:00:00 2001
From: Neil Armstrong <narmstrong@baylibre.com>
Date: Mon, 20 May 2019 15:37:51 +0200
Subject: [PATCH 3/5] drm/bridge: dw-hdmi: Add support for dynamic output
format setup
In order to support the HDMI2.0 YUV420, YUV422 and the 10bit, 12bit and
16bits outpu use cases, add support for the recently introduced bridge
callback format_set().
This callback will setup the new input format and encoding from encoder,
then these information will be used instead of the default ones
in the dw_hdmi_setup() function.
To determine the output bus format, has been added :
- support for the connector display_info bus_formats, where a fixed
output bus format can be enforced by the encoder
- support for synami output bus format depending on the input format,
especially the YUV420 input bus format, enforcing YUV420 as output
with the correct bit depth
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 121 ++++++++++++++++++++--
1 file changed, 112 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 8c273270d7ea..eb02191d9f88 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -100,6 +100,8 @@ struct hdmi_vmode {
};
struct hdmi_data_info {
+ unsigned int bridge_in_bus_format;
+ unsigned int bridge_in_encoding;
unsigned int enc_in_bus_format;
unsigned int enc_out_bus_format;
unsigned int enc_in_encoding;
@@ -1909,8 +1911,51 @@ static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi)
HDMI_IH_MUTE_FC_STAT2);
}
+/*
+ * The DW-HDMI CSC can only interpolate and decimate from 4:2:2 to 4:4:4/RGB
+ * and from 4:4:4/RGB to 4:2:2.
+ * Default to RGB output except if 4:2:0 as input, which CSC cannot convert.
+ */
+static unsigned long dw_hdmi_determine_output_bus_format(struct dw_hdmi *hdmi)
+{
+ unsigned int depth = hdmi_bus_fmt_color_depth(
+ hdmi->hdmi_data.enc_in_bus_format);
+ bool is_420 = hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_in_bus_format);
+ unsigned long fmt = MEDIA_BUS_FMT_RGB888_1X24;
+
+ switch (depth) {
+ case 8:
+ if (is_420)
+ fmt = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
+ else
+ fmt = MEDIA_BUS_FMT_RGB888_1X24;
+ break;
+ case 10:
+ if (is_420)
+ fmt = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
+ else
+ fmt = MEDIA_BUS_FMT_RGB101010_1X30;
+ break;
+ case 12:
+ if (is_420)
+ fmt = MEDIA_BUS_FMT_UYYVYY12_0_5X36;
+ else
+ fmt = MEDIA_BUS_FMT_RGB121212_1X36;
+ break;
+ case 16:
+ if (is_420)
+ fmt = MEDIA_BUS_FMT_UYYVYY16_0_5X48;
+ else
+ fmt = MEDIA_BUS_FMT_RGB161616_1X48;
+ break;
+ }
+
+ return fmt;
+}
+
static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
{
+ struct drm_display_info *display = &hdmi->connector.display_info;
int ret;
hdmi_disable_overflow_interrupts(hdmi);
@@ -1924,9 +1969,9 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
}
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->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;
@@ -1934,22 +1979,29 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
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->hdmi_data.bridge_in_bus_format)
+ hdmi->hdmi_data.enc_in_bus_format =
+ hdmi->hdmi_data.bridge_in_bus_format;
+ 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->hdmi_data.bridge_in_encoding)
+ hdmi->hdmi_data.enc_in_encoding =
+ hdmi->hdmi_data.bridge_in_encoding;
+ 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 (display->num_bus_formats)
+ hdmi->hdmi_data.enc_out_bus_format = display->bus_formats[0];
+ else
+ hdmi->hdmi_data.enc_out_bus_format =
+ dw_hdmi_determine_output_bus_format(hdmi);
hdmi->hdmi_data.pix_repet_factor = 0;
hdmi->hdmi_data.hdcp_enable = 0;
@@ -2211,6 +2263,56 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
return mode_status;
}
+static bool dw_hdmi_drm_bridge_format_set(struct drm_bridge *bridge,
+ const u32 input_bus_format,
+ const u32 input_encoding)
+{
+ struct dw_hdmi *hdmi = bridge->driver_private;
+
+ /* Filter supported input bus formats */
+ switch (input_bus_format) {
+ case MEDIA_BUS_FMT_RGB888_1X24:
+ case MEDIA_BUS_FMT_RGB101010_1X30:
+ case MEDIA_BUS_FMT_RGB121212_1X36:
+ case MEDIA_BUS_FMT_RGB161616_1X48:
+ case MEDIA_BUS_FMT_YUV8_1X24:
+ case MEDIA_BUS_FMT_YUV10_1X30:
+ case MEDIA_BUS_FMT_YUV12_1X36:
+ case MEDIA_BUS_FMT_YUV16_1X48:
+ case MEDIA_BUS_FMT_UYVY8_1X16:
+ case MEDIA_BUS_FMT_UYVY10_1X20:
+ case MEDIA_BUS_FMT_UYVY12_1X24:
+ 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:
+ break;
+ default:
+ dev_dbg(hdmi->dev, "Unsupported Input bus format %x\n",
+ input_bus_format);
+ return false;
+ }
+
+ /* Filter supported input bus encoding */
+ switch (input_encoding) {
+ case V4L2_YCBCR_ENC_DEFAULT:
+ case V4L2_YCBCR_ENC_601:
+ case V4L2_YCBCR_ENC_709:
+ case V4L2_YCBCR_ENC_XV601:
+ case V4L2_YCBCR_ENC_XV709:
+ break;
+ default:
+ dev_dbg(hdmi->dev, "Unsupported Input encoding %x\n",
+ input_bus_format);
+ return false;
+ }
+
+ hdmi->hdmi_data.bridge_in_bus_format = input_bus_format;
+ hdmi->hdmi_data.bridge_in_encoding = input_encoding;
+
+ return true;
+}
+
static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *orig_mode,
const struct drm_display_mode *mode)
@@ -2253,6 +2355,7 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
.disable = dw_hdmi_bridge_disable,
.mode_set = dw_hdmi_bridge_mode_set,
.mode_valid = dw_hdmi_bridge_mode_valid,
+ .format_set = dw_hdmi_drm_bridge_format_set,
};
static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi)
--
2.20.1