| From 9fe77147d40e0dc58e7297e79ba8b50e13b8269d Mon Sep 17 00:00:00 2001 | 
 | From: Maxime Ripard <maxime@cerno.tech> | 
 | Date: Thu, 19 Dec 2019 16:53:33 +0100 | 
 | Subject: [PATCH] drm/vc4: hdmi: Add PHY init and disable function | 
 |  | 
 | The HDMI PHY in the BCM2711 HDMI controller is significantly more | 
 | complicated to setup than in the older BCM283x SoCs. | 
 |  | 
 | Let's add hooks to enable and disable the PHY. | 
 |  | 
 | Signed-off-by: Maxime Ripard <maxime@cerno.tech> | 
 | --- | 
 |  drivers/gpu/drm/vc4/Makefile       |  1 + | 
 |  drivers/gpu/drm/vc4/vc4_hdmi.c     | 14 +++++++------- | 
 |  drivers/gpu/drm/vc4/vc4_hdmi.h     | 13 +++++++++++++ | 
 |  drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 25 +++++++++++++++++++++++++ | 
 |  4 files changed, 46 insertions(+), 7 deletions(-) | 
 |  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 
 |  | 
 | --- a/drivers/gpu/drm/vc4/Makefile | 
 | +++ b/drivers/gpu/drm/vc4/Makefile | 
 | @@ -13,6 +13,7 @@ vc4-y := \ | 
 |  	vc4_kms.o \ | 
 |  	vc4_gem.o \ | 
 |  	vc4_hdmi.o \ | 
 | +	vc4_hdmi_phy.o \ | 
 |  	vc4_vec.o \ | 
 |  	vc4_hvs.o \ | 
 |  	vc4_irq.o \ | 
 | --- a/drivers/gpu/drm/vc4/vc4_hdmi.c | 
 | +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c | 
 | @@ -324,7 +324,9 @@ static void vc4_hdmi_encoder_disable(str | 
 |   | 
 |  	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0); | 
 |   | 
 | -	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); | 
 | +	if (vc4_hdmi->variant->phy_disable) | 
 | +		vc4_hdmi->variant->phy_disable(vc4_hdmi); | 
 | + | 
 |  	HDMI_WRITE(HDMI_VID_CTL, | 
 |  		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); | 
 |   | 
 | @@ -384,12 +386,8 @@ static void vc4_hdmi_encoder_enable(stru | 
 |  	if (vc4_hdmi->variant->reset) | 
 |  		vc4_hdmi->variant->reset(vc4_hdmi); | 
 |   | 
 | -	/* PHY should be in reset, like | 
 | -	 * vc4_hdmi_encoder_disable() does. | 
 | -	 */ | 
 | -	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); | 
 | - | 
 | -	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0); | 
 | +	if (vc4_hdmi->variant->phy_init) | 
 | +		vc4_hdmi->variant->phy_init(vc4_hdmi, mode); | 
 |   | 
 |  	if (debug_dump_regs) { | 
 |  		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev); | 
 | @@ -1429,6 +1427,8 @@ static const struct vc4_hdmi_variant bcm | 
 |   | 
 |  	.init_resources		= vc4_hdmi_init_resources, | 
 |  	.reset			= vc4_hdmi_reset, | 
 | +	.phy_init		= vc4_hdmi_phy_init, | 
 | +	.phy_disable		= vc4_hdmi_phy_disable, | 
 |  }; | 
 |   | 
 |  static const struct of_device_id vc4_hdmi_dt_match[] = { | 
 | --- a/drivers/gpu/drm/vc4/vc4_hdmi.h | 
 | +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h | 
 | @@ -21,6 +21,8 @@ to_vc4_hdmi_encoder(struct drm_encoder * | 
 |  	return container_of(encoder, struct vc4_hdmi_encoder, base.base); | 
 |  } | 
 |   | 
 | +struct drm_display_mode; | 
 | + | 
 |  struct vc4_hdmi; | 
 |  struct vc4_hdmi_register; | 
 |   | 
 | @@ -38,6 +40,13 @@ struct vc4_hdmi_variant { | 
 |   | 
 |  	/* Callback to reset the HDMI block */ | 
 |  	void (*reset)(struct vc4_hdmi *vc4_hdmi); | 
 | + | 
 | +	/* Callback to initialize the PHY according to the mode */ | 
 | +	void (*phy_init)(struct vc4_hdmi *vc4_hdmi, | 
 | +			 struct drm_display_mode *mode); | 
 | + | 
 | +	/* Callback to disable the PHY */ | 
 | +	void (*phy_disable)(struct vc4_hdmi *vc4_hdmi); | 
 |  }; | 
 |   | 
 |  /* HDMI audio information */ | 
 | @@ -95,4 +104,8 @@ encoder_to_vc4_hdmi(struct drm_encoder * | 
 |  	return container_of(_encoder, struct vc4_hdmi, encoder); | 
 |  } | 
 |   | 
 | +void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, | 
 | +		       struct drm_display_mode *mode); | 
 | +void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); | 
 | + | 
 |  #endif /* _VC4_HDMI_H_ */ | 
 | --- /dev/null | 
 | +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 
 | @@ -0,0 +1,25 @@ | 
 | +// SPDX-License-Identifier: GPL-2.0 | 
 | +/* | 
 | + * Copyright (C) 2015 Broadcom | 
 | + * Copyright (c) 2014 The Linux Foundation. All rights reserved. | 
 | + * Copyright (C) 2013 Red Hat | 
 | + * Author: Rob Clark <robdclark@gmail.com> | 
 | + */ | 
 | + | 
 | +#include "vc4_hdmi.h" | 
 | +#include "vc4_hdmi_regs.h" | 
 | + | 
 | +void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode) | 
 | +{ | 
 | +	/* PHY should be in reset, like | 
 | +         * vc4_hdmi_encoder_disable() does. | 
 | +         */ | 
 | + | 
 | +	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); | 
 | +	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0); | 
 | +} | 
 | + | 
 | +void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) | 
 | +{ | 
 | +	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); | 
 | +} |