diff mbox

[v4,4/6] drm: bridge: dw-hdmi: Switch to V4L bus format and encodings

Message ID 1490109161-20529-5-git-send-email-narmstrong@baylibre.com (mailing list archive)
State New, archived
Headers show

Commit Message

Neil Armstrong March 21, 2017, 3:12 p.m. UTC
Some display pipelines can only provide non-RBG input pixels to the HDMI TX
Controller, this patch takes the pixel format from the plat_data if provided.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 326 +++++++++++++++++++++---------
 include/drm/bridge/dw_hdmi.h              |  63 ++++++
 2 files changed, 294 insertions(+), 95 deletions(-)

Comments

Jose Abreu March 22, 2017, 4:08 p.m. UTC | #1
Hi Neil,


On 21-03-2017 15:12, Neil Armstrong wrote:
> Some display pipelines can only provide non-RBG input pixels to the HDMI TX
> Controller, this patch takes the pixel format from the plat_data if provided.
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

Looks fine, I'm assuming you test this on your platform which has
non RGB in input and the CSC worked correctly, right?

Reviewed-by: Jose Abreu <joabreu@synopsys.com>

Best regards,
Jose Miguel Abreu

> ---
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 326 +++++++++++++++++++++---------
>  include/drm/bridge/dw_hdmi.h              |  63 ++++++
>  2 files changed, 294 insertions(+), 95 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index f82750a..fcb0a27 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -30,18 +30,15 @@
>  #include <drm/drm_encoder_slave.h>
>  #include <drm/bridge/dw_hdmi.h>
>  
> +#include <uapi/linux/media-bus-format.h>
> +#include <uapi/linux/videodev2.h>
> +
>  #include "dw-hdmi.h"
>  #include "dw-hdmi-audio.h"
>  
>  #define DDC_SEGMENT_ADDR	0x30
>  #define HDMI_EDID_LEN		512
>  
> -#define RGB			0
> -#define YCBCR444		1
> -#define YCBCR422_16BITS		2
> -#define YCBCR422_8BITS		3
> -#define XVYCC444		4
> -
>  enum hdmi_datamap {
>  	RGB444_8B = 0x01,
>  	RGB444_10B = 0x03,
> @@ -95,10 +92,10 @@ struct hdmi_vmode {
>  };
>  
>  struct hdmi_data_info {
> -	unsigned int enc_in_format;
> -	unsigned int enc_out_format;
> -	unsigned int enc_color_depth;
> -	unsigned int colorimetry;
> +	unsigned int enc_in_bus_format;
> +	unsigned int enc_out_bus_format;
> +	unsigned int enc_in_encoding;
> +	unsigned int enc_out_encoding;
>  	unsigned int pix_repet_factor;
>  	unsigned int hdcp_enable;
>  	struct hdmi_vmode video_mode;
> @@ -567,6 +564,92 @@ void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
>  }
>  EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
>  
> +static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
> +{
> +	switch (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:
> +		return true;
> +
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
> +{
> +	switch (bus_format) {
> +	case MEDIA_BUS_FMT_YUV8_1X24:
> +	case MEDIA_BUS_FMT_YUV10_1X30:
> +	case MEDIA_BUS_FMT_YUV12_1X36:
> +	case MEDIA_BUS_FMT_YUV16_1X48:
> +		return true;
> +
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
> +{
> +	switch (bus_format) {
> +	case MEDIA_BUS_FMT_UYVY8_1X16:
> +	case MEDIA_BUS_FMT_UYVY10_1X20:
> +	case MEDIA_BUS_FMT_UYVY12_1X24:
> +		return true;
> +
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
> +{
> +	switch (bus_format) {
> +	case MEDIA_BUS_FMT_UYYVYY8_1X24:
> +	case MEDIA_BUS_FMT_UYYVYY10_1X30:
> +	case MEDIA_BUS_FMT_UYYVYY12_1X36:
> +	case MEDIA_BUS_FMT_UYYVYY16_1X48:
> +		return true;
> +
> +	default:
> +		return false;
> +	}
> +}
> +
> +static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
> +{
> +	switch (bus_format) {
> +	case MEDIA_BUS_FMT_RGB888_1X24:
> +	case MEDIA_BUS_FMT_YUV8_1X24:
> +	case MEDIA_BUS_FMT_UYVY8_1X16:
> +	case MEDIA_BUS_FMT_UYYVYY8_1X24:
> +		return 8;
> +
> +	case MEDIA_BUS_FMT_RGB101010_1X30:
> +	case MEDIA_BUS_FMT_YUV10_1X30:
> +	case MEDIA_BUS_FMT_UYVY10_1X20:
> +	case MEDIA_BUS_FMT_UYYVYY10_1X30:
> +		return 10;
> +
> +	case MEDIA_BUS_FMT_RGB121212_1X36:
> +	case MEDIA_BUS_FMT_YUV12_1X36:
> +	case MEDIA_BUS_FMT_UYVY12_1X24:
> +	case MEDIA_BUS_FMT_UYYVYY12_1X36:
> +		return 12;
> +
> +	case MEDIA_BUS_FMT_RGB161616_1X48:
> +	case MEDIA_BUS_FMT_YUV16_1X48:
> +	case MEDIA_BUS_FMT_UYYVYY16_1X48:
> +		return 16;
> +
> +	default:
> +		return 0;
> +	}
> +}
> +
>  /*
>   * this submodule is responsible for the video data synchronization.
>   * for example, for RGB 4:4:4 input, the data map is defined as
> @@ -579,37 +662,49 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
>  	int color_format = 0;
>  	u8 val;
>  
> -	if (hdmi->hdmi_data.enc_in_format == RGB) {
> -		if (hdmi->hdmi_data.enc_color_depth == 8)
> -			color_format = 0x01;
> -		else if (hdmi->hdmi_data.enc_color_depth == 10)
> -			color_format = 0x03;
> -		else if (hdmi->hdmi_data.enc_color_depth == 12)
> -			color_format = 0x05;
> -		else if (hdmi->hdmi_data.enc_color_depth == 16)
> -			color_format = 0x07;
> -		else
> -			return;
> -	} else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
> -		if (hdmi->hdmi_data.enc_color_depth == 8)
> -			color_format = 0x09;
> -		else if (hdmi->hdmi_data.enc_color_depth == 10)
> -			color_format = 0x0B;
> -		else if (hdmi->hdmi_data.enc_color_depth == 12)
> -			color_format = 0x0D;
> -		else if (hdmi->hdmi_data.enc_color_depth == 16)
> -			color_format = 0x0F;
> -		else
> -			return;
> -	} else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
> -		if (hdmi->hdmi_data.enc_color_depth == 8)
> -			color_format = 0x16;
> -		else if (hdmi->hdmi_data.enc_color_depth == 10)
> -			color_format = 0x14;
> -		else if (hdmi->hdmi_data.enc_color_depth == 12)
> -			color_format = 0x12;
> -		else
> -			return;
> +	switch (hdmi->hdmi_data.enc_in_bus_format) {
> +	case MEDIA_BUS_FMT_RGB888_1X24:
> +		color_format = 0x01;
> +		break;
> +	case MEDIA_BUS_FMT_RGB101010_1X30:
> +		color_format = 0x03;
> +		break;
> +	case MEDIA_BUS_FMT_RGB121212_1X36:
> +		color_format = 0x05;
> +		break;
> +	case MEDIA_BUS_FMT_RGB161616_1X48:
> +		color_format = 0x07;
> +		break;
> +
> +	case MEDIA_BUS_FMT_YUV8_1X24:
> +	case MEDIA_BUS_FMT_UYYVYY8_1X24:
> +		color_format = 0x09;
> +		break;
> +	case MEDIA_BUS_FMT_YUV10_1X30:
> +	case MEDIA_BUS_FMT_UYYVYY10_1X30:
> +		color_format = 0x0B;
> +		break;
> +	case MEDIA_BUS_FMT_YUV12_1X36:
> +	case MEDIA_BUS_FMT_UYYVYY12_1X36:
> +		color_format = 0x0D;
> +		break;
> +	case MEDIA_BUS_FMT_YUV16_1X48:
> +	case MEDIA_BUS_FMT_UYYVYY16_1X48:
> +		color_format = 0x0F;
> +		break;
> +
> +	case MEDIA_BUS_FMT_UYVY8_1X16:
> +		color_format = 0x16;
> +		break;
> +	case MEDIA_BUS_FMT_UYVY10_1X20:
> +		color_format = 0x14;
> +		break;
> +	case MEDIA_BUS_FMT_UYVY12_1X24:
> +		color_format = 0x12;
> +		break;
> +
> +	default:
> +		return;
>  	}
>  
>  	val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
> @@ -632,26 +727,30 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
>  
>  static int is_color_space_conversion(struct dw_hdmi *hdmi)
>  {
> -	return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
> +	return hdmi->hdmi_data.enc_in_bus_format != hdmi->hdmi_data.enc_out_bus_format;
>  }
>  
>  static int is_color_space_decimation(struct dw_hdmi *hdmi)
>  {
> -	if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
> +	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
>  		return 0;
> -	if (hdmi->hdmi_data.enc_in_format == RGB ||
> -	    hdmi->hdmi_data.enc_in_format == YCBCR444)
> +
> +	if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) ||
> +	    hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format))
>  		return 1;
> +
>  	return 0;
>  }
>  
>  static int is_color_space_interpolation(struct dw_hdmi *hdmi)
>  {
> -	if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
> +	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
>  		return 0;
> -	if (hdmi->hdmi_data.enc_out_format == RGB ||
> -	    hdmi->hdmi_data.enc_out_format == YCBCR444)
> +
> +	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))
>  		return 1;
> +
>  	return 0;
>  }
>  
> @@ -662,15 +761,16 @@ static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
>  	u32 csc_scale = 1;
>  
>  	if (is_color_space_conversion(hdmi)) {
> -		if (hdmi->hdmi_data.enc_out_format == RGB) {
> -			if (hdmi->hdmi_data.colorimetry ==
> -					HDMI_COLORIMETRY_ITU_601)
> +		if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
> +			if (hdmi->hdmi_data.enc_out_encoding ==
> +						V4L2_YCBCR_ENC_601)
>  				csc_coeff = &csc_coeff_rgb_out_eitu601;
>  			else
>  				csc_coeff = &csc_coeff_rgb_out_eitu709;
> -		} else if (hdmi->hdmi_data.enc_in_format == RGB) {
> -			if (hdmi->hdmi_data.colorimetry ==
> -					HDMI_COLORIMETRY_ITU_601)
> +		} else if (hdmi_bus_fmt_is_rgb(
> +					hdmi->hdmi_data.enc_in_bus_format)) {
> +			if (hdmi->hdmi_data.enc_out_encoding ==
> +						V4L2_YCBCR_ENC_601)
>  				csc_coeff = &csc_coeff_rgb_in_eitu601;
>  			else
>  				csc_coeff = &csc_coeff_rgb_in_eitu709;
> @@ -708,16 +808,23 @@ static void hdmi_video_csc(struct dw_hdmi *hdmi)
>  	else if (is_color_space_decimation(hdmi))
>  		decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
>  
> -	if (hdmi->hdmi_data.enc_color_depth == 8)
> +	switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
> +	case 8:
>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
> -	else if (hdmi->hdmi_data.enc_color_depth == 10)
> +		break;
> +	case 10:
>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
> -	else if (hdmi->hdmi_data.enc_color_depth == 12)
> +		break;
> +	case 12:
>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
> -	else if (hdmi->hdmi_data.enc_color_depth == 16)
> +		break;
> +	case 16:
>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
> -	else
> +		break;
> +
> +	default:
>  		return;
> +	}
>  
>  	/* Configure the CSC registers */
>  	hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
> @@ -740,32 +847,43 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
>  	struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
>  	u8 val, vp_conf;
>  
> -	if (hdmi_data->enc_out_format == RGB ||
> -	    hdmi_data->enc_out_format == YCBCR444) {
> -		if (!hdmi_data->enc_color_depth) {
> -			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
> -		} else if (hdmi_data->enc_color_depth == 8) {
> +	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)) {
> +		switch (hdmi_bus_fmt_color_depth(
> +					hdmi->hdmi_data.enc_out_bus_format)) {
> +		case 8:
>  			color_depth = 4;
>  			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
> -		} else if (hdmi_data->enc_color_depth == 10) {
> +			break;
> +		case 10:
>  			color_depth = 5;
> -		} else if (hdmi_data->enc_color_depth == 12) {
> +			break;
> +		case 12:
>  			color_depth = 6;
> -		} else if (hdmi_data->enc_color_depth == 16) {
> +			break;
> +		case 16:
>  			color_depth = 7;
> -		} else {
> -			return;
> +			break;
> +		default:
> +			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
>  		}
> -	} else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
> -		if (!hdmi_data->enc_color_depth ||
> -		    hdmi_data->enc_color_depth == 8)
> +	} else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) {
> +		switch (hdmi_bus_fmt_color_depth(
> +					hdmi->hdmi_data.enc_out_bus_format)) {
> +		case 0:
> +		case 8:
>  			remap_size = HDMI_VP_REMAP_YCC422_16bit;
> -		else if (hdmi_data->enc_color_depth == 10)
> +			break;
> +		case 10:
>  			remap_size = HDMI_VP_REMAP_YCC422_20bit;
> -		else if (hdmi_data->enc_color_depth == 12)
> +			break;
> +		case 12:
>  			remap_size = HDMI_VP_REMAP_YCC422_24bit;
> -		else
> +			break;
> +
> +		default:
>  			return;
> +		}
>  		output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
>  	} else {
>  		return;
> @@ -1148,28 +1266,35 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>  	/* Initialise info frame from DRM mode */
>  	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>  
> -	if (hdmi->hdmi_data.enc_out_format == YCBCR444)
> +	if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
>  		frame.colorspace = HDMI_COLORSPACE_YUV444;
> -	else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
> +	else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
>  		frame.colorspace = HDMI_COLORSPACE_YUV422;
>  	else
>  		frame.colorspace = HDMI_COLORSPACE_RGB;
>  
>  	/* Set up colorimetry */
> -	if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
> -		frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
> -		if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
> -			frame.extended_colorimetry =
> +	switch (hdmi->hdmi_data.enc_out_encoding) {
> +	case V4L2_YCBCR_ENC_601:
> +		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601)
> +			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
> +		else
> +			frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
> +		frame.extended_colorimetry =
>  				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
> -		else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
> -			frame.extended_colorimetry =
> +	case V4L2_YCBCR_ENC_709:
> +		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709)
> +			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
> +		else
> +			frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
> +		frame.extended_colorimetry =
>  				HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
> -	} else if (hdmi->hdmi_data.enc_out_format != RGB) {
> -		frame.colorimetry = hdmi->hdmi_data.colorimetry;
> -		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
> -	} else { /* Carries no data */
> -		frame.colorimetry = HDMI_COLORIMETRY_NONE;
> -		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
> +		break;
> +	default: /* Carries no data */
> +		frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
> +		frame.extended_colorimetry =
> +				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
> +		break;
>  	}
>  
>  	frame.scan_mode = HDMI_SCAN_MODE_NONE;
> @@ -1498,19 +1623,30 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>  	    (hdmi->vic == 21) || (hdmi->vic == 22) ||
>  	    (hdmi->vic == 2) || (hdmi->vic == 3) ||
>  	    (hdmi->vic == 17) || (hdmi->vic == 18))
> -		hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
> +		hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_601;
>  	else
> -		hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
> +		hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_709;
>  
>  	hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
>  	hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
>  
> -	/* TODO: Get input format from IPU (via FB driver interface) */
> -	hdmi->hdmi_data.enc_in_format = RGB;
> +	/* TOFIX: Get input format from plat data or fallback to RGB888 */
> +	if (hdmi->plat_data->input_bus_format >= 0)
> +		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 >= 0)
> +		hdmi->hdmi_data.enc_in_encoding =
> +			hdmi->plat_data->input_bus_encoding;
> +	else
> +		hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT;
>  
> -	hdmi->hdmi_data.enc_out_format = RGB;
> +	/* TOFIX: Default to RGB888 output format */
> +	hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
>  
> -	hdmi->hdmi_data.enc_color_depth = 8;
>  	hdmi->hdmi_data.pix_repet_factor = 0;
>  	hdmi->hdmi_data.hdcp_enable = 0;
>  	hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
> diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
> index bcceee8..0da74fb 100644
> --- a/include/drm/bridge/dw_hdmi.h
> +++ b/include/drm/bridge/dw_hdmi.h
> @@ -14,6 +14,67 @@
>  
>  struct dw_hdmi;
>  
> +/**
> + * DOC: Supported input formats and encodings
> + *
> + * Depending on the Hardware configuration of the Controller IP, it supports
> + * a subset of the following input formats and encodings on it's internal
> + * 48bit bus.
> + *
> + * +----------------------+---------------------------------+------------------------------+
> + * + Format Name          + Format Code                     + Encodings                    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + RGB 4:4:4 8bit       + ``MEDIA_BUS_FMT_RGB888_1X24``   + ``V4L2_YCBCR_ENC_DEFAULT``   +
> + * +----------------------+---------------------------------+------------------------------+
> + * + RGB 4:4:4 10bits     + ``MEDIA_BUS_FMT_RGB101010_1X30``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
> + * +----------------------+---------------------------------+------------------------------+
> + * + RGB 4:4:4 12bits     + ``MEDIA_BUS_FMT_RGB121212_1X36``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
> + * +----------------------+---------------------------------+------------------------------+
> + * + RGB 4:4:4 16bits     + ``MEDIA_BUS_FMT_RGB161616_1X48``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:4:4 8bit     + ``MEDIA_BUS_FMT_YUV8_1X24``     + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:4:4 10bits   + ``MEDIA_BUS_FMT_YUV10_1X30``    + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:4:4 12bits   + ``MEDIA_BUS_FMT_YUV12_1X36``    + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:4:4 16bits   + ``MEDIA_BUS_FMT_YUV16_1X48``    + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:2 8bit     + ``MEDIA_BUS_FMT_UYVY8_1X16``    + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:2 10bits   + ``MEDIA_BUS_FMT_UYVY10_1X20``   + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:2 12bits   + ``MEDIA_BUS_FMT_UYVY12_1X24``   + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:0 8bit     + ``MEDIA_BUS_FMT_UYYVYY8_1X24``  + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:0 10bits   + ``MEDIA_BUS_FMT_UYYVYY10_1X30`` + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:0 12bits   + ``MEDIA_BUS_FMT_UYYVYY12_1X36`` + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:0 16bits   + ``MEDIA_BUS_FMT_UYYVYY16_1X48`` + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + */
> +
>  enum {
>  	DW_HDMI_RES_8,
>  	DW_HDMI_RES_10,
> @@ -62,6 +123,8 @@ struct dw_hdmi_plat_data {
>  	struct regmap *regm;
>  	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
>  					   struct drm_display_mode *mode);
> +	unsigned long input_bus_format;
> +	unsigned long input_bus_encoding;
>  
>  	/* Vendor PHY support */
>  	const struct dw_hdmi_phy_ops *phy_ops;
Neil Armstrong March 22, 2017, 4:09 p.m. UTC | #2
On 03/22/2017 05:08 PM, Jose Abreu wrote:
> Hi Neil,
> 
> 
> On 21-03-2017 15:12, Neil Armstrong wrote:
>> Some display pipelines can only provide non-RBG input pixels to the HDMI TX
>> Controller, this patch takes the pixel format from the plat_data if provided.
>>
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> 
> Looks fine, I'm assuming you test this on your platform which has
> non RGB in input and the CSC worked correctly, right?

Exact.

Thanks,
Neil

> 
> Reviewed-by: Jose Abreu <joabreu@synopsys.com>
> 
> Best regards,
> Jose Miguel Abreu
> 
>> ---
>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 326 +++++++++++++++++++++---------
>>  include/drm/bridge/dw_hdmi.h              |  63 ++++++
>>  2 files changed, 294 insertions(+), 95 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> index f82750a..fcb0a27 100644
>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> @@ -30,18 +30,15 @@
>>  #include <drm/drm_encoder_slave.h>
>>  #include <drm/bridge/dw_hdmi.h>
>>  
>> +#include <uapi/linux/media-bus-format.h>
>> +#include <uapi/linux/videodev2.h>
>> +
>>  #include "dw-hdmi.h"
>>  #include "dw-hdmi-audio.h"
>>  
>>  #define DDC_SEGMENT_ADDR	0x30
>>  #define HDMI_EDID_LEN		512
>>  
>> -#define RGB			0
>> -#define YCBCR444		1
>> -#define YCBCR422_16BITS		2
>> -#define YCBCR422_8BITS		3
>> -#define XVYCC444		4
>> -
>>  enum hdmi_datamap {
>>  	RGB444_8B = 0x01,
>>  	RGB444_10B = 0x03,
>> @@ -95,10 +92,10 @@ struct hdmi_vmode {
>>  };
>>  
>>  struct hdmi_data_info {
>> -	unsigned int enc_in_format;
>> -	unsigned int enc_out_format;
>> -	unsigned int enc_color_depth;
>> -	unsigned int colorimetry;
>> +	unsigned int enc_in_bus_format;
>> +	unsigned int enc_out_bus_format;
>> +	unsigned int enc_in_encoding;
>> +	unsigned int enc_out_encoding;
>>  	unsigned int pix_repet_factor;
>>  	unsigned int hdcp_enable;
>>  	struct hdmi_vmode video_mode;
>> @@ -567,6 +564,92 @@ void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
>>  }
>>  EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
>>  
>> +static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
>> +{
>> +	switch (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:
>> +		return true;
>> +
>> +	default:
>> +		return false;
>> +	}
>> +}
>> +
>> +static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
>> +{
>> +	switch (bus_format) {
>> +	case MEDIA_BUS_FMT_YUV8_1X24:
>> +	case MEDIA_BUS_FMT_YUV10_1X30:
>> +	case MEDIA_BUS_FMT_YUV12_1X36:
>> +	case MEDIA_BUS_FMT_YUV16_1X48:
>> +		return true;
>> +
>> +	default:
>> +		return false;
>> +	}
>> +}
>> +
>> +static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
>> +{
>> +	switch (bus_format) {
>> +	case MEDIA_BUS_FMT_UYVY8_1X16:
>> +	case MEDIA_BUS_FMT_UYVY10_1X20:
>> +	case MEDIA_BUS_FMT_UYVY12_1X24:
>> +		return true;
>> +
>> +	default:
>> +		return false;
>> +	}
>> +}
>> +
>> +static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
>> +{
>> +	switch (bus_format) {
>> +	case MEDIA_BUS_FMT_UYYVYY8_1X24:
>> +	case MEDIA_BUS_FMT_UYYVYY10_1X30:
>> +	case MEDIA_BUS_FMT_UYYVYY12_1X36:
>> +	case MEDIA_BUS_FMT_UYYVYY16_1X48:
>> +		return true;
>> +
>> +	default:
>> +		return false;
>> +	}
>> +}
>> +
>> +static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
>> +{
>> +	switch (bus_format) {
>> +	case MEDIA_BUS_FMT_RGB888_1X24:
>> +	case MEDIA_BUS_FMT_YUV8_1X24:
>> +	case MEDIA_BUS_FMT_UYVY8_1X16:
>> +	case MEDIA_BUS_FMT_UYYVYY8_1X24:
>> +		return 8;
>> +
>> +	case MEDIA_BUS_FMT_RGB101010_1X30:
>> +	case MEDIA_BUS_FMT_YUV10_1X30:
>> +	case MEDIA_BUS_FMT_UYVY10_1X20:
>> +	case MEDIA_BUS_FMT_UYYVYY10_1X30:
>> +		return 10;
>> +
>> +	case MEDIA_BUS_FMT_RGB121212_1X36:
>> +	case MEDIA_BUS_FMT_YUV12_1X36:
>> +	case MEDIA_BUS_FMT_UYVY12_1X24:
>> +	case MEDIA_BUS_FMT_UYYVYY12_1X36:
>> +		return 12;
>> +
>> +	case MEDIA_BUS_FMT_RGB161616_1X48:
>> +	case MEDIA_BUS_FMT_YUV16_1X48:
>> +	case MEDIA_BUS_FMT_UYYVYY16_1X48:
>> +		return 16;
>> +
>> +	default:
>> +		return 0;
>> +	}
>> +}
>> +
>>  /*
>>   * this submodule is responsible for the video data synchronization.
>>   * for example, for RGB 4:4:4 input, the data map is defined as
>> @@ -579,37 +662,49 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
>>  	int color_format = 0;
>>  	u8 val;
>>  
>> -	if (hdmi->hdmi_data.enc_in_format == RGB) {
>> -		if (hdmi->hdmi_data.enc_color_depth == 8)
>> -			color_format = 0x01;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 10)
>> -			color_format = 0x03;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 12)
>> -			color_format = 0x05;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 16)
>> -			color_format = 0x07;
>> -		else
>> -			return;
>> -	} else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
>> -		if (hdmi->hdmi_data.enc_color_depth == 8)
>> -			color_format = 0x09;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 10)
>> -			color_format = 0x0B;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 12)
>> -			color_format = 0x0D;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 16)
>> -			color_format = 0x0F;
>> -		else
>> -			return;
>> -	} else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
>> -		if (hdmi->hdmi_data.enc_color_depth == 8)
>> -			color_format = 0x16;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 10)
>> -			color_format = 0x14;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 12)
>> -			color_format = 0x12;
>> -		else
>> -			return;
>> +	switch (hdmi->hdmi_data.enc_in_bus_format) {
>> +	case MEDIA_BUS_FMT_RGB888_1X24:
>> +		color_format = 0x01;
>> +		break;
>> +	case MEDIA_BUS_FMT_RGB101010_1X30:
>> +		color_format = 0x03;
>> +		break;
>> +	case MEDIA_BUS_FMT_RGB121212_1X36:
>> +		color_format = 0x05;
>> +		break;
>> +	case MEDIA_BUS_FMT_RGB161616_1X48:
>> +		color_format = 0x07;
>> +		break;
>> +
>> +	case MEDIA_BUS_FMT_YUV8_1X24:
>> +	case MEDIA_BUS_FMT_UYYVYY8_1X24:
>> +		color_format = 0x09;
>> +		break;
>> +	case MEDIA_BUS_FMT_YUV10_1X30:
>> +	case MEDIA_BUS_FMT_UYYVYY10_1X30:
>> +		color_format = 0x0B;
>> +		break;
>> +	case MEDIA_BUS_FMT_YUV12_1X36:
>> +	case MEDIA_BUS_FMT_UYYVYY12_1X36:
>> +		color_format = 0x0D;
>> +		break;
>> +	case MEDIA_BUS_FMT_YUV16_1X48:
>> +	case MEDIA_BUS_FMT_UYYVYY16_1X48:
>> +		color_format = 0x0F;
>> +		break;
>> +
>> +	case MEDIA_BUS_FMT_UYVY8_1X16:
>> +		color_format = 0x16;
>> +		break;
>> +	case MEDIA_BUS_FMT_UYVY10_1X20:
>> +		color_format = 0x14;
>> +		break;
>> +	case MEDIA_BUS_FMT_UYVY12_1X24:
>> +		color_format = 0x12;
>> +		break;
>> +
>> +	default:
>> +		return;
>>  	}
>>  
>>  	val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
>> @@ -632,26 +727,30 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
>>  
>>  static int is_color_space_conversion(struct dw_hdmi *hdmi)
>>  {
>> -	return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
>> +	return hdmi->hdmi_data.enc_in_bus_format != hdmi->hdmi_data.enc_out_bus_format;
>>  }
>>  
>>  static int is_color_space_decimation(struct dw_hdmi *hdmi)
>>  {
>> -	if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
>> +	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
>>  		return 0;
>> -	if (hdmi->hdmi_data.enc_in_format == RGB ||
>> -	    hdmi->hdmi_data.enc_in_format == YCBCR444)
>> +
>> +	if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) ||
>> +	    hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format))
>>  		return 1;
>> +
>>  	return 0;
>>  }
>>  
>>  static int is_color_space_interpolation(struct dw_hdmi *hdmi)
>>  {
>> -	if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
>> +	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
>>  		return 0;
>> -	if (hdmi->hdmi_data.enc_out_format == RGB ||
>> -	    hdmi->hdmi_data.enc_out_format == YCBCR444)
>> +
>> +	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))
>>  		return 1;
>> +
>>  	return 0;
>>  }
>>  
>> @@ -662,15 +761,16 @@ static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
>>  	u32 csc_scale = 1;
>>  
>>  	if (is_color_space_conversion(hdmi)) {
>> -		if (hdmi->hdmi_data.enc_out_format == RGB) {
>> -			if (hdmi->hdmi_data.colorimetry ==
>> -					HDMI_COLORIMETRY_ITU_601)
>> +		if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
>> +			if (hdmi->hdmi_data.enc_out_encoding ==
>> +						V4L2_YCBCR_ENC_601)
>>  				csc_coeff = &csc_coeff_rgb_out_eitu601;
>>  			else
>>  				csc_coeff = &csc_coeff_rgb_out_eitu709;
>> -		} else if (hdmi->hdmi_data.enc_in_format == RGB) {
>> -			if (hdmi->hdmi_data.colorimetry ==
>> -					HDMI_COLORIMETRY_ITU_601)
>> +		} else if (hdmi_bus_fmt_is_rgb(
>> +					hdmi->hdmi_data.enc_in_bus_format)) {
>> +			if (hdmi->hdmi_data.enc_out_encoding ==
>> +						V4L2_YCBCR_ENC_601)
>>  				csc_coeff = &csc_coeff_rgb_in_eitu601;
>>  			else
>>  				csc_coeff = &csc_coeff_rgb_in_eitu709;
>> @@ -708,16 +808,23 @@ static void hdmi_video_csc(struct dw_hdmi *hdmi)
>>  	else if (is_color_space_decimation(hdmi))
>>  		decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
>>  
>> -	if (hdmi->hdmi_data.enc_color_depth == 8)
>> +	switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
>> +	case 8:
>>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
>> -	else if (hdmi->hdmi_data.enc_color_depth == 10)
>> +		break;
>> +	case 10:
>>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
>> -	else if (hdmi->hdmi_data.enc_color_depth == 12)
>> +		break;
>> +	case 12:
>>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
>> -	else if (hdmi->hdmi_data.enc_color_depth == 16)
>> +		break;
>> +	case 16:
>>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
>> -	else
>> +		break;
>> +
>> +	default:
>>  		return;
>> +	}
>>  
>>  	/* Configure the CSC registers */
>>  	hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
>> @@ -740,32 +847,43 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
>>  	struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
>>  	u8 val, vp_conf;
>>  
>> -	if (hdmi_data->enc_out_format == RGB ||
>> -	    hdmi_data->enc_out_format == YCBCR444) {
>> -		if (!hdmi_data->enc_color_depth) {
>> -			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
>> -		} else if (hdmi_data->enc_color_depth == 8) {
>> +	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)) {
>> +		switch (hdmi_bus_fmt_color_depth(
>> +					hdmi->hdmi_data.enc_out_bus_format)) {
>> +		case 8:
>>  			color_depth = 4;
>>  			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
>> -		} else if (hdmi_data->enc_color_depth == 10) {
>> +			break;
>> +		case 10:
>>  			color_depth = 5;
>> -		} else if (hdmi_data->enc_color_depth == 12) {
>> +			break;
>> +		case 12:
>>  			color_depth = 6;
>> -		} else if (hdmi_data->enc_color_depth == 16) {
>> +			break;
>> +		case 16:
>>  			color_depth = 7;
>> -		} else {
>> -			return;
>> +			break;
>> +		default:
>> +			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
>>  		}
>> -	} else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
>> -		if (!hdmi_data->enc_color_depth ||
>> -		    hdmi_data->enc_color_depth == 8)
>> +	} else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) {
>> +		switch (hdmi_bus_fmt_color_depth(
>> +					hdmi->hdmi_data.enc_out_bus_format)) {
>> +		case 0:
>> +		case 8:
>>  			remap_size = HDMI_VP_REMAP_YCC422_16bit;
>> -		else if (hdmi_data->enc_color_depth == 10)
>> +			break;
>> +		case 10:
>>  			remap_size = HDMI_VP_REMAP_YCC422_20bit;
>> -		else if (hdmi_data->enc_color_depth == 12)
>> +			break;
>> +		case 12:
>>  			remap_size = HDMI_VP_REMAP_YCC422_24bit;
>> -		else
>> +			break;
>> +
>> +		default:
>>  			return;
>> +		}
>>  		output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
>>  	} else {
>>  		return;
>> @@ -1148,28 +1266,35 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>>  	/* Initialise info frame from DRM mode */
>>  	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>>  
>> -	if (hdmi->hdmi_data.enc_out_format == YCBCR444)
>> +	if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
>>  		frame.colorspace = HDMI_COLORSPACE_YUV444;
>> -	else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
>> +	else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
>>  		frame.colorspace = HDMI_COLORSPACE_YUV422;
>>  	else
>>  		frame.colorspace = HDMI_COLORSPACE_RGB;
>>  
>>  	/* Set up colorimetry */
>> -	if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
>> -		frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
>> -		if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
>> -			frame.extended_colorimetry =
>> +	switch (hdmi->hdmi_data.enc_out_encoding) {
>> +	case V4L2_YCBCR_ENC_601:
>> +		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601)
>> +			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
>> +		else
>> +			frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
>> +		frame.extended_colorimetry =
>>  				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
>> -		else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
>> -			frame.extended_colorimetry =
>> +	case V4L2_YCBCR_ENC_709:
>> +		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709)
>> +			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
>> +		else
>> +			frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
>> +		frame.extended_colorimetry =
>>  				HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
>> -	} else if (hdmi->hdmi_data.enc_out_format != RGB) {
>> -		frame.colorimetry = hdmi->hdmi_data.colorimetry;
>> -		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
>> -	} else { /* Carries no data */
>> -		frame.colorimetry = HDMI_COLORIMETRY_NONE;
>> -		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
>> +		break;
>> +	default: /* Carries no data */
>> +		frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
>> +		frame.extended_colorimetry =
>> +				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
>> +		break;
>>  	}
>>  
>>  	frame.scan_mode = HDMI_SCAN_MODE_NONE;
>> @@ -1498,19 +1623,30 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>>  	    (hdmi->vic == 21) || (hdmi->vic == 22) ||
>>  	    (hdmi->vic == 2) || (hdmi->vic == 3) ||
>>  	    (hdmi->vic == 17) || (hdmi->vic == 18))
>> -		hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
>> +		hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_601;
>>  	else
>> -		hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
>> +		hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_709;
>>  
>>  	hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
>>  	hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
>>  
>> -	/* TODO: Get input format from IPU (via FB driver interface) */
>> -	hdmi->hdmi_data.enc_in_format = RGB;
>> +	/* TOFIX: Get input format from plat data or fallback to RGB888 */
>> +	if (hdmi->plat_data->input_bus_format >= 0)
>> +		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 >= 0)
>> +		hdmi->hdmi_data.enc_in_encoding =
>> +			hdmi->plat_data->input_bus_encoding;
>> +	else
>> +		hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT;
>>  
>> -	hdmi->hdmi_data.enc_out_format = RGB;
>> +	/* TOFIX: Default to RGB888 output format */
>> +	hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
>>  
>> -	hdmi->hdmi_data.enc_color_depth = 8;
>>  	hdmi->hdmi_data.pix_repet_factor = 0;
>>  	hdmi->hdmi_data.hdcp_enable = 0;
>>  	hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
>> diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
>> index bcceee8..0da74fb 100644
>> --- a/include/drm/bridge/dw_hdmi.h
>> +++ b/include/drm/bridge/dw_hdmi.h
>> @@ -14,6 +14,67 @@
>>  
>>  struct dw_hdmi;
>>  
>> +/**
>> + * DOC: Supported input formats and encodings
>> + *
>> + * Depending on the Hardware configuration of the Controller IP, it supports
>> + * a subset of the following input formats and encodings on it's internal
>> + * 48bit bus.
>> + *
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + Format Name          + Format Code                     + Encodings                    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + RGB 4:4:4 8bit       + ``MEDIA_BUS_FMT_RGB888_1X24``   + ``V4L2_YCBCR_ENC_DEFAULT``   +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + RGB 4:4:4 10bits     + ``MEDIA_BUS_FMT_RGB101010_1X30``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + RGB 4:4:4 12bits     + ``MEDIA_BUS_FMT_RGB121212_1X36``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + RGB 4:4:4 16bits     + ``MEDIA_BUS_FMT_RGB161616_1X48``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:4:4 8bit     + ``MEDIA_BUS_FMT_YUV8_1X24``     + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:4:4 10bits   + ``MEDIA_BUS_FMT_YUV10_1X30``    + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:4:4 12bits   + ``MEDIA_BUS_FMT_YUV12_1X36``    + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:4:4 16bits   + ``MEDIA_BUS_FMT_YUV16_1X48``    + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:2 8bit     + ``MEDIA_BUS_FMT_UYVY8_1X16``    + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:2 10bits   + ``MEDIA_BUS_FMT_UYVY10_1X20``   + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:2 12bits   + ``MEDIA_BUS_FMT_UYVY12_1X24``   + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:0 8bit     + ``MEDIA_BUS_FMT_UYYVYY8_1X24``  + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:0 10bits   + ``MEDIA_BUS_FMT_UYYVYY10_1X30`` + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:0 12bits   + ``MEDIA_BUS_FMT_UYYVYY12_1X36`` + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:0 16bits   + ``MEDIA_BUS_FMT_UYYVYY16_1X48`` + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + */
>> +
>>  enum {
>>  	DW_HDMI_RES_8,
>>  	DW_HDMI_RES_10,
>> @@ -62,6 +123,8 @@ struct dw_hdmi_plat_data {
>>  	struct regmap *regm;
>>  	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
>>  					   struct drm_display_mode *mode);
>> +	unsigned long input_bus_format;
>> +	unsigned long input_bus_encoding;
>>  
>>  	/* Vendor PHY support */
>>  	const struct dw_hdmi_phy_ops *phy_ops;
>
Philipp Zabel March 22, 2017, 4:21 p.m. UTC | #3
On Tue, 2017-03-21 at 16:12 +0100, Neil Armstrong wrote:
> Some display pipelines can only provide non-RBG input pixels to the HDMI TX
> Controller, this patch takes the pixel format from the plat_data if provided.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>

On i.MX6 we could provide RGB/YUV bus formats dynamically. Would it make
sense to negotiate this with the pixel provider instead of fixing it in
platform data?
I imagine that if a YUV image with the correct colorspace is supposed to
be transmitted to a TV that supports that format, it might be useful to
avoid passing through two colorspace converters on the way.

regards
Philipp

> ---
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 326 +++++++++++++++++++++---------
>  include/drm/bridge/dw_hdmi.h              |  63 ++++++
>  2 files changed, 294 insertions(+), 95 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index f82750a..fcb0a27 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -30,18 +30,15 @@
>  #include <drm/drm_encoder_slave.h>
>  #include <drm/bridge/dw_hdmi.h>
>  
> +#include <uapi/linux/media-bus-format.h>
> +#include <uapi/linux/videodev2.h>
> +
>  #include "dw-hdmi.h"
>  #include "dw-hdmi-audio.h"
>  
>  #define DDC_SEGMENT_ADDR	0x30
>  #define HDMI_EDID_LEN		512
>  
> -#define RGB			0
> -#define YCBCR444		1
> -#define YCBCR422_16BITS		2
> -#define YCBCR422_8BITS		3
> -#define XVYCC444		4
> -
>  enum hdmi_datamap {
>  	RGB444_8B = 0x01,
>  	RGB444_10B = 0x03,
> @@ -95,10 +92,10 @@ struct hdmi_vmode {
>  };
>  
>  struct hdmi_data_info {
> -	unsigned int enc_in_format;
> -	unsigned int enc_out_format;
> -	unsigned int enc_color_depth;
> -	unsigned int colorimetry;
> +	unsigned int enc_in_bus_format;
> +	unsigned int enc_out_bus_format;
> +	unsigned int enc_in_encoding;
> +	unsigned int enc_out_encoding;
>  	unsigned int pix_repet_factor;
>  	unsigned int hdcp_enable;
>  	struct hdmi_vmode video_mode;
> @@ -567,6 +564,92 @@ void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
>  }
>  EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
>  
> +static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
> +{
> +	switch (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:
> +		return true;
> +
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
> +{
> +	switch (bus_format) {
> +	case MEDIA_BUS_FMT_YUV8_1X24:
> +	case MEDIA_BUS_FMT_YUV10_1X30:
> +	case MEDIA_BUS_FMT_YUV12_1X36:
> +	case MEDIA_BUS_FMT_YUV16_1X48:
> +		return true;
> +
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
> +{
> +	switch (bus_format) {
> +	case MEDIA_BUS_FMT_UYVY8_1X16:
> +	case MEDIA_BUS_FMT_UYVY10_1X20:
> +	case MEDIA_BUS_FMT_UYVY12_1X24:
> +		return true;
> +
> +	default:
> +		return false;
> +	}
> +}
> +
> +static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
> +{
> +	switch (bus_format) {
> +	case MEDIA_BUS_FMT_UYYVYY8_1X24:
> +	case MEDIA_BUS_FMT_UYYVYY10_1X30:
> +	case MEDIA_BUS_FMT_UYYVYY12_1X36:
> +	case MEDIA_BUS_FMT_UYYVYY16_1X48:
> +		return true;
> +
> +	default:
> +		return false;
> +	}
> +}
> +
> +static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
> +{
> +	switch (bus_format) {
> +	case MEDIA_BUS_FMT_RGB888_1X24:
> +	case MEDIA_BUS_FMT_YUV8_1X24:
> +	case MEDIA_BUS_FMT_UYVY8_1X16:
> +	case MEDIA_BUS_FMT_UYYVYY8_1X24:
> +		return 8;
> +
> +	case MEDIA_BUS_FMT_RGB101010_1X30:
> +	case MEDIA_BUS_FMT_YUV10_1X30:
> +	case MEDIA_BUS_FMT_UYVY10_1X20:
> +	case MEDIA_BUS_FMT_UYYVYY10_1X30:
> +		return 10;
> +
> +	case MEDIA_BUS_FMT_RGB121212_1X36:
> +	case MEDIA_BUS_FMT_YUV12_1X36:
> +	case MEDIA_BUS_FMT_UYVY12_1X24:
> +	case MEDIA_BUS_FMT_UYYVYY12_1X36:
> +		return 12;
> +
> +	case MEDIA_BUS_FMT_RGB161616_1X48:
> +	case MEDIA_BUS_FMT_YUV16_1X48:
> +	case MEDIA_BUS_FMT_UYYVYY16_1X48:
> +		return 16;
> +
> +	default:
> +		return 0;
> +	}
> +}
> +
>  /*
>   * this submodule is responsible for the video data synchronization.
>   * for example, for RGB 4:4:4 input, the data map is defined as
> @@ -579,37 +662,49 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
>  	int color_format = 0;
>  	u8 val;
>  
> -	if (hdmi->hdmi_data.enc_in_format == RGB) {
> -		if (hdmi->hdmi_data.enc_color_depth == 8)
> -			color_format = 0x01;
> -		else if (hdmi->hdmi_data.enc_color_depth == 10)
> -			color_format = 0x03;
> -		else if (hdmi->hdmi_data.enc_color_depth == 12)
> -			color_format = 0x05;
> -		else if (hdmi->hdmi_data.enc_color_depth == 16)
> -			color_format = 0x07;
> -		else
> -			return;
> -	} else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
> -		if (hdmi->hdmi_data.enc_color_depth == 8)
> -			color_format = 0x09;
> -		else if (hdmi->hdmi_data.enc_color_depth == 10)
> -			color_format = 0x0B;
> -		else if (hdmi->hdmi_data.enc_color_depth == 12)
> -			color_format = 0x0D;
> -		else if (hdmi->hdmi_data.enc_color_depth == 16)
> -			color_format = 0x0F;
> -		else
> -			return;
> -	} else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
> -		if (hdmi->hdmi_data.enc_color_depth == 8)
> -			color_format = 0x16;
> -		else if (hdmi->hdmi_data.enc_color_depth == 10)
> -			color_format = 0x14;
> -		else if (hdmi->hdmi_data.enc_color_depth == 12)
> -			color_format = 0x12;
> -		else
> -			return;
> +	switch (hdmi->hdmi_data.enc_in_bus_format) {
> +	case MEDIA_BUS_FMT_RGB888_1X24:
> +		color_format = 0x01;
> +		break;
> +	case MEDIA_BUS_FMT_RGB101010_1X30:
> +		color_format = 0x03;
> +		break;
> +	case MEDIA_BUS_FMT_RGB121212_1X36:
> +		color_format = 0x05;
> +		break;
> +	case MEDIA_BUS_FMT_RGB161616_1X48:
> +		color_format = 0x07;
> +		break;
> +
> +	case MEDIA_BUS_FMT_YUV8_1X24:
> +	case MEDIA_BUS_FMT_UYYVYY8_1X24:
> +		color_format = 0x09;
> +		break;
> +	case MEDIA_BUS_FMT_YUV10_1X30:
> +	case MEDIA_BUS_FMT_UYYVYY10_1X30:
> +		color_format = 0x0B;
> +		break;
> +	case MEDIA_BUS_FMT_YUV12_1X36:
> +	case MEDIA_BUS_FMT_UYYVYY12_1X36:
> +		color_format = 0x0D;
> +		break;
> +	case MEDIA_BUS_FMT_YUV16_1X48:
> +	case MEDIA_BUS_FMT_UYYVYY16_1X48:
> +		color_format = 0x0F;
> +		break;
> +
> +	case MEDIA_BUS_FMT_UYVY8_1X16:
> +		color_format = 0x16;
> +		break;
> +	case MEDIA_BUS_FMT_UYVY10_1X20:
> +		color_format = 0x14;
> +		break;
> +	case MEDIA_BUS_FMT_UYVY12_1X24:
> +		color_format = 0x12;
> +		break;
> +
> +	default:
> +		return;
>  	}
>  
>  	val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
> @@ -632,26 +727,30 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
>  
>  static int is_color_space_conversion(struct dw_hdmi *hdmi)
>  {
> -	return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
> +	return hdmi->hdmi_data.enc_in_bus_format != hdmi->hdmi_data.enc_out_bus_format;
>  }
>  
>  static int is_color_space_decimation(struct dw_hdmi *hdmi)
>  {
> -	if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
> +	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
>  		return 0;
> -	if (hdmi->hdmi_data.enc_in_format == RGB ||
> -	    hdmi->hdmi_data.enc_in_format == YCBCR444)
> +
> +	if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) ||
> +	    hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format))
>  		return 1;
> +
>  	return 0;
>  }
>  
>  static int is_color_space_interpolation(struct dw_hdmi *hdmi)
>  {
> -	if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
> +	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
>  		return 0;
> -	if (hdmi->hdmi_data.enc_out_format == RGB ||
> -	    hdmi->hdmi_data.enc_out_format == YCBCR444)
> +
> +	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))
>  		return 1;
> +
>  	return 0;
>  }
>  
> @@ -662,15 +761,16 @@ static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
>  	u32 csc_scale = 1;
>  
>  	if (is_color_space_conversion(hdmi)) {
> -		if (hdmi->hdmi_data.enc_out_format == RGB) {
> -			if (hdmi->hdmi_data.colorimetry ==
> -					HDMI_COLORIMETRY_ITU_601)
> +		if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
> +			if (hdmi->hdmi_data.enc_out_encoding ==
> +						V4L2_YCBCR_ENC_601)
>  				csc_coeff = &csc_coeff_rgb_out_eitu601;
>  			else
>  				csc_coeff = &csc_coeff_rgb_out_eitu709;
> -		} else if (hdmi->hdmi_data.enc_in_format == RGB) {
> -			if (hdmi->hdmi_data.colorimetry ==
> -					HDMI_COLORIMETRY_ITU_601)
> +		} else if (hdmi_bus_fmt_is_rgb(
> +					hdmi->hdmi_data.enc_in_bus_format)) {
> +			if (hdmi->hdmi_data.enc_out_encoding ==
> +						V4L2_YCBCR_ENC_601)
>  				csc_coeff = &csc_coeff_rgb_in_eitu601;
>  			else
>  				csc_coeff = &csc_coeff_rgb_in_eitu709;
> @@ -708,16 +808,23 @@ static void hdmi_video_csc(struct dw_hdmi *hdmi)
>  	else if (is_color_space_decimation(hdmi))
>  		decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
>  
> -	if (hdmi->hdmi_data.enc_color_depth == 8)
> +	switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
> +	case 8:
>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
> -	else if (hdmi->hdmi_data.enc_color_depth == 10)
> +		break;
> +	case 10:
>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
> -	else if (hdmi->hdmi_data.enc_color_depth == 12)
> +		break;
> +	case 12:
>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
> -	else if (hdmi->hdmi_data.enc_color_depth == 16)
> +		break;
> +	case 16:
>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
> -	else
> +		break;
> +
> +	default:
>  		return;
> +	}
>  
>  	/* Configure the CSC registers */
>  	hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
> @@ -740,32 +847,43 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
>  	struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
>  	u8 val, vp_conf;
>  
> -	if (hdmi_data->enc_out_format == RGB ||
> -	    hdmi_data->enc_out_format == YCBCR444) {
> -		if (!hdmi_data->enc_color_depth) {
> -			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
> -		} else if (hdmi_data->enc_color_depth == 8) {
> +	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)) {
> +		switch (hdmi_bus_fmt_color_depth(
> +					hdmi->hdmi_data.enc_out_bus_format)) {
> +		case 8:
>  			color_depth = 4;
>  			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
> -		} else if (hdmi_data->enc_color_depth == 10) {
> +			break;
> +		case 10:
>  			color_depth = 5;
> -		} else if (hdmi_data->enc_color_depth == 12) {
> +			break;
> +		case 12:
>  			color_depth = 6;
> -		} else if (hdmi_data->enc_color_depth == 16) {
> +			break;
> +		case 16:
>  			color_depth = 7;
> -		} else {
> -			return;
> +			break;
> +		default:
> +			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
>  		}
> -	} else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
> -		if (!hdmi_data->enc_color_depth ||
> -		    hdmi_data->enc_color_depth == 8)
> +	} else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) {
> +		switch (hdmi_bus_fmt_color_depth(
> +					hdmi->hdmi_data.enc_out_bus_format)) {
> +		case 0:
> +		case 8:
>  			remap_size = HDMI_VP_REMAP_YCC422_16bit;
> -		else if (hdmi_data->enc_color_depth == 10)
> +			break;
> +		case 10:
>  			remap_size = HDMI_VP_REMAP_YCC422_20bit;
> -		else if (hdmi_data->enc_color_depth == 12)
> +			break;
> +		case 12:
>  			remap_size = HDMI_VP_REMAP_YCC422_24bit;
> -		else
> +			break;
> +
> +		default:
>  			return;
> +		}
>  		output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
>  	} else {
>  		return;
> @@ -1148,28 +1266,35 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>  	/* Initialise info frame from DRM mode */
>  	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>  
> -	if (hdmi->hdmi_data.enc_out_format == YCBCR444)
> +	if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
>  		frame.colorspace = HDMI_COLORSPACE_YUV444;
> -	else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
> +	else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
>  		frame.colorspace = HDMI_COLORSPACE_YUV422;
>  	else
>  		frame.colorspace = HDMI_COLORSPACE_RGB;
>  
>  	/* Set up colorimetry */
> -	if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
> -		frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
> -		if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
> -			frame.extended_colorimetry =
> +	switch (hdmi->hdmi_data.enc_out_encoding) {
> +	case V4L2_YCBCR_ENC_601:
> +		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601)
> +			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
> +		else
> +			frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
> +		frame.extended_colorimetry =
>  				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
> -		else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
> -			frame.extended_colorimetry =
> +	case V4L2_YCBCR_ENC_709:
> +		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709)
> +			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
> +		else
> +			frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
> +		frame.extended_colorimetry =
>  				HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
> -	} else if (hdmi->hdmi_data.enc_out_format != RGB) {
> -		frame.colorimetry = hdmi->hdmi_data.colorimetry;
> -		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
> -	} else { /* Carries no data */
> -		frame.colorimetry = HDMI_COLORIMETRY_NONE;
> -		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
> +		break;
> +	default: /* Carries no data */
> +		frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
> +		frame.extended_colorimetry =
> +				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
> +		break;
>  	}
>  
>  	frame.scan_mode = HDMI_SCAN_MODE_NONE;
> @@ -1498,19 +1623,30 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>  	    (hdmi->vic == 21) || (hdmi->vic == 22) ||
>  	    (hdmi->vic == 2) || (hdmi->vic == 3) ||
>  	    (hdmi->vic == 17) || (hdmi->vic == 18))
> -		hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
> +		hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_601;
>  	else
> -		hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
> +		hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_709;
>  
>  	hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
>  	hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
>  
> -	/* TODO: Get input format from IPU (via FB driver interface) */
> -	hdmi->hdmi_data.enc_in_format = RGB;
> +	/* TOFIX: Get input format from plat data or fallback to RGB888 */
> +	if (hdmi->plat_data->input_bus_format >= 0)
> +		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 >= 0)
> +		hdmi->hdmi_data.enc_in_encoding =
> +			hdmi->plat_data->input_bus_encoding;
> +	else
> +		hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT;
>  
> -	hdmi->hdmi_data.enc_out_format = RGB;
> +	/* TOFIX: Default to RGB888 output format */
> +	hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
>  
> -	hdmi->hdmi_data.enc_color_depth = 8;
>  	hdmi->hdmi_data.pix_repet_factor = 0;
>  	hdmi->hdmi_data.hdcp_enable = 0;
>  	hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
> diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
> index bcceee8..0da74fb 100644
> --- a/include/drm/bridge/dw_hdmi.h
> +++ b/include/drm/bridge/dw_hdmi.h
> @@ -14,6 +14,67 @@
>  
>  struct dw_hdmi;
>  
> +/**
> + * DOC: Supported input formats and encodings
> + *
> + * Depending on the Hardware configuration of the Controller IP, it supports
> + * a subset of the following input formats and encodings on it's internal
> + * 48bit bus.
> + *
> + * +----------------------+---------------------------------+------------------------------+
> + * + Format Name          + Format Code                     + Encodings                    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + RGB 4:4:4 8bit       + ``MEDIA_BUS_FMT_RGB888_1X24``   + ``V4L2_YCBCR_ENC_DEFAULT``   +
> + * +----------------------+---------------------------------+------------------------------+
> + * + RGB 4:4:4 10bits     + ``MEDIA_BUS_FMT_RGB101010_1X30``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
> + * +----------------------+---------------------------------+------------------------------+
> + * + RGB 4:4:4 12bits     + ``MEDIA_BUS_FMT_RGB121212_1X36``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
> + * +----------------------+---------------------------------+------------------------------+
> + * + RGB 4:4:4 16bits     + ``MEDIA_BUS_FMT_RGB161616_1X48``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:4:4 8bit     + ``MEDIA_BUS_FMT_YUV8_1X24``     + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:4:4 10bits   + ``MEDIA_BUS_FMT_YUV10_1X30``    + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:4:4 12bits   + ``MEDIA_BUS_FMT_YUV12_1X36``    + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:4:4 16bits   + ``MEDIA_BUS_FMT_YUV16_1X48``    + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:2 8bit     + ``MEDIA_BUS_FMT_UYVY8_1X16``    + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:2 10bits   + ``MEDIA_BUS_FMT_UYVY10_1X20``   + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:2 12bits   + ``MEDIA_BUS_FMT_UYVY12_1X24``   + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:0 8bit     + ``MEDIA_BUS_FMT_UYYVYY8_1X24``  + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:0 10bits   + ``MEDIA_BUS_FMT_UYYVYY10_1X30`` + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:0 12bits   + ``MEDIA_BUS_FMT_UYYVYY12_1X36`` + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + * + YCbCr 4:2:0 16bits   + ``MEDIA_BUS_FMT_UYYVYY16_1X48`` + ``V4L2_YCBCR_ENC_601``       +
> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
> + * +----------------------+---------------------------------+------------------------------+
> + */
> +
>  enum {
>  	DW_HDMI_RES_8,
>  	DW_HDMI_RES_10,
> @@ -62,6 +123,8 @@ struct dw_hdmi_plat_data {
>  	struct regmap *regm;
>  	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
>  					   struct drm_display_mode *mode);
> +	unsigned long input_bus_format;
> +	unsigned long input_bus_encoding;
>  
>  	/* Vendor PHY support */
>  	const struct dw_hdmi_phy_ops *phy_ops;
Neil Armstrong March 22, 2017, 4:33 p.m. UTC | #4
On 03/22/2017 05:21 PM, Philipp Zabel wrote:
> On Tue, 2017-03-21 at 16:12 +0100, Neil Armstrong wrote:
>> Some display pipelines can only provide non-RBG input pixels to the HDMI TX
>> Controller, this patch takes the pixel format from the plat_data if provided.
>>
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> 
> On i.MX6 we could provide RGB/YUV bus formats dynamically. Would it make
> sense to negotiate this with the pixel provider instead of fixing it in
> platform data?
> I imagine that if a YUV image with the correct colorspace is supposed to
> be transmitted to a TV that supports that format, it might be useful to
> avoid passing through two colorspace converters on the way.

Hi Philipp,

Yes the next step is to add this negociation.
On Amlogic platform, we can add some colorspace process to output 10bit HDMI for example,
or provide 4:2:0 YUV to the controller.

We still need to discuss a provide some implementation, but at least we have
the correct defines for the bus formats....

The platform_data is only a temporary solution that should go away when the negociation
is implemented.

Neil

> 
> regards
> Philipp
> 
>> ---
>>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 326 +++++++++++++++++++++---------
>>  include/drm/bridge/dw_hdmi.h              |  63 ++++++
>>  2 files changed, 294 insertions(+), 95 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> index f82750a..fcb0a27 100644
>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> @@ -30,18 +30,15 @@
>>  #include <drm/drm_encoder_slave.h>
>>  #include <drm/bridge/dw_hdmi.h>
>>  
>> +#include <uapi/linux/media-bus-format.h>
>> +#include <uapi/linux/videodev2.h>
>> +
>>  #include "dw-hdmi.h"
>>  #include "dw-hdmi-audio.h"
>>  
>>  #define DDC_SEGMENT_ADDR	0x30
>>  #define HDMI_EDID_LEN		512
>>  
>> -#define RGB			0
>> -#define YCBCR444		1
>> -#define YCBCR422_16BITS		2
>> -#define YCBCR422_8BITS		3
>> -#define XVYCC444		4
>> -
>>  enum hdmi_datamap {
>>  	RGB444_8B = 0x01,
>>  	RGB444_10B = 0x03,
>> @@ -95,10 +92,10 @@ struct hdmi_vmode {
>>  };
>>  
>>  struct hdmi_data_info {
>> -	unsigned int enc_in_format;
>> -	unsigned int enc_out_format;
>> -	unsigned int enc_color_depth;
>> -	unsigned int colorimetry;
>> +	unsigned int enc_in_bus_format;
>> +	unsigned int enc_out_bus_format;
>> +	unsigned int enc_in_encoding;
>> +	unsigned int enc_out_encoding;
>>  	unsigned int pix_repet_factor;
>>  	unsigned int hdcp_enable;
>>  	struct hdmi_vmode video_mode;
>> @@ -567,6 +564,92 @@ void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
>>  }
>>  EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
>>  
>> +static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
>> +{
>> +	switch (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:
>> +		return true;
>> +
>> +	default:
>> +		return false;
>> +	}
>> +}
>> +
>> +static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
>> +{
>> +	switch (bus_format) {
>> +	case MEDIA_BUS_FMT_YUV8_1X24:
>> +	case MEDIA_BUS_FMT_YUV10_1X30:
>> +	case MEDIA_BUS_FMT_YUV12_1X36:
>> +	case MEDIA_BUS_FMT_YUV16_1X48:
>> +		return true;
>> +
>> +	default:
>> +		return false;
>> +	}
>> +}
>> +
>> +static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
>> +{
>> +	switch (bus_format) {
>> +	case MEDIA_BUS_FMT_UYVY8_1X16:
>> +	case MEDIA_BUS_FMT_UYVY10_1X20:
>> +	case MEDIA_BUS_FMT_UYVY12_1X24:
>> +		return true;
>> +
>> +	default:
>> +		return false;
>> +	}
>> +}
>> +
>> +static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
>> +{
>> +	switch (bus_format) {
>> +	case MEDIA_BUS_FMT_UYYVYY8_1X24:
>> +	case MEDIA_BUS_FMT_UYYVYY10_1X30:
>> +	case MEDIA_BUS_FMT_UYYVYY12_1X36:
>> +	case MEDIA_BUS_FMT_UYYVYY16_1X48:
>> +		return true;
>> +
>> +	default:
>> +		return false;
>> +	}
>> +}
>> +
>> +static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
>> +{
>> +	switch (bus_format) {
>> +	case MEDIA_BUS_FMT_RGB888_1X24:
>> +	case MEDIA_BUS_FMT_YUV8_1X24:
>> +	case MEDIA_BUS_FMT_UYVY8_1X16:
>> +	case MEDIA_BUS_FMT_UYYVYY8_1X24:
>> +		return 8;
>> +
>> +	case MEDIA_BUS_FMT_RGB101010_1X30:
>> +	case MEDIA_BUS_FMT_YUV10_1X30:
>> +	case MEDIA_BUS_FMT_UYVY10_1X20:
>> +	case MEDIA_BUS_FMT_UYYVYY10_1X30:
>> +		return 10;
>> +
>> +	case MEDIA_BUS_FMT_RGB121212_1X36:
>> +	case MEDIA_BUS_FMT_YUV12_1X36:
>> +	case MEDIA_BUS_FMT_UYVY12_1X24:
>> +	case MEDIA_BUS_FMT_UYYVYY12_1X36:
>> +		return 12;
>> +
>> +	case MEDIA_BUS_FMT_RGB161616_1X48:
>> +	case MEDIA_BUS_FMT_YUV16_1X48:
>> +	case MEDIA_BUS_FMT_UYYVYY16_1X48:
>> +		return 16;
>> +
>> +	default:
>> +		return 0;
>> +	}
>> +}
>> +
>>  /*
>>   * this submodule is responsible for the video data synchronization.
>>   * for example, for RGB 4:4:4 input, the data map is defined as
>> @@ -579,37 +662,49 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
>>  	int color_format = 0;
>>  	u8 val;
>>  
>> -	if (hdmi->hdmi_data.enc_in_format == RGB) {
>> -		if (hdmi->hdmi_data.enc_color_depth == 8)
>> -			color_format = 0x01;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 10)
>> -			color_format = 0x03;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 12)
>> -			color_format = 0x05;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 16)
>> -			color_format = 0x07;
>> -		else
>> -			return;
>> -	} else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
>> -		if (hdmi->hdmi_data.enc_color_depth == 8)
>> -			color_format = 0x09;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 10)
>> -			color_format = 0x0B;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 12)
>> -			color_format = 0x0D;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 16)
>> -			color_format = 0x0F;
>> -		else
>> -			return;
>> -	} else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
>> -		if (hdmi->hdmi_data.enc_color_depth == 8)
>> -			color_format = 0x16;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 10)
>> -			color_format = 0x14;
>> -		else if (hdmi->hdmi_data.enc_color_depth == 12)
>> -			color_format = 0x12;
>> -		else
>> -			return;
>> +	switch (hdmi->hdmi_data.enc_in_bus_format) {
>> +	case MEDIA_BUS_FMT_RGB888_1X24:
>> +		color_format = 0x01;
>> +		break;
>> +	case MEDIA_BUS_FMT_RGB101010_1X30:
>> +		color_format = 0x03;
>> +		break;
>> +	case MEDIA_BUS_FMT_RGB121212_1X36:
>> +		color_format = 0x05;
>> +		break;
>> +	case MEDIA_BUS_FMT_RGB161616_1X48:
>> +		color_format = 0x07;
>> +		break;
>> +
>> +	case MEDIA_BUS_FMT_YUV8_1X24:
>> +	case MEDIA_BUS_FMT_UYYVYY8_1X24:
>> +		color_format = 0x09;
>> +		break;
>> +	case MEDIA_BUS_FMT_YUV10_1X30:
>> +	case MEDIA_BUS_FMT_UYYVYY10_1X30:
>> +		color_format = 0x0B;
>> +		break;
>> +	case MEDIA_BUS_FMT_YUV12_1X36:
>> +	case MEDIA_BUS_FMT_UYYVYY12_1X36:
>> +		color_format = 0x0D;
>> +		break;
>> +	case MEDIA_BUS_FMT_YUV16_1X48:
>> +	case MEDIA_BUS_FMT_UYYVYY16_1X48:
>> +		color_format = 0x0F;
>> +		break;
>> +
>> +	case MEDIA_BUS_FMT_UYVY8_1X16:
>> +		color_format = 0x16;
>> +		break;
>> +	case MEDIA_BUS_FMT_UYVY10_1X20:
>> +		color_format = 0x14;
>> +		break;
>> +	case MEDIA_BUS_FMT_UYVY12_1X24:
>> +		color_format = 0x12;
>> +		break;
>> +
>> +	default:
>> +		return;
>>  	}
>>  
>>  	val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
>> @@ -632,26 +727,30 @@ static void hdmi_video_sample(struct dw_hdmi *hdmi)
>>  
>>  static int is_color_space_conversion(struct dw_hdmi *hdmi)
>>  {
>> -	return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
>> +	return hdmi->hdmi_data.enc_in_bus_format != hdmi->hdmi_data.enc_out_bus_format;
>>  }
>>  
>>  static int is_color_space_decimation(struct dw_hdmi *hdmi)
>>  {
>> -	if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
>> +	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
>>  		return 0;
>> -	if (hdmi->hdmi_data.enc_in_format == RGB ||
>> -	    hdmi->hdmi_data.enc_in_format == YCBCR444)
>> +
>> +	if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) ||
>> +	    hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format))
>>  		return 1;
>> +
>>  	return 0;
>>  }
>>  
>>  static int is_color_space_interpolation(struct dw_hdmi *hdmi)
>>  {
>> -	if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
>> +	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
>>  		return 0;
>> -	if (hdmi->hdmi_data.enc_out_format == RGB ||
>> -	    hdmi->hdmi_data.enc_out_format == YCBCR444)
>> +
>> +	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))
>>  		return 1;
>> +
>>  	return 0;
>>  }
>>  
>> @@ -662,15 +761,16 @@ static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
>>  	u32 csc_scale = 1;
>>  
>>  	if (is_color_space_conversion(hdmi)) {
>> -		if (hdmi->hdmi_data.enc_out_format == RGB) {
>> -			if (hdmi->hdmi_data.colorimetry ==
>> -					HDMI_COLORIMETRY_ITU_601)
>> +		if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
>> +			if (hdmi->hdmi_data.enc_out_encoding ==
>> +						V4L2_YCBCR_ENC_601)
>>  				csc_coeff = &csc_coeff_rgb_out_eitu601;
>>  			else
>>  				csc_coeff = &csc_coeff_rgb_out_eitu709;
>> -		} else if (hdmi->hdmi_data.enc_in_format == RGB) {
>> -			if (hdmi->hdmi_data.colorimetry ==
>> -					HDMI_COLORIMETRY_ITU_601)
>> +		} else if (hdmi_bus_fmt_is_rgb(
>> +					hdmi->hdmi_data.enc_in_bus_format)) {
>> +			if (hdmi->hdmi_data.enc_out_encoding ==
>> +						V4L2_YCBCR_ENC_601)
>>  				csc_coeff = &csc_coeff_rgb_in_eitu601;
>>  			else
>>  				csc_coeff = &csc_coeff_rgb_in_eitu709;
>> @@ -708,16 +808,23 @@ static void hdmi_video_csc(struct dw_hdmi *hdmi)
>>  	else if (is_color_space_decimation(hdmi))
>>  		decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
>>  
>> -	if (hdmi->hdmi_data.enc_color_depth == 8)
>> +	switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
>> +	case 8:
>>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
>> -	else if (hdmi->hdmi_data.enc_color_depth == 10)
>> +		break;
>> +	case 10:
>>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
>> -	else if (hdmi->hdmi_data.enc_color_depth == 12)
>> +		break;
>> +	case 12:
>>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
>> -	else if (hdmi->hdmi_data.enc_color_depth == 16)
>> +		break;
>> +	case 16:
>>  		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
>> -	else
>> +		break;
>> +
>> +	default:
>>  		return;
>> +	}
>>  
>>  	/* Configure the CSC registers */
>>  	hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
>> @@ -740,32 +847,43 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi)
>>  	struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
>>  	u8 val, vp_conf;
>>  
>> -	if (hdmi_data->enc_out_format == RGB ||
>> -	    hdmi_data->enc_out_format == YCBCR444) {
>> -		if (!hdmi_data->enc_color_depth) {
>> -			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
>> -		} else if (hdmi_data->enc_color_depth == 8) {
>> +	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)) {
>> +		switch (hdmi_bus_fmt_color_depth(
>> +					hdmi->hdmi_data.enc_out_bus_format)) {
>> +		case 8:
>>  			color_depth = 4;
>>  			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
>> -		} else if (hdmi_data->enc_color_depth == 10) {
>> +			break;
>> +		case 10:
>>  			color_depth = 5;
>> -		} else if (hdmi_data->enc_color_depth == 12) {
>> +			break;
>> +		case 12:
>>  			color_depth = 6;
>> -		} else if (hdmi_data->enc_color_depth == 16) {
>> +			break;
>> +		case 16:
>>  			color_depth = 7;
>> -		} else {
>> -			return;
>> +			break;
>> +		default:
>> +			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
>>  		}
>> -	} else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
>> -		if (!hdmi_data->enc_color_depth ||
>> -		    hdmi_data->enc_color_depth == 8)
>> +	} else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) {
>> +		switch (hdmi_bus_fmt_color_depth(
>> +					hdmi->hdmi_data.enc_out_bus_format)) {
>> +		case 0:
>> +		case 8:
>>  			remap_size = HDMI_VP_REMAP_YCC422_16bit;
>> -		else if (hdmi_data->enc_color_depth == 10)
>> +			break;
>> +		case 10:
>>  			remap_size = HDMI_VP_REMAP_YCC422_20bit;
>> -		else if (hdmi_data->enc_color_depth == 12)
>> +			break;
>> +		case 12:
>>  			remap_size = HDMI_VP_REMAP_YCC422_24bit;
>> -		else
>> +			break;
>> +
>> +		default:
>>  			return;
>> +		}
>>  		output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
>>  	} else {
>>  		return;
>> @@ -1148,28 +1266,35 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>>  	/* Initialise info frame from DRM mode */
>>  	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>>  
>> -	if (hdmi->hdmi_data.enc_out_format == YCBCR444)
>> +	if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
>>  		frame.colorspace = HDMI_COLORSPACE_YUV444;
>> -	else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
>> +	else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
>>  		frame.colorspace = HDMI_COLORSPACE_YUV422;
>>  	else
>>  		frame.colorspace = HDMI_COLORSPACE_RGB;
>>  
>>  	/* Set up colorimetry */
>> -	if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
>> -		frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
>> -		if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
>> -			frame.extended_colorimetry =
>> +	switch (hdmi->hdmi_data.enc_out_encoding) {
>> +	case V4L2_YCBCR_ENC_601:
>> +		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601)
>> +			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
>> +		else
>> +			frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
>> +		frame.extended_colorimetry =
>>  				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
>> -		else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
>> -			frame.extended_colorimetry =
>> +	case V4L2_YCBCR_ENC_709:
>> +		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709)
>> +			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
>> +		else
>> +			frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
>> +		frame.extended_colorimetry =
>>  				HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
>> -	} else if (hdmi->hdmi_data.enc_out_format != RGB) {
>> -		frame.colorimetry = hdmi->hdmi_data.colorimetry;
>> -		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
>> -	} else { /* Carries no data */
>> -		frame.colorimetry = HDMI_COLORIMETRY_NONE;
>> -		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
>> +		break;
>> +	default: /* Carries no data */
>> +		frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
>> +		frame.extended_colorimetry =
>> +				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
>> +		break;
>>  	}
>>  
>>  	frame.scan_mode = HDMI_SCAN_MODE_NONE;
>> @@ -1498,19 +1623,30 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>>  	    (hdmi->vic == 21) || (hdmi->vic == 22) ||
>>  	    (hdmi->vic == 2) || (hdmi->vic == 3) ||
>>  	    (hdmi->vic == 17) || (hdmi->vic == 18))
>> -		hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
>> +		hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_601;
>>  	else
>> -		hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
>> +		hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_709;
>>  
>>  	hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
>>  	hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
>>  
>> -	/* TODO: Get input format from IPU (via FB driver interface) */
>> -	hdmi->hdmi_data.enc_in_format = RGB;
>> +	/* TOFIX: Get input format from plat data or fallback to RGB888 */
>> +	if (hdmi->plat_data->input_bus_format >= 0)
>> +		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 >= 0)
>> +		hdmi->hdmi_data.enc_in_encoding =
>> +			hdmi->plat_data->input_bus_encoding;
>> +	else
>> +		hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT;
>>  
>> -	hdmi->hdmi_data.enc_out_format = RGB;
>> +	/* TOFIX: Default to RGB888 output format */
>> +	hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
>>  
>> -	hdmi->hdmi_data.enc_color_depth = 8;
>>  	hdmi->hdmi_data.pix_repet_factor = 0;
>>  	hdmi->hdmi_data.hdcp_enable = 0;
>>  	hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
>> diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
>> index bcceee8..0da74fb 100644
>> --- a/include/drm/bridge/dw_hdmi.h
>> +++ b/include/drm/bridge/dw_hdmi.h
>> @@ -14,6 +14,67 @@
>>  
>>  struct dw_hdmi;
>>  
>> +/**
>> + * DOC: Supported input formats and encodings
>> + *
>> + * Depending on the Hardware configuration of the Controller IP, it supports
>> + * a subset of the following input formats and encodings on it's internal
>> + * 48bit bus.
>> + *
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + Format Name          + Format Code                     + Encodings                    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + RGB 4:4:4 8bit       + ``MEDIA_BUS_FMT_RGB888_1X24``   + ``V4L2_YCBCR_ENC_DEFAULT``   +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + RGB 4:4:4 10bits     + ``MEDIA_BUS_FMT_RGB101010_1X30``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + RGB 4:4:4 12bits     + ``MEDIA_BUS_FMT_RGB121212_1X36``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + RGB 4:4:4 16bits     + ``MEDIA_BUS_FMT_RGB161616_1X48``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:4:4 8bit     + ``MEDIA_BUS_FMT_YUV8_1X24``     + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:4:4 10bits   + ``MEDIA_BUS_FMT_YUV10_1X30``    + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:4:4 12bits   + ``MEDIA_BUS_FMT_YUV12_1X36``    + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:4:4 16bits   + ``MEDIA_BUS_FMT_YUV16_1X48``    + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:2 8bit     + ``MEDIA_BUS_FMT_UYVY8_1X16``    + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:2 10bits   + ``MEDIA_BUS_FMT_UYVY10_1X20``   + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:2 12bits   + ``MEDIA_BUS_FMT_UYVY12_1X24``   + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:0 8bit     + ``MEDIA_BUS_FMT_UYYVYY8_1X24``  + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:0 10bits   + ``MEDIA_BUS_FMT_UYYVYY10_1X30`` + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:0 12bits   + ``MEDIA_BUS_FMT_UYYVYY12_1X36`` + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + * + YCbCr 4:2:0 16bits   + ``MEDIA_BUS_FMT_UYYVYY16_1X48`` + ``V4L2_YCBCR_ENC_601``       +
>> + * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
>> + * +----------------------+---------------------------------+------------------------------+
>> + */
>> +
>>  enum {
>>  	DW_HDMI_RES_8,
>>  	DW_HDMI_RES_10,
>> @@ -62,6 +123,8 @@ struct dw_hdmi_plat_data {
>>  	struct regmap *regm;
>>  	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
>>  					   struct drm_display_mode *mode);
>> +	unsigned long input_bus_format;
>> +	unsigned long input_bus_encoding;
>>  
>>  	/* Vendor PHY support */
>>  	const struct dw_hdmi_phy_ops *phy_ops;
> 
>
diff mbox

Patch

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index f82750a..fcb0a27 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -30,18 +30,15 @@ 
 #include <drm/drm_encoder_slave.h>
 #include <drm/bridge/dw_hdmi.h>
 
+#include <uapi/linux/media-bus-format.h>
+#include <uapi/linux/videodev2.h>
+
 #include "dw-hdmi.h"
 #include "dw-hdmi-audio.h"
 
 #define DDC_SEGMENT_ADDR	0x30
 #define HDMI_EDID_LEN		512
 
-#define RGB			0
-#define YCBCR444		1
-#define YCBCR422_16BITS		2
-#define YCBCR422_8BITS		3
-#define XVYCC444		4
-
 enum hdmi_datamap {
 	RGB444_8B = 0x01,
 	RGB444_10B = 0x03,
@@ -95,10 +92,10 @@  struct hdmi_vmode {
 };
 
 struct hdmi_data_info {
-	unsigned int enc_in_format;
-	unsigned int enc_out_format;
-	unsigned int enc_color_depth;
-	unsigned int colorimetry;
+	unsigned int enc_in_bus_format;
+	unsigned int enc_out_bus_format;
+	unsigned int enc_in_encoding;
+	unsigned int enc_out_encoding;
 	unsigned int pix_repet_factor;
 	unsigned int hdcp_enable;
 	struct hdmi_vmode video_mode;
@@ -567,6 +564,92 @@  void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
 
+static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
+{
+	switch (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:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_YUV12_1X36:
+	case MEDIA_BUS_FMT_YUV16_1X48:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+	case MEDIA_BUS_FMT_UYVY12_1X24:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+static bool hdmi_bus_fmt_is_yuv420(unsigned int bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_UYYVYY8_1X24:
+	case MEDIA_BUS_FMT_UYYVYY10_1X30:
+	case MEDIA_BUS_FMT_UYYVYY12_1X36:
+	case MEDIA_BUS_FMT_UYYVYY16_1X48:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
+{
+	switch (bus_format) {
+	case MEDIA_BUS_FMT_RGB888_1X24:
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_UYYVYY8_1X24:
+		return 8;
+
+	case MEDIA_BUS_FMT_RGB101010_1X30:
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+	case MEDIA_BUS_FMT_UYYVYY10_1X30:
+		return 10;
+
+	case MEDIA_BUS_FMT_RGB121212_1X36:
+	case MEDIA_BUS_FMT_YUV12_1X36:
+	case MEDIA_BUS_FMT_UYVY12_1X24:
+	case MEDIA_BUS_FMT_UYYVYY12_1X36:
+		return 12;
+
+	case MEDIA_BUS_FMT_RGB161616_1X48:
+	case MEDIA_BUS_FMT_YUV16_1X48:
+	case MEDIA_BUS_FMT_UYYVYY16_1X48:
+		return 16;
+
+	default:
+		return 0;
+	}
+}
+
 /*
  * this submodule is responsible for the video data synchronization.
  * for example, for RGB 4:4:4 input, the data map is defined as
@@ -579,37 +662,49 @@  static void hdmi_video_sample(struct dw_hdmi *hdmi)
 	int color_format = 0;
 	u8 val;
 
-	if (hdmi->hdmi_data.enc_in_format == RGB) {
-		if (hdmi->hdmi_data.enc_color_depth == 8)
-			color_format = 0x01;
-		else if (hdmi->hdmi_data.enc_color_depth == 10)
-			color_format = 0x03;
-		else if (hdmi->hdmi_data.enc_color_depth == 12)
-			color_format = 0x05;
-		else if (hdmi->hdmi_data.enc_color_depth == 16)
-			color_format = 0x07;
-		else
-			return;
-	} else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
-		if (hdmi->hdmi_data.enc_color_depth == 8)
-			color_format = 0x09;
-		else if (hdmi->hdmi_data.enc_color_depth == 10)
-			color_format = 0x0B;
-		else if (hdmi->hdmi_data.enc_color_depth == 12)
-			color_format = 0x0D;
-		else if (hdmi->hdmi_data.enc_color_depth == 16)
-			color_format = 0x0F;
-		else
-			return;
-	} else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
-		if (hdmi->hdmi_data.enc_color_depth == 8)
-			color_format = 0x16;
-		else if (hdmi->hdmi_data.enc_color_depth == 10)
-			color_format = 0x14;
-		else if (hdmi->hdmi_data.enc_color_depth == 12)
-			color_format = 0x12;
-		else
-			return;
+	switch (hdmi->hdmi_data.enc_in_bus_format) {
+	case MEDIA_BUS_FMT_RGB888_1X24:
+		color_format = 0x01;
+		break;
+	case MEDIA_BUS_FMT_RGB101010_1X30:
+		color_format = 0x03;
+		break;
+	case MEDIA_BUS_FMT_RGB121212_1X36:
+		color_format = 0x05;
+		break;
+	case MEDIA_BUS_FMT_RGB161616_1X48:
+		color_format = 0x07;
+		break;
+
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_UYYVYY8_1X24:
+		color_format = 0x09;
+		break;
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_UYYVYY10_1X30:
+		color_format = 0x0B;
+		break;
+	case MEDIA_BUS_FMT_YUV12_1X36:
+	case MEDIA_BUS_FMT_UYYVYY12_1X36:
+		color_format = 0x0D;
+		break;
+	case MEDIA_BUS_FMT_YUV16_1X48:
+	case MEDIA_BUS_FMT_UYYVYY16_1X48:
+		color_format = 0x0F;
+		break;
+
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+		color_format = 0x16;
+		break;
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+		color_format = 0x14;
+		break;
+	case MEDIA_BUS_FMT_UYVY12_1X24:
+		color_format = 0x12;
+		break;
+
+	default:
+		return;
 	}
 
 	val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
@@ -632,26 +727,30 @@  static void hdmi_video_sample(struct dw_hdmi *hdmi)
 
 static int is_color_space_conversion(struct dw_hdmi *hdmi)
 {
-	return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format;
+	return hdmi->hdmi_data.enc_in_bus_format != hdmi->hdmi_data.enc_out_bus_format;
 }
 
 static int is_color_space_decimation(struct dw_hdmi *hdmi)
 {
-	if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS)
+	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
 		return 0;
-	if (hdmi->hdmi_data.enc_in_format == RGB ||
-	    hdmi->hdmi_data.enc_in_format == YCBCR444)
+
+	if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) ||
+	    hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format))
 		return 1;
+
 	return 0;
 }
 
 static int is_color_space_interpolation(struct dw_hdmi *hdmi)
 {
-	if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS)
+	if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
 		return 0;
-	if (hdmi->hdmi_data.enc_out_format == RGB ||
-	    hdmi->hdmi_data.enc_out_format == YCBCR444)
+
+	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))
 		return 1;
+
 	return 0;
 }
 
@@ -662,15 +761,16 @@  static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
 	u32 csc_scale = 1;
 
 	if (is_color_space_conversion(hdmi)) {
-		if (hdmi->hdmi_data.enc_out_format == RGB) {
-			if (hdmi->hdmi_data.colorimetry ==
-					HDMI_COLORIMETRY_ITU_601)
+		if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
+			if (hdmi->hdmi_data.enc_out_encoding ==
+						V4L2_YCBCR_ENC_601)
 				csc_coeff = &csc_coeff_rgb_out_eitu601;
 			else
 				csc_coeff = &csc_coeff_rgb_out_eitu709;
-		} else if (hdmi->hdmi_data.enc_in_format == RGB) {
-			if (hdmi->hdmi_data.colorimetry ==
-					HDMI_COLORIMETRY_ITU_601)
+		} else if (hdmi_bus_fmt_is_rgb(
+					hdmi->hdmi_data.enc_in_bus_format)) {
+			if (hdmi->hdmi_data.enc_out_encoding ==
+						V4L2_YCBCR_ENC_601)
 				csc_coeff = &csc_coeff_rgb_in_eitu601;
 			else
 				csc_coeff = &csc_coeff_rgb_in_eitu709;
@@ -708,16 +808,23 @@  static void hdmi_video_csc(struct dw_hdmi *hdmi)
 	else if (is_color_space_decimation(hdmi))
 		decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
 
-	if (hdmi->hdmi_data.enc_color_depth == 8)
+	switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
+	case 8:
 		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
-	else if (hdmi->hdmi_data.enc_color_depth == 10)
+		break;
+	case 10:
 		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
-	else if (hdmi->hdmi_data.enc_color_depth == 12)
+		break;
+	case 12:
 		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
-	else if (hdmi->hdmi_data.enc_color_depth == 16)
+		break;
+	case 16:
 		color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
-	else
+		break;
+
+	default:
 		return;
+	}
 
 	/* Configure the CSC registers */
 	hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
@@ -740,32 +847,43 @@  static void hdmi_video_packetize(struct dw_hdmi *hdmi)
 	struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
 	u8 val, vp_conf;
 
-	if (hdmi_data->enc_out_format == RGB ||
-	    hdmi_data->enc_out_format == YCBCR444) {
-		if (!hdmi_data->enc_color_depth) {
-			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
-		} else if (hdmi_data->enc_color_depth == 8) {
+	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)) {
+		switch (hdmi_bus_fmt_color_depth(
+					hdmi->hdmi_data.enc_out_bus_format)) {
+		case 8:
 			color_depth = 4;
 			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
-		} else if (hdmi_data->enc_color_depth == 10) {
+			break;
+		case 10:
 			color_depth = 5;
-		} else if (hdmi_data->enc_color_depth == 12) {
+			break;
+		case 12:
 			color_depth = 6;
-		} else if (hdmi_data->enc_color_depth == 16) {
+			break;
+		case 16:
 			color_depth = 7;
-		} else {
-			return;
+			break;
+		default:
+			output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
 		}
-	} else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
-		if (!hdmi_data->enc_color_depth ||
-		    hdmi_data->enc_color_depth == 8)
+	} else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) {
+		switch (hdmi_bus_fmt_color_depth(
+					hdmi->hdmi_data.enc_out_bus_format)) {
+		case 0:
+		case 8:
 			remap_size = HDMI_VP_REMAP_YCC422_16bit;
-		else if (hdmi_data->enc_color_depth == 10)
+			break;
+		case 10:
 			remap_size = HDMI_VP_REMAP_YCC422_20bit;
-		else if (hdmi_data->enc_color_depth == 12)
+			break;
+		case 12:
 			remap_size = HDMI_VP_REMAP_YCC422_24bit;
-		else
+			break;
+
+		default:
 			return;
+		}
 		output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
 	} else {
 		return;
@@ -1148,28 +1266,35 @@  static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 	/* Initialise info frame from DRM mode */
 	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
 
-	if (hdmi->hdmi_data.enc_out_format == YCBCR444)
+	if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
 		frame.colorspace = HDMI_COLORSPACE_YUV444;
-	else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
+	else if (hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
 		frame.colorspace = HDMI_COLORSPACE_YUV422;
 	else
 		frame.colorspace = HDMI_COLORSPACE_RGB;
 
 	/* Set up colorimetry */
-	if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
-		frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
-		if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
-			frame.extended_colorimetry =
+	switch (hdmi->hdmi_data.enc_out_encoding) {
+	case V4L2_YCBCR_ENC_601:
+		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601)
+			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
+		else
+			frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
+		frame.extended_colorimetry =
 				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-		else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
-			frame.extended_colorimetry =
+	case V4L2_YCBCR_ENC_709:
+		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709)
+			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
+		else
+			frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
+		frame.extended_colorimetry =
 				HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
-	} else if (hdmi->hdmi_data.enc_out_format != RGB) {
-		frame.colorimetry = hdmi->hdmi_data.colorimetry;
-		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-	} else { /* Carries no data */
-		frame.colorimetry = HDMI_COLORIMETRY_NONE;
-		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
+		break;
+	default: /* Carries no data */
+		frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
+		frame.extended_colorimetry =
+				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
+		break;
 	}
 
 	frame.scan_mode = HDMI_SCAN_MODE_NONE;
@@ -1498,19 +1623,30 @@  static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 	    (hdmi->vic == 21) || (hdmi->vic == 22) ||
 	    (hdmi->vic == 2) || (hdmi->vic == 3) ||
 	    (hdmi->vic == 17) || (hdmi->vic == 18))
-		hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
+		hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_601;
 	else
-		hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
+		hdmi->hdmi_data.enc_out_encoding = V4L2_YCBCR_ENC_709;
 
 	hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
 	hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
 
-	/* TODO: Get input format from IPU (via FB driver interface) */
-	hdmi->hdmi_data.enc_in_format = RGB;
+	/* TOFIX: Get input format from plat data or fallback to RGB888 */
+	if (hdmi->plat_data->input_bus_format >= 0)
+		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 >= 0)
+		hdmi->hdmi_data.enc_in_encoding =
+			hdmi->plat_data->input_bus_encoding;
+	else
+		hdmi->hdmi_data.enc_in_encoding = V4L2_YCBCR_ENC_DEFAULT;
 
-	hdmi->hdmi_data.enc_out_format = RGB;
+	/* TOFIX: Default to RGB888 output format */
+	hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 
-	hdmi->hdmi_data.enc_color_depth = 8;
 	hdmi->hdmi_data.pix_repet_factor = 0;
 	hdmi->hdmi_data.hdcp_enable = 0;
 	hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index bcceee8..0da74fb 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -14,6 +14,67 @@ 
 
 struct dw_hdmi;
 
+/**
+ * DOC: Supported input formats and encodings
+ *
+ * Depending on the Hardware configuration of the Controller IP, it supports
+ * a subset of the following input formats and encodings on it's internal
+ * 48bit bus.
+ *
+ * +----------------------+---------------------------------+------------------------------+
+ * + Format Name          + Format Code                     + Encodings                    +
+ * +----------------------+---------------------------------+------------------------------+
+ * + RGB 4:4:4 8bit       + ``MEDIA_BUS_FMT_RGB888_1X24``   + ``V4L2_YCBCR_ENC_DEFAULT``   +
+ * +----------------------+---------------------------------+------------------------------+
+ * + RGB 4:4:4 10bits     + ``MEDIA_BUS_FMT_RGB101010_1X30``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
+ * +----------------------+---------------------------------+------------------------------+
+ * + RGB 4:4:4 12bits     + ``MEDIA_BUS_FMT_RGB121212_1X36``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
+ * +----------------------+---------------------------------+------------------------------+
+ * + RGB 4:4:4 16bits     + ``MEDIA_BUS_FMT_RGB161616_1X48``+ ``V4L2_YCBCR_ENC_DEFAULT``   +
+ * +----------------------+---------------------------------+------------------------------+
+ * + YCbCr 4:4:4 8bit     + ``MEDIA_BUS_FMT_YUV8_1X24``     + ``V4L2_YCBCR_ENC_601``       +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
+ * +----------------------+---------------------------------+------------------------------+
+ * + YCbCr 4:4:4 10bits   + ``MEDIA_BUS_FMT_YUV10_1X30``    + ``V4L2_YCBCR_ENC_601``       +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
+ * +----------------------+---------------------------------+------------------------------+
+ * + YCbCr 4:4:4 12bits   + ``MEDIA_BUS_FMT_YUV12_1X36``    + ``V4L2_YCBCR_ENC_601``       +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
+ * +----------------------+---------------------------------+------------------------------+
+ * + YCbCr 4:4:4 16bits   + ``MEDIA_BUS_FMT_YUV16_1X48``    + ``V4L2_YCBCR_ENC_601``       +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_XV601``  +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_XV709``  +
+ * +----------------------+---------------------------------+------------------------------+
+ * + YCbCr 4:2:2 8bit     + ``MEDIA_BUS_FMT_UYVY8_1X16``    + ``V4L2_YCBCR_ENC_601``       +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
+ * +----------------------+---------------------------------+------------------------------+
+ * + YCbCr 4:2:2 10bits   + ``MEDIA_BUS_FMT_UYVY10_1X20``   + ``V4L2_YCBCR_ENC_601``       +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
+ * +----------------------+---------------------------------+------------------------------+
+ * + YCbCr 4:2:2 12bits   + ``MEDIA_BUS_FMT_UYVY12_1X24``   + ``V4L2_YCBCR_ENC_601``       +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
+ * +----------------------+---------------------------------+------------------------------+
+ * + YCbCr 4:2:0 8bit     + ``MEDIA_BUS_FMT_UYYVYY8_1X24``  + ``V4L2_YCBCR_ENC_601``       +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
+ * +----------------------+---------------------------------+------------------------------+
+ * + YCbCr 4:2:0 10bits   + ``MEDIA_BUS_FMT_UYYVYY10_1X30`` + ``V4L2_YCBCR_ENC_601``       +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
+ * +----------------------+---------------------------------+------------------------------+
+ * + YCbCr 4:2:0 12bits   + ``MEDIA_BUS_FMT_UYYVYY12_1X36`` + ``V4L2_YCBCR_ENC_601``       +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
+ * +----------------------+---------------------------------+------------------------------+
+ * + YCbCr 4:2:0 16bits   + ``MEDIA_BUS_FMT_UYYVYY16_1X48`` + ``V4L2_YCBCR_ENC_601``       +
+ * +                      +                                 + or ``V4L2_YCBCR_ENC_709``    +
+ * +----------------------+---------------------------------+------------------------------+
+ */
+
 enum {
 	DW_HDMI_RES_8,
 	DW_HDMI_RES_10,
@@ -62,6 +123,8 @@  struct dw_hdmi_plat_data {
 	struct regmap *regm;
 	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
 					   struct drm_display_mode *mode);
+	unsigned long input_bus_format;
+	unsigned long input_bus_encoding;
 
 	/* Vendor PHY support */
 	const struct dw_hdmi_phy_ops *phy_ops;