Re: [PATCH 4/5] drm/meson: Add YUV420 output support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Neil Armstrong <narmstrong@xxxxxxxxxxxx> writes:

> This patch adds support for the YUV420 output from the Amlogic Meson SoCs
> Video Processing Unit to the HDMI Controller.
>
> The YUV420 is obtained by generating a YUV444 pixel stream like
> the classic HDMI display modes, but then the Video Encoder output
> can be configured to down-sample the YUV444 pixel stream to a YUV420
> stream.
> In addition if pixel stream down-sampling, the Y Cb Cr components must
> also be mapped differently to align with the HDMI2.0 specifications.
>
> This mode needs a different clock generation scheme since the TMDS PHY
> clock must match the 10x ration with the YUV420 pixel clock, but

s/ration/ratio/

> the video encoder must run at 2x the pixel clock.
>
> This patch adds the TMDS PHY clock value in all the video clock setup
> in order to better support these specific uses cases and switch
> to the Common Clock framework for clocks handling in the future.
>
> When 420 is needed, it calls drm_bridge_format_set() for notify the
> bridge the input format has changed to YUV420.
>
> Signed-off-by: Neil Armstrong <narmstrong@xxxxxxxxxxxx>

Reviewed-by: Kevin Hilman <khilman@xxxxxxxxxxxx>

with a couple very minor nits to cleanup below...

> ---
>  drivers/gpu/drm/meson/meson_dw_hdmi.c   | 100 +++++++++++++++++++-----
>  drivers/gpu/drm/meson/meson_vclk.c      |  93 ++++++++++++++++------
>  drivers/gpu/drm/meson/meson_vclk.h      |   7 +-
>  drivers/gpu/drm/meson/meson_venc.c      |   6 +-
>  drivers/gpu/drm/meson/meson_venc.h      |  11 +++
>  drivers/gpu/drm/meson/meson_venc_cvbs.c |   3 +-
>  6 files changed, 174 insertions(+), 46 deletions(-)
>
> diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
> index 779da21143b9..5d67e2beba58 100644
> --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
> +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
> @@ -159,6 +159,7 @@ struct meson_dw_hdmi {
>  	struct regulator *hdmi_supply;
>  	u32 irq_stat;
>  	struct dw_hdmi *hdmi;
> +	unsigned long input_bus_format;
>  };
>  #define encoder_to_meson_dw_hdmi(x) \
>  	container_of(x, struct meson_dw_hdmi, encoder)
> @@ -308,6 +309,10 @@ static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
>  	struct meson_drm *priv = dw_hdmi->priv;
>  	unsigned int pixel_clock = mode->clock;
>  
> +	/* For 420, pixel clock is half unlike venc clock */
> +	if (dw_hdmi->input_bus_format == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
> +		pixel_clock /= 2;
> +
>  	if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
>  	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) {
>  		if (pixel_clock >= 371250) {
> @@ -383,25 +388,36 @@ static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
>  {
>  	struct meson_drm *priv = dw_hdmi->priv;
>  	int vic = drm_match_cea_mode(mode);
> +	unsigned int phy_freq;
>  	unsigned int vclk_freq;
>  	unsigned int venc_freq;
>  	unsigned int hdmi_freq;
>  
>  	vclk_freq = mode->clock;
>  
> +	/* For 420, pixel clock is half unlike venc clock */

minor grammar nit: put a comma after "half" (here and several other
places in the patch)

[...]

> @@ -722,17 +773,29 @@ static void meson_venc_hdmi_encoder_mode_set(struct drm_encoder *encoder,
>  	struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
>  	struct meson_drm *priv = dw_hdmi->priv;
>  	int vic = drm_match_cea_mode(mode);
> +	unsigned int ycrcb_map = MESON_VENC_MAP_CB_Y_CR;
> +	bool yuv420_mode = false;
>  
>  	DRM_DEBUG_DRIVER("\"%s\" vic %d\n", mode->name, vic);
>  
> +	if (dw_hdmi->input_bus_format == MEDIA_BUS_FMT_UYYVYY8_0_5X24) {
> +		ycrcb_map = MESON_VENC_MAP_CR_Y_CB;
> +		yuv420_mode = true;
> +	}
> +
>  	/* VENC + VENC-DVI Mode setup */
> -	meson_venc_hdmi_mode_set(priv, vic, mode);
> +	meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode);
>  
>  	/* VCLK Set clock */
>  	dw_hdmi_set_vclk(dw_hdmi, mode);
>  
> -	/* Setup YUV444 to HDMI-TX, no 10bit diphering */
> -	writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
> +	if (dw_hdmi->input_bus_format == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
> +		/* Setup YUV420 to HDMI-TX, no 10bit diphering */
> +		writel_relaxed(2 | (2 << 2),

nit: #define'd bitfields would be better, IIUC, I see these named as
"use average" and "Convert to 420" in the datasheet.

[...]

> @@ -1508,8 +1510,8 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
>  	writel_relaxed((use_enci ? 1 : 2) |
>  		       (mode->flags & DRM_MODE_FLAG_PHSYNC ? 1 << 2 : 0) |
>  		       (mode->flags & DRM_MODE_FLAG_PVSYNC ? 1 << 3 : 0) |
> -		       4 << 5 |
> -		       (venc_repeat ? 1 << 8 : 0) |
> +		       (ycrcb_map << 5) |
> +		       (venc_repeat || yuv420_mode ? 1 << 8 : 0) |

Lots of magic constants here, but I guess there's no new ones, so it's
just a(nother) reminder for a future readability cleanup.

>  		       (hdmi_repeat ? 1 << 12 : 0),
>  		       priv->io_base + _REG(VPU_HDMI_SETTING));
>  

Kevin
_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/dri-devel




[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux