diff mbox series

[2/2] drm/msm/hdmi: switch to drm_bridge_connector

Message ID 20211015001100.4193241-2-dmitry.baryshkov@linaro.org
State Accepted
Commit caa24223463dfd75702a24daac13c93edb4aafac
Headers show
Series [1/2] drm/msm/hdmi: use bulk regulator API | expand

Commit Message

Dmitry Baryshkov Oct. 15, 2021, 12:11 a.m. UTC
Merge old hdmi_bridge and hdmi_connector implementations. Use
drm_bridge_connector instead.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/Makefile                  |   2 +-
 drivers/gpu/drm/msm/hdmi/hdmi.c               |  12 +-
 drivers/gpu/drm/msm/hdmi/hdmi.h               |  19 ++-
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c        |  81 ++++++++-
 .../msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} | 154 ++----------------
 5 files changed, 109 insertions(+), 159 deletions(-)
 rename drivers/gpu/drm/msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} (62%)

-- 
2.33.0

Comments

Abhinav Kumar Oct. 15, 2021, 10:25 p.m. UTC | #1
Hi Dmitry

On 2021-10-14 17:11, Dmitry Baryshkov wrote:
> Merge old hdmi_bridge and hdmi_connector implementations. Use

> drm_bridge_connector instead.

> 

Can you please comment on the validation done on this change?
Has basic bootup been verified on db820c as thats the only platform 
which shall use this.

> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

> ---

>  drivers/gpu/drm/msm/Makefile                  |   2 +-

>  drivers/gpu/drm/msm/hdmi/hdmi.c               |  12 +-

>  drivers/gpu/drm/msm/hdmi/hdmi.h               |  19 ++-

>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c        |  81 ++++++++-

>  .../msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} | 154 ++----------------

>  5 files changed, 109 insertions(+), 159 deletions(-)

>  rename drivers/gpu/drm/msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} (62%)

> 

> diff --git a/drivers/gpu/drm/msm/Makefile 

> b/drivers/gpu/drm/msm/Makefile

> index 904535eda0c4..91b09cda8a9c 100644

> --- a/drivers/gpu/drm/msm/Makefile

> +++ b/drivers/gpu/drm/msm/Makefile

> @@ -19,7 +19,7 @@ msm-y := \

>  	hdmi/hdmi.o \

>  	hdmi/hdmi_audio.o \

>  	hdmi/hdmi_bridge.o \

> -	hdmi/hdmi_connector.o \

> +	hdmi/hdmi_hpd.o \

>  	hdmi/hdmi_i2c.o \

>  	hdmi/hdmi_phy.o \

>  	hdmi/hdmi_phy_8960.o \

> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c 

> b/drivers/gpu/drm/msm/hdmi/hdmi.c

> index db17a000d968..d1cf4df7188c 100644

> --- a/drivers/gpu/drm/msm/hdmi/hdmi.c

> +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c

> @@ -8,6 +8,8 @@

>  #include <linux/of_irq.h>

>  #include <linux/of_gpio.h>

> 

> +#include <drm/drm_bridge_connector.h>

> +

>  #include <sound/hdmi-codec.h>

>  #include "hdmi.h"

> 

> @@ -41,7 +43,7 @@ static irqreturn_t msm_hdmi_irq(int irq, void 

> *dev_id)

>  	struct hdmi *hdmi = dev_id;

> 

>  	/* Process HPD: */

> -	msm_hdmi_connector_irq(hdmi->connector);

> +	msm_hdmi_hpd_irq(hdmi->bridge);

> 

>  	/* Process DDC: */

>  	msm_hdmi_i2c_irq(hdmi->i2c);

> @@ -283,7 +285,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,

>  		goto fail;

>  	}

> 

> -	hdmi->connector = msm_hdmi_connector_init(hdmi);

> +	hdmi->connector = drm_bridge_connector_init(hdmi->dev, encoder);

>  	if (IS_ERR(hdmi->connector)) {

>  		ret = PTR_ERR(hdmi->connector);

>  		DRM_DEV_ERROR(dev->dev, "failed to create HDMI connector: %d\n", 

> ret);

> @@ -291,6 +293,8 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,

>  		goto fail;

>  	}

> 

> +	drm_connector_attach_encoder(hdmi->connector, hdmi->encoder);

> +

>  	hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);

>  	if (hdmi->irq < 0) {

>  		ret = hdmi->irq;

> @@ -307,7 +311,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,

>  		goto fail;

>  	}

> 

> -	ret = msm_hdmi_hpd_enable(hdmi->connector);

> +	drm_bridge_connector_enable_hpd(hdmi->connector);

> +

> +	ret = msm_hdmi_hpd_enable(hdmi->bridge);

>  	if (ret < 0) {

>  		DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);

>  		goto fail;

> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h 

> b/drivers/gpu/drm/msm/hdmi/hdmi.h

> index 82261078c6b1..736f348befb3 100644

> --- a/drivers/gpu/drm/msm/hdmi/hdmi.h

> +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h

> @@ -114,6 +114,13 @@ struct hdmi_platform_config {

>  	struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO];

>  };

> 

> +struct hdmi_bridge {

> +	struct drm_bridge base;

> +	struct hdmi *hdmi;

> +	struct work_struct hpd_work;

> +};

> +#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)

> +

>  void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on);

> 

>  static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data)

> @@ -230,13 +237,11 @@ void msm_hdmi_audio_set_sample_rate(struct hdmi

> *hdmi, int rate);

>  struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi);

>  void msm_hdmi_bridge_destroy(struct drm_bridge *bridge);

> 

> -/*

> - * hdmi connector:

> - */

> -

> -void msm_hdmi_connector_irq(struct drm_connector *connector);

> -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi);

> -int msm_hdmi_hpd_enable(struct drm_connector *connector);

> +void msm_hdmi_hpd_irq(struct drm_bridge *bridge);

> +enum drm_connector_status msm_hdmi_bridge_detect(

> +		struct drm_bridge *bridge);

> +int msm_hdmi_hpd_enable(struct drm_bridge *bridge);

> +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge);

> 

>  /*

>   * i2c adapter for ddc:

> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

> b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

> index f04eb4a70f0d..211b73dddf65 100644

> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

> @@ -5,17 +5,16 @@

>   */

> 

>  #include <linux/delay.h>

> +#include <drm/drm_bridge_connector.h>

> 

> +#include "msm_kms.h"

>  #include "hdmi.h"

> 

> -struct hdmi_bridge {

> -	struct drm_bridge base;

> -	struct hdmi *hdmi;

> -};

> -#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)

> -

>  void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)

>  {

> +	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

> +

> +	msm_hdmi_hpd_disable(hdmi_bridge);

>  }

> 

>  static void msm_hdmi_power_on(struct drm_bridge *bridge)

> @@ -251,14 +250,76 @@ static void msm_hdmi_bridge_mode_set(struct

> drm_bridge *bridge,

>  		msm_hdmi_audio_update(hdmi);

>  }

> 

> +static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge 

> *bridge,

> +		struct drm_connector *connector)

> +{

> +	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

> +	struct hdmi *hdmi = hdmi_bridge->hdmi;

> +	struct edid *edid;

> +	uint32_t hdmi_ctrl;

> +

> +	hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);

> +	hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);

> +

> +	edid = drm_get_edid(connector, hdmi->i2c);

> +

> +	hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);

> +

> +	hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);

> +

> +	return edid;

> +}

> +

> +static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct

> drm_bridge *bridge,

> +		const struct drm_display_info *info,

> +		const struct drm_display_mode *mode)

> +{

> +	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

> +	struct hdmi *hdmi = hdmi_bridge->hdmi;

> +	const struct hdmi_platform_config *config = hdmi->config;

> +	struct msm_drm_private *priv = bridge->dev->dev_private;

> +	struct msm_kms *kms = priv->kms;

> +	long actual, requested;

> +

> +	requested = 1000 * mode->clock;

> +	actual = kms->funcs->round_pixclk(kms,

> +			requested, hdmi_bridge->hdmi->encoder);

> +

> +	/* for mdp5/apq8074, we manage our own pixel clk (as opposed to

> +	 * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder

> +	 * instead):

> +	 */

> +	if (config->pwr_clk_cnt > 0)

> +		actual = clk_round_rate(hdmi->pwr_clks[0], actual);

> +

> +	DBG("requested=%ld, actual=%ld", requested, actual);

> +

> +	if (actual != requested)

> +		return MODE_CLOCK_RANGE;

> +

> +	return 0;

> +}

> +

>  static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {

>  		.pre_enable = msm_hdmi_bridge_pre_enable,

>  		.enable = msm_hdmi_bridge_enable,

>  		.disable = msm_hdmi_bridge_disable,

>  		.post_disable = msm_hdmi_bridge_post_disable,

>  		.mode_set = msm_hdmi_bridge_mode_set,

> +		.mode_valid = msm_hdmi_bridge_mode_valid,

> +		.get_edid = msm_hdmi_bridge_get_edid,

> +		.detect = msm_hdmi_bridge_detect,

>  };

> 

> +static void

> +msm_hdmi_hotplug_work(struct work_struct *work)

> +{

> +	struct hdmi_bridge *hdmi_bridge =

> +		container_of(work, struct hdmi_bridge, hpd_work);

> +	struct drm_bridge *bridge = &hdmi_bridge->base;

> +

> +	drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge));

> +}

> 

>  /* initialize bridge */

>  struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)

> @@ -275,11 +336,17 @@ struct drm_bridge *msm_hdmi_bridge_init(struct 

> hdmi *hdmi)

>  	}

> 

>  	hdmi_bridge->hdmi = hdmi;

> +	INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);

> 

>  	bridge = &hdmi_bridge->base;

>  	bridge->funcs = &msm_hdmi_bridge_funcs;

> +	bridge->ddc = hdmi->i2c;

> +	bridge->type = DRM_MODE_CONNECTOR_HDMIA;

> +	bridge->ops = DRM_BRIDGE_OP_HPD |

> +		DRM_BRIDGE_OP_DETECT |

> +		DRM_BRIDGE_OP_EDID;

> 

> -	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0);

> +	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL,

> DRM_BRIDGE_ATTACH_NO_CONNECTOR);

>  	if (ret)

>  		goto fail;

> 

> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c

> b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c

> similarity index 62%

> rename from drivers/gpu/drm/msm/hdmi/hdmi_connector.c

> rename to drivers/gpu/drm/msm/hdmi/hdmi_hpd.c

> index a7f729cdec7b..1cda7bf23b3b 100644

> --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c

> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c

> @@ -11,13 +11,6 @@

>  #include "msm_kms.h"

>  #include "hdmi.h"

> 

> -struct hdmi_connector {

> -	struct drm_connector base;

> -	struct hdmi *hdmi;

> -	struct work_struct hpd_work;

> -};

> -#define to_hdmi_connector(x) container_of(x, struct hdmi_connector, 

> base)

> -

>  static void msm_hdmi_phy_reset(struct hdmi *hdmi)

>  {

>  	unsigned int val;

> @@ -139,10 +132,10 @@ static void enable_hpd_clocks(struct hdmi *hdmi,

> bool enable)

>  	}

>  }

> 

> -int msm_hdmi_hpd_enable(struct drm_connector *connector)

> +int msm_hdmi_hpd_enable(struct drm_bridge *bridge)

>  {

> -	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

> -	struct hdmi *hdmi = hdmi_connector->hdmi;

> +	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

> +	struct hdmi *hdmi = hdmi_bridge->hdmi;

>  	const struct hdmi_platform_config *config = hdmi->config;

>  	struct device *dev = &hdmi->pdev->dev;

>  	uint32_t hpd_ctrl;

> @@ -199,9 +192,9 @@ int msm_hdmi_hpd_enable(struct drm_connector 

> *connector)

>  	return ret;

>  }

> 

> -static void hdp_disable(struct hdmi_connector *hdmi_connector)

> +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge)

>  {

> -	struct hdmi *hdmi = hdmi_connector->hdmi;

> +	struct hdmi *hdmi = hdmi_bridge->hdmi;

>  	const struct hdmi_platform_config *config = hdmi->config;

>  	struct device *dev = &hdmi->pdev->dev;

>  	int ret;

> @@ -227,19 +220,10 @@ static void hdp_disable(struct hdmi_connector

> *hdmi_connector)

>  		dev_warn(dev, "failed to disable hpd regulator: %d\n", ret);

>  }

> 

> -static void

> -msm_hdmi_hotplug_work(struct work_struct *work)

> -{

> -	struct hdmi_connector *hdmi_connector =

> -		container_of(work, struct hdmi_connector, hpd_work);

> -	struct drm_connector *connector = &hdmi_connector->base;

> -	drm_helper_hpd_irq_event(connector->dev);

> -}

> -

> -void msm_hdmi_connector_irq(struct drm_connector *connector)

> +void msm_hdmi_hpd_irq(struct drm_bridge *bridge)

>  {

> -	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

> -	struct hdmi *hdmi = hdmi_connector->hdmi;

> +	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

> +	struct hdmi *hdmi = hdmi_bridge->hdmi;

>  	uint32_t hpd_int_status, hpd_int_ctrl;

> 

>  	/* Process HPD: */

> @@ -262,7 +246,7 @@ void msm_hdmi_connector_irq(struct drm_connector 

> *connector)

>  			hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;

>  		hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);

> 

> -		queue_work(hdmi->workq, &hdmi_connector->hpd_work);

> +		queue_work(hdmi->workq, &hdmi_bridge->hpd_work);

>  	}

>  }

> 

> @@ -293,11 +277,11 @@ static enum drm_connector_status

> detect_gpio(struct hdmi *hdmi)

>  			connector_status_disconnected;

>  }

> 

> -static enum drm_connector_status hdmi_connector_detect(

> -		struct drm_connector *connector, bool force)

> +enum drm_connector_status msm_hdmi_bridge_detect(

> +		struct drm_bridge *bridge)

>  {

> -	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

> -	struct hdmi *hdmi = hdmi_connector->hdmi;

> +	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

> +	struct hdmi *hdmi = hdmi_bridge->hdmi;

>  	const struct hdmi_platform_config *config = hdmi->config;

>  	struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];

>  	enum drm_connector_status stat_gpio, stat_reg;

> @@ -331,115 +315,3 @@ static enum drm_connector_status 

> hdmi_connector_detect(

> 

>  	return stat_gpio;

>  }

> -

> -static void hdmi_connector_destroy(struct drm_connector *connector)

> -{

> -	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

> -

> -	hdp_disable(hdmi_connector);

> -

> -	drm_connector_cleanup(connector);

> -

> -	kfree(hdmi_connector);

> -}

> -

> -static int msm_hdmi_connector_get_modes(struct drm_connector 

> *connector)

> -{

> -	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

> -	struct hdmi *hdmi = hdmi_connector->hdmi;

> -	struct edid *edid;

> -	uint32_t hdmi_ctrl;

> -	int ret = 0;

> -

> -	hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);

> -	hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);

> -

> -	edid = drm_get_edid(connector, hdmi->i2c);

> -

> -	hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);

> -

> -	hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);

> -	drm_connector_update_edid_property(connector, edid);

> -

> -	if (edid) {

> -		ret = drm_add_edid_modes(connector, edid);

> -		kfree(edid);

> -	}

> -

> -	return ret;

> -}

> -

> -static int msm_hdmi_connector_mode_valid(struct drm_connector 

> *connector,

> -				 struct drm_display_mode *mode)

> -{

> -	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

> -	struct hdmi *hdmi = hdmi_connector->hdmi;

> -	const struct hdmi_platform_config *config = hdmi->config;

> -	struct msm_drm_private *priv = connector->dev->dev_private;

> -	struct msm_kms *kms = priv->kms;

> -	long actual, requested;

> -

> -	requested = 1000 * mode->clock;

> -	actual = kms->funcs->round_pixclk(kms,

> -			requested, hdmi_connector->hdmi->encoder);

> -

> -	/* for mdp5/apq8074, we manage our own pixel clk (as opposed to

> -	 * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder

> -	 * instead):

> -	 */

> -	if (config->pwr_clk_cnt > 0)

> -		actual = clk_round_rate(hdmi->pwr_clks[0], actual);

> -

> -	DBG("requested=%ld, actual=%ld", requested, actual);

> -

> -	if (actual != requested)

> -		return MODE_CLOCK_RANGE;

> -

> -	return 0;

> -}

> -

> -static const struct drm_connector_funcs hdmi_connector_funcs = {

> -	.detect = hdmi_connector_detect,

> -	.fill_modes = drm_helper_probe_single_connector_modes,

> -	.destroy = hdmi_connector_destroy,

> -	.reset = drm_atomic_helper_connector_reset,

> -	.atomic_duplicate_state = 

> drm_atomic_helper_connector_duplicate_state,

> -	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,

> -};

> -

> -static const struct drm_connector_helper_funcs

> msm_hdmi_connector_helper_funcs = {

> -	.get_modes = msm_hdmi_connector_get_modes,

> -	.mode_valid = msm_hdmi_connector_mode_valid,

> -};

> -

> -/* initialize connector */

> -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)

> -{

> -	struct drm_connector *connector = NULL;

> -	struct hdmi_connector *hdmi_connector;

> -

> -	hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);

> -	if (!hdmi_connector)

> -		return ERR_PTR(-ENOMEM);

> -

> -	hdmi_connector->hdmi = hdmi;

> -	INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);

> -

> -	connector = &hdmi_connector->base;

> -

> -	drm_connector_init_with_ddc(hdmi->dev, connector,

> -				    &hdmi_connector_funcs,

> -				    DRM_MODE_CONNECTOR_HDMIA,

> -				    hdmi->i2c);

> -	drm_connector_helper_add(connector, 

> &msm_hdmi_connector_helper_funcs);

> -

> -	connector->polled = DRM_CONNECTOR_POLL_CONNECT |

> -			DRM_CONNECTOR_POLL_DISCONNECT;

> -

> -	connector->interlace_allowed = 0;

> -	connector->doublescan_allowed = 0;

> -

> -	drm_connector_attach_encoder(connector, hdmi->encoder);

> -

> -	return connector;

> -}
Dmitry Baryshkov Oct. 16, 2021, 2:21 p.m. UTC | #2
On Sat, 16 Oct 2021 at 01:25, <abhinavk@codeaurora.org> wrote:
>

> Hi Dmitry

>

> On 2021-10-14 17:11, Dmitry Baryshkov wrote:

> > Merge old hdmi_bridge and hdmi_connector implementations. Use

> > drm_bridge_connector instead.

> >

> Can you please comment on the validation done on this change?

> Has basic bootup been verified on db820c as thats the only platform

> which shall use this.


Yes, this has been developed and validated on db820c

>

> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

> > ---

> >  drivers/gpu/drm/msm/Makefile                  |   2 +-

> >  drivers/gpu/drm/msm/hdmi/hdmi.c               |  12 +-

> >  drivers/gpu/drm/msm/hdmi/hdmi.h               |  19 ++-

> >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c        |  81 ++++++++-

> >  .../msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} | 154 ++----------------

> >  5 files changed, 109 insertions(+), 159 deletions(-)

> >  rename drivers/gpu/drm/msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} (62%)

> >

> > diff --git a/drivers/gpu/drm/msm/Makefile

> > b/drivers/gpu/drm/msm/Makefile

> > index 904535eda0c4..91b09cda8a9c 100644

> > --- a/drivers/gpu/drm/msm/Makefile

> > +++ b/drivers/gpu/drm/msm/Makefile

> > @@ -19,7 +19,7 @@ msm-y := \

> >       hdmi/hdmi.o \

> >       hdmi/hdmi_audio.o \

> >       hdmi/hdmi_bridge.o \

> > -     hdmi/hdmi_connector.o \

> > +     hdmi/hdmi_hpd.o \

> >       hdmi/hdmi_i2c.o \

> >       hdmi/hdmi_phy.o \

> >       hdmi/hdmi_phy_8960.o \

> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c

> > b/drivers/gpu/drm/msm/hdmi/hdmi.c

> > index db17a000d968..d1cf4df7188c 100644

> > --- a/drivers/gpu/drm/msm/hdmi/hdmi.c

> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c

> > @@ -8,6 +8,8 @@

> >  #include <linux/of_irq.h>

> >  #include <linux/of_gpio.h>

> >

> > +#include <drm/drm_bridge_connector.h>

> > +

> >  #include <sound/hdmi-codec.h>

> >  #include "hdmi.h"

> >

> > @@ -41,7 +43,7 @@ static irqreturn_t msm_hdmi_irq(int irq, void

> > *dev_id)

> >       struct hdmi *hdmi = dev_id;

> >

> >       /* Process HPD: */

> > -     msm_hdmi_connector_irq(hdmi->connector);

> > +     msm_hdmi_hpd_irq(hdmi->bridge);

> >

> >       /* Process DDC: */

> >       msm_hdmi_i2c_irq(hdmi->i2c);

> > @@ -283,7 +285,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,

> >               goto fail;

> >       }

> >

> > -     hdmi->connector = msm_hdmi_connector_init(hdmi);

> > +     hdmi->connector = drm_bridge_connector_init(hdmi->dev, encoder);

> >       if (IS_ERR(hdmi->connector)) {

> >               ret = PTR_ERR(hdmi->connector);

> >               DRM_DEV_ERROR(dev->dev, "failed to create HDMI connector: %d\n",

> > ret);

> > @@ -291,6 +293,8 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,

> >               goto fail;

> >       }

> >

> > +     drm_connector_attach_encoder(hdmi->connector, hdmi->encoder);

> > +

> >       hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);

> >       if (hdmi->irq < 0) {

> >               ret = hdmi->irq;

> > @@ -307,7 +311,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,

> >               goto fail;

> >       }

> >

> > -     ret = msm_hdmi_hpd_enable(hdmi->connector);

> > +     drm_bridge_connector_enable_hpd(hdmi->connector);

> > +

> > +     ret = msm_hdmi_hpd_enable(hdmi->bridge);

> >       if (ret < 0) {

> >               DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);

> >               goto fail;

> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h

> > b/drivers/gpu/drm/msm/hdmi/hdmi.h

> > index 82261078c6b1..736f348befb3 100644

> > --- a/drivers/gpu/drm/msm/hdmi/hdmi.h

> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h

> > @@ -114,6 +114,13 @@ struct hdmi_platform_config {

> >       struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO];

> >  };

> >

> > +struct hdmi_bridge {

> > +     struct drm_bridge base;

> > +     struct hdmi *hdmi;

> > +     struct work_struct hpd_work;

> > +};

> > +#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)

> > +

> >  void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on);

> >

> >  static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data)

> > @@ -230,13 +237,11 @@ void msm_hdmi_audio_set_sample_rate(struct hdmi

> > *hdmi, int rate);

> >  struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi);

> >  void msm_hdmi_bridge_destroy(struct drm_bridge *bridge);

> >

> > -/*

> > - * hdmi connector:

> > - */

> > -

> > -void msm_hdmi_connector_irq(struct drm_connector *connector);

> > -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi);

> > -int msm_hdmi_hpd_enable(struct drm_connector *connector);

> > +void msm_hdmi_hpd_irq(struct drm_bridge *bridge);

> > +enum drm_connector_status msm_hdmi_bridge_detect(

> > +             struct drm_bridge *bridge);

> > +int msm_hdmi_hpd_enable(struct drm_bridge *bridge);

> > +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge);

> >

> >  /*

> >   * i2c adapter for ddc:

> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

> > b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

> > index f04eb4a70f0d..211b73dddf65 100644

> > --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

> > @@ -5,17 +5,16 @@

> >   */

> >

> >  #include <linux/delay.h>

> > +#include <drm/drm_bridge_connector.h>

> >

> > +#include "msm_kms.h"

> >  #include "hdmi.h"

> >

> > -struct hdmi_bridge {

> > -     struct drm_bridge base;

> > -     struct hdmi *hdmi;

> > -};

> > -#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)

> > -

> >  void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)

> >  {

> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

> > +

> > +     msm_hdmi_hpd_disable(hdmi_bridge);

> >  }

> >

> >  static void msm_hdmi_power_on(struct drm_bridge *bridge)

> > @@ -251,14 +250,76 @@ static void msm_hdmi_bridge_mode_set(struct

> > drm_bridge *bridge,

> >               msm_hdmi_audio_update(hdmi);

> >  }

> >

> > +static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge

> > *bridge,

> > +             struct drm_connector *connector)

> > +{

> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;

> > +     struct edid *edid;

> > +     uint32_t hdmi_ctrl;

> > +

> > +     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);

> > +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);

> > +

> > +     edid = drm_get_edid(connector, hdmi->i2c);

> > +

> > +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);

> > +

> > +     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);

> > +

> > +     return edid;

> > +}

> > +

> > +static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct

> > drm_bridge *bridge,

> > +             const struct drm_display_info *info,

> > +             const struct drm_display_mode *mode)

> > +{

> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;

> > +     const struct hdmi_platform_config *config = hdmi->config;

> > +     struct msm_drm_private *priv = bridge->dev->dev_private;

> > +     struct msm_kms *kms = priv->kms;

> > +     long actual, requested;

> > +

> > +     requested = 1000 * mode->clock;

> > +     actual = kms->funcs->round_pixclk(kms,

> > +                     requested, hdmi_bridge->hdmi->encoder);

> > +

> > +     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to

> > +      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder

> > +      * instead):

> > +      */

> > +     if (config->pwr_clk_cnt > 0)

> > +             actual = clk_round_rate(hdmi->pwr_clks[0], actual);

> > +

> > +     DBG("requested=%ld, actual=%ld", requested, actual);

> > +

> > +     if (actual != requested)

> > +             return MODE_CLOCK_RANGE;

> > +

> > +     return 0;

> > +}

> > +

> >  static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {

> >               .pre_enable = msm_hdmi_bridge_pre_enable,

> >               .enable = msm_hdmi_bridge_enable,

> >               .disable = msm_hdmi_bridge_disable,

> >               .post_disable = msm_hdmi_bridge_post_disable,

> >               .mode_set = msm_hdmi_bridge_mode_set,

> > +             .mode_valid = msm_hdmi_bridge_mode_valid,

> > +             .get_edid = msm_hdmi_bridge_get_edid,

> > +             .detect = msm_hdmi_bridge_detect,

> >  };

> >

> > +static void

> > +msm_hdmi_hotplug_work(struct work_struct *work)

> > +{

> > +     struct hdmi_bridge *hdmi_bridge =

> > +             container_of(work, struct hdmi_bridge, hpd_work);

> > +     struct drm_bridge *bridge = &hdmi_bridge->base;

> > +

> > +     drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge));

> > +}

> >

> >  /* initialize bridge */

> >  struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)

> > @@ -275,11 +336,17 @@ struct drm_bridge *msm_hdmi_bridge_init(struct

> > hdmi *hdmi)

> >       }

> >

> >       hdmi_bridge->hdmi = hdmi;

> > +     INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);

> >

> >       bridge = &hdmi_bridge->base;

> >       bridge->funcs = &msm_hdmi_bridge_funcs;

> > +     bridge->ddc = hdmi->i2c;

> > +     bridge->type = DRM_MODE_CONNECTOR_HDMIA;

> > +     bridge->ops = DRM_BRIDGE_OP_HPD |

> > +             DRM_BRIDGE_OP_DETECT |

> > +             DRM_BRIDGE_OP_EDID;

> >

> > -     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0);

> > +     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL,

> > DRM_BRIDGE_ATTACH_NO_CONNECTOR);

> >       if (ret)

> >               goto fail;

> >

> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c

> > b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c

> > similarity index 62%

> > rename from drivers/gpu/drm/msm/hdmi/hdmi_connector.c

> > rename to drivers/gpu/drm/msm/hdmi/hdmi_hpd.c

> > index a7f729cdec7b..1cda7bf23b3b 100644

> > --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c

> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c

> > @@ -11,13 +11,6 @@

> >  #include "msm_kms.h"

> >  #include "hdmi.h"

> >

> > -struct hdmi_connector {

> > -     struct drm_connector base;

> > -     struct hdmi *hdmi;

> > -     struct work_struct hpd_work;

> > -};

> > -#define to_hdmi_connector(x) container_of(x, struct hdmi_connector,

> > base)

> > -

> >  static void msm_hdmi_phy_reset(struct hdmi *hdmi)

> >  {

> >       unsigned int val;

> > @@ -139,10 +132,10 @@ static void enable_hpd_clocks(struct hdmi *hdmi,

> > bool enable)

> >       }

> >  }

> >

> > -int msm_hdmi_hpd_enable(struct drm_connector *connector)

> > +int msm_hdmi_hpd_enable(struct drm_bridge *bridge)

> >  {

> > -     struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

> > -     struct hdmi *hdmi = hdmi_connector->hdmi;

> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;

> >       const struct hdmi_platform_config *config = hdmi->config;

> >       struct device *dev = &hdmi->pdev->dev;

> >       uint32_t hpd_ctrl;

> > @@ -199,9 +192,9 @@ int msm_hdmi_hpd_enable(struct drm_connector

> > *connector)

> >       return ret;

> >  }

> >

> > -static void hdp_disable(struct hdmi_connector *hdmi_connector)

> > +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge)

> >  {

> > -     struct hdmi *hdmi = hdmi_connector->hdmi;

> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;

> >       const struct hdmi_platform_config *config = hdmi->config;

> >       struct device *dev = &hdmi->pdev->dev;

> >       int ret;

> > @@ -227,19 +220,10 @@ static void hdp_disable(struct hdmi_connector

> > *hdmi_connector)

> >               dev_warn(dev, "failed to disable hpd regulator: %d\n", ret);

> >  }

> >

> > -static void

> > -msm_hdmi_hotplug_work(struct work_struct *work)

> > -{

> > -     struct hdmi_connector *hdmi_connector =

> > -             container_of(work, struct hdmi_connector, hpd_work);

> > -     struct drm_connector *connector = &hdmi_connector->base;

> > -     drm_helper_hpd_irq_event(connector->dev);

> > -}

> > -

> > -void msm_hdmi_connector_irq(struct drm_connector *connector)

> > +void msm_hdmi_hpd_irq(struct drm_bridge *bridge)

> >  {

> > -     struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

> > -     struct hdmi *hdmi = hdmi_connector->hdmi;

> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;

> >       uint32_t hpd_int_status, hpd_int_ctrl;

> >

> >       /* Process HPD: */

> > @@ -262,7 +246,7 @@ void msm_hdmi_connector_irq(struct drm_connector

> > *connector)

> >                       hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;

> >               hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);

> >

> > -             queue_work(hdmi->workq, &hdmi_connector->hpd_work);

> > +             queue_work(hdmi->workq, &hdmi_bridge->hpd_work);

> >       }

> >  }

> >

> > @@ -293,11 +277,11 @@ static enum drm_connector_status

> > detect_gpio(struct hdmi *hdmi)

> >                       connector_status_disconnected;

> >  }

> >

> > -static enum drm_connector_status hdmi_connector_detect(

> > -             struct drm_connector *connector, bool force)

> > +enum drm_connector_status msm_hdmi_bridge_detect(

> > +             struct drm_bridge *bridge)

> >  {

> > -     struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

> > -     struct hdmi *hdmi = hdmi_connector->hdmi;

> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;

> >       const struct hdmi_platform_config *config = hdmi->config;

> >       struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];

> >       enum drm_connector_status stat_gpio, stat_reg;

> > @@ -331,115 +315,3 @@ static enum drm_connector_status

> > hdmi_connector_detect(

> >

> >       return stat_gpio;

> >  }

> > -

> > -static void hdmi_connector_destroy(struct drm_connector *connector)

> > -{

> > -     struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

> > -

> > -     hdp_disable(hdmi_connector);

> > -

> > -     drm_connector_cleanup(connector);

> > -

> > -     kfree(hdmi_connector);

> > -}

> > -

> > -static int msm_hdmi_connector_get_modes(struct drm_connector

> > *connector)

> > -{

> > -     struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

> > -     struct hdmi *hdmi = hdmi_connector->hdmi;

> > -     struct edid *edid;

> > -     uint32_t hdmi_ctrl;

> > -     int ret = 0;

> > -

> > -     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);

> > -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);

> > -

> > -     edid = drm_get_edid(connector, hdmi->i2c);

> > -

> > -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);

> > -

> > -     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);

> > -     drm_connector_update_edid_property(connector, edid);

> > -

> > -     if (edid) {

> > -             ret = drm_add_edid_modes(connector, edid);

> > -             kfree(edid);

> > -     }

> > -

> > -     return ret;

> > -}

> > -

> > -static int msm_hdmi_connector_mode_valid(struct drm_connector

> > *connector,

> > -                              struct drm_display_mode *mode)

> > -{

> > -     struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

> > -     struct hdmi *hdmi = hdmi_connector->hdmi;

> > -     const struct hdmi_platform_config *config = hdmi->config;

> > -     struct msm_drm_private *priv = connector->dev->dev_private;

> > -     struct msm_kms *kms = priv->kms;

> > -     long actual, requested;

> > -

> > -     requested = 1000 * mode->clock;

> > -     actual = kms->funcs->round_pixclk(kms,

> > -                     requested, hdmi_connector->hdmi->encoder);

> > -

> > -     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to

> > -      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder

> > -      * instead):

> > -      */

> > -     if (config->pwr_clk_cnt > 0)

> > -             actual = clk_round_rate(hdmi->pwr_clks[0], actual);

> > -

> > -     DBG("requested=%ld, actual=%ld", requested, actual);

> > -

> > -     if (actual != requested)

> > -             return MODE_CLOCK_RANGE;

> > -

> > -     return 0;

> > -}

> > -

> > -static const struct drm_connector_funcs hdmi_connector_funcs = {

> > -     .detect = hdmi_connector_detect,

> > -     .fill_modes = drm_helper_probe_single_connector_modes,

> > -     .destroy = hdmi_connector_destroy,

> > -     .reset = drm_atomic_helper_connector_reset,

> > -     .atomic_duplicate_state =

> > drm_atomic_helper_connector_duplicate_state,

> > -     .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,

> > -};

> > -

> > -static const struct drm_connector_helper_funcs

> > msm_hdmi_connector_helper_funcs = {

> > -     .get_modes = msm_hdmi_connector_get_modes,

> > -     .mode_valid = msm_hdmi_connector_mode_valid,

> > -};

> > -

> > -/* initialize connector */

> > -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)

> > -{

> > -     struct drm_connector *connector = NULL;

> > -     struct hdmi_connector *hdmi_connector;

> > -

> > -     hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);

> > -     if (!hdmi_connector)

> > -             return ERR_PTR(-ENOMEM);

> > -

> > -     hdmi_connector->hdmi = hdmi;

> > -     INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);

> > -

> > -     connector = &hdmi_connector->base;

> > -

> > -     drm_connector_init_with_ddc(hdmi->dev, connector,

> > -                                 &hdmi_connector_funcs,

> > -                                 DRM_MODE_CONNECTOR_HDMIA,

> > -                                 hdmi->i2c);

> > -     drm_connector_helper_add(connector,

> > &msm_hdmi_connector_helper_funcs);

> > -

> > -     connector->polled = DRM_CONNECTOR_POLL_CONNECT |

> > -                     DRM_CONNECTOR_POLL_DISCONNECT;

> > -

> > -     connector->interlace_allowed = 0;

> > -     connector->doublescan_allowed = 0;

> > -

> > -     drm_connector_attach_encoder(connector, hdmi->encoder);

> > -

> > -     return connector;

> > -}




-- 
With best wishes
Dmitry
Abhinav Kumar Oct. 18, 2021, 11:54 p.m. UTC | #3
On 2021-10-16 07:21, Dmitry Baryshkov wrote:
> On Sat, 16 Oct 2021 at 01:25, <abhinavk@codeaurora.org> wrote:

>> 

>> Hi Dmitry

>> 

>> On 2021-10-14 17:11, Dmitry Baryshkov wrote:

>> > Merge old hdmi_bridge and hdmi_connector implementations. Use

>> > drm_bridge_connector instead.

>> >

>> Can you please comment on the validation done on this change?

>> Has basic bootup been verified on db820c as thats the only platform

>> which shall use this.

> 

> Yes, this has been developed and validated on db820c

Thanks for confirming.
> 

>> 

>> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

>> > ---

>> >  drivers/gpu/drm/msm/Makefile                  |   2 +-

>> >  drivers/gpu/drm/msm/hdmi/hdmi.c               |  12 +-

>> >  drivers/gpu/drm/msm/hdmi/hdmi.h               |  19 ++-

>> >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c        |  81 ++++++++-

>> >  .../msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} | 154 ++----------------

>> >  5 files changed, 109 insertions(+), 159 deletions(-)

>> >  rename drivers/gpu/drm/msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} (62%)

>> >

>> > diff --git a/drivers/gpu/drm/msm/Makefile

>> > b/drivers/gpu/drm/msm/Makefile

>> > index 904535eda0c4..91b09cda8a9c 100644

>> > --- a/drivers/gpu/drm/msm/Makefile

>> > +++ b/drivers/gpu/drm/msm/Makefile

>> > @@ -19,7 +19,7 @@ msm-y := \

>> >       hdmi/hdmi.o \

>> >       hdmi/hdmi_audio.o \

>> >       hdmi/hdmi_bridge.o \

>> > -     hdmi/hdmi_connector.o \

>> > +     hdmi/hdmi_hpd.o \

>> >       hdmi/hdmi_i2c.o \

>> >       hdmi/hdmi_phy.o \

>> >       hdmi/hdmi_phy_8960.o \

>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c

>> > b/drivers/gpu/drm/msm/hdmi/hdmi.c

>> > index db17a000d968..d1cf4df7188c 100644

>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi.c

>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c

>> > @@ -8,6 +8,8 @@

>> >  #include <linux/of_irq.h>

>> >  #include <linux/of_gpio.h>

>> >

>> > +#include <drm/drm_bridge_connector.h>

>> > +

>> >  #include <sound/hdmi-codec.h>

>> >  #include "hdmi.h"

>> >

>> > @@ -41,7 +43,7 @@ static irqreturn_t msm_hdmi_irq(int irq, void

>> > *dev_id)

>> >       struct hdmi *hdmi = dev_id;

>> >

>> >       /* Process HPD: */

>> > -     msm_hdmi_connector_irq(hdmi->connector);

>> > +     msm_hdmi_hpd_irq(hdmi->bridge);

>> >

>> >       /* Process DDC: */

>> >       msm_hdmi_i2c_irq(hdmi->i2c);

>> > @@ -283,7 +285,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,

>> >               goto fail;

>> >       }

>> >

>> > -     hdmi->connector = msm_hdmi_connector_init(hdmi);

>> > +     hdmi->connector = drm_bridge_connector_init(hdmi->dev, encoder);

>> >       if (IS_ERR(hdmi->connector)) {

>> >               ret = PTR_ERR(hdmi->connector);

>> >               DRM_DEV_ERROR(dev->dev, "failed to create HDMI connector: %d\n",

>> > ret);

>> > @@ -291,6 +293,8 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,

>> >               goto fail;

>> >       }

>> >

>> > +     drm_connector_attach_encoder(hdmi->connector, hdmi->encoder);

>> > +

>> >       hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);

>> >       if (hdmi->irq < 0) {

>> >               ret = hdmi->irq;

>> > @@ -307,7 +311,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,

>> >               goto fail;

>> >       }

>> >

>> > -     ret = msm_hdmi_hpd_enable(hdmi->connector);

>> > +     drm_bridge_connector_enable_hpd(hdmi->connector);

>> > +

>> > +     ret = msm_hdmi_hpd_enable(hdmi->bridge);

>> >       if (ret < 0) {

>> >               DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);

>> >               goto fail;

>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h

>> > b/drivers/gpu/drm/msm/hdmi/hdmi.h

>> > index 82261078c6b1..736f348befb3 100644

>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi.h

>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h

>> > @@ -114,6 +114,13 @@ struct hdmi_platform_config {

>> >       struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO];

>> >  };

>> >

>> > +struct hdmi_bridge {

>> > +     struct drm_bridge base;

>> > +     struct hdmi *hdmi;

>> > +     struct work_struct hpd_work;

>> > +};

>> > +#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)

>> > +

>> >  void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on);

>> >

>> >  static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data)

>> > @@ -230,13 +237,11 @@ void msm_hdmi_audio_set_sample_rate(struct hdmi

>> > *hdmi, int rate);

>> >  struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi);

>> >  void msm_hdmi_bridge_destroy(struct drm_bridge *bridge);

>> >

>> > -/*

>> > - * hdmi connector:

>> > - */

>> > -

>> > -void msm_hdmi_connector_irq(struct drm_connector *connector);

>> > -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi);

>> > -int msm_hdmi_hpd_enable(struct drm_connector *connector);

>> > +void msm_hdmi_hpd_irq(struct drm_bridge *bridge);

>> > +enum drm_connector_status msm_hdmi_bridge_detect(

>> > +             struct drm_bridge *bridge);

>> > +int msm_hdmi_hpd_enable(struct drm_bridge *bridge);

>> > +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge);

>> >

>> >  /*

>> >   * i2c adapter for ddc:

>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

>> > b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

>> > index f04eb4a70f0d..211b73dddf65 100644

>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c

>> > @@ -5,17 +5,16 @@

>> >   */

>> >

>> >  #include <linux/delay.h>

>> > +#include <drm/drm_bridge_connector.h>

>> >

>> > +#include "msm_kms.h"

>> >  #include "hdmi.h"

>> >

>> > -struct hdmi_bridge {

>> > -     struct drm_bridge base;

>> > -     struct hdmi *hdmi;

>> > -};

>> > -#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)

>> > -

>> >  void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)

>> >  {

>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

>> > +

>> > +     msm_hdmi_hpd_disable(hdmi_bridge);

>> >  }

>> >

>> >  static void msm_hdmi_power_on(struct drm_bridge *bridge)

>> > @@ -251,14 +250,76 @@ static void msm_hdmi_bridge_mode_set(struct

>> > drm_bridge *bridge,

>> >               msm_hdmi_audio_update(hdmi);

>> >  }

>> >

>> > +static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge

>> > *bridge,

>> > +             struct drm_connector *connector)

>> > +{

>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;

>> > +     struct edid *edid;

>> > +     uint32_t hdmi_ctrl;

>> > +

>> > +     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);

>> > +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);

>> > +

>> > +     edid = drm_get_edid(connector, hdmi->i2c);

>> > +

>> > +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);

>> > +

>> > +     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);

>> > +

>> > +     return edid;

>> > +}

>> > +

>> > +static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct

>> > drm_bridge *bridge,

>> > +             const struct drm_display_info *info,

>> > +             const struct drm_display_mode *mode)

>> > +{

>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;

>> > +     const struct hdmi_platform_config *config = hdmi->config;

>> > +     struct msm_drm_private *priv = bridge->dev->dev_private;

>> > +     struct msm_kms *kms = priv->kms;

>> > +     long actual, requested;

>> > +

>> > +     requested = 1000 * mode->clock;

>> > +     actual = kms->funcs->round_pixclk(kms,

>> > +                     requested, hdmi_bridge->hdmi->encoder);

>> > +

>> > +     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to

>> > +      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder

>> > +      * instead):

>> > +      */

>> > +     if (config->pwr_clk_cnt > 0)

>> > +             actual = clk_round_rate(hdmi->pwr_clks[0], actual);

>> > +

>> > +     DBG("requested=%ld, actual=%ld", requested, actual);

>> > +

>> > +     if (actual != requested)

>> > +             return MODE_CLOCK_RANGE;

>> > +

>> > +     return 0;

>> > +}

>> > +

>> >  static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {

>> >               .pre_enable = msm_hdmi_bridge_pre_enable,

>> >               .enable = msm_hdmi_bridge_enable,

>> >               .disable = msm_hdmi_bridge_disable,

>> >               .post_disable = msm_hdmi_bridge_post_disable,

>> >               .mode_set = msm_hdmi_bridge_mode_set,

>> > +             .mode_valid = msm_hdmi_bridge_mode_valid,

>> > +             .get_edid = msm_hdmi_bridge_get_edid,

>> > +             .detect = msm_hdmi_bridge_detect,

>> >  };

>> >

>> > +static void

>> > +msm_hdmi_hotplug_work(struct work_struct *work)

>> > +{

>> > +     struct hdmi_bridge *hdmi_bridge =

>> > +             container_of(work, struct hdmi_bridge, hpd_work);

>> > +     struct drm_bridge *bridge = &hdmi_bridge->base;

>> > +

>> > +     drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge));

>> > +}

>> >

>> >  /* initialize bridge */

>> >  struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)

>> > @@ -275,11 +336,17 @@ struct drm_bridge *msm_hdmi_bridge_init(struct

>> > hdmi *hdmi)

>> >       }

>> >

>> >       hdmi_bridge->hdmi = hdmi;

>> > +     INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);

>> >

>> >       bridge = &hdmi_bridge->base;

>> >       bridge->funcs = &msm_hdmi_bridge_funcs;

>> > +     bridge->ddc = hdmi->i2c;

>> > +     bridge->type = DRM_MODE_CONNECTOR_HDMIA;

>> > +     bridge->ops = DRM_BRIDGE_OP_HPD |

>> > +             DRM_BRIDGE_OP_DETECT |

>> > +             DRM_BRIDGE_OP_EDID;

Please correct me if wrong here. When we set DRM_BRIDGE_OP_HPD, it means 
we need to
set the hpd_enable and hpd_disable callbacks. I am not seeing those 
being set.

707 	 * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and 
hot-unplug
708 	 * without requiring polling. Bridges that set this flag shall
709 	 * implement the &drm_bridge_funcs->hpd_enable and
710 	 * &drm_bridge_funcs->hpd_disable callbacks if they support 
enabling
711 	 * and disabling hot-plug detection dynamically.
712 	 */
713 	DRM_BRIDGE_OP_HPD = BIT(2),

So when drm_bridge_connector_enable_hpd() is called, its a no-op as 
hpd_enable() callback
is not set.

msm_hdmi_hpd_enable() actually enables the HPD logic which is getting 
called from msm_hdmi_modeset_init()
and not from hpd_enable().

In that case, do we need to set DRM_BRIDGE_OP_HPD for this? If we dont, 
what will happen?



>> >

>> > -     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0);

>> > +     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL,

>> > DRM_BRIDGE_ATTACH_NO_CONNECTOR);

>> >       if (ret)

>> >               goto fail;

>> >

>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c

>> > b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c

>> > similarity index 62%

>> > rename from drivers/gpu/drm/msm/hdmi/hdmi_connector.c

>> > rename to drivers/gpu/drm/msm/hdmi/hdmi_hpd.c

>> > index a7f729cdec7b..1cda7bf23b3b 100644

>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c

>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c

>> > @@ -11,13 +11,6 @@

>> >  #include "msm_kms.h"

>> >  #include "hdmi.h"

>> >

>> > -struct hdmi_connector {

>> > -     struct drm_connector base;

>> > -     struct hdmi *hdmi;

>> > -     struct work_struct hpd_work;

>> > -};

>> > -#define to_hdmi_connector(x) container_of(x, struct hdmi_connector,

>> > base)

>> > -

>> >  static void msm_hdmi_phy_reset(struct hdmi *hdmi)

>> >  {

>> >       unsigned int val;

>> > @@ -139,10 +132,10 @@ static void enable_hpd_clocks(struct hdmi *hdmi,

>> > bool enable)

>> >       }

>> >  }

>> >

>> > -int msm_hdmi_hpd_enable(struct drm_connector *connector)

>> > +int msm_hdmi_hpd_enable(struct drm_bridge *bridge)

>> >  {

>> > -     struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;

>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;

>> >       const struct hdmi_platform_config *config = hdmi->config;

>> >       struct device *dev = &hdmi->pdev->dev;

>> >       uint32_t hpd_ctrl;

>> > @@ -199,9 +192,9 @@ int msm_hdmi_hpd_enable(struct drm_connector

>> > *connector)

>> >       return ret;

>> >  }

>> >

>> > -static void hdp_disable(struct hdmi_connector *hdmi_connector)

>> > +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge)

>> >  {

>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;

>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;

>> >       const struct hdmi_platform_config *config = hdmi->config;

>> >       struct device *dev = &hdmi->pdev->dev;

>> >       int ret;

>> > @@ -227,19 +220,10 @@ static void hdp_disable(struct hdmi_connector

>> > *hdmi_connector)

>> >               dev_warn(dev, "failed to disable hpd regulator: %d\n", ret);

>> >  }

>> >

>> > -static void

>> > -msm_hdmi_hotplug_work(struct work_struct *work)

>> > -{

>> > -     struct hdmi_connector *hdmi_connector =

>> > -             container_of(work, struct hdmi_connector, hpd_work);

>> > -     struct drm_connector *connector = &hdmi_connector->base;

>> > -     drm_helper_hpd_irq_event(connector->dev);

>> > -}

>> > -

>> > -void msm_hdmi_connector_irq(struct drm_connector *connector)

>> > +void msm_hdmi_hpd_irq(struct drm_bridge *bridge)

>> >  {

>> > -     struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;

>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;

>> >       uint32_t hpd_int_status, hpd_int_ctrl;

>> >

>> >       /* Process HPD: */

>> > @@ -262,7 +246,7 @@ void msm_hdmi_connector_irq(struct drm_connector

>> > *connector)

>> >                       hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;

>> >               hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);

>> >

>> > -             queue_work(hdmi->workq, &hdmi_connector->hpd_work);

>> > +             queue_work(hdmi->workq, &hdmi_bridge->hpd_work);

>> >       }

>> >  }

>> >

>> > @@ -293,11 +277,11 @@ static enum drm_connector_status

>> > detect_gpio(struct hdmi *hdmi)

>> >                       connector_status_disconnected;

>> >  }

>> >

>> > -static enum drm_connector_status hdmi_connector_detect(

>> > -             struct drm_connector *connector, bool force)

>> > +enum drm_connector_status msm_hdmi_bridge_detect(

>> > +             struct drm_bridge *bridge)

>> >  {

>> > -     struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;

>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);

>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;

>> >       const struct hdmi_platform_config *config = hdmi->config;

>> >       struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];

>> >       enum drm_connector_status stat_gpio, stat_reg;

>> > @@ -331,115 +315,3 @@ static enum drm_connector_status

>> > hdmi_connector_detect(

>> >

>> >       return stat_gpio;

>> >  }

>> > -

>> > -static void hdmi_connector_destroy(struct drm_connector *connector)

>> > -{

>> > -     struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

>> > -

>> > -     hdp_disable(hdmi_connector);

>> > -

>> > -     drm_connector_cleanup(connector);

>> > -

>> > -     kfree(hdmi_connector);

>> > -}

>> > -

>> > -static int msm_hdmi_connector_get_modes(struct drm_connector

>> > *connector)

>> > -{

>> > -     struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;

>> > -     struct edid *edid;

>> > -     uint32_t hdmi_ctrl;

>> > -     int ret = 0;

>> > -

>> > -     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);

>> > -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);

>> > -

>> > -     edid = drm_get_edid(connector, hdmi->i2c);

>> > -

>> > -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);

>> > -

>> > -     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);

>> > -     drm_connector_update_edid_property(connector, edid);

>> > -

>> > -     if (edid) {

>> > -             ret = drm_add_edid_modes(connector, edid);

>> > -             kfree(edid);

>> > -     }

>> > -

>> > -     return ret;

>> > -}

>> > -

>> > -static int msm_hdmi_connector_mode_valid(struct drm_connector

>> > *connector,

>> > -                              struct drm_display_mode *mode)

>> > -{

>> > -     struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;

>> > -     const struct hdmi_platform_config *config = hdmi->config;

>> > -     struct msm_drm_private *priv = connector->dev->dev_private;

>> > -     struct msm_kms *kms = priv->kms;

>> > -     long actual, requested;

>> > -

>> > -     requested = 1000 * mode->clock;

>> > -     actual = kms->funcs->round_pixclk(kms,

>> > -                     requested, hdmi_connector->hdmi->encoder);

>> > -

>> > -     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to

>> > -      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder

>> > -      * instead):

>> > -      */

>> > -     if (config->pwr_clk_cnt > 0)

>> > -             actual = clk_round_rate(hdmi->pwr_clks[0], actual);

>> > -

>> > -     DBG("requested=%ld, actual=%ld", requested, actual);

>> > -

>> > -     if (actual != requested)

>> > -             return MODE_CLOCK_RANGE;

>> > -

>> > -     return 0;

>> > -}

>> > -

>> > -static const struct drm_connector_funcs hdmi_connector_funcs = {

>> > -     .detect = hdmi_connector_detect,

>> > -     .fill_modes = drm_helper_probe_single_connector_modes,

>> > -     .destroy = hdmi_connector_destroy,

>> > -     .reset = drm_atomic_helper_connector_reset,

>> > -     .atomic_duplicate_state =

>> > drm_atomic_helper_connector_duplicate_state,

>> > -     .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,

>> > -};

>> > -

>> > -static const struct drm_connector_helper_funcs

>> > msm_hdmi_connector_helper_funcs = {

>> > -     .get_modes = msm_hdmi_connector_get_modes,

>> > -     .mode_valid = msm_hdmi_connector_mode_valid,

>> > -};

>> > -

>> > -/* initialize connector */

>> > -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)

>> > -{

>> > -     struct drm_connector *connector = NULL;

>> > -     struct hdmi_connector *hdmi_connector;

>> > -

>> > -     hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);

>> > -     if (!hdmi_connector)

>> > -             return ERR_PTR(-ENOMEM);

>> > -

>> > -     hdmi_connector->hdmi = hdmi;

>> > -     INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);

>> > -

>> > -     connector = &hdmi_connector->base;

>> > -

>> > -     drm_connector_init_with_ddc(hdmi->dev, connector,

>> > -                                 &hdmi_connector_funcs,

>> > -                                 DRM_MODE_CONNECTOR_HDMIA,

>> > -                                 hdmi->i2c);

>> > -     drm_connector_helper_add(connector,

>> > &msm_hdmi_connector_helper_funcs);

>> > -

>> > -     connector->polled = DRM_CONNECTOR_POLL_CONNECT |

>> > -                     DRM_CONNECTOR_POLL_DISCONNECT;

>> > -

>> > -     connector->interlace_allowed = 0;

>> > -     connector->doublescan_allowed = 0;

>> > -

>> > -     drm_connector_attach_encoder(connector, hdmi->encoder);

>> > -

>> > -     return connector;

>> > -}
Dmitry Baryshkov Nov. 25, 2021, 12:50 p.m. UTC | #4
On 19/10/2021 02:54, abhinavk@codeaurora.org wrote:
> On 2021-10-16 07:21, Dmitry Baryshkov wrote:
>> On Sat, 16 Oct 2021 at 01:25, <abhinavk@codeaurora.org> wrote:
>>>
>>> Hi Dmitry
>>>
>>> On 2021-10-14 17:11, Dmitry Baryshkov wrote:
>>> > Merge old hdmi_bridge and hdmi_connector implementations. Use
>>> > drm_bridge_connector instead.
>>> >
>>> Can you please comment on the validation done on this change?
>>> Has basic bootup been verified on db820c as thats the only platform
>>> which shall use this.
>>
>> Yes, this has been developed and validated on db820c
> Thanks for confirming.
>>
>>>
>>> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>> > ---
>>> >  drivers/gpu/drm/msm/Makefile                  |   2 +-
>>> >  drivers/gpu/drm/msm/hdmi/hdmi.c               |  12 +-
>>> >  drivers/gpu/drm/msm/hdmi/hdmi.h               |  19 ++-
>>> >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c        |  81 ++++++++-
>>> >  .../msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} | 154 
>>> ++----------------
>>> >  5 files changed, 109 insertions(+), 159 deletions(-)
>>> >  rename drivers/gpu/drm/msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} 
>>> (62%)
>>> >
>>> > diff --git a/drivers/gpu/drm/msm/Makefile
>>> > b/drivers/gpu/drm/msm/Makefile
>>> > index 904535eda0c4..91b09cda8a9c 100644
>>> > --- a/drivers/gpu/drm/msm/Makefile
>>> > +++ b/drivers/gpu/drm/msm/Makefile
>>> > @@ -19,7 +19,7 @@ msm-y := \
>>> >       hdmi/hdmi.o \
>>> >       hdmi/hdmi_audio.o \
>>> >       hdmi/hdmi_bridge.o \
>>> > -     hdmi/hdmi_connector.o \
>>> > +     hdmi/hdmi_hpd.o \
>>> >       hdmi/hdmi_i2c.o \
>>> >       hdmi/hdmi_phy.o \
>>> >       hdmi/hdmi_phy_8960.o \
>>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c
>>> > b/drivers/gpu/drm/msm/hdmi/hdmi.c
>>> > index db17a000d968..d1cf4df7188c 100644
>>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi.c
>>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
>>> > @@ -8,6 +8,8 @@
>>> >  #include <linux/of_irq.h>
>>> >  #include <linux/of_gpio.h>
>>> >
>>> > +#include <drm/drm_bridge_connector.h>
>>> > +
>>> >  #include <sound/hdmi-codec.h>
>>> >  #include "hdmi.h"
>>> >
>>> > @@ -41,7 +43,7 @@ static irqreturn_t msm_hdmi_irq(int irq, void
>>> > *dev_id)
>>> >       struct hdmi *hdmi = dev_id;
>>> >
>>> >       /* Process HPD: */
>>> > -     msm_hdmi_connector_irq(hdmi->connector);
>>> > +     msm_hdmi_hpd_irq(hdmi->bridge);
>>> >
>>> >       /* Process DDC: */
>>> >       msm_hdmi_i2c_irq(hdmi->i2c);
>>> > @@ -283,7 +285,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
>>> >               goto fail;
>>> >       }
>>> >
>>> > -     hdmi->connector = msm_hdmi_connector_init(hdmi);
>>> > +     hdmi->connector = drm_bridge_connector_init(hdmi->dev, encoder);
>>> >       if (IS_ERR(hdmi->connector)) {
>>> >               ret = PTR_ERR(hdmi->connector);
>>> >               DRM_DEV_ERROR(dev->dev, "failed to create HDMI 
>>> connector: %d\n",
>>> > ret);
>>> > @@ -291,6 +293,8 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
>>> >               goto fail;
>>> >       }
>>> >
>>> > +     drm_connector_attach_encoder(hdmi->connector, hdmi->encoder);
>>> > +
>>> >       hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
>>> >       if (hdmi->irq < 0) {
>>> >               ret = hdmi->irq;
>>> > @@ -307,7 +311,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
>>> >               goto fail;
>>> >       }
>>> >
>>> > -     ret = msm_hdmi_hpd_enable(hdmi->connector);
>>> > +     drm_bridge_connector_enable_hpd(hdmi->connector);
>>> > +
>>> > +     ret = msm_hdmi_hpd_enable(hdmi->bridge);
>>> >       if (ret < 0) {
>>> >               DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable 
>>> HPD: %d\n", ret);
>>> >               goto fail;
>>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h
>>> > b/drivers/gpu/drm/msm/hdmi/hdmi.h
>>> > index 82261078c6b1..736f348befb3 100644
>>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi.h
>>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
>>> > @@ -114,6 +114,13 @@ struct hdmi_platform_config {
>>> >       struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO];
>>> >  };
>>> >
>>> > +struct hdmi_bridge {
>>> > +     struct drm_bridge base;
>>> > +     struct hdmi *hdmi;
>>> > +     struct work_struct hpd_work;
>>> > +};
>>> > +#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
>>> > +
>>> >  void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on);
>>> >
>>> >  static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data)
>>> > @@ -230,13 +237,11 @@ void msm_hdmi_audio_set_sample_rate(struct hdmi
>>> > *hdmi, int rate);
>>> >  struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi);
>>> >  void msm_hdmi_bridge_destroy(struct drm_bridge *bridge);
>>> >
>>> > -/*
>>> > - * hdmi connector:
>>> > - */
>>> > -
>>> > -void msm_hdmi_connector_irq(struct drm_connector *connector);
>>> > -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi);
>>> > -int msm_hdmi_hpd_enable(struct drm_connector *connector);
>>> > +void msm_hdmi_hpd_irq(struct drm_bridge *bridge);
>>> > +enum drm_connector_status msm_hdmi_bridge_detect(
>>> > +             struct drm_bridge *bridge);
>>> > +int msm_hdmi_hpd_enable(struct drm_bridge *bridge);
>>> > +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge);
>>> >
>>> >  /*
>>> >   * i2c adapter for ddc:
>>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>> > b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>> > index f04eb4a70f0d..211b73dddf65 100644
>>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>> > @@ -5,17 +5,16 @@
>>> >   */
>>> >
>>> >  #include <linux/delay.h>
>>> > +#include <drm/drm_bridge_connector.h>
>>> >
>>> > +#include "msm_kms.h"
>>> >  #include "hdmi.h"
>>> >
>>> > -struct hdmi_bridge {
>>> > -     struct drm_bridge base;
>>> > -     struct hdmi *hdmi;
>>> > -};
>>> > -#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
>>> > -
>>> >  void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)
>>> >  {
>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>> > +
>>> > +     msm_hdmi_hpd_disable(hdmi_bridge);
>>> >  }
>>> >
>>> >  static void msm_hdmi_power_on(struct drm_bridge *bridge)
>>> > @@ -251,14 +250,76 @@ static void msm_hdmi_bridge_mode_set(struct
>>> > drm_bridge *bridge,
>>> >               msm_hdmi_audio_update(hdmi);
>>> >  }
>>> >
>>> > +static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge
>>> > *bridge,
>>> > +             struct drm_connector *connector)
>>> > +{
>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>> > +     struct edid *edid;
>>> > +     uint32_t hdmi_ctrl;
>>> > +
>>> > +     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
>>> > +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
>>> > +
>>> > +     edid = drm_get_edid(connector, hdmi->i2c);
>>> > +
>>> > +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
>>> > +
>>> > +     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
>>> > +
>>> > +     return edid;
>>> > +}
>>> > +
>>> > +static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct
>>> > drm_bridge *bridge,
>>> > +             const struct drm_display_info *info,
>>> > +             const struct drm_display_mode *mode)
>>> > +{
>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>> > +     const struct hdmi_platform_config *config = hdmi->config;
>>> > +     struct msm_drm_private *priv = bridge->dev->dev_private;
>>> > +     struct msm_kms *kms = priv->kms;
>>> > +     long actual, requested;
>>> > +
>>> > +     requested = 1000 * mode->clock;
>>> > +     actual = kms->funcs->round_pixclk(kms,
>>> > +                     requested, hdmi_bridge->hdmi->encoder);
>>> > +
>>> > +     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
>>> > +      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
>>> > +      * instead):
>>> > +      */
>>> > +     if (config->pwr_clk_cnt > 0)
>>> > +             actual = clk_round_rate(hdmi->pwr_clks[0], actual);
>>> > +
>>> > +     DBG("requested=%ld, actual=%ld", requested, actual);
>>> > +
>>> > +     if (actual != requested)
>>> > +             return MODE_CLOCK_RANGE;
>>> > +
>>> > +     return 0;
>>> > +}
>>> > +
>>> >  static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
>>> >               .pre_enable = msm_hdmi_bridge_pre_enable,
>>> >               .enable = msm_hdmi_bridge_enable,
>>> >               .disable = msm_hdmi_bridge_disable,
>>> >               .post_disable = msm_hdmi_bridge_post_disable,
>>> >               .mode_set = msm_hdmi_bridge_mode_set,
>>> > +             .mode_valid = msm_hdmi_bridge_mode_valid,
>>> > +             .get_edid = msm_hdmi_bridge_get_edid,
>>> > +             .detect = msm_hdmi_bridge_detect,
>>> >  };
>>> >
>>> > +static void
>>> > +msm_hdmi_hotplug_work(struct work_struct *work)
>>> > +{
>>> > +     struct hdmi_bridge *hdmi_bridge =
>>> > +             container_of(work, struct hdmi_bridge, hpd_work);
>>> > +     struct drm_bridge *bridge = &hdmi_bridge->base;
>>> > +
>>> > +     drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge));
>>> > +}
>>> >
>>> >  /* initialize bridge */
>>> >  struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
>>> > @@ -275,11 +336,17 @@ struct drm_bridge *msm_hdmi_bridge_init(struct
>>> > hdmi *hdmi)
>>> >       }
>>> >
>>> >       hdmi_bridge->hdmi = hdmi;
>>> > +     INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);
>>> >
>>> >       bridge = &hdmi_bridge->base;
>>> >       bridge->funcs = &msm_hdmi_bridge_funcs;
>>> > +     bridge->ddc = hdmi->i2c;
>>> > +     bridge->type = DRM_MODE_CONNECTOR_HDMIA;
>>> > +     bridge->ops = DRM_BRIDGE_OP_HPD |
>>> > +             DRM_BRIDGE_OP_DETECT |
>>> > +             DRM_BRIDGE_OP_EDID;
> Please correct me if wrong here. When we set DRM_BRIDGE_OP_HPD, it means 
> we need to
> set the hpd_enable and hpd_disable callbacks. I am not seeing those 
> being set.
> 
> 707      * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and 
> hot-unplug
> 708      * without requiring polling. Bridges that set this flag shall
> 709      * implement the &drm_bridge_funcs->hpd_enable and
> 710      * &drm_bridge_funcs->hpd_disable callbacks if they support 
> enabling
> 711      * and disabling hot-plug detection dynamically.
> 712      */
> 713     DRM_BRIDGE_OP_HPD = BIT(2),
> 
> So when drm_bridge_connector_enable_hpd() is called, its a no-op as 
> hpd_enable() callback
> is not set.
> 
> msm_hdmi_hpd_enable() actually enables the HPD logic which is getting 
> called from msm_hdmi_modeset_init()
> and not from hpd_enable().
> 
> In that case, do we need to set DRM_BRIDGE_OP_HPD for this? If we dont, 
> what will happen?
> 

Without this flag, the drm_bridge_connector will not know that this 
bridge is capable of generating HPD events on its own, ending up with 
polling implementation. See drm_bridge_connector_init(), 
drm_helper_hpd_irq_event(), etc.

> 
> 
>>> >
>>> > -     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0);
>>> > +     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL,
>>> > DRM_BRIDGE_ATTACH_NO_CONNECTOR);
>>> >       if (ret)
>>> >               goto fail;
>>> >
>>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
>>> > b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
>>> > similarity index 62%
>>> > rename from drivers/gpu/drm/msm/hdmi/hdmi_connector.c
>>> > rename to drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
>>> > index a7f729cdec7b..1cda7bf23b3b 100644
>>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
>>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
>>> > @@ -11,13 +11,6 @@
>>> >  #include "msm_kms.h"
>>> >  #include "hdmi.h"
>>> >
>>> > -struct hdmi_connector {
>>> > -     struct drm_connector base;
>>> > -     struct hdmi *hdmi;
>>> > -     struct work_struct hpd_work;
>>> > -};
>>> > -#define to_hdmi_connector(x) container_of(x, struct hdmi_connector,
>>> > base)
>>> > -
>>> >  static void msm_hdmi_phy_reset(struct hdmi *hdmi)
>>> >  {
>>> >       unsigned int val;
>>> > @@ -139,10 +132,10 @@ static void enable_hpd_clocks(struct hdmi *hdmi,
>>> > bool enable)
>>> >       }
>>> >  }
>>> >
>>> > -int msm_hdmi_hpd_enable(struct drm_connector *connector)
>>> > +int msm_hdmi_hpd_enable(struct drm_bridge *bridge)
>>> >  {
>>> > -     struct hdmi_connector *hdmi_connector = 
>>> to_hdmi_connector(connector);
>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>> >       const struct hdmi_platform_config *config = hdmi->config;
>>> >       struct device *dev = &hdmi->pdev->dev;
>>> >       uint32_t hpd_ctrl;
>>> > @@ -199,9 +192,9 @@ int msm_hdmi_hpd_enable(struct drm_connector
>>> > *connector)
>>> >       return ret;
>>> >  }
>>> >
>>> > -static void hdp_disable(struct hdmi_connector *hdmi_connector)
>>> > +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge)
>>> >  {
>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>> >       const struct hdmi_platform_config *config = hdmi->config;
>>> >       struct device *dev = &hdmi->pdev->dev;
>>> >       int ret;
>>> > @@ -227,19 +220,10 @@ static void hdp_disable(struct hdmi_connector
>>> > *hdmi_connector)
>>> >               dev_warn(dev, "failed to disable hpd regulator: 
>>> %d\n", ret);
>>> >  }
>>> >
>>> > -static void
>>> > -msm_hdmi_hotplug_work(struct work_struct *work)
>>> > -{
>>> > -     struct hdmi_connector *hdmi_connector =
>>> > -             container_of(work, struct hdmi_connector, hpd_work);
>>> > -     struct drm_connector *connector = &hdmi_connector->base;
>>> > -     drm_helper_hpd_irq_event(connector->dev);
>>> > -}
>>> > -
>>> > -void msm_hdmi_connector_irq(struct drm_connector *connector)
>>> > +void msm_hdmi_hpd_irq(struct drm_bridge *bridge)
>>> >  {
>>> > -     struct hdmi_connector *hdmi_connector = 
>>> to_hdmi_connector(connector);
>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>> >       uint32_t hpd_int_status, hpd_int_ctrl;
>>> >
>>> >       /* Process HPD: */
>>> > @@ -262,7 +246,7 @@ void msm_hdmi_connector_irq(struct drm_connector
>>> > *connector)
>>> >                       hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
>>> >               hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
>>> >
>>> > -             queue_work(hdmi->workq, &hdmi_connector->hpd_work);
>>> > +             queue_work(hdmi->workq, &hdmi_bridge->hpd_work);
>>> >       }
>>> >  }
>>> >
>>> > @@ -293,11 +277,11 @@ static enum drm_connector_status
>>> > detect_gpio(struct hdmi *hdmi)
>>> >                       connector_status_disconnected;
>>> >  }
>>> >
>>> > -static enum drm_connector_status hdmi_connector_detect(
>>> > -             struct drm_connector *connector, bool force)
>>> > +enum drm_connector_status msm_hdmi_bridge_detect(
>>> > +             struct drm_bridge *bridge)
>>> >  {
>>> > -     struct hdmi_connector *hdmi_connector = 
>>> to_hdmi_connector(connector);
>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>> >       const struct hdmi_platform_config *config = hdmi->config;
>>> >       struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
>>> >       enum drm_connector_status stat_gpio, stat_reg;
>>> > @@ -331,115 +315,3 @@ static enum drm_connector_status
>>> > hdmi_connector_detect(
>>> >
>>> >       return stat_gpio;
>>> >  }
>>> > -
>>> > -static void hdmi_connector_destroy(struct drm_connector *connector)
>>> > -{
>>> > -     struct hdmi_connector *hdmi_connector = 
>>> to_hdmi_connector(connector);
>>> > -
>>> > -     hdp_disable(hdmi_connector);
>>> > -
>>> > -     drm_connector_cleanup(connector);
>>> > -
>>> > -     kfree(hdmi_connector);
>>> > -}
>>> > -
>>> > -static int msm_hdmi_connector_get_modes(struct drm_connector
>>> > *connector)
>>> > -{
>>> > -     struct hdmi_connector *hdmi_connector = 
>>> to_hdmi_connector(connector);
>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>> > -     struct edid *edid;
>>> > -     uint32_t hdmi_ctrl;
>>> > -     int ret = 0;
>>> > -
>>> > -     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
>>> > -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
>>> > -
>>> > -     edid = drm_get_edid(connector, hdmi->i2c);
>>> > -
>>> > -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
>>> > -
>>> > -     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
>>> > -     drm_connector_update_edid_property(connector, edid);
>>> > -
>>> > -     if (edid) {
>>> > -             ret = drm_add_edid_modes(connector, edid);
>>> > -             kfree(edid);
>>> > -     }
>>> > -
>>> > -     return ret;
>>> > -}
>>> > -
>>> > -static int msm_hdmi_connector_mode_valid(struct drm_connector
>>> > *connector,
>>> > -                              struct drm_display_mode *mode)
>>> > -{
>>> > -     struct hdmi_connector *hdmi_connector = 
>>> to_hdmi_connector(connector);
>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>> > -     const struct hdmi_platform_config *config = hdmi->config;
>>> > -     struct msm_drm_private *priv = connector->dev->dev_private;
>>> > -     struct msm_kms *kms = priv->kms;
>>> > -     long actual, requested;
>>> > -
>>> > -     requested = 1000 * mode->clock;
>>> > -     actual = kms->funcs->round_pixclk(kms,
>>> > -                     requested, hdmi_connector->hdmi->encoder);
>>> > -
>>> > -     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
>>> > -      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
>>> > -      * instead):
>>> > -      */
>>> > -     if (config->pwr_clk_cnt > 0)
>>> > -             actual = clk_round_rate(hdmi->pwr_clks[0], actual);
>>> > -
>>> > -     DBG("requested=%ld, actual=%ld", requested, actual);
>>> > -
>>> > -     if (actual != requested)
>>> > -             return MODE_CLOCK_RANGE;
>>> > -
>>> > -     return 0;
>>> > -}
>>> > -
>>> > -static const struct drm_connector_funcs hdmi_connector_funcs = {
>>> > -     .detect = hdmi_connector_detect,
>>> > -     .fill_modes = drm_helper_probe_single_connector_modes,
>>> > -     .destroy = hdmi_connector_destroy,
>>> > -     .reset = drm_atomic_helper_connector_reset,
>>> > -     .atomic_duplicate_state =
>>> > drm_atomic_helper_connector_duplicate_state,
>>> > -     .atomic_destroy_state = 
>>> drm_atomic_helper_connector_destroy_state,
>>> > -};
>>> > -
>>> > -static const struct drm_connector_helper_funcs
>>> > msm_hdmi_connector_helper_funcs = {
>>> > -     .get_modes = msm_hdmi_connector_get_modes,
>>> > -     .mode_valid = msm_hdmi_connector_mode_valid,
>>> > -};
>>> > -
>>> > -/* initialize connector */
>>> > -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
>>> > -{
>>> > -     struct drm_connector *connector = NULL;
>>> > -     struct hdmi_connector *hdmi_connector;
>>> > -
>>> > -     hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
>>> > -     if (!hdmi_connector)
>>> > -             return ERR_PTR(-ENOMEM);
>>> > -
>>> > -     hdmi_connector->hdmi = hdmi;
>>> > -     INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);
>>> > -
>>> > -     connector = &hdmi_connector->base;
>>> > -
>>> > -     drm_connector_init_with_ddc(hdmi->dev, connector,
>>> > -                                 &hdmi_connector_funcs,
>>> > -                                 DRM_MODE_CONNECTOR_HDMIA,
>>> > -                                 hdmi->i2c);
>>> > -     drm_connector_helper_add(connector,
>>> > &msm_hdmi_connector_helper_funcs);
>>> > -
>>> > -     connector->polled = DRM_CONNECTOR_POLL_CONNECT |
>>> > -                     DRM_CONNECTOR_POLL_DISCONNECT;
>>> > -
>>> > -     connector->interlace_allowed = 0;
>>> > -     connector->doublescan_allowed = 0;
>>> > -
>>> > -     drm_connector_attach_encoder(connector, hdmi->encoder);
>>> > -
>>> > -     return connector;
>>> > -}
Abhinav Kumar Dec. 6, 2021, 8:42 p.m. UTC | #5
On 11/25/2021 4:50 AM, Dmitry Baryshkov wrote:
> On 19/10/2021 02:54, abhinavk@codeaurora.org wrote:
>> On 2021-10-16 07:21, Dmitry Baryshkov wrote:
>>> On Sat, 16 Oct 2021 at 01:25, <abhinavk@codeaurora.org> wrote:
>>>>
>>>> Hi Dmitry
>>>>
>>>> On 2021-10-14 17:11, Dmitry Baryshkov wrote:
>>>> > Merge old hdmi_bridge and hdmi_connector implementations. Use
>>>> > drm_bridge_connector instead.
>>>> >
>>>> Can you please comment on the validation done on this change?
>>>> Has basic bootup been verified on db820c as thats the only platform
>>>> which shall use this.
>>>
>>> Yes, this has been developed and validated on db820c
>> Thanks for confirming.
>>>
>>>>
>>>> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>> > ---
>>>> >  drivers/gpu/drm/msm/Makefile                  |   2 +-
>>>> >  drivers/gpu/drm/msm/hdmi/hdmi.c               |  12 +-
>>>> >  drivers/gpu/drm/msm/hdmi/hdmi.h               |  19 ++-
>>>> >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c        |  81 ++++++++-
>>>> >  .../msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} | 154 
>>>> ++----------------
>>>> >  5 files changed, 109 insertions(+), 159 deletions(-)
>>>> >  rename drivers/gpu/drm/msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} 
>>>> (62%)
>>>> >
>>>> > diff --git a/drivers/gpu/drm/msm/Makefile
>>>> > b/drivers/gpu/drm/msm/Makefile
>>>> > index 904535eda0c4..91b09cda8a9c 100644
>>>> > --- a/drivers/gpu/drm/msm/Makefile
>>>> > +++ b/drivers/gpu/drm/msm/Makefile
>>>> > @@ -19,7 +19,7 @@ msm-y := \
>>>> >       hdmi/hdmi.o \
>>>> >       hdmi/hdmi_audio.o \
>>>> >       hdmi/hdmi_bridge.o \
>>>> > -     hdmi/hdmi_connector.o \
>>>> > +     hdmi/hdmi_hpd.o \
>>>> >       hdmi/hdmi_i2c.o \
>>>> >       hdmi/hdmi_phy.o \
>>>> >       hdmi/hdmi_phy_8960.o \
>>>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c
>>>> > b/drivers/gpu/drm/msm/hdmi/hdmi.c
>>>> > index db17a000d968..d1cf4df7188c 100644
>>>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi.c
>>>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
>>>> > @@ -8,6 +8,8 @@
>>>> >  #include <linux/of_irq.h>
>>>> >  #include <linux/of_gpio.h>
>>>> >
>>>> > +#include <drm/drm_bridge_connector.h>
>>>> > +
>>>> >  #include <sound/hdmi-codec.h>
>>>> >  #include "hdmi.h"
>>>> >
>>>> > @@ -41,7 +43,7 @@ static irqreturn_t msm_hdmi_irq(int irq, void
>>>> > *dev_id)
>>>> >       struct hdmi *hdmi = dev_id;
>>>> >
>>>> >       /* Process HPD: */
>>>> > -     msm_hdmi_connector_irq(hdmi->connector);
>>>> > +     msm_hdmi_hpd_irq(hdmi->bridge);
>>>> >
>>>> >       /* Process DDC: */
>>>> >       msm_hdmi_i2c_irq(hdmi->i2c);
>>>> > @@ -283,7 +285,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
>>>> >               goto fail;
>>>> >       }
>>>> >
>>>> > -     hdmi->connector = msm_hdmi_connector_init(hdmi);
>>>> > +     hdmi->connector = drm_bridge_connector_init(hdmi->dev, 
>>>> encoder);
>>>> >       if (IS_ERR(hdmi->connector)) {
>>>> >               ret = PTR_ERR(hdmi->connector);
>>>> >               DRM_DEV_ERROR(dev->dev, "failed to create HDMI 
>>>> connector: %d\n",
>>>> > ret);
>>>> > @@ -291,6 +293,8 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
>>>> >               goto fail;
>>>> >       }
>>>> >
>>>> > +     drm_connector_attach_encoder(hdmi->connector, hdmi->encoder);
>>>> > +
>>>> >       hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
>>>> >       if (hdmi->irq < 0) {
>>>> >               ret = hdmi->irq;
>>>> > @@ -307,7 +311,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
>>>> >               goto fail;
>>>> >       }
>>>> >
>>>> > -     ret = msm_hdmi_hpd_enable(hdmi->connector);
>>>> > +     drm_bridge_connector_enable_hpd(hdmi->connector);
>>>> > +
>>>> > +     ret = msm_hdmi_hpd_enable(hdmi->bridge);
>>>> >       if (ret < 0) {
>>>> >               DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable 
>>>> HPD: %d\n", ret);
>>>> >               goto fail;
>>>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h
>>>> > b/drivers/gpu/drm/msm/hdmi/hdmi.h
>>>> > index 82261078c6b1..736f348befb3 100644
>>>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi.h
>>>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
>>>> > @@ -114,6 +114,13 @@ struct hdmi_platform_config {
>>>> >       struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO];
>>>> >  };
>>>> >
>>>> > +struct hdmi_bridge {
>>>> > +     struct drm_bridge base;
>>>> > +     struct hdmi *hdmi;
>>>> > +     struct work_struct hpd_work;
>>>> > +};
>>>> > +#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
>>>> > +
>>>> >  void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on);
>>>> >
>>>> >  static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data)
>>>> > @@ -230,13 +237,11 @@ void msm_hdmi_audio_set_sample_rate(struct hdmi
>>>> > *hdmi, int rate);
>>>> >  struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi);
>>>> >  void msm_hdmi_bridge_destroy(struct drm_bridge *bridge);
>>>> >
>>>> > -/*
>>>> > - * hdmi connector:
>>>> > - */
>>>> > -
>>>> > -void msm_hdmi_connector_irq(struct drm_connector *connector);
>>>> > -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi);
>>>> > -int msm_hdmi_hpd_enable(struct drm_connector *connector);
>>>> > +void msm_hdmi_hpd_irq(struct drm_bridge *bridge);
>>>> > +enum drm_connector_status msm_hdmi_bridge_detect(
>>>> > +             struct drm_bridge *bridge);
>>>> > +int msm_hdmi_hpd_enable(struct drm_bridge *bridge);
>>>> > +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge);
>>>> >
>>>> >  /*
>>>> >   * i2c adapter for ddc:
>>>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>>> > b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>>> > index f04eb4a70f0d..211b73dddf65 100644
>>>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>>> > @@ -5,17 +5,16 @@
>>>> >   */
>>>> >
>>>> >  #include <linux/delay.h>
>>>> > +#include <drm/drm_bridge_connector.h>
>>>> >
>>>> > +#include "msm_kms.h"
>>>> >  #include "hdmi.h"
>>>> >
>>>> > -struct hdmi_bridge {
>>>> > -     struct drm_bridge base;
>>>> > -     struct hdmi *hdmi;
>>>> > -};
>>>> > -#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
>>>> > -
>>>> >  void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)
>>>> >  {
>>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>> > +
>>>> > +     msm_hdmi_hpd_disable(hdmi_bridge);
>>>> >  }
>>>> >
>>>> >  static void msm_hdmi_power_on(struct drm_bridge *bridge)
>>>> > @@ -251,14 +250,76 @@ static void msm_hdmi_bridge_mode_set(struct
>>>> > drm_bridge *bridge,
>>>> >               msm_hdmi_audio_update(hdmi);
>>>> >  }
>>>> >
>>>> > +static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge
>>>> > *bridge,
>>>> > +             struct drm_connector *connector)
>>>> > +{
>>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>> > +     struct edid *edid;
>>>> > +     uint32_t hdmi_ctrl;
>>>> > +
>>>> > +     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
>>>> > +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
>>>> > +
>>>> > +     edid = drm_get_edid(connector, hdmi->i2c);
>>>> > +
>>>> > +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
>>>> > +
>>>> > +     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
>>>> > +
>>>> > +     return edid;
>>>> > +}
>>>> > +
>>>> > +static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct
>>>> > drm_bridge *bridge,
>>>> > +             const struct drm_display_info *info,
>>>> > +             const struct drm_display_mode *mode)
>>>> > +{
>>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>> > +     const struct hdmi_platform_config *config = hdmi->config;
>>>> > +     struct msm_drm_private *priv = bridge->dev->dev_private;
>>>> > +     struct msm_kms *kms = priv->kms;
>>>> > +     long actual, requested;
>>>> > +
>>>> > +     requested = 1000 * mode->clock;
>>>> > +     actual = kms->funcs->round_pixclk(kms,
>>>> > +                     requested, hdmi_bridge->hdmi->encoder);
>>>> > +
>>>> > +     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
>>>> > +      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
>>>> > +      * instead):
>>>> > +      */
>>>> > +     if (config->pwr_clk_cnt > 0)
>>>> > +             actual = clk_round_rate(hdmi->pwr_clks[0], actual);
>>>> > +
>>>> > +     DBG("requested=%ld, actual=%ld", requested, actual);
>>>> > +
>>>> > +     if (actual != requested)
>>>> > +             return MODE_CLOCK_RANGE;
>>>> > +
>>>> > +     return 0;
>>>> > +}
>>>> > +
>>>> >  static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
>>>> >               .pre_enable = msm_hdmi_bridge_pre_enable,
>>>> >               .enable = msm_hdmi_bridge_enable,
>>>> >               .disable = msm_hdmi_bridge_disable,
>>>> >               .post_disable = msm_hdmi_bridge_post_disable,
>>>> >               .mode_set = msm_hdmi_bridge_mode_set,
>>>> > +             .mode_valid = msm_hdmi_bridge_mode_valid,
>>>> > +             .get_edid = msm_hdmi_bridge_get_edid,
>>>> > +             .detect = msm_hdmi_bridge_detect,
>>>> >  };
>>>> >
>>>> > +static void
>>>> > +msm_hdmi_hotplug_work(struct work_struct *work)
>>>> > +{
>>>> > +     struct hdmi_bridge *hdmi_bridge =
>>>> > +             container_of(work, struct hdmi_bridge, hpd_work);
>>>> > +     struct drm_bridge *bridge = &hdmi_bridge->base;
>>>> > +
>>>> > +     drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge));
>>>> > +}
>>>> >
>>>> >  /* initialize bridge */
>>>> >  struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
>>>> > @@ -275,11 +336,17 @@ struct drm_bridge *msm_hdmi_bridge_init(struct
>>>> > hdmi *hdmi)
>>>> >       }
>>>> >
>>>> >       hdmi_bridge->hdmi = hdmi;
>>>> > +     INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);
>>>> >
>>>> >       bridge = &hdmi_bridge->base;
>>>> >       bridge->funcs = &msm_hdmi_bridge_funcs;
>>>> > +     bridge->ddc = hdmi->i2c;
>>>> > +     bridge->type = DRM_MODE_CONNECTOR_HDMIA;
>>>> > +     bridge->ops = DRM_BRIDGE_OP_HPD |
>>>> > +             DRM_BRIDGE_OP_DETECT |
>>>> > +             DRM_BRIDGE_OP_EDID;
>> Please correct me if wrong here. When we set DRM_BRIDGE_OP_HPD, it 
>> means we need to
>> set the hpd_enable and hpd_disable callbacks. I am not seeing those 
>> being set.
>>
>> 707      * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and 
>> hot-unplug
>> 708      * without requiring polling. Bridges that set this flag shall
>> 709      * implement the &drm_bridge_funcs->hpd_enable and
>> 710      * &drm_bridge_funcs->hpd_disable callbacks if they support 
>> enabling
>> 711      * and disabling hot-plug detection dynamically.
>> 712      */
>> 713     DRM_BRIDGE_OP_HPD = BIT(2),
>>
>> So when drm_bridge_connector_enable_hpd() is called, its a no-op as 
>> hpd_enable() callback
>> is not set.
>>
>> msm_hdmi_hpd_enable() actually enables the HPD logic which is getting 
>> called from msm_hdmi_modeset_init()
>> and not from hpd_enable().
>>
>> In that case, do we need to set DRM_BRIDGE_OP_HPD for this? If we 
>> dont, what will happen?
>>
> 
> Without this flag, the drm_bridge_connector will not know that this 
> bridge is capable of generating HPD events on its own, ending up with 
> polling implementation. See drm_bridge_connector_init(), 
> drm_helper_hpd_irq_event(), etc.
> 

Thanks for the details. Then, as per the documentation on the 
DRM_BRIDGE_OP_HPD, shouldnt we also assign msm_hdmi_hpd_enable to 
hpd_enable callback? Since we are already calling 
drm_bridge_connector_enable_hpd(), that should take care of calling it
using the callback then.

Similarly, you can assign msm_hdmi_hpd_disable to hpd_disable op and 
then call drm_bridge_connector_disable_hpd() in those places.

That way, functionality remains intact and we follow the documentation.

>>
>>
>>>> >
>>>> > -     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0);
>>>> > +     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL,
>>>> > DRM_BRIDGE_ATTACH_NO_CONNECTOR);
>>>> >       if (ret)
>>>> >               goto fail;
>>>> >
>>>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
>>>> > b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
>>>> > similarity index 62%
>>>> > rename from drivers/gpu/drm/msm/hdmi/hdmi_connector.c
>>>> > rename to drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
>>>> > index a7f729cdec7b..1cda7bf23b3b 100644
>>>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
>>>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
>>>> > @@ -11,13 +11,6 @@
>>>> >  #include "msm_kms.h"
>>>> >  #include "hdmi.h"
>>>> >
>>>> > -struct hdmi_connector {
>>>> > -     struct drm_connector base;
>>>> > -     struct hdmi *hdmi;
>>>> > -     struct work_struct hpd_work;
>>>> > -};
>>>> > -#define to_hdmi_connector(x) container_of(x, struct hdmi_connector,
>>>> > base)
>>>> > -
>>>> >  static void msm_hdmi_phy_reset(struct hdmi *hdmi)
>>>> >  {
>>>> >       unsigned int val;
>>>> > @@ -139,10 +132,10 @@ static void enable_hpd_clocks(struct hdmi 
>>>> *hdmi,
>>>> > bool enable)
>>>> >       }
>>>> >  }
>>>> >
>>>> > -int msm_hdmi_hpd_enable(struct drm_connector *connector)
>>>> > +int msm_hdmi_hpd_enable(struct drm_bridge *bridge)
>>>> >  {
>>>> > -     struct hdmi_connector *hdmi_connector = 
>>>> to_hdmi_connector(connector);
>>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>> >       const struct hdmi_platform_config *config = hdmi->config;
>>>> >       struct device *dev = &hdmi->pdev->dev;
>>>> >       uint32_t hpd_ctrl;
>>>> > @@ -199,9 +192,9 @@ int msm_hdmi_hpd_enable(struct drm_connector
>>>> > *connector)
>>>> >       return ret;
>>>> >  }
>>>> >
>>>> > -static void hdp_disable(struct hdmi_connector *hdmi_connector)
>>>> > +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge)
>>>> >  {
>>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>> >       const struct hdmi_platform_config *config = hdmi->config;
>>>> >       struct device *dev = &hdmi->pdev->dev;
>>>> >       int ret;
>>>> > @@ -227,19 +220,10 @@ static void hdp_disable(struct hdmi_connector
>>>> > *hdmi_connector)
>>>> >               dev_warn(dev, "failed to disable hpd regulator: 
>>>> %d\n", ret);
>>>> >  }
>>>> >
>>>> > -static void
>>>> > -msm_hdmi_hotplug_work(struct work_struct *work)
>>>> > -{
>>>> > -     struct hdmi_connector *hdmi_connector =
>>>> > -             container_of(work, struct hdmi_connector, hpd_work);
>>>> > -     struct drm_connector *connector = &hdmi_connector->base;
>>>> > -     drm_helper_hpd_irq_event(connector->dev);
>>>> > -}
>>>> > -
>>>> > -void msm_hdmi_connector_irq(struct drm_connector *connector)
>>>> > +void msm_hdmi_hpd_irq(struct drm_bridge *bridge)
>>>> >  {
>>>> > -     struct hdmi_connector *hdmi_connector = 
>>>> to_hdmi_connector(connector);
>>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>> >       uint32_t hpd_int_status, hpd_int_ctrl;
>>>> >
>>>> >       /* Process HPD: */
>>>> > @@ -262,7 +246,7 @@ void msm_hdmi_connector_irq(struct drm_connector
>>>> > *connector)
>>>> >                       hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
>>>> >               hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
>>>> >
>>>> > -             queue_work(hdmi->workq, &hdmi_connector->hpd_work);
>>>> > +             queue_work(hdmi->workq, &hdmi_bridge->hpd_work);
>>>> >       }
>>>> >  }
>>>> >
>>>> > @@ -293,11 +277,11 @@ static enum drm_connector_status
>>>> > detect_gpio(struct hdmi *hdmi)
>>>> >                       connector_status_disconnected;
>>>> >  }
>>>> >
>>>> > -static enum drm_connector_status hdmi_connector_detect(
>>>> > -             struct drm_connector *connector, bool force)
>>>> > +enum drm_connector_status msm_hdmi_bridge_detect(
>>>> > +             struct drm_bridge *bridge)
>>>> >  {
>>>> > -     struct hdmi_connector *hdmi_connector = 
>>>> to_hdmi_connector(connector);
>>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>> >       const struct hdmi_platform_config *config = hdmi->config;
>>>> >       struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
>>>> >       enum drm_connector_status stat_gpio, stat_reg;
>>>> > @@ -331,115 +315,3 @@ static enum drm_connector_status
>>>> > hdmi_connector_detect(
>>>> >
>>>> >       return stat_gpio;
>>>> >  }
>>>> > -
>>>> > -static void hdmi_connector_destroy(struct drm_connector *connector)
>>>> > -{
>>>> > -     struct hdmi_connector *hdmi_connector = 
>>>> to_hdmi_connector(connector);
>>>> > -
>>>> > -     hdp_disable(hdmi_connector);
>>>> > -
>>>> > -     drm_connector_cleanup(connector);
>>>> > -
>>>> > -     kfree(hdmi_connector);
>>>> > -}
>>>> > -
>>>> > -static int msm_hdmi_connector_get_modes(struct drm_connector
>>>> > *connector)
>>>> > -{
>>>> > -     struct hdmi_connector *hdmi_connector = 
>>>> to_hdmi_connector(connector);
>>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>> > -     struct edid *edid;
>>>> > -     uint32_t hdmi_ctrl;
>>>> > -     int ret = 0;
>>>> > -
>>>> > -     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
>>>> > -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
>>>> > -
>>>> > -     edid = drm_get_edid(connector, hdmi->i2c);
>>>> > -
>>>> > -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
>>>> > -
>>>> > -     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
>>>> > -     drm_connector_update_edid_property(connector, edid);
>>>> > -
>>>> > -     if (edid) {
>>>> > -             ret = drm_add_edid_modes(connector, edid);
>>>> > -             kfree(edid);
>>>> > -     }
>>>> > -
>>>> > -     return ret;
>>>> > -}
>>>> > -
>>>> > -static int msm_hdmi_connector_mode_valid(struct drm_connector
>>>> > *connector,
>>>> > -                              struct drm_display_mode *mode)
>>>> > -{
>>>> > -     struct hdmi_connector *hdmi_connector = 
>>>> to_hdmi_connector(connector);
>>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>> > -     const struct hdmi_platform_config *config = hdmi->config;
>>>> > -     struct msm_drm_private *priv = connector->dev->dev_private;
>>>> > -     struct msm_kms *kms = priv->kms;
>>>> > -     long actual, requested;
>>>> > -
>>>> > -     requested = 1000 * mode->clock;
>>>> > -     actual = kms->funcs->round_pixclk(kms,
>>>> > -                     requested, hdmi_connector->hdmi->encoder);
>>>> > -
>>>> > -     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
>>>> > -      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
>>>> > -      * instead):
>>>> > -      */
>>>> > -     if (config->pwr_clk_cnt > 0)
>>>> > -             actual = clk_round_rate(hdmi->pwr_clks[0], actual);
>>>> > -
>>>> > -     DBG("requested=%ld, actual=%ld", requested, actual);
>>>> > -
>>>> > -     if (actual != requested)
>>>> > -             return MODE_CLOCK_RANGE;
>>>> > -
>>>> > -     return 0;
>>>> > -}
>>>> > -
>>>> > -static const struct drm_connector_funcs hdmi_connector_funcs = {
>>>> > -     .detect = hdmi_connector_detect,
>>>> > -     .fill_modes = drm_helper_probe_single_connector_modes,
>>>> > -     .destroy = hdmi_connector_destroy,
>>>> > -     .reset = drm_atomic_helper_connector_reset,
>>>> > -     .atomic_duplicate_state =
>>>> > drm_atomic_helper_connector_duplicate_state,
>>>> > -     .atomic_destroy_state = 
>>>> drm_atomic_helper_connector_destroy_state,
>>>> > -};
>>>> > -
>>>> > -static const struct drm_connector_helper_funcs
>>>> > msm_hdmi_connector_helper_funcs = {
>>>> > -     .get_modes = msm_hdmi_connector_get_modes,
>>>> > -     .mode_valid = msm_hdmi_connector_mode_valid,
>>>> > -};
>>>> > -
>>>> > -/* initialize connector */
>>>> > -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
>>>> > -{
>>>> > -     struct drm_connector *connector = NULL;
>>>> > -     struct hdmi_connector *hdmi_connector;
>>>> > -
>>>> > -     hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
>>>> > -     if (!hdmi_connector)
>>>> > -             return ERR_PTR(-ENOMEM);
>>>> > -
>>>> > -     hdmi_connector->hdmi = hdmi;
>>>> > -     INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);
>>>> > -
>>>> > -     connector = &hdmi_connector->base;
>>>> > -
>>>> > -     drm_connector_init_with_ddc(hdmi->dev, connector,
>>>> > -                                 &hdmi_connector_funcs,
>>>> > -                                 DRM_MODE_CONNECTOR_HDMIA,
>>>> > -                                 hdmi->i2c);
>>>> > -     drm_connector_helper_add(connector,
>>>> > &msm_hdmi_connector_helper_funcs);
>>>> > -
>>>> > -     connector->polled = DRM_CONNECTOR_POLL_CONNECT |
>>>> > -                     DRM_CONNECTOR_POLL_DISCONNECT;
>>>> > -
>>>> > -     connector->interlace_allowed = 0;
>>>> > -     connector->doublescan_allowed = 0;
>>>> > -
>>>> > -     drm_connector_attach_encoder(connector, hdmi->encoder);
>>>> > -
>>>> > -     return connector;
>>>> > -}
> 
>
Dmitry Baryshkov Dec. 6, 2021, 10:47 p.m. UTC | #6
On Mon, 6 Dec 2021 at 23:42, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 11/25/2021 4:50 AM, Dmitry Baryshkov wrote:
> > On 19/10/2021 02:54, abhinavk@codeaurora.org wrote:
> >> On 2021-10-16 07:21, Dmitry Baryshkov wrote:
> >>> On Sat, 16 Oct 2021 at 01:25, <abhinavk@codeaurora.org> wrote:
> >>>>
> >>>> Hi Dmitry
> >>>>
> >>>> On 2021-10-14 17:11, Dmitry Baryshkov wrote:
> >>>> > Merge old hdmi_bridge and hdmi_connector implementations. Use
> >>>> > drm_bridge_connector instead.
> >>>> >
> >>>> Can you please comment on the validation done on this change?
> >>>> Has basic bootup been verified on db820c as thats the only platform
> >>>> which shall use this.
> >>>
> >>> Yes, this has been developed and validated on db820c
> >> Thanks for confirming.
> >>>
> >>>>
> >>>> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> >>>> > ---
> >>>> >  drivers/gpu/drm/msm/Makefile                  |   2 +-
> >>>> >  drivers/gpu/drm/msm/hdmi/hdmi.c               |  12 +-
> >>>> >  drivers/gpu/drm/msm/hdmi/hdmi.h               |  19 ++-
> >>>> >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c        |  81 ++++++++-
> >>>> >  .../msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} | 154
> >>>> ++----------------
> >>>> >  5 files changed, 109 insertions(+), 159 deletions(-)
> >>>> >  rename drivers/gpu/drm/msm/hdmi/{hdmi_connector.c => hdmi_hpd.c}
> >>>> (62%)
> >>>> >
> >>>> > diff --git a/drivers/gpu/drm/msm/Makefile
> >>>> > b/drivers/gpu/drm/msm/Makefile
> >>>> > index 904535eda0c4..91b09cda8a9c 100644
> >>>> > --- a/drivers/gpu/drm/msm/Makefile
> >>>> > +++ b/drivers/gpu/drm/msm/Makefile
> >>>> > @@ -19,7 +19,7 @@ msm-y := \
> >>>> >       hdmi/hdmi.o \
> >>>> >       hdmi/hdmi_audio.o \
> >>>> >       hdmi/hdmi_bridge.o \
> >>>> > -     hdmi/hdmi_connector.o \
> >>>> > +     hdmi/hdmi_hpd.o \
> >>>> >       hdmi/hdmi_i2c.o \
> >>>> >       hdmi/hdmi_phy.o \
> >>>> >       hdmi/hdmi_phy_8960.o \
> >>>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c
> >>>> > b/drivers/gpu/drm/msm/hdmi/hdmi.c
> >>>> > index db17a000d968..d1cf4df7188c 100644
> >>>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi.c
> >>>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
> >>>> > @@ -8,6 +8,8 @@
> >>>> >  #include <linux/of_irq.h>
> >>>> >  #include <linux/of_gpio.h>
> >>>> >
> >>>> > +#include <drm/drm_bridge_connector.h>
> >>>> > +
> >>>> >  #include <sound/hdmi-codec.h>
> >>>> >  #include "hdmi.h"
> >>>> >
> >>>> > @@ -41,7 +43,7 @@ static irqreturn_t msm_hdmi_irq(int irq, void
> >>>> > *dev_id)
> >>>> >       struct hdmi *hdmi = dev_id;
> >>>> >
> >>>> >       /* Process HPD: */
> >>>> > -     msm_hdmi_connector_irq(hdmi->connector);
> >>>> > +     msm_hdmi_hpd_irq(hdmi->bridge);
> >>>> >
> >>>> >       /* Process DDC: */
> >>>> >       msm_hdmi_i2c_irq(hdmi->i2c);
> >>>> > @@ -283,7 +285,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
> >>>> >               goto fail;
> >>>> >       }
> >>>> >
> >>>> > -     hdmi->connector = msm_hdmi_connector_init(hdmi);
> >>>> > +     hdmi->connector = drm_bridge_connector_init(hdmi->dev,
> >>>> encoder);
> >>>> >       if (IS_ERR(hdmi->connector)) {
> >>>> >               ret = PTR_ERR(hdmi->connector);
> >>>> >               DRM_DEV_ERROR(dev->dev, "failed to create HDMI
> >>>> connector: %d\n",
> >>>> > ret);
> >>>> > @@ -291,6 +293,8 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
> >>>> >               goto fail;
> >>>> >       }
> >>>> >
> >>>> > +     drm_connector_attach_encoder(hdmi->connector, hdmi->encoder);
> >>>> > +
> >>>> >       hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
> >>>> >       if (hdmi->irq < 0) {
> >>>> >               ret = hdmi->irq;
> >>>> > @@ -307,7 +311,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
> >>>> >               goto fail;
> >>>> >       }
> >>>> >
> >>>> > -     ret = msm_hdmi_hpd_enable(hdmi->connector);
> >>>> > +     drm_bridge_connector_enable_hpd(hdmi->connector);
> >>>> > +
> >>>> > +     ret = msm_hdmi_hpd_enable(hdmi->bridge);
> >>>> >       if (ret < 0) {
> >>>> >               DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable
> >>>> HPD: %d\n", ret);
> >>>> >               goto fail;
> >>>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h
> >>>> > b/drivers/gpu/drm/msm/hdmi/hdmi.h
> >>>> > index 82261078c6b1..736f348befb3 100644
> >>>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi.h
> >>>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
> >>>> > @@ -114,6 +114,13 @@ struct hdmi_platform_config {
> >>>> >       struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO];
> >>>> >  };
> >>>> >
> >>>> > +struct hdmi_bridge {
> >>>> > +     struct drm_bridge base;
> >>>> > +     struct hdmi *hdmi;
> >>>> > +     struct work_struct hpd_work;
> >>>> > +};
> >>>> > +#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
> >>>> > +
> >>>> >  void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on);
> >>>> >
> >>>> >  static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data)
> >>>> > @@ -230,13 +237,11 @@ void msm_hdmi_audio_set_sample_rate(struct hdmi
> >>>> > *hdmi, int rate);
> >>>> >  struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi);
> >>>> >  void msm_hdmi_bridge_destroy(struct drm_bridge *bridge);
> >>>> >
> >>>> > -/*
> >>>> > - * hdmi connector:
> >>>> > - */
> >>>> > -
> >>>> > -void msm_hdmi_connector_irq(struct drm_connector *connector);
> >>>> > -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi);
> >>>> > -int msm_hdmi_hpd_enable(struct drm_connector *connector);
> >>>> > +void msm_hdmi_hpd_irq(struct drm_bridge *bridge);
> >>>> > +enum drm_connector_status msm_hdmi_bridge_detect(
> >>>> > +             struct drm_bridge *bridge);
> >>>> > +int msm_hdmi_hpd_enable(struct drm_bridge *bridge);
> >>>> > +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge);
> >>>> >
> >>>> >  /*
> >>>> >   * i2c adapter for ddc:
> >>>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> >>>> > b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> >>>> > index f04eb4a70f0d..211b73dddf65 100644
> >>>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> >>>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> >>>> > @@ -5,17 +5,16 @@
> >>>> >   */
> >>>> >
> >>>> >  #include <linux/delay.h>
> >>>> > +#include <drm/drm_bridge_connector.h>
> >>>> >
> >>>> > +#include "msm_kms.h"
> >>>> >  #include "hdmi.h"
> >>>> >
> >>>> > -struct hdmi_bridge {
> >>>> > -     struct drm_bridge base;
> >>>> > -     struct hdmi *hdmi;
> >>>> > -};
> >>>> > -#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
> >>>> > -
> >>>> >  void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)
> >>>> >  {
> >>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
> >>>> > +
> >>>> > +     msm_hdmi_hpd_disable(hdmi_bridge);
> >>>> >  }
> >>>> >
> >>>> >  static void msm_hdmi_power_on(struct drm_bridge *bridge)
> >>>> > @@ -251,14 +250,76 @@ static void msm_hdmi_bridge_mode_set(struct
> >>>> > drm_bridge *bridge,
> >>>> >               msm_hdmi_audio_update(hdmi);
> >>>> >  }
> >>>> >
> >>>> > +static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge
> >>>> > *bridge,
> >>>> > +             struct drm_connector *connector)
> >>>> > +{
> >>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
> >>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
> >>>> > +     struct edid *edid;
> >>>> > +     uint32_t hdmi_ctrl;
> >>>> > +
> >>>> > +     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
> >>>> > +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
> >>>> > +
> >>>> > +     edid = drm_get_edid(connector, hdmi->i2c);
> >>>> > +
> >>>> > +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
> >>>> > +
> >>>> > +     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
> >>>> > +
> >>>> > +     return edid;
> >>>> > +}
> >>>> > +
> >>>> > +static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct
> >>>> > drm_bridge *bridge,
> >>>> > +             const struct drm_display_info *info,
> >>>> > +             const struct drm_display_mode *mode)
> >>>> > +{
> >>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
> >>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
> >>>> > +     const struct hdmi_platform_config *config = hdmi->config;
> >>>> > +     struct msm_drm_private *priv = bridge->dev->dev_private;
> >>>> > +     struct msm_kms *kms = priv->kms;
> >>>> > +     long actual, requested;
> >>>> > +
> >>>> > +     requested = 1000 * mode->clock;
> >>>> > +     actual = kms->funcs->round_pixclk(kms,
> >>>> > +                     requested, hdmi_bridge->hdmi->encoder);
> >>>> > +
> >>>> > +     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
> >>>> > +      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
> >>>> > +      * instead):
> >>>> > +      */
> >>>> > +     if (config->pwr_clk_cnt > 0)
> >>>> > +             actual = clk_round_rate(hdmi->pwr_clks[0], actual);
> >>>> > +
> >>>> > +     DBG("requested=%ld, actual=%ld", requested, actual);
> >>>> > +
> >>>> > +     if (actual != requested)
> >>>> > +             return MODE_CLOCK_RANGE;
> >>>> > +
> >>>> > +     return 0;
> >>>> > +}
> >>>> > +
> >>>> >  static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
> >>>> >               .pre_enable = msm_hdmi_bridge_pre_enable,
> >>>> >               .enable = msm_hdmi_bridge_enable,
> >>>> >               .disable = msm_hdmi_bridge_disable,
> >>>> >               .post_disable = msm_hdmi_bridge_post_disable,
> >>>> >               .mode_set = msm_hdmi_bridge_mode_set,
> >>>> > +             .mode_valid = msm_hdmi_bridge_mode_valid,
> >>>> > +             .get_edid = msm_hdmi_bridge_get_edid,
> >>>> > +             .detect = msm_hdmi_bridge_detect,
> >>>> >  };
> >>>> >
> >>>> > +static void
> >>>> > +msm_hdmi_hotplug_work(struct work_struct *work)
> >>>> > +{
> >>>> > +     struct hdmi_bridge *hdmi_bridge =
> >>>> > +             container_of(work, struct hdmi_bridge, hpd_work);
> >>>> > +     struct drm_bridge *bridge = &hdmi_bridge->base;
> >>>> > +
> >>>> > +     drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge));
> >>>> > +}
> >>>> >
> >>>> >  /* initialize bridge */
> >>>> >  struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
> >>>> > @@ -275,11 +336,17 @@ struct drm_bridge *msm_hdmi_bridge_init(struct
> >>>> > hdmi *hdmi)
> >>>> >       }
> >>>> >
> >>>> >       hdmi_bridge->hdmi = hdmi;
> >>>> > +     INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);
> >>>> >
> >>>> >       bridge = &hdmi_bridge->base;
> >>>> >       bridge->funcs = &msm_hdmi_bridge_funcs;
> >>>> > +     bridge->ddc = hdmi->i2c;
> >>>> > +     bridge->type = DRM_MODE_CONNECTOR_HDMIA;
> >>>> > +     bridge->ops = DRM_BRIDGE_OP_HPD |
> >>>> > +             DRM_BRIDGE_OP_DETECT |
> >>>> > +             DRM_BRIDGE_OP_EDID;
> >> Please correct me if wrong here. When we set DRM_BRIDGE_OP_HPD, it
> >> means we need to
> >> set the hpd_enable and hpd_disable callbacks. I am not seeing those
> >> being set.
> >>
> >> 707      * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and
> >> hot-unplug
> >> 708      * without requiring polling. Bridges that set this flag shall
> >> 709      * implement the &drm_bridge_funcs->hpd_enable and
> >> 710      * &drm_bridge_funcs->hpd_disable callbacks if they support
> >> enabling
> >> 711      * and disabling hot-plug detection dynamically.
> >> 712      */
> >> 713     DRM_BRIDGE_OP_HPD = BIT(2),
> >>
> >> So when drm_bridge_connector_enable_hpd() is called, its a no-op as
> >> hpd_enable() callback
> >> is not set.
> >>
> >> msm_hdmi_hpd_enable() actually enables the HPD logic which is getting
> >> called from msm_hdmi_modeset_init()
> >> and not from hpd_enable().
> >>
> >> In that case, do we need to set DRM_BRIDGE_OP_HPD for this? If we
> >> dont, what will happen?
> >>
> >
> > Without this flag, the drm_bridge_connector will not know that this
> > bridge is capable of generating HPD events on its own, ending up with
> > polling implementation. See drm_bridge_connector_init(),
> > drm_helper_hpd_irq_event(), etc.
> >
>
> Thanks for the details. Then, as per the documentation on the
> DRM_BRIDGE_OP_HPD, shouldnt we also assign msm_hdmi_hpd_enable to
> hpd_enable callback? Since we are already calling
> drm_bridge_connector_enable_hpd(), that should take care of calling it
> using the callback then.
>
> Similarly, you can assign msm_hdmi_hpd_disable to hpd_disable op and
> then call drm_bridge_connector_disable_hpd() in those places.

Since that would be a change in the functionality, I'd prefer to have
that in a separate patch.
It looks like a nice cleanup idea, so I'd implement that at some point.

>
> That way, functionality remains intact and we follow the documentation.
>
> >>
> >>
> >>>> >
> >>>> > -     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0);
> >>>> > +     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL,
> >>>> > DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> >>>> >       if (ret)
> >>>> >               goto fail;
> >>>> >
> >>>> > diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
> >>>> > b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
> >>>> > similarity index 62%
> >>>> > rename from drivers/gpu/drm/msm/hdmi/hdmi_connector.c
> >>>> > rename to drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
> >>>> > index a7f729cdec7b..1cda7bf23b3b 100644
> >>>> > --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
> >>>> > +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
> >>>> > @@ -11,13 +11,6 @@
> >>>> >  #include "msm_kms.h"
> >>>> >  #include "hdmi.h"
> >>>> >
> >>>> > -struct hdmi_connector {
> >>>> > -     struct drm_connector base;
> >>>> > -     struct hdmi *hdmi;
> >>>> > -     struct work_struct hpd_work;
> >>>> > -};
> >>>> > -#define to_hdmi_connector(x) container_of(x, struct hdmi_connector,
> >>>> > base)
> >>>> > -
> >>>> >  static void msm_hdmi_phy_reset(struct hdmi *hdmi)
> >>>> >  {
> >>>> >       unsigned int val;
> >>>> > @@ -139,10 +132,10 @@ static void enable_hpd_clocks(struct hdmi
> >>>> *hdmi,
> >>>> > bool enable)
> >>>> >       }
> >>>> >  }
> >>>> >
> >>>> > -int msm_hdmi_hpd_enable(struct drm_connector *connector)
> >>>> > +int msm_hdmi_hpd_enable(struct drm_bridge *bridge)
> >>>> >  {
> >>>> > -     struct hdmi_connector *hdmi_connector =
> >>>> to_hdmi_connector(connector);
> >>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
> >>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
> >>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
> >>>> >       const struct hdmi_platform_config *config = hdmi->config;
> >>>> >       struct device *dev = &hdmi->pdev->dev;
> >>>> >       uint32_t hpd_ctrl;
> >>>> > @@ -199,9 +192,9 @@ int msm_hdmi_hpd_enable(struct drm_connector
> >>>> > *connector)
> >>>> >       return ret;
> >>>> >  }
> >>>> >
> >>>> > -static void hdp_disable(struct hdmi_connector *hdmi_connector)
> >>>> > +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge)
> >>>> >  {
> >>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
> >>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
> >>>> >       const struct hdmi_platform_config *config = hdmi->config;
> >>>> >       struct device *dev = &hdmi->pdev->dev;
> >>>> >       int ret;
> >>>> > @@ -227,19 +220,10 @@ static void hdp_disable(struct hdmi_connector
> >>>> > *hdmi_connector)
> >>>> >               dev_warn(dev, "failed to disable hpd regulator:
> >>>> %d\n", ret);
> >>>> >  }
> >>>> >
> >>>> > -static void
> >>>> > -msm_hdmi_hotplug_work(struct work_struct *work)
> >>>> > -{
> >>>> > -     struct hdmi_connector *hdmi_connector =
> >>>> > -             container_of(work, struct hdmi_connector, hpd_work);
> >>>> > -     struct drm_connector *connector = &hdmi_connector->base;
> >>>> > -     drm_helper_hpd_irq_event(connector->dev);
> >>>> > -}
> >>>> > -
> >>>> > -void msm_hdmi_connector_irq(struct drm_connector *connector)
> >>>> > +void msm_hdmi_hpd_irq(struct drm_bridge *bridge)
> >>>> >  {
> >>>> > -     struct hdmi_connector *hdmi_connector =
> >>>> to_hdmi_connector(connector);
> >>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
> >>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
> >>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
> >>>> >       uint32_t hpd_int_status, hpd_int_ctrl;
> >>>> >
> >>>> >       /* Process HPD: */
> >>>> > @@ -262,7 +246,7 @@ void msm_hdmi_connector_irq(struct drm_connector
> >>>> > *connector)
> >>>> >                       hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
> >>>> >               hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
> >>>> >
> >>>> > -             queue_work(hdmi->workq, &hdmi_connector->hpd_work);
> >>>> > +             queue_work(hdmi->workq, &hdmi_bridge->hpd_work);
> >>>> >       }
> >>>> >  }
> >>>> >
> >>>> > @@ -293,11 +277,11 @@ static enum drm_connector_status
> >>>> > detect_gpio(struct hdmi *hdmi)
> >>>> >                       connector_status_disconnected;
> >>>> >  }
> >>>> >
> >>>> > -static enum drm_connector_status hdmi_connector_detect(
> >>>> > -             struct drm_connector *connector, bool force)
> >>>> > +enum drm_connector_status msm_hdmi_bridge_detect(
> >>>> > +             struct drm_bridge *bridge)
> >>>> >  {
> >>>> > -     struct hdmi_connector *hdmi_connector =
> >>>> to_hdmi_connector(connector);
> >>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
> >>>> > +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
> >>>> > +     struct hdmi *hdmi = hdmi_bridge->hdmi;
> >>>> >       const struct hdmi_platform_config *config = hdmi->config;
> >>>> >       struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
> >>>> >       enum drm_connector_status stat_gpio, stat_reg;
> >>>> > @@ -331,115 +315,3 @@ static enum drm_connector_status
> >>>> > hdmi_connector_detect(
> >>>> >
> >>>> >       return stat_gpio;
> >>>> >  }
> >>>> > -
> >>>> > -static void hdmi_connector_destroy(struct drm_connector *connector)
> >>>> > -{
> >>>> > -     struct hdmi_connector *hdmi_connector =
> >>>> to_hdmi_connector(connector);
> >>>> > -
> >>>> > -     hdp_disable(hdmi_connector);
> >>>> > -
> >>>> > -     drm_connector_cleanup(connector);
> >>>> > -
> >>>> > -     kfree(hdmi_connector);
> >>>> > -}
> >>>> > -
> >>>> > -static int msm_hdmi_connector_get_modes(struct drm_connector
> >>>> > *connector)
> >>>> > -{
> >>>> > -     struct hdmi_connector *hdmi_connector =
> >>>> to_hdmi_connector(connector);
> >>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
> >>>> > -     struct edid *edid;
> >>>> > -     uint32_t hdmi_ctrl;
> >>>> > -     int ret = 0;
> >>>> > -
> >>>> > -     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
> >>>> > -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
> >>>> > -
> >>>> > -     edid = drm_get_edid(connector, hdmi->i2c);
> >>>> > -
> >>>> > -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
> >>>> > -
> >>>> > -     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
> >>>> > -     drm_connector_update_edid_property(connector, edid);
> >>>> > -
> >>>> > -     if (edid) {
> >>>> > -             ret = drm_add_edid_modes(connector, edid);
> >>>> > -             kfree(edid);
> >>>> > -     }
> >>>> > -
> >>>> > -     return ret;
> >>>> > -}
> >>>> > -
> >>>> > -static int msm_hdmi_connector_mode_valid(struct drm_connector
> >>>> > *connector,
> >>>> > -                              struct drm_display_mode *mode)
> >>>> > -{
> >>>> > -     struct hdmi_connector *hdmi_connector =
> >>>> to_hdmi_connector(connector);
> >>>> > -     struct hdmi *hdmi = hdmi_connector->hdmi;
> >>>> > -     const struct hdmi_platform_config *config = hdmi->config;
> >>>> > -     struct msm_drm_private *priv = connector->dev->dev_private;
> >>>> > -     struct msm_kms *kms = priv->kms;
> >>>> > -     long actual, requested;
> >>>> > -
> >>>> > -     requested = 1000 * mode->clock;
> >>>> > -     actual = kms->funcs->round_pixclk(kms,
> >>>> > -                     requested, hdmi_connector->hdmi->encoder);
> >>>> > -
> >>>> > -     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
> >>>> > -      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
> >>>> > -      * instead):
> >>>> > -      */
> >>>> > -     if (config->pwr_clk_cnt > 0)
> >>>> > -             actual = clk_round_rate(hdmi->pwr_clks[0], actual);
> >>>> > -
> >>>> > -     DBG("requested=%ld, actual=%ld", requested, actual);
> >>>> > -
> >>>> > -     if (actual != requested)
> >>>> > -             return MODE_CLOCK_RANGE;
> >>>> > -
> >>>> > -     return 0;
> >>>> > -}
> >>>> > -
> >>>> > -static const struct drm_connector_funcs hdmi_connector_funcs = {
> >>>> > -     .detect = hdmi_connector_detect,
> >>>> > -     .fill_modes = drm_helper_probe_single_connector_modes,
> >>>> > -     .destroy = hdmi_connector_destroy,
> >>>> > -     .reset = drm_atomic_helper_connector_reset,
> >>>> > -     .atomic_duplicate_state =
> >>>> > drm_atomic_helper_connector_duplicate_state,
> >>>> > -     .atomic_destroy_state =
> >>>> drm_atomic_helper_connector_destroy_state,
> >>>> > -};
> >>>> > -
> >>>> > -static const struct drm_connector_helper_funcs
> >>>> > msm_hdmi_connector_helper_funcs = {
> >>>> > -     .get_modes = msm_hdmi_connector_get_modes,
> >>>> > -     .mode_valid = msm_hdmi_connector_mode_valid,
> >>>> > -};
> >>>> > -
> >>>> > -/* initialize connector */
> >>>> > -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
> >>>> > -{
> >>>> > -     struct drm_connector *connector = NULL;
> >>>> > -     struct hdmi_connector *hdmi_connector;
> >>>> > -
> >>>> > -     hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
> >>>> > -     if (!hdmi_connector)
> >>>> > -             return ERR_PTR(-ENOMEM);
> >>>> > -
> >>>> > -     hdmi_connector->hdmi = hdmi;
> >>>> > -     INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);
> >>>> > -
> >>>> > -     connector = &hdmi_connector->base;
> >>>> > -
> >>>> > -     drm_connector_init_with_ddc(hdmi->dev, connector,
> >>>> > -                                 &hdmi_connector_funcs,
> >>>> > -                                 DRM_MODE_CONNECTOR_HDMIA,
> >>>> > -                                 hdmi->i2c);
> >>>> > -     drm_connector_helper_add(connector,
> >>>> > &msm_hdmi_connector_helper_funcs);
> >>>> > -
> >>>> > -     connector->polled = DRM_CONNECTOR_POLL_CONNECT |
> >>>> > -                     DRM_CONNECTOR_POLL_DISCONNECT;
> >>>> > -
> >>>> > -     connector->interlace_allowed = 0;
> >>>> > -     connector->doublescan_allowed = 0;
> >>>> > -
> >>>> > -     drm_connector_attach_encoder(connector, hdmi->encoder);
> >>>> > -
> >>>> > -     return connector;
> >>>> > -}
> >
> >
Abhinav Kumar Dec. 6, 2021, 10:58 p.m. UTC | #7
Hi Dmitry

On 12/6/2021 2:47 PM, Dmitry Baryshkov wrote:
> On Mon, 6 Dec 2021 at 23:42, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 11/25/2021 4:50 AM, Dmitry Baryshkov wrote:
>>> On 19/10/2021 02:54, abhinavk@codeaurora.org wrote:
>>>> On 2021-10-16 07:21, Dmitry Baryshkov wrote:
>>>>> On Sat, 16 Oct 2021 at 01:25, <abhinavk@codeaurora.org> wrote:
>>>>>>
>>>>>> Hi Dmitry
>>>>>>
>>>>>> On 2021-10-14 17:11, Dmitry Baryshkov wrote:
>>>>>>> Merge old hdmi_bridge and hdmi_connector implementations. Use
>>>>>>> drm_bridge_connector instead.
>>>>>>>
>>>>>> Can you please comment on the validation done on this change?
>>>>>> Has basic bootup been verified on db820c as thats the only platform
>>>>>> which shall use this.
>>>>>
>>>>> Yes, this has been developed and validated on db820c
>>>> Thanks for confirming.
>>>>>
>>>>>>
>>>>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>>>>> ---
>>>>>>>   drivers/gpu/drm/msm/Makefile                  |   2 +-
>>>>>>>   drivers/gpu/drm/msm/hdmi/hdmi.c               |  12 +-
>>>>>>>   drivers/gpu/drm/msm/hdmi/hdmi.h               |  19 ++-
>>>>>>>   drivers/gpu/drm/msm/hdmi/hdmi_bridge.c        |  81 ++++++++-
>>>>>>>   .../msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} | 154
>>>>>> ++----------------
>>>>>>>   5 files changed, 109 insertions(+), 159 deletions(-)
>>>>>>>   rename drivers/gpu/drm/msm/hdmi/{hdmi_connector.c => hdmi_hpd.c}
>>>>>> (62%)
>>>>>>>
>>>>>>> diff --git a/drivers/gpu/drm/msm/Makefile
>>>>>>> b/drivers/gpu/drm/msm/Makefile
>>>>>>> index 904535eda0c4..91b09cda8a9c 100644
>>>>>>> --- a/drivers/gpu/drm/msm/Makefile
>>>>>>> +++ b/drivers/gpu/drm/msm/Makefile
>>>>>>> @@ -19,7 +19,7 @@ msm-y := \
>>>>>>>        hdmi/hdmi.o \
>>>>>>>        hdmi/hdmi_audio.o \
>>>>>>>        hdmi/hdmi_bridge.o \
>>>>>>> -     hdmi/hdmi_connector.o \
>>>>>>> +     hdmi/hdmi_hpd.o \
>>>>>>>        hdmi/hdmi_i2c.o \
>>>>>>>        hdmi/hdmi_phy.o \
>>>>>>>        hdmi/hdmi_phy_8960.o \
>>>>>>> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c
>>>>>>> b/drivers/gpu/drm/msm/hdmi/hdmi.c
>>>>>>> index db17a000d968..d1cf4df7188c 100644
>>>>>>> --- a/drivers/gpu/drm/msm/hdmi/hdmi.c
>>>>>>> +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
>>>>>>> @@ -8,6 +8,8 @@
>>>>>>>   #include <linux/of_irq.h>
>>>>>>>   #include <linux/of_gpio.h>
>>>>>>>
>>>>>>> +#include <drm/drm_bridge_connector.h>
>>>>>>> +
>>>>>>>   #include <sound/hdmi-codec.h>
>>>>>>>   #include "hdmi.h"
>>>>>>>
>>>>>>> @@ -41,7 +43,7 @@ static irqreturn_t msm_hdmi_irq(int irq, void
>>>>>>> *dev_id)
>>>>>>>        struct hdmi *hdmi = dev_id;
>>>>>>>
>>>>>>>        /* Process HPD: */
>>>>>>> -     msm_hdmi_connector_irq(hdmi->connector);
>>>>>>> +     msm_hdmi_hpd_irq(hdmi->bridge);
>>>>>>>
>>>>>>>        /* Process DDC: */
>>>>>>>        msm_hdmi_i2c_irq(hdmi->i2c);
>>>>>>> @@ -283,7 +285,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
>>>>>>>                goto fail;
>>>>>>>        }
>>>>>>>
>>>>>>> -     hdmi->connector = msm_hdmi_connector_init(hdmi);
>>>>>>> +     hdmi->connector = drm_bridge_connector_init(hdmi->dev,
>>>>>> encoder);
>>>>>>>        if (IS_ERR(hdmi->connector)) {
>>>>>>>                ret = PTR_ERR(hdmi->connector);
>>>>>>>                DRM_DEV_ERROR(dev->dev, "failed to create HDMI
>>>>>> connector: %d\n",
>>>>>>> ret);
>>>>>>> @@ -291,6 +293,8 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
>>>>>>>                goto fail;
>>>>>>>        }
>>>>>>>
>>>>>>> +     drm_connector_attach_encoder(hdmi->connector, hdmi->encoder);
>>>>>>> +
>>>>>>>        hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
>>>>>>>        if (hdmi->irq < 0) {
>>>>>>>                ret = hdmi->irq;
>>>>>>> @@ -307,7 +311,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
>>>>>>>                goto fail;
>>>>>>>        }
>>>>>>>
>>>>>>> -     ret = msm_hdmi_hpd_enable(hdmi->connector);
>>>>>>> +     drm_bridge_connector_enable_hpd(hdmi->connector);
>>>>>>> +
>>>>>>> +     ret = msm_hdmi_hpd_enable(hdmi->bridge);
>>>>>>>        if (ret < 0) {
>>>>>>>                DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable
>>>>>> HPD: %d\n", ret);
>>>>>>>                goto fail;
>>>>>>> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h
>>>>>>> b/drivers/gpu/drm/msm/hdmi/hdmi.h
>>>>>>> index 82261078c6b1..736f348befb3 100644
>>>>>>> --- a/drivers/gpu/drm/msm/hdmi/hdmi.h
>>>>>>> +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
>>>>>>> @@ -114,6 +114,13 @@ struct hdmi_platform_config {
>>>>>>>        struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO];
>>>>>>>   };
>>>>>>>
>>>>>>> +struct hdmi_bridge {
>>>>>>> +     struct drm_bridge base;
>>>>>>> +     struct hdmi *hdmi;
>>>>>>> +     struct work_struct hpd_work;
>>>>>>> +};
>>>>>>> +#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
>>>>>>> +
>>>>>>>   void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on);
>>>>>>>
>>>>>>>   static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data)
>>>>>>> @@ -230,13 +237,11 @@ void msm_hdmi_audio_set_sample_rate(struct hdmi
>>>>>>> *hdmi, int rate);
>>>>>>>   struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi);
>>>>>>>   void msm_hdmi_bridge_destroy(struct drm_bridge *bridge);
>>>>>>>
>>>>>>> -/*
>>>>>>> - * hdmi connector:
>>>>>>> - */
>>>>>>> -
>>>>>>> -void msm_hdmi_connector_irq(struct drm_connector *connector);
>>>>>>> -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi);
>>>>>>> -int msm_hdmi_hpd_enable(struct drm_connector *connector);
>>>>>>> +void msm_hdmi_hpd_irq(struct drm_bridge *bridge);
>>>>>>> +enum drm_connector_status msm_hdmi_bridge_detect(
>>>>>>> +             struct drm_bridge *bridge);
>>>>>>> +int msm_hdmi_hpd_enable(struct drm_bridge *bridge);
>>>>>>> +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge);
>>>>>>>
>>>>>>>   /*
>>>>>>>    * i2c adapter for ddc:
>>>>>>> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>>>>>> b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>>>>>> index f04eb4a70f0d..211b73dddf65 100644
>>>>>>> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>>>>>> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>>>>>> @@ -5,17 +5,16 @@
>>>>>>>    */
>>>>>>>
>>>>>>>   #include <linux/delay.h>
>>>>>>> +#include <drm/drm_bridge_connector.h>
>>>>>>>
>>>>>>> +#include "msm_kms.h"
>>>>>>>   #include "hdmi.h"
>>>>>>>
>>>>>>> -struct hdmi_bridge {
>>>>>>> -     struct drm_bridge base;
>>>>>>> -     struct hdmi *hdmi;
>>>>>>> -};
>>>>>>> -#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
>>>>>>> -
>>>>>>>   void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)
>>>>>>>   {
>>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>>>>> +
>>>>>>> +     msm_hdmi_hpd_disable(hdmi_bridge);
>>>>>>>   }
>>>>>>>
>>>>>>>   static void msm_hdmi_power_on(struct drm_bridge *bridge)
>>>>>>> @@ -251,14 +250,76 @@ static void msm_hdmi_bridge_mode_set(struct
>>>>>>> drm_bridge *bridge,
>>>>>>>                msm_hdmi_audio_update(hdmi);
>>>>>>>   }
>>>>>>>
>>>>>>> +static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge
>>>>>>> *bridge,
>>>>>>> +             struct drm_connector *connector)
>>>>>>> +{
>>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>>>>> +     struct edid *edid;
>>>>>>> +     uint32_t hdmi_ctrl;
>>>>>>> +
>>>>>>> +     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
>>>>>>> +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
>>>>>>> +
>>>>>>> +     edid = drm_get_edid(connector, hdmi->i2c);
>>>>>>> +
>>>>>>> +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
>>>>>>> +
>>>>>>> +     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
>>>>>>> +
>>>>>>> +     return edid;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct
>>>>>>> drm_bridge *bridge,
>>>>>>> +             const struct drm_display_info *info,
>>>>>>> +             const struct drm_display_mode *mode)
>>>>>>> +{
>>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>>>>> +     const struct hdmi_platform_config *config = hdmi->config;
>>>>>>> +     struct msm_drm_private *priv = bridge->dev->dev_private;
>>>>>>> +     struct msm_kms *kms = priv->kms;
>>>>>>> +     long actual, requested;
>>>>>>> +
>>>>>>> +     requested = 1000 * mode->clock;
>>>>>>> +     actual = kms->funcs->round_pixclk(kms,
>>>>>>> +                     requested, hdmi_bridge->hdmi->encoder);
>>>>>>> +
>>>>>>> +     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
>>>>>>> +      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
>>>>>>> +      * instead):
>>>>>>> +      */
>>>>>>> +     if (config->pwr_clk_cnt > 0)
>>>>>>> +             actual = clk_round_rate(hdmi->pwr_clks[0], actual);
>>>>>>> +
>>>>>>> +     DBG("requested=%ld, actual=%ld", requested, actual);
>>>>>>> +
>>>>>>> +     if (actual != requested)
>>>>>>> +             return MODE_CLOCK_RANGE;
>>>>>>> +
>>>>>>> +     return 0;
>>>>>>> +}
>>>>>>> +
>>>>>>>   static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
>>>>>>>                .pre_enable = msm_hdmi_bridge_pre_enable,
>>>>>>>                .enable = msm_hdmi_bridge_enable,
>>>>>>>                .disable = msm_hdmi_bridge_disable,
>>>>>>>                .post_disable = msm_hdmi_bridge_post_disable,
>>>>>>>                .mode_set = msm_hdmi_bridge_mode_set,
>>>>>>> +             .mode_valid = msm_hdmi_bridge_mode_valid,
>>>>>>> +             .get_edid = msm_hdmi_bridge_get_edid,
>>>>>>> +             .detect = msm_hdmi_bridge_detect,
>>>>>>>   };
>>>>>>>
>>>>>>> +static void
>>>>>>> +msm_hdmi_hotplug_work(struct work_struct *work)
>>>>>>> +{
>>>>>>> +     struct hdmi_bridge *hdmi_bridge =
>>>>>>> +             container_of(work, struct hdmi_bridge, hpd_work);
>>>>>>> +     struct drm_bridge *bridge = &hdmi_bridge->base;
>>>>>>> +
>>>>>>> +     drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge));
>>>>>>> +}
>>>>>>>
>>>>>>>   /* initialize bridge */
>>>>>>>   struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
>>>>>>> @@ -275,11 +336,17 @@ struct drm_bridge *msm_hdmi_bridge_init(struct
>>>>>>> hdmi *hdmi)
>>>>>>>        }
>>>>>>>
>>>>>>>        hdmi_bridge->hdmi = hdmi;
>>>>>>> +     INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);
>>>>>>>
>>>>>>>        bridge = &hdmi_bridge->base;
>>>>>>>        bridge->funcs = &msm_hdmi_bridge_funcs;
>>>>>>> +     bridge->ddc = hdmi->i2c;
>>>>>>> +     bridge->type = DRM_MODE_CONNECTOR_HDMIA;
>>>>>>> +     bridge->ops = DRM_BRIDGE_OP_HPD |
>>>>>>> +             DRM_BRIDGE_OP_DETECT |
>>>>>>> +             DRM_BRIDGE_OP_EDID;
>>>> Please correct me if wrong here. When we set DRM_BRIDGE_OP_HPD, it
>>>> means we need to
>>>> set the hpd_enable and hpd_disable callbacks. I am not seeing those
>>>> being set.
>>>>
>>>> 707      * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and
>>>> hot-unplug
>>>> 708      * without requiring polling. Bridges that set this flag shall
>>>> 709      * implement the &drm_bridge_funcs->hpd_enable and
>>>> 710      * &drm_bridge_funcs->hpd_disable callbacks if they support
>>>> enabling
>>>> 711      * and disabling hot-plug detection dynamically.
>>>> 712      */
>>>> 713     DRM_BRIDGE_OP_HPD = BIT(2),
>>>>
>>>> So when drm_bridge_connector_enable_hpd() is called, its a no-op as
>>>> hpd_enable() callback
>>>> is not set.
>>>>
>>>> msm_hdmi_hpd_enable() actually enables the HPD logic which is getting
>>>> called from msm_hdmi_modeset_init()
>>>> and not from hpd_enable().
>>>>
>>>> In that case, do we need to set DRM_BRIDGE_OP_HPD for this? If we
>>>> dont, what will happen?
>>>>
>>>
>>> Without this flag, the drm_bridge_connector will not know that this
>>> bridge is capable of generating HPD events on its own, ending up with
>>> polling implementation. See drm_bridge_connector_init(),
>>> drm_helper_hpd_irq_event(), etc.
>>>
>>
>> Thanks for the details. Then, as per the documentation on the
>> DRM_BRIDGE_OP_HPD, shouldnt we also assign msm_hdmi_hpd_enable to
>> hpd_enable callback? Since we are already calling
>> drm_bridge_connector_enable_hpd(), that should take care of calling it
>> using the callback then.
>>
>> Similarly, you can assign msm_hdmi_hpd_disable to hpd_disable op and
>> then call drm_bridge_connector_disable_hpd() in those places.
> 
> Since that would be a change in the functionality, I'd prefer to have
> that in a separate patch.
> It looks like a nice cleanup idea, so I'd implement that at some point.
> 
>>
I didnt follow this part. Why would there be a change in functionality?
You are only going to assign the hpd_enable/hpd_disable callbacks.
And replace the calls msm_hdmi_hpd_enable/msm_hdmi_hpd_disable with
drm_bridge_connector_enable_hpd()/drm_bridge_connector_disable_hpd()
within the driver. AFAICT, noone else is going to issue the 
enable/disable so it should not affect functionality.

>> That way, functionality remains intact and we follow the documentation.
>>
>>>>
>>>>
>>>>>>>
>>>>>>> -     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0);
>>>>>>> +     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL,
>>>>>>> DRM_BRIDGE_ATTACH_NO_CONNECTOR);
>>>>>>>        if (ret)
>>>>>>>                goto fail;
>>>>>>>
>>>>>>> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
>>>>>>> b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
>>>>>>> similarity index 62%
>>>>>>> rename from drivers/gpu/drm/msm/hdmi/hdmi_connector.c
>>>>>>> rename to drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
>>>>>>> index a7f729cdec7b..1cda7bf23b3b 100644
>>>>>>> --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
>>>>>>> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
>>>>>>> @@ -11,13 +11,6 @@
>>>>>>>   #include "msm_kms.h"
>>>>>>>   #include "hdmi.h"
>>>>>>>
>>>>>>> -struct hdmi_connector {
>>>>>>> -     struct drm_connector base;
>>>>>>> -     struct hdmi *hdmi;
>>>>>>> -     struct work_struct hpd_work;
>>>>>>> -};
>>>>>>> -#define to_hdmi_connector(x) container_of(x, struct hdmi_connector,
>>>>>>> base)
>>>>>>> -
>>>>>>>   static void msm_hdmi_phy_reset(struct hdmi *hdmi)
>>>>>>>   {
>>>>>>>        unsigned int val;
>>>>>>> @@ -139,10 +132,10 @@ static void enable_hpd_clocks(struct hdmi
>>>>>> *hdmi,
>>>>>>> bool enable)
>>>>>>>        }
>>>>>>>   }
>>>>>>>
>>>>>>> -int msm_hdmi_hpd_enable(struct drm_connector *connector)
>>>>>>> +int msm_hdmi_hpd_enable(struct drm_bridge *bridge)
>>>>>>>   {
>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>> to_hdmi_connector(connector);
>>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>>>>>        const struct hdmi_platform_config *config = hdmi->config;
>>>>>>>        struct device *dev = &hdmi->pdev->dev;
>>>>>>>        uint32_t hpd_ctrl;
>>>>>>> @@ -199,9 +192,9 @@ int msm_hdmi_hpd_enable(struct drm_connector
>>>>>>> *connector)
>>>>>>>        return ret;
>>>>>>>   }
>>>>>>>
>>>>>>> -static void hdp_disable(struct hdmi_connector *hdmi_connector)
>>>>>>> +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge)
>>>>>>>   {
>>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>>>>>        const struct hdmi_platform_config *config = hdmi->config;
>>>>>>>        struct device *dev = &hdmi->pdev->dev;
>>>>>>>        int ret;
>>>>>>> @@ -227,19 +220,10 @@ static void hdp_disable(struct hdmi_connector
>>>>>>> *hdmi_connector)
>>>>>>>                dev_warn(dev, "failed to disable hpd regulator:
>>>>>> %d\n", ret);
>>>>>>>   }
>>>>>>>
>>>>>>> -static void
>>>>>>> -msm_hdmi_hotplug_work(struct work_struct *work)
>>>>>>> -{
>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>>> -             container_of(work, struct hdmi_connector, hpd_work);
>>>>>>> -     struct drm_connector *connector = &hdmi_connector->base;
>>>>>>> -     drm_helper_hpd_irq_event(connector->dev);
>>>>>>> -}
>>>>>>> -
>>>>>>> -void msm_hdmi_connector_irq(struct drm_connector *connector)
>>>>>>> +void msm_hdmi_hpd_irq(struct drm_bridge *bridge)
>>>>>>>   {
>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>> to_hdmi_connector(connector);
>>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>>>>>        uint32_t hpd_int_status, hpd_int_ctrl;
>>>>>>>
>>>>>>>        /* Process HPD: */
>>>>>>> @@ -262,7 +246,7 @@ void msm_hdmi_connector_irq(struct drm_connector
>>>>>>> *connector)
>>>>>>>                        hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
>>>>>>>                hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
>>>>>>>
>>>>>>> -             queue_work(hdmi->workq, &hdmi_connector->hpd_work);
>>>>>>> +             queue_work(hdmi->workq, &hdmi_bridge->hpd_work);
>>>>>>>        }
>>>>>>>   }
>>>>>>>
>>>>>>> @@ -293,11 +277,11 @@ static enum drm_connector_status
>>>>>>> detect_gpio(struct hdmi *hdmi)
>>>>>>>                        connector_status_disconnected;
>>>>>>>   }
>>>>>>>
>>>>>>> -static enum drm_connector_status hdmi_connector_detect(
>>>>>>> -             struct drm_connector *connector, bool force)
>>>>>>> +enum drm_connector_status msm_hdmi_bridge_detect(
>>>>>>> +             struct drm_bridge *bridge)
>>>>>>>   {
>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>> to_hdmi_connector(connector);
>>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>>>>>        const struct hdmi_platform_config *config = hdmi->config;
>>>>>>>        struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
>>>>>>>        enum drm_connector_status stat_gpio, stat_reg;
>>>>>>> @@ -331,115 +315,3 @@ static enum drm_connector_status
>>>>>>> hdmi_connector_detect(
>>>>>>>
>>>>>>>        return stat_gpio;
>>>>>>>   }
>>>>>>> -
>>>>>>> -static void hdmi_connector_destroy(struct drm_connector *connector)
>>>>>>> -{
>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>> to_hdmi_connector(connector);
>>>>>>> -
>>>>>>> -     hdp_disable(hdmi_connector);
>>>>>>> -
>>>>>>> -     drm_connector_cleanup(connector);
>>>>>>> -
>>>>>>> -     kfree(hdmi_connector);
>>>>>>> -}
>>>>>>> -
>>>>>>> -static int msm_hdmi_connector_get_modes(struct drm_connector
>>>>>>> *connector)
>>>>>>> -{
>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>> to_hdmi_connector(connector);
>>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>>>>> -     struct edid *edid;
>>>>>>> -     uint32_t hdmi_ctrl;
>>>>>>> -     int ret = 0;
>>>>>>> -
>>>>>>> -     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
>>>>>>> -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
>>>>>>> -
>>>>>>> -     edid = drm_get_edid(connector, hdmi->i2c);
>>>>>>> -
>>>>>>> -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
>>>>>>> -
>>>>>>> -     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
>>>>>>> -     drm_connector_update_edid_property(connector, edid);
>>>>>>> -
>>>>>>> -     if (edid) {
>>>>>>> -             ret = drm_add_edid_modes(connector, edid);
>>>>>>> -             kfree(edid);
>>>>>>> -     }
>>>>>>> -
>>>>>>> -     return ret;
>>>>>>> -}
>>>>>>> -
>>>>>>> -static int msm_hdmi_connector_mode_valid(struct drm_connector
>>>>>>> *connector,
>>>>>>> -                              struct drm_display_mode *mode)
>>>>>>> -{
>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>> to_hdmi_connector(connector);
>>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>>>>> -     const struct hdmi_platform_config *config = hdmi->config;
>>>>>>> -     struct msm_drm_private *priv = connector->dev->dev_private;
>>>>>>> -     struct msm_kms *kms = priv->kms;
>>>>>>> -     long actual, requested;
>>>>>>> -
>>>>>>> -     requested = 1000 * mode->clock;
>>>>>>> -     actual = kms->funcs->round_pixclk(kms,
>>>>>>> -                     requested, hdmi_connector->hdmi->encoder);
>>>>>>> -
>>>>>>> -     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
>>>>>>> -      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
>>>>>>> -      * instead):
>>>>>>> -      */
>>>>>>> -     if (config->pwr_clk_cnt > 0)
>>>>>>> -             actual = clk_round_rate(hdmi->pwr_clks[0], actual);
>>>>>>> -
>>>>>>> -     DBG("requested=%ld, actual=%ld", requested, actual);
>>>>>>> -
>>>>>>> -     if (actual != requested)
>>>>>>> -             return MODE_CLOCK_RANGE;
>>>>>>> -
>>>>>>> -     return 0;
>>>>>>> -}
>>>>>>> -
>>>>>>> -static const struct drm_connector_funcs hdmi_connector_funcs = {
>>>>>>> -     .detect = hdmi_connector_detect,
>>>>>>> -     .fill_modes = drm_helper_probe_single_connector_modes,
>>>>>>> -     .destroy = hdmi_connector_destroy,
>>>>>>> -     .reset = drm_atomic_helper_connector_reset,
>>>>>>> -     .atomic_duplicate_state =
>>>>>>> drm_atomic_helper_connector_duplicate_state,
>>>>>>> -     .atomic_destroy_state =
>>>>>> drm_atomic_helper_connector_destroy_state,
>>>>>>> -};
>>>>>>> -
>>>>>>> -static const struct drm_connector_helper_funcs
>>>>>>> msm_hdmi_connector_helper_funcs = {
>>>>>>> -     .get_modes = msm_hdmi_connector_get_modes,
>>>>>>> -     .mode_valid = msm_hdmi_connector_mode_valid,
>>>>>>> -};
>>>>>>> -
>>>>>>> -/* initialize connector */
>>>>>>> -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
>>>>>>> -{
>>>>>>> -     struct drm_connector *connector = NULL;
>>>>>>> -     struct hdmi_connector *hdmi_connector;
>>>>>>> -
>>>>>>> -     hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
>>>>>>> -     if (!hdmi_connector)
>>>>>>> -             return ERR_PTR(-ENOMEM);
>>>>>>> -
>>>>>>> -     hdmi_connector->hdmi = hdmi;
>>>>>>> -     INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);
>>>>>>> -
>>>>>>> -     connector = &hdmi_connector->base;
>>>>>>> -
>>>>>>> -     drm_connector_init_with_ddc(hdmi->dev, connector,
>>>>>>> -                                 &hdmi_connector_funcs,
>>>>>>> -                                 DRM_MODE_CONNECTOR_HDMIA,
>>>>>>> -                                 hdmi->i2c);
>>>>>>> -     drm_connector_helper_add(connector,
>>>>>>> &msm_hdmi_connector_helper_funcs);
>>>>>>> -
>>>>>>> -     connector->polled = DRM_CONNECTOR_POLL_CONNECT |
>>>>>>> -                     DRM_CONNECTOR_POLL_DISCONNECT;
>>>>>>> -
>>>>>>> -     connector->interlace_allowed = 0;
>>>>>>> -     connector->doublescan_allowed = 0;
>>>>>>> -
>>>>>>> -     drm_connector_attach_encoder(connector, hdmi->encoder);
>>>>>>> -
>>>>>>> -     return connector;
>>>>>>> -}
>>>
>>>
> 
> 
>
Dmitry Baryshkov Dec. 7, 2021, 12:21 a.m. UTC | #8
On Tue, 7 Dec 2021 at 01:58, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Hi Dmitry
>
> On 12/6/2021 2:47 PM, Dmitry Baryshkov wrote:
> > On Mon, 6 Dec 2021 at 23:42, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 11/25/2021 4:50 AM, Dmitry Baryshkov wrote:
> >>> On 19/10/2021 02:54, abhinavk@codeaurora.org wrote:
> >>>> On 2021-10-16 07:21, Dmitry Baryshkov wrote:
> >>>>> On Sat, 16 Oct 2021 at 01:25, <abhinavk@codeaurora.org> wrote:
> >>>>>>
> >>>>>> Hi Dmitry
> >>>>>>
> >>>>>> On 2021-10-14 17:11, Dmitry Baryshkov wrote:
> >>>>>>> Merge old hdmi_bridge and hdmi_connector implementations. Use
> >>>>>>> drm_bridge_connector instead.
> >>>>>>>
> >>>>>> Can you please comment on the validation done on this change?
> >>>>>> Has basic bootup been verified on db820c as thats the only platform
> >>>>>> which shall use this.
> >>>>>
> >>>>> Yes, this has been developed and validated on db820c
> >>>> Thanks for confirming.
> >>>>>
> >>>>>>
> >>>>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> >>>>>>> ---
> >>>>>>>   drivers/gpu/drm/msm/Makefile                  |   2 +-
> >>>>>>>   drivers/gpu/drm/msm/hdmi/hdmi.c               |  12 +-
> >>>>>>>   drivers/gpu/drm/msm/hdmi/hdmi.h               |  19 ++-
> >>>>>>>   drivers/gpu/drm/msm/hdmi/hdmi_bridge.c        |  81 ++++++++-
> >>>>>>>   .../msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} | 154
> >>>>>> ++----------------
> >>>>>>>   5 files changed, 109 insertions(+), 159 deletions(-)
> >>>>>>>   rename drivers/gpu/drm/msm/hdmi/{hdmi_connector.c => hdmi_hpd.c}
> >>>>>> (62%)
> >>>>>>>
> >>>>>>> diff --git a/drivers/gpu/drm/msm/Makefile
> >>>>>>> b/drivers/gpu/drm/msm/Makefile
> >>>>>>> index 904535eda0c4..91b09cda8a9c 100644
> >>>>>>> --- a/drivers/gpu/drm/msm/Makefile
> >>>>>>> +++ b/drivers/gpu/drm/msm/Makefile
> >>>>>>> @@ -19,7 +19,7 @@ msm-y := \
> >>>>>>>        hdmi/hdmi.o \
> >>>>>>>        hdmi/hdmi_audio.o \
> >>>>>>>        hdmi/hdmi_bridge.o \
> >>>>>>> -     hdmi/hdmi_connector.o \
> >>>>>>> +     hdmi/hdmi_hpd.o \
> >>>>>>>        hdmi/hdmi_i2c.o \
> >>>>>>>        hdmi/hdmi_phy.o \
> >>>>>>>        hdmi/hdmi_phy_8960.o \
> >>>>>>> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c
> >>>>>>> b/drivers/gpu/drm/msm/hdmi/hdmi.c
> >>>>>>> index db17a000d968..d1cf4df7188c 100644
> >>>>>>> --- a/drivers/gpu/drm/msm/hdmi/hdmi.c
> >>>>>>> +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
> >>>>>>> @@ -8,6 +8,8 @@
> >>>>>>>   #include <linux/of_irq.h>
> >>>>>>>   #include <linux/of_gpio.h>
> >>>>>>>
> >>>>>>> +#include <drm/drm_bridge_connector.h>
> >>>>>>> +
> >>>>>>>   #include <sound/hdmi-codec.h>
> >>>>>>>   #include "hdmi.h"
> >>>>>>>
> >>>>>>> @@ -41,7 +43,7 @@ static irqreturn_t msm_hdmi_irq(int irq, void
> >>>>>>> *dev_id)
> >>>>>>>        struct hdmi *hdmi = dev_id;
> >>>>>>>
> >>>>>>>        /* Process HPD: */
> >>>>>>> -     msm_hdmi_connector_irq(hdmi->connector);
> >>>>>>> +     msm_hdmi_hpd_irq(hdmi->bridge);
> >>>>>>>
> >>>>>>>        /* Process DDC: */
> >>>>>>>        msm_hdmi_i2c_irq(hdmi->i2c);
> >>>>>>> @@ -283,7 +285,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
> >>>>>>>                goto fail;
> >>>>>>>        }
> >>>>>>>
> >>>>>>> -     hdmi->connector = msm_hdmi_connector_init(hdmi);
> >>>>>>> +     hdmi->connector = drm_bridge_connector_init(hdmi->dev,
> >>>>>> encoder);
> >>>>>>>        if (IS_ERR(hdmi->connector)) {
> >>>>>>>                ret = PTR_ERR(hdmi->connector);
> >>>>>>>                DRM_DEV_ERROR(dev->dev, "failed to create HDMI
> >>>>>> connector: %d\n",
> >>>>>>> ret);
> >>>>>>> @@ -291,6 +293,8 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
> >>>>>>>                goto fail;
> >>>>>>>        }
> >>>>>>>
> >>>>>>> +     drm_connector_attach_encoder(hdmi->connector, hdmi->encoder);
> >>>>>>> +
> >>>>>>>        hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
> >>>>>>>        if (hdmi->irq < 0) {
> >>>>>>>                ret = hdmi->irq;
> >>>>>>> @@ -307,7 +311,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
> >>>>>>>                goto fail;
> >>>>>>>        }
> >>>>>>>
> >>>>>>> -     ret = msm_hdmi_hpd_enable(hdmi->connector);
> >>>>>>> +     drm_bridge_connector_enable_hpd(hdmi->connector);
> >>>>>>> +
> >>>>>>> +     ret = msm_hdmi_hpd_enable(hdmi->bridge);
> >>>>>>>        if (ret < 0) {
> >>>>>>>                DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable
> >>>>>> HPD: %d\n", ret);
> >>>>>>>                goto fail;
> >>>>>>> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h
> >>>>>>> b/drivers/gpu/drm/msm/hdmi/hdmi.h
> >>>>>>> index 82261078c6b1..736f348befb3 100644
> >>>>>>> --- a/drivers/gpu/drm/msm/hdmi/hdmi.h
> >>>>>>> +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
> >>>>>>> @@ -114,6 +114,13 @@ struct hdmi_platform_config {
> >>>>>>>        struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO];
> >>>>>>>   };
> >>>>>>>
> >>>>>>> +struct hdmi_bridge {
> >>>>>>> +     struct drm_bridge base;
> >>>>>>> +     struct hdmi *hdmi;
> >>>>>>> +     struct work_struct hpd_work;
> >>>>>>> +};
> >>>>>>> +#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
> >>>>>>> +
> >>>>>>>   void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on);
> >>>>>>>
> >>>>>>>   static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data)
> >>>>>>> @@ -230,13 +237,11 @@ void msm_hdmi_audio_set_sample_rate(struct hdmi
> >>>>>>> *hdmi, int rate);
> >>>>>>>   struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi);
> >>>>>>>   void msm_hdmi_bridge_destroy(struct drm_bridge *bridge);
> >>>>>>>
> >>>>>>> -/*
> >>>>>>> - * hdmi connector:
> >>>>>>> - */
> >>>>>>> -
> >>>>>>> -void msm_hdmi_connector_irq(struct drm_connector *connector);
> >>>>>>> -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi);
> >>>>>>> -int msm_hdmi_hpd_enable(struct drm_connector *connector);
> >>>>>>> +void msm_hdmi_hpd_irq(struct drm_bridge *bridge);
> >>>>>>> +enum drm_connector_status msm_hdmi_bridge_detect(
> >>>>>>> +             struct drm_bridge *bridge);
> >>>>>>> +int msm_hdmi_hpd_enable(struct drm_bridge *bridge);
> >>>>>>> +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge);
> >>>>>>>
> >>>>>>>   /*
> >>>>>>>    * i2c adapter for ddc:
> >>>>>>> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> >>>>>>> b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> >>>>>>> index f04eb4a70f0d..211b73dddf65 100644
> >>>>>>> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> >>>>>>> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> >>>>>>> @@ -5,17 +5,16 @@
> >>>>>>>    */
> >>>>>>>
> >>>>>>>   #include <linux/delay.h>
> >>>>>>> +#include <drm/drm_bridge_connector.h>
> >>>>>>>
> >>>>>>> +#include "msm_kms.h"
> >>>>>>>   #include "hdmi.h"
> >>>>>>>
> >>>>>>> -struct hdmi_bridge {
> >>>>>>> -     struct drm_bridge base;
> >>>>>>> -     struct hdmi *hdmi;
> >>>>>>> -};
> >>>>>>> -#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
> >>>>>>> -
> >>>>>>>   void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)
> >>>>>>>   {
> >>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
> >>>>>>> +
> >>>>>>> +     msm_hdmi_hpd_disable(hdmi_bridge);
> >>>>>>>   }
> >>>>>>>
> >>>>>>>   static void msm_hdmi_power_on(struct drm_bridge *bridge)
> >>>>>>> @@ -251,14 +250,76 @@ static void msm_hdmi_bridge_mode_set(struct
> >>>>>>> drm_bridge *bridge,
> >>>>>>>                msm_hdmi_audio_update(hdmi);
> >>>>>>>   }
> >>>>>>>
> >>>>>>> +static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge
> >>>>>>> *bridge,
> >>>>>>> +             struct drm_connector *connector)
> >>>>>>> +{
> >>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
> >>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
> >>>>>>> +     struct edid *edid;
> >>>>>>> +     uint32_t hdmi_ctrl;
> >>>>>>> +
> >>>>>>> +     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
> >>>>>>> +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
> >>>>>>> +
> >>>>>>> +     edid = drm_get_edid(connector, hdmi->i2c);
> >>>>>>> +
> >>>>>>> +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
> >>>>>>> +
> >>>>>>> +     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
> >>>>>>> +
> >>>>>>> +     return edid;
> >>>>>>> +}
> >>>>>>> +
> >>>>>>> +static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct
> >>>>>>> drm_bridge *bridge,
> >>>>>>> +             const struct drm_display_info *info,
> >>>>>>> +             const struct drm_display_mode *mode)
> >>>>>>> +{
> >>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
> >>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
> >>>>>>> +     const struct hdmi_platform_config *config = hdmi->config;
> >>>>>>> +     struct msm_drm_private *priv = bridge->dev->dev_private;
> >>>>>>> +     struct msm_kms *kms = priv->kms;
> >>>>>>> +     long actual, requested;
> >>>>>>> +
> >>>>>>> +     requested = 1000 * mode->clock;
> >>>>>>> +     actual = kms->funcs->round_pixclk(kms,
> >>>>>>> +                     requested, hdmi_bridge->hdmi->encoder);
> >>>>>>> +
> >>>>>>> +     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
> >>>>>>> +      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
> >>>>>>> +      * instead):
> >>>>>>> +      */
> >>>>>>> +     if (config->pwr_clk_cnt > 0)
> >>>>>>> +             actual = clk_round_rate(hdmi->pwr_clks[0], actual);
> >>>>>>> +
> >>>>>>> +     DBG("requested=%ld, actual=%ld", requested, actual);
> >>>>>>> +
> >>>>>>> +     if (actual != requested)
> >>>>>>> +             return MODE_CLOCK_RANGE;
> >>>>>>> +
> >>>>>>> +     return 0;
> >>>>>>> +}
> >>>>>>> +
> >>>>>>>   static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
> >>>>>>>                .pre_enable = msm_hdmi_bridge_pre_enable,
> >>>>>>>                .enable = msm_hdmi_bridge_enable,
> >>>>>>>                .disable = msm_hdmi_bridge_disable,
> >>>>>>>                .post_disable = msm_hdmi_bridge_post_disable,
> >>>>>>>                .mode_set = msm_hdmi_bridge_mode_set,
> >>>>>>> +             .mode_valid = msm_hdmi_bridge_mode_valid,
> >>>>>>> +             .get_edid = msm_hdmi_bridge_get_edid,
> >>>>>>> +             .detect = msm_hdmi_bridge_detect,
> >>>>>>>   };
> >>>>>>>
> >>>>>>> +static void
> >>>>>>> +msm_hdmi_hotplug_work(struct work_struct *work)
> >>>>>>> +{
> >>>>>>> +     struct hdmi_bridge *hdmi_bridge =
> >>>>>>> +             container_of(work, struct hdmi_bridge, hpd_work);
> >>>>>>> +     struct drm_bridge *bridge = &hdmi_bridge->base;
> >>>>>>> +
> >>>>>>> +     drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge));
> >>>>>>> +}
> >>>>>>>
> >>>>>>>   /* initialize bridge */
> >>>>>>>   struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
> >>>>>>> @@ -275,11 +336,17 @@ struct drm_bridge *msm_hdmi_bridge_init(struct
> >>>>>>> hdmi *hdmi)
> >>>>>>>        }
> >>>>>>>
> >>>>>>>        hdmi_bridge->hdmi = hdmi;
> >>>>>>> +     INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);
> >>>>>>>
> >>>>>>>        bridge = &hdmi_bridge->base;
> >>>>>>>        bridge->funcs = &msm_hdmi_bridge_funcs;
> >>>>>>> +     bridge->ddc = hdmi->i2c;
> >>>>>>> +     bridge->type = DRM_MODE_CONNECTOR_HDMIA;
> >>>>>>> +     bridge->ops = DRM_BRIDGE_OP_HPD |
> >>>>>>> +             DRM_BRIDGE_OP_DETECT |
> >>>>>>> +             DRM_BRIDGE_OP_EDID;
> >>>> Please correct me if wrong here. When we set DRM_BRIDGE_OP_HPD, it
> >>>> means we need to
> >>>> set the hpd_enable and hpd_disable callbacks. I am not seeing those
> >>>> being set.
> >>>>
> >>>> 707      * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and
> >>>> hot-unplug
> >>>> 708      * without requiring polling. Bridges that set this flag shall
> >>>> 709      * implement the &drm_bridge_funcs->hpd_enable and
> >>>> 710      * &drm_bridge_funcs->hpd_disable callbacks if they support
> >>>> enabling
> >>>> 711      * and disabling hot-plug detection dynamically.
> >>>> 712      */
> >>>> 713     DRM_BRIDGE_OP_HPD = BIT(2),
> >>>>
> >>>> So when drm_bridge_connector_enable_hpd() is called, its a no-op as
> >>>> hpd_enable() callback
> >>>> is not set.
> >>>>
> >>>> msm_hdmi_hpd_enable() actually enables the HPD logic which is getting
> >>>> called from msm_hdmi_modeset_init()
> >>>> and not from hpd_enable().
> >>>>
> >>>> In that case, do we need to set DRM_BRIDGE_OP_HPD for this? If we
> >>>> dont, what will happen?
> >>>>
> >>>
> >>> Without this flag, the drm_bridge_connector will not know that this
> >>> bridge is capable of generating HPD events on its own, ending up with
> >>> polling implementation. See drm_bridge_connector_init(),
> >>> drm_helper_hpd_irq_event(), etc.
> >>>
> >>
> >> Thanks for the details. Then, as per the documentation on the
> >> DRM_BRIDGE_OP_HPD, shouldnt we also assign msm_hdmi_hpd_enable to
> >> hpd_enable callback? Since we are already calling
> >> drm_bridge_connector_enable_hpd(), that should take care of calling it
> >> using the callback then.
> >>
> >> Similarly, you can assign msm_hdmi_hpd_disable to hpd_disable op and
> >> then call drm_bridge_connector_disable_hpd() in those places.
> >
> > Since that would be a change in the functionality, I'd prefer to have
> > that in a separate patch.
> > It looks like a nice cleanup idea, so I'd implement that at some point.
> >
> >>
> I didnt follow this part. Why would there be a change in functionality?
> You are only going to assign the hpd_enable/hpd_disable callbacks.
> And replace the calls msm_hdmi_hpd_enable/msm_hdmi_hpd_disable with
> drm_bridge_connector_enable_hpd()/drm_bridge_connector_disable_hpd()
> within the driver. AFAICT, noone else is going to issue the
> enable/disable so it should not affect functionality.

You have described the change in the functionality: to use
hpd_enable/_disable callbacks.
Since we were not using them up to now, I'd like to keep that change separate.

>
> >> That way, functionality remains intact and we follow the documentation.
> >>
> >>>>
> >>>>
> >>>>>>>
> >>>>>>> -     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0);
> >>>>>>> +     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL,
> >>>>>>> DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> >>>>>>>        if (ret)
> >>>>>>>                goto fail;
> >>>>>>>
> >>>>>>> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
> >>>>>>> b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
> >>>>>>> similarity index 62%
> >>>>>>> rename from drivers/gpu/drm/msm/hdmi/hdmi_connector.c
> >>>>>>> rename to drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
> >>>>>>> index a7f729cdec7b..1cda7bf23b3b 100644
> >>>>>>> --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
> >>>>>>> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
> >>>>>>> @@ -11,13 +11,6 @@
> >>>>>>>   #include "msm_kms.h"
> >>>>>>>   #include "hdmi.h"
> >>>>>>>
> >>>>>>> -struct hdmi_connector {
> >>>>>>> -     struct drm_connector base;
> >>>>>>> -     struct hdmi *hdmi;
> >>>>>>> -     struct work_struct hpd_work;
> >>>>>>> -};
> >>>>>>> -#define to_hdmi_connector(x) container_of(x, struct hdmi_connector,
> >>>>>>> base)
> >>>>>>> -
> >>>>>>>   static void msm_hdmi_phy_reset(struct hdmi *hdmi)
> >>>>>>>   {
> >>>>>>>        unsigned int val;
> >>>>>>> @@ -139,10 +132,10 @@ static void enable_hpd_clocks(struct hdmi
> >>>>>> *hdmi,
> >>>>>>> bool enable)
> >>>>>>>        }
> >>>>>>>   }
> >>>>>>>
> >>>>>>> -int msm_hdmi_hpd_enable(struct drm_connector *connector)
> >>>>>>> +int msm_hdmi_hpd_enable(struct drm_bridge *bridge)
> >>>>>>>   {
> >>>>>>> -     struct hdmi_connector *hdmi_connector =
> >>>>>> to_hdmi_connector(connector);
> >>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
> >>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
> >>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
> >>>>>>>        const struct hdmi_platform_config *config = hdmi->config;
> >>>>>>>        struct device *dev = &hdmi->pdev->dev;
> >>>>>>>        uint32_t hpd_ctrl;
> >>>>>>> @@ -199,9 +192,9 @@ int msm_hdmi_hpd_enable(struct drm_connector
> >>>>>>> *connector)
> >>>>>>>        return ret;
> >>>>>>>   }
> >>>>>>>
> >>>>>>> -static void hdp_disable(struct hdmi_connector *hdmi_connector)
> >>>>>>> +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge)
> >>>>>>>   {
> >>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
> >>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
> >>>>>>>        const struct hdmi_platform_config *config = hdmi->config;
> >>>>>>>        struct device *dev = &hdmi->pdev->dev;
> >>>>>>>        int ret;
> >>>>>>> @@ -227,19 +220,10 @@ static void hdp_disable(struct hdmi_connector
> >>>>>>> *hdmi_connector)
> >>>>>>>                dev_warn(dev, "failed to disable hpd regulator:
> >>>>>> %d\n", ret);
> >>>>>>>   }
> >>>>>>>
> >>>>>>> -static void
> >>>>>>> -msm_hdmi_hotplug_work(struct work_struct *work)
> >>>>>>> -{
> >>>>>>> -     struct hdmi_connector *hdmi_connector =
> >>>>>>> -             container_of(work, struct hdmi_connector, hpd_work);
> >>>>>>> -     struct drm_connector *connector = &hdmi_connector->base;
> >>>>>>> -     drm_helper_hpd_irq_event(connector->dev);
> >>>>>>> -}
> >>>>>>> -
> >>>>>>> -void msm_hdmi_connector_irq(struct drm_connector *connector)
> >>>>>>> +void msm_hdmi_hpd_irq(struct drm_bridge *bridge)
> >>>>>>>   {
> >>>>>>> -     struct hdmi_connector *hdmi_connector =
> >>>>>> to_hdmi_connector(connector);
> >>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
> >>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
> >>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
> >>>>>>>        uint32_t hpd_int_status, hpd_int_ctrl;
> >>>>>>>
> >>>>>>>        /* Process HPD: */
> >>>>>>> @@ -262,7 +246,7 @@ void msm_hdmi_connector_irq(struct drm_connector
> >>>>>>> *connector)
> >>>>>>>                        hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
> >>>>>>>                hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
> >>>>>>>
> >>>>>>> -             queue_work(hdmi->workq, &hdmi_connector->hpd_work);
> >>>>>>> +             queue_work(hdmi->workq, &hdmi_bridge->hpd_work);
> >>>>>>>        }
> >>>>>>>   }
> >>>>>>>
> >>>>>>> @@ -293,11 +277,11 @@ static enum drm_connector_status
> >>>>>>> detect_gpio(struct hdmi *hdmi)
> >>>>>>>                        connector_status_disconnected;
> >>>>>>>   }
> >>>>>>>
> >>>>>>> -static enum drm_connector_status hdmi_connector_detect(
> >>>>>>> -             struct drm_connector *connector, bool force)
> >>>>>>> +enum drm_connector_status msm_hdmi_bridge_detect(
> >>>>>>> +             struct drm_bridge *bridge)
> >>>>>>>   {
> >>>>>>> -     struct hdmi_connector *hdmi_connector =
> >>>>>> to_hdmi_connector(connector);
> >>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
> >>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
> >>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
> >>>>>>>        const struct hdmi_platform_config *config = hdmi->config;
> >>>>>>>        struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
> >>>>>>>        enum drm_connector_status stat_gpio, stat_reg;
> >>>>>>> @@ -331,115 +315,3 @@ static enum drm_connector_status
> >>>>>>> hdmi_connector_detect(
> >>>>>>>
> >>>>>>>        return stat_gpio;
> >>>>>>>   }
> >>>>>>> -
> >>>>>>> -static void hdmi_connector_destroy(struct drm_connector *connector)
> >>>>>>> -{
> >>>>>>> -     struct hdmi_connector *hdmi_connector =
> >>>>>> to_hdmi_connector(connector);
> >>>>>>> -
> >>>>>>> -     hdp_disable(hdmi_connector);
> >>>>>>> -
> >>>>>>> -     drm_connector_cleanup(connector);
> >>>>>>> -
> >>>>>>> -     kfree(hdmi_connector);
> >>>>>>> -}
> >>>>>>> -
> >>>>>>> -static int msm_hdmi_connector_get_modes(struct drm_connector
> >>>>>>> *connector)
> >>>>>>> -{
> >>>>>>> -     struct hdmi_connector *hdmi_connector =
> >>>>>> to_hdmi_connector(connector);
> >>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
> >>>>>>> -     struct edid *edid;
> >>>>>>> -     uint32_t hdmi_ctrl;
> >>>>>>> -     int ret = 0;
> >>>>>>> -
> >>>>>>> -     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
> >>>>>>> -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
> >>>>>>> -
> >>>>>>> -     edid = drm_get_edid(connector, hdmi->i2c);
> >>>>>>> -
> >>>>>>> -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
> >>>>>>> -
> >>>>>>> -     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
> >>>>>>> -     drm_connector_update_edid_property(connector, edid);
> >>>>>>> -
> >>>>>>> -     if (edid) {
> >>>>>>> -             ret = drm_add_edid_modes(connector, edid);
> >>>>>>> -             kfree(edid);
> >>>>>>> -     }
> >>>>>>> -
> >>>>>>> -     return ret;
> >>>>>>> -}
> >>>>>>> -
> >>>>>>> -static int msm_hdmi_connector_mode_valid(struct drm_connector
> >>>>>>> *connector,
> >>>>>>> -                              struct drm_display_mode *mode)
> >>>>>>> -{
> >>>>>>> -     struct hdmi_connector *hdmi_connector =
> >>>>>> to_hdmi_connector(connector);
> >>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
> >>>>>>> -     const struct hdmi_platform_config *config = hdmi->config;
> >>>>>>> -     struct msm_drm_private *priv = connector->dev->dev_private;
> >>>>>>> -     struct msm_kms *kms = priv->kms;
> >>>>>>> -     long actual, requested;
> >>>>>>> -
> >>>>>>> -     requested = 1000 * mode->clock;
> >>>>>>> -     actual = kms->funcs->round_pixclk(kms,
> >>>>>>> -                     requested, hdmi_connector->hdmi->encoder);
> >>>>>>> -
> >>>>>>> -     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
> >>>>>>> -      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
> >>>>>>> -      * instead):
> >>>>>>> -      */
> >>>>>>> -     if (config->pwr_clk_cnt > 0)
> >>>>>>> -             actual = clk_round_rate(hdmi->pwr_clks[0], actual);
> >>>>>>> -
> >>>>>>> -     DBG("requested=%ld, actual=%ld", requested, actual);
> >>>>>>> -
> >>>>>>> -     if (actual != requested)
> >>>>>>> -             return MODE_CLOCK_RANGE;
> >>>>>>> -
> >>>>>>> -     return 0;
> >>>>>>> -}
> >>>>>>> -
> >>>>>>> -static const struct drm_connector_funcs hdmi_connector_funcs = {
> >>>>>>> -     .detect = hdmi_connector_detect,
> >>>>>>> -     .fill_modes = drm_helper_probe_single_connector_modes,
> >>>>>>> -     .destroy = hdmi_connector_destroy,
> >>>>>>> -     .reset = drm_atomic_helper_connector_reset,
> >>>>>>> -     .atomic_duplicate_state =
> >>>>>>> drm_atomic_helper_connector_duplicate_state,
> >>>>>>> -     .atomic_destroy_state =
> >>>>>> drm_atomic_helper_connector_destroy_state,
> >>>>>>> -};
> >>>>>>> -
> >>>>>>> -static const struct drm_connector_helper_funcs
> >>>>>>> msm_hdmi_connector_helper_funcs = {
> >>>>>>> -     .get_modes = msm_hdmi_connector_get_modes,
> >>>>>>> -     .mode_valid = msm_hdmi_connector_mode_valid,
> >>>>>>> -};
> >>>>>>> -
> >>>>>>> -/* initialize connector */
> >>>>>>> -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
> >>>>>>> -{
> >>>>>>> -     struct drm_connector *connector = NULL;
> >>>>>>> -     struct hdmi_connector *hdmi_connector;
> >>>>>>> -
> >>>>>>> -     hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
> >>>>>>> -     if (!hdmi_connector)
> >>>>>>> -             return ERR_PTR(-ENOMEM);
> >>>>>>> -
> >>>>>>> -     hdmi_connector->hdmi = hdmi;
> >>>>>>> -     INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);
> >>>>>>> -
> >>>>>>> -     connector = &hdmi_connector->base;
> >>>>>>> -
> >>>>>>> -     drm_connector_init_with_ddc(hdmi->dev, connector,
> >>>>>>> -                                 &hdmi_connector_funcs,
> >>>>>>> -                                 DRM_MODE_CONNECTOR_HDMIA,
> >>>>>>> -                                 hdmi->i2c);
> >>>>>>> -     drm_connector_helper_add(connector,
> >>>>>>> &msm_hdmi_connector_helper_funcs);
> >>>>>>> -
> >>>>>>> -     connector->polled = DRM_CONNECTOR_POLL_CONNECT |
> >>>>>>> -                     DRM_CONNECTOR_POLL_DISCONNECT;
> >>>>>>> -
> >>>>>>> -     connector->interlace_allowed = 0;
> >>>>>>> -     connector->doublescan_allowed = 0;
> >>>>>>> -
> >>>>>>> -     drm_connector_attach_encoder(connector, hdmi->encoder);
> >>>>>>> -
> >>>>>>> -     return connector;
> >>>>>>> -}
> >>>
> >>>
> >
> >
> >
Abhinav Kumar Dec. 7, 2021, 12:26 a.m. UTC | #9
On 12/6/2021 4:21 PM, Dmitry Baryshkov wrote:
> On Tue, 7 Dec 2021 at 01:58, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> Hi Dmitry
>>
>> On 12/6/2021 2:47 PM, Dmitry Baryshkov wrote:
>>> On Mon, 6 Dec 2021 at 23:42, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>>
>>>>
>>>> On 11/25/2021 4:50 AM, Dmitry Baryshkov wrote:
>>>>> On 19/10/2021 02:54, abhinavk@codeaurora.org wrote:
>>>>>> On 2021-10-16 07:21, Dmitry Baryshkov wrote:
>>>>>>> On Sat, 16 Oct 2021 at 01:25, <abhinavk@codeaurora.org> wrote:
>>>>>>>>
>>>>>>>> Hi Dmitry
>>>>>>>>
>>>>>>>> On 2021-10-14 17:11, Dmitry Baryshkov wrote:
>>>>>>>>> Merge old hdmi_bridge and hdmi_connector implementations. Use
>>>>>>>>> drm_bridge_connector instead.
>>>>>>>>>
>>>>>>>> Can you please comment on the validation done on this change?
>>>>>>>> Has basic bootup been verified on db820c as thats the only platform
>>>>>>>> which shall use this.
>>>>>>>
>>>>>>> Yes, this has been developed and validated on db820c
>>>>>> Thanks for confirming.
>>>>>>>
>>>>>>>>
>>>>>>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>>>>>>> ---
>>>>>>>>>    drivers/gpu/drm/msm/Makefile                  |   2 +-
>>>>>>>>>    drivers/gpu/drm/msm/hdmi/hdmi.c               |  12 +-
>>>>>>>>>    drivers/gpu/drm/msm/hdmi/hdmi.h               |  19 ++-
>>>>>>>>>    drivers/gpu/drm/msm/hdmi/hdmi_bridge.c        |  81 ++++++++-
>>>>>>>>>    .../msm/hdmi/{hdmi_connector.c => hdmi_hpd.c} | 154
>>>>>>>> ++----------------
>>>>>>>>>    5 files changed, 109 insertions(+), 159 deletions(-)
>>>>>>>>>    rename drivers/gpu/drm/msm/hdmi/{hdmi_connector.c => hdmi_hpd.c}
>>>>>>>> (62%)
>>>>>>>>>
>>>>>>>>> diff --git a/drivers/gpu/drm/msm/Makefile
>>>>>>>>> b/drivers/gpu/drm/msm/Makefile
>>>>>>>>> index 904535eda0c4..91b09cda8a9c 100644
>>>>>>>>> --- a/drivers/gpu/drm/msm/Makefile
>>>>>>>>> +++ b/drivers/gpu/drm/msm/Makefile
>>>>>>>>> @@ -19,7 +19,7 @@ msm-y := \
>>>>>>>>>         hdmi/hdmi.o \
>>>>>>>>>         hdmi/hdmi_audio.o \
>>>>>>>>>         hdmi/hdmi_bridge.o \
>>>>>>>>> -     hdmi/hdmi_connector.o \
>>>>>>>>> +     hdmi/hdmi_hpd.o \
>>>>>>>>>         hdmi/hdmi_i2c.o \
>>>>>>>>>         hdmi/hdmi_phy.o \
>>>>>>>>>         hdmi/hdmi_phy_8960.o \
>>>>>>>>> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c
>>>>>>>>> b/drivers/gpu/drm/msm/hdmi/hdmi.c
>>>>>>>>> index db17a000d968..d1cf4df7188c 100644
>>>>>>>>> --- a/drivers/gpu/drm/msm/hdmi/hdmi.c
>>>>>>>>> +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
>>>>>>>>> @@ -8,6 +8,8 @@
>>>>>>>>>    #include <linux/of_irq.h>
>>>>>>>>>    #include <linux/of_gpio.h>
>>>>>>>>>
>>>>>>>>> +#include <drm/drm_bridge_connector.h>
>>>>>>>>> +
>>>>>>>>>    #include <sound/hdmi-codec.h>
>>>>>>>>>    #include "hdmi.h"
>>>>>>>>>
>>>>>>>>> @@ -41,7 +43,7 @@ static irqreturn_t msm_hdmi_irq(int irq, void
>>>>>>>>> *dev_id)
>>>>>>>>>         struct hdmi *hdmi = dev_id;
>>>>>>>>>
>>>>>>>>>         /* Process HPD: */
>>>>>>>>> -     msm_hdmi_connector_irq(hdmi->connector);
>>>>>>>>> +     msm_hdmi_hpd_irq(hdmi->bridge);
>>>>>>>>>
>>>>>>>>>         /* Process DDC: */
>>>>>>>>>         msm_hdmi_i2c_irq(hdmi->i2c);
>>>>>>>>> @@ -283,7 +285,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
>>>>>>>>>                 goto fail;
>>>>>>>>>         }
>>>>>>>>>
>>>>>>>>> -     hdmi->connector = msm_hdmi_connector_init(hdmi);
>>>>>>>>> +     hdmi->connector = drm_bridge_connector_init(hdmi->dev,
>>>>>>>> encoder);
>>>>>>>>>         if (IS_ERR(hdmi->connector)) {
>>>>>>>>>                 ret = PTR_ERR(hdmi->connector);
>>>>>>>>>                 DRM_DEV_ERROR(dev->dev, "failed to create HDMI
>>>>>>>> connector: %d\n",
>>>>>>>>> ret);
>>>>>>>>> @@ -291,6 +293,8 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
>>>>>>>>>                 goto fail;
>>>>>>>>>         }
>>>>>>>>>
>>>>>>>>> +     drm_connector_attach_encoder(hdmi->connector, hdmi->encoder);
>>>>>>>>> +
>>>>>>>>>         hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
>>>>>>>>>         if (hdmi->irq < 0) {
>>>>>>>>>                 ret = hdmi->irq;
>>>>>>>>> @@ -307,7 +311,9 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
>>>>>>>>>                 goto fail;
>>>>>>>>>         }
>>>>>>>>>
>>>>>>>>> -     ret = msm_hdmi_hpd_enable(hdmi->connector);
>>>>>>>>> +     drm_bridge_connector_enable_hpd(hdmi->connector);
>>>>>>>>> +
>>>>>>>>> +     ret = msm_hdmi_hpd_enable(hdmi->bridge);
>>>>>>>>>         if (ret < 0) {
>>>>>>>>>                 DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable
>>>>>>>> HPD: %d\n", ret);
>>>>>>>>>                 goto fail;
>>>>>>>>> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h
>>>>>>>>> b/drivers/gpu/drm/msm/hdmi/hdmi.h
>>>>>>>>> index 82261078c6b1..736f348befb3 100644
>>>>>>>>> --- a/drivers/gpu/drm/msm/hdmi/hdmi.h
>>>>>>>>> +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
>>>>>>>>> @@ -114,6 +114,13 @@ struct hdmi_platform_config {
>>>>>>>>>         struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO];
>>>>>>>>>    };
>>>>>>>>>
>>>>>>>>> +struct hdmi_bridge {
>>>>>>>>> +     struct drm_bridge base;
>>>>>>>>> +     struct hdmi *hdmi;
>>>>>>>>> +     struct work_struct hpd_work;
>>>>>>>>> +};
>>>>>>>>> +#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
>>>>>>>>> +
>>>>>>>>>    void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on);
>>>>>>>>>
>>>>>>>>>    static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data)
>>>>>>>>> @@ -230,13 +237,11 @@ void msm_hdmi_audio_set_sample_rate(struct hdmi
>>>>>>>>> *hdmi, int rate);
>>>>>>>>>    struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi);
>>>>>>>>>    void msm_hdmi_bridge_destroy(struct drm_bridge *bridge);
>>>>>>>>>
>>>>>>>>> -/*
>>>>>>>>> - * hdmi connector:
>>>>>>>>> - */
>>>>>>>>> -
>>>>>>>>> -void msm_hdmi_connector_irq(struct drm_connector *connector);
>>>>>>>>> -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi);
>>>>>>>>> -int msm_hdmi_hpd_enable(struct drm_connector *connector);
>>>>>>>>> +void msm_hdmi_hpd_irq(struct drm_bridge *bridge);
>>>>>>>>> +enum drm_connector_status msm_hdmi_bridge_detect(
>>>>>>>>> +             struct drm_bridge *bridge);
>>>>>>>>> +int msm_hdmi_hpd_enable(struct drm_bridge *bridge);
>>>>>>>>> +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge);
>>>>>>>>>
>>>>>>>>>    /*
>>>>>>>>>     * i2c adapter for ddc:
>>>>>>>>> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>>>>>>>> b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>>>>>>>> index f04eb4a70f0d..211b73dddf65 100644
>>>>>>>>> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>>>>>>>> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
>>>>>>>>> @@ -5,17 +5,16 @@
>>>>>>>>>     */
>>>>>>>>>
>>>>>>>>>    #include <linux/delay.h>
>>>>>>>>> +#include <drm/drm_bridge_connector.h>
>>>>>>>>>
>>>>>>>>> +#include "msm_kms.h"
>>>>>>>>>    #include "hdmi.h"
>>>>>>>>>
>>>>>>>>> -struct hdmi_bridge {
>>>>>>>>> -     struct drm_bridge base;
>>>>>>>>> -     struct hdmi *hdmi;
>>>>>>>>> -};
>>>>>>>>> -#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
>>>>>>>>> -
>>>>>>>>>    void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)
>>>>>>>>>    {
>>>>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>>>>>>> +
>>>>>>>>> +     msm_hdmi_hpd_disable(hdmi_bridge);
>>>>>>>>>    }
>>>>>>>>>
>>>>>>>>>    static void msm_hdmi_power_on(struct drm_bridge *bridge)
>>>>>>>>> @@ -251,14 +250,76 @@ static void msm_hdmi_bridge_mode_set(struct
>>>>>>>>> drm_bridge *bridge,
>>>>>>>>>                 msm_hdmi_audio_update(hdmi);
>>>>>>>>>    }
>>>>>>>>>
>>>>>>>>> +static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge
>>>>>>>>> *bridge,
>>>>>>>>> +             struct drm_connector *connector)
>>>>>>>>> +{
>>>>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>>>>>>> +     struct edid *edid;
>>>>>>>>> +     uint32_t hdmi_ctrl;
>>>>>>>>> +
>>>>>>>>> +     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
>>>>>>>>> +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
>>>>>>>>> +
>>>>>>>>> +     edid = drm_get_edid(connector, hdmi->i2c);
>>>>>>>>> +
>>>>>>>>> +     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
>>>>>>>>> +
>>>>>>>>> +     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
>>>>>>>>> +
>>>>>>>>> +     return edid;
>>>>>>>>> +}
>>>>>>>>> +
>>>>>>>>> +static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct
>>>>>>>>> drm_bridge *bridge,
>>>>>>>>> +             const struct drm_display_info *info,
>>>>>>>>> +             const struct drm_display_mode *mode)
>>>>>>>>> +{
>>>>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>>>>>>> +     const struct hdmi_platform_config *config = hdmi->config;
>>>>>>>>> +     struct msm_drm_private *priv = bridge->dev->dev_private;
>>>>>>>>> +     struct msm_kms *kms = priv->kms;
>>>>>>>>> +     long actual, requested;
>>>>>>>>> +
>>>>>>>>> +     requested = 1000 * mode->clock;
>>>>>>>>> +     actual = kms->funcs->round_pixclk(kms,
>>>>>>>>> +                     requested, hdmi_bridge->hdmi->encoder);
>>>>>>>>> +
>>>>>>>>> +     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
>>>>>>>>> +      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
>>>>>>>>> +      * instead):
>>>>>>>>> +      */
>>>>>>>>> +     if (config->pwr_clk_cnt > 0)
>>>>>>>>> +             actual = clk_round_rate(hdmi->pwr_clks[0], actual);
>>>>>>>>> +
>>>>>>>>> +     DBG("requested=%ld, actual=%ld", requested, actual);
>>>>>>>>> +
>>>>>>>>> +     if (actual != requested)
>>>>>>>>> +             return MODE_CLOCK_RANGE;
>>>>>>>>> +
>>>>>>>>> +     return 0;
>>>>>>>>> +}
>>>>>>>>> +
>>>>>>>>>    static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
>>>>>>>>>                 .pre_enable = msm_hdmi_bridge_pre_enable,
>>>>>>>>>                 .enable = msm_hdmi_bridge_enable,
>>>>>>>>>                 .disable = msm_hdmi_bridge_disable,
>>>>>>>>>                 .post_disable = msm_hdmi_bridge_post_disable,
>>>>>>>>>                 .mode_set = msm_hdmi_bridge_mode_set,
>>>>>>>>> +             .mode_valid = msm_hdmi_bridge_mode_valid,
>>>>>>>>> +             .get_edid = msm_hdmi_bridge_get_edid,
>>>>>>>>> +             .detect = msm_hdmi_bridge_detect,
>>>>>>>>>    };
>>>>>>>>>
>>>>>>>>> +static void
>>>>>>>>> +msm_hdmi_hotplug_work(struct work_struct *work)
>>>>>>>>> +{
>>>>>>>>> +     struct hdmi_bridge *hdmi_bridge =
>>>>>>>>> +             container_of(work, struct hdmi_bridge, hpd_work);
>>>>>>>>> +     struct drm_bridge *bridge = &hdmi_bridge->base;
>>>>>>>>> +
>>>>>>>>> +     drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge));
>>>>>>>>> +}
>>>>>>>>>
>>>>>>>>>    /* initialize bridge */
>>>>>>>>>    struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
>>>>>>>>> @@ -275,11 +336,17 @@ struct drm_bridge *msm_hdmi_bridge_init(struct
>>>>>>>>> hdmi *hdmi)
>>>>>>>>>         }
>>>>>>>>>
>>>>>>>>>         hdmi_bridge->hdmi = hdmi;
>>>>>>>>> +     INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);
>>>>>>>>>
>>>>>>>>>         bridge = &hdmi_bridge->base;
>>>>>>>>>         bridge->funcs = &msm_hdmi_bridge_funcs;
>>>>>>>>> +     bridge->ddc = hdmi->i2c;
>>>>>>>>> +     bridge->type = DRM_MODE_CONNECTOR_HDMIA;
>>>>>>>>> +     bridge->ops = DRM_BRIDGE_OP_HPD |
>>>>>>>>> +             DRM_BRIDGE_OP_DETECT |
>>>>>>>>> +             DRM_BRIDGE_OP_EDID;
>>>>>> Please correct me if wrong here. When we set DRM_BRIDGE_OP_HPD, it
>>>>>> means we need to
>>>>>> set the hpd_enable and hpd_disable callbacks. I am not seeing those
>>>>>> being set.
>>>>>>
>>>>>> 707      * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and
>>>>>> hot-unplug
>>>>>> 708      * without requiring polling. Bridges that set this flag shall
>>>>>> 709      * implement the &drm_bridge_funcs->hpd_enable and
>>>>>> 710      * &drm_bridge_funcs->hpd_disable callbacks if they support
>>>>>> enabling
>>>>>> 711      * and disabling hot-plug detection dynamically.
>>>>>> 712      */
>>>>>> 713     DRM_BRIDGE_OP_HPD = BIT(2),
>>>>>>
>>>>>> So when drm_bridge_connector_enable_hpd() is called, its a no-op as
>>>>>> hpd_enable() callback
>>>>>> is not set.
>>>>>>
>>>>>> msm_hdmi_hpd_enable() actually enables the HPD logic which is getting
>>>>>> called from msm_hdmi_modeset_init()
>>>>>> and not from hpd_enable().
>>>>>>
>>>>>> In that case, do we need to set DRM_BRIDGE_OP_HPD for this? If we
>>>>>> dont, what will happen?
>>>>>>
>>>>>
>>>>> Without this flag, the drm_bridge_connector will not know that this
>>>>> bridge is capable of generating HPD events on its own, ending up with
>>>>> polling implementation. See drm_bridge_connector_init(),
>>>>> drm_helper_hpd_irq_event(), etc.
>>>>>
>>>>
>>>> Thanks for the details. Then, as per the documentation on the
>>>> DRM_BRIDGE_OP_HPD, shouldnt we also assign msm_hdmi_hpd_enable to
>>>> hpd_enable callback? Since we are already calling
>>>> drm_bridge_connector_enable_hpd(), that should take care of calling it
>>>> using the callback then.
>>>>
>>>> Similarly, you can assign msm_hdmi_hpd_disable to hpd_disable op and
>>>> then call drm_bridge_connector_disable_hpd() in those places.
>>>
>>> Since that would be a change in the functionality, I'd prefer to have
>>> that in a separate patch.
>>> It looks like a nice cleanup idea, so I'd implement that at some point.
>>>
>>>>
>> I didnt follow this part. Why would there be a change in functionality?
>> You are only going to assign the hpd_enable/hpd_disable callbacks.
>> And replace the calls msm_hdmi_hpd_enable/msm_hdmi_hpd_disable with
>> drm_bridge_connector_enable_hpd()/drm_bridge_connector_disable_hpd()
>> within the driver. AFAICT, noone else is going to issue the
>> enable/disable so it should not affect functionality.
> 
> You have described the change in the functionality: to use
> hpd_enable/_disable callbacks.
> Since we were not using them up to now, I'd like to keep that change separate.
> 
I really dont think the change is big enough to push it out to another 
patch. But if you insist,
Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>>
>>>> That way, functionality remains intact and we follow the documentation.
>>>>
>>>>>>
>>>>>>
>>>>>>>>>
>>>>>>>>> -     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0);
>>>>>>>>> +     ret = drm_bridge_attach(hdmi->encoder, bridge, NULL,
>>>>>>>>> DRM_BRIDGE_ATTACH_NO_CONNECTOR);
>>>>>>>>>         if (ret)
>>>>>>>>>                 goto fail;
>>>>>>>>>
>>>>>>>>> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
>>>>>>>>> b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
>>>>>>>>> similarity index 62%
>>>>>>>>> rename from drivers/gpu/drm/msm/hdmi/hdmi_connector.c
>>>>>>>>> rename to drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
>>>>>>>>> index a7f729cdec7b..1cda7bf23b3b 100644
>>>>>>>>> --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
>>>>>>>>> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
>>>>>>>>> @@ -11,13 +11,6 @@
>>>>>>>>>    #include "msm_kms.h"
>>>>>>>>>    #include "hdmi.h"
>>>>>>>>>
>>>>>>>>> -struct hdmi_connector {
>>>>>>>>> -     struct drm_connector base;
>>>>>>>>> -     struct hdmi *hdmi;
>>>>>>>>> -     struct work_struct hpd_work;
>>>>>>>>> -};
>>>>>>>>> -#define to_hdmi_connector(x) container_of(x, struct hdmi_connector,
>>>>>>>>> base)
>>>>>>>>> -
>>>>>>>>>    static void msm_hdmi_phy_reset(struct hdmi *hdmi)
>>>>>>>>>    {
>>>>>>>>>         unsigned int val;
>>>>>>>>> @@ -139,10 +132,10 @@ static void enable_hpd_clocks(struct hdmi
>>>>>>>> *hdmi,
>>>>>>>>> bool enable)
>>>>>>>>>         }
>>>>>>>>>    }
>>>>>>>>>
>>>>>>>>> -int msm_hdmi_hpd_enable(struct drm_connector *connector)
>>>>>>>>> +int msm_hdmi_hpd_enable(struct drm_bridge *bridge)
>>>>>>>>>    {
>>>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>>>> to_hdmi_connector(connector);
>>>>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>>>>>>>         const struct hdmi_platform_config *config = hdmi->config;
>>>>>>>>>         struct device *dev = &hdmi->pdev->dev;
>>>>>>>>>         uint32_t hpd_ctrl;
>>>>>>>>> @@ -199,9 +192,9 @@ int msm_hdmi_hpd_enable(struct drm_connector
>>>>>>>>> *connector)
>>>>>>>>>         return ret;
>>>>>>>>>    }
>>>>>>>>>
>>>>>>>>> -static void hdp_disable(struct hdmi_connector *hdmi_connector)
>>>>>>>>> +void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge)
>>>>>>>>>    {
>>>>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>>>>>>>         const struct hdmi_platform_config *config = hdmi->config;
>>>>>>>>>         struct device *dev = &hdmi->pdev->dev;
>>>>>>>>>         int ret;
>>>>>>>>> @@ -227,19 +220,10 @@ static void hdp_disable(struct hdmi_connector
>>>>>>>>> *hdmi_connector)
>>>>>>>>>                 dev_warn(dev, "failed to disable hpd regulator:
>>>>>>>> %d\n", ret);
>>>>>>>>>    }
>>>>>>>>>
>>>>>>>>> -static void
>>>>>>>>> -msm_hdmi_hotplug_work(struct work_struct *work)
>>>>>>>>> -{
>>>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>>>>> -             container_of(work, struct hdmi_connector, hpd_work);
>>>>>>>>> -     struct drm_connector *connector = &hdmi_connector->base;
>>>>>>>>> -     drm_helper_hpd_irq_event(connector->dev);
>>>>>>>>> -}
>>>>>>>>> -
>>>>>>>>> -void msm_hdmi_connector_irq(struct drm_connector *connector)
>>>>>>>>> +void msm_hdmi_hpd_irq(struct drm_bridge *bridge)
>>>>>>>>>    {
>>>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>>>> to_hdmi_connector(connector);
>>>>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>>>>>>>         uint32_t hpd_int_status, hpd_int_ctrl;
>>>>>>>>>
>>>>>>>>>         /* Process HPD: */
>>>>>>>>> @@ -262,7 +246,7 @@ void msm_hdmi_connector_irq(struct drm_connector
>>>>>>>>> *connector)
>>>>>>>>>                         hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
>>>>>>>>>                 hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
>>>>>>>>>
>>>>>>>>> -             queue_work(hdmi->workq, &hdmi_connector->hpd_work);
>>>>>>>>> +             queue_work(hdmi->workq, &hdmi_bridge->hpd_work);
>>>>>>>>>         }
>>>>>>>>>    }
>>>>>>>>>
>>>>>>>>> @@ -293,11 +277,11 @@ static enum drm_connector_status
>>>>>>>>> detect_gpio(struct hdmi *hdmi)
>>>>>>>>>                         connector_status_disconnected;
>>>>>>>>>    }
>>>>>>>>>
>>>>>>>>> -static enum drm_connector_status hdmi_connector_detect(
>>>>>>>>> -             struct drm_connector *connector, bool force)
>>>>>>>>> +enum drm_connector_status msm_hdmi_bridge_detect(
>>>>>>>>> +             struct drm_bridge *bridge)
>>>>>>>>>    {
>>>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>>>> to_hdmi_connector(connector);
>>>>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>>>>>>> +     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
>>>>>>>>> +     struct hdmi *hdmi = hdmi_bridge->hdmi;
>>>>>>>>>         const struct hdmi_platform_config *config = hdmi->config;
>>>>>>>>>         struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
>>>>>>>>>         enum drm_connector_status stat_gpio, stat_reg;
>>>>>>>>> @@ -331,115 +315,3 @@ static enum drm_connector_status
>>>>>>>>> hdmi_connector_detect(
>>>>>>>>>
>>>>>>>>>         return stat_gpio;
>>>>>>>>>    }
>>>>>>>>> -
>>>>>>>>> -static void hdmi_connector_destroy(struct drm_connector *connector)
>>>>>>>>> -{
>>>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>>>> to_hdmi_connector(connector);
>>>>>>>>> -
>>>>>>>>> -     hdp_disable(hdmi_connector);
>>>>>>>>> -
>>>>>>>>> -     drm_connector_cleanup(connector);
>>>>>>>>> -
>>>>>>>>> -     kfree(hdmi_connector);
>>>>>>>>> -}
>>>>>>>>> -
>>>>>>>>> -static int msm_hdmi_connector_get_modes(struct drm_connector
>>>>>>>>> *connector)
>>>>>>>>> -{
>>>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>>>> to_hdmi_connector(connector);
>>>>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>>>>>>> -     struct edid *edid;
>>>>>>>>> -     uint32_t hdmi_ctrl;
>>>>>>>>> -     int ret = 0;
>>>>>>>>> -
>>>>>>>>> -     hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
>>>>>>>>> -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
>>>>>>>>> -
>>>>>>>>> -     edid = drm_get_edid(connector, hdmi->i2c);
>>>>>>>>> -
>>>>>>>>> -     hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
>>>>>>>>> -
>>>>>>>>> -     hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
>>>>>>>>> -     drm_connector_update_edid_property(connector, edid);
>>>>>>>>> -
>>>>>>>>> -     if (edid) {
>>>>>>>>> -             ret = drm_add_edid_modes(connector, edid);
>>>>>>>>> -             kfree(edid);
>>>>>>>>> -     }
>>>>>>>>> -
>>>>>>>>> -     return ret;
>>>>>>>>> -}
>>>>>>>>> -
>>>>>>>>> -static int msm_hdmi_connector_mode_valid(struct drm_connector
>>>>>>>>> *connector,
>>>>>>>>> -                              struct drm_display_mode *mode)
>>>>>>>>> -{
>>>>>>>>> -     struct hdmi_connector *hdmi_connector =
>>>>>>>> to_hdmi_connector(connector);
>>>>>>>>> -     struct hdmi *hdmi = hdmi_connector->hdmi;
>>>>>>>>> -     const struct hdmi_platform_config *config = hdmi->config;
>>>>>>>>> -     struct msm_drm_private *priv = connector->dev->dev_private;
>>>>>>>>> -     struct msm_kms *kms = priv->kms;
>>>>>>>>> -     long actual, requested;
>>>>>>>>> -
>>>>>>>>> -     requested = 1000 * mode->clock;
>>>>>>>>> -     actual = kms->funcs->round_pixclk(kms,
>>>>>>>>> -                     requested, hdmi_connector->hdmi->encoder);
>>>>>>>>> -
>>>>>>>>> -     /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
>>>>>>>>> -      * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
>>>>>>>>> -      * instead):
>>>>>>>>> -      */
>>>>>>>>> -     if (config->pwr_clk_cnt > 0)
>>>>>>>>> -             actual = clk_round_rate(hdmi->pwr_clks[0], actual);
>>>>>>>>> -
>>>>>>>>> -     DBG("requested=%ld, actual=%ld", requested, actual);
>>>>>>>>> -
>>>>>>>>> -     if (actual != requested)
>>>>>>>>> -             return MODE_CLOCK_RANGE;
>>>>>>>>> -
>>>>>>>>> -     return 0;
>>>>>>>>> -}
>>>>>>>>> -
>>>>>>>>> -static const struct drm_connector_funcs hdmi_connector_funcs = {
>>>>>>>>> -     .detect = hdmi_connector_detect,
>>>>>>>>> -     .fill_modes = drm_helper_probe_single_connector_modes,
>>>>>>>>> -     .destroy = hdmi_connector_destroy,
>>>>>>>>> -     .reset = drm_atomic_helper_connector_reset,
>>>>>>>>> -     .atomic_duplicate_state =
>>>>>>>>> drm_atomic_helper_connector_duplicate_state,
>>>>>>>>> -     .atomic_destroy_state =
>>>>>>>> drm_atomic_helper_connector_destroy_state,
>>>>>>>>> -};
>>>>>>>>> -
>>>>>>>>> -static const struct drm_connector_helper_funcs
>>>>>>>>> msm_hdmi_connector_helper_funcs = {
>>>>>>>>> -     .get_modes = msm_hdmi_connector_get_modes,
>>>>>>>>> -     .mode_valid = msm_hdmi_connector_mode_valid,
>>>>>>>>> -};
>>>>>>>>> -
>>>>>>>>> -/* initialize connector */
>>>>>>>>> -struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
>>>>>>>>> -{
>>>>>>>>> -     struct drm_connector *connector = NULL;
>>>>>>>>> -     struct hdmi_connector *hdmi_connector;
>>>>>>>>> -
>>>>>>>>> -     hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
>>>>>>>>> -     if (!hdmi_connector)
>>>>>>>>> -             return ERR_PTR(-ENOMEM);
>>>>>>>>> -
>>>>>>>>> -     hdmi_connector->hdmi = hdmi;
>>>>>>>>> -     INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);
>>>>>>>>> -
>>>>>>>>> -     connector = &hdmi_connector->base;
>>>>>>>>> -
>>>>>>>>> -     drm_connector_init_with_ddc(hdmi->dev, connector,
>>>>>>>>> -                                 &hdmi_connector_funcs,
>>>>>>>>> -                                 DRM_MODE_CONNECTOR_HDMIA,
>>>>>>>>> -                                 hdmi->i2c);
>>>>>>>>> -     drm_connector_helper_add(connector,
>>>>>>>>> &msm_hdmi_connector_helper_funcs);
>>>>>>>>> -
>>>>>>>>> -     connector->polled = DRM_CONNECTOR_POLL_CONNECT |
>>>>>>>>> -                     DRM_CONNECTOR_POLL_DISCONNECT;
>>>>>>>>> -
>>>>>>>>> -     connector->interlace_allowed = 0;
>>>>>>>>> -     connector->doublescan_allowed = 0;
>>>>>>>>> -
>>>>>>>>> -     drm_connector_attach_encoder(connector, hdmi->encoder);
>>>>>>>>> -
>>>>>>>>> -     return connector;
>>>>>>>>> -}
>>>>>
>>>>>
>>>
>>>
>>>
> 
> 
>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 904535eda0c4..91b09cda8a9c 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -19,7 +19,7 @@  msm-y := \
 	hdmi/hdmi.o \
 	hdmi/hdmi_audio.o \
 	hdmi/hdmi_bridge.o \
-	hdmi/hdmi_connector.o \
+	hdmi/hdmi_hpd.o \
 	hdmi/hdmi_i2c.o \
 	hdmi/hdmi_phy.o \
 	hdmi/hdmi_phy_8960.o \
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index db17a000d968..d1cf4df7188c 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -8,6 +8,8 @@ 
 #include <linux/of_irq.h>
 #include <linux/of_gpio.h>
 
+#include <drm/drm_bridge_connector.h>
+
 #include <sound/hdmi-codec.h>
 #include "hdmi.h"
 
@@ -41,7 +43,7 @@  static irqreturn_t msm_hdmi_irq(int irq, void *dev_id)
 	struct hdmi *hdmi = dev_id;
 
 	/* Process HPD: */
-	msm_hdmi_connector_irq(hdmi->connector);
+	msm_hdmi_hpd_irq(hdmi->bridge);
 
 	/* Process DDC: */
 	msm_hdmi_i2c_irq(hdmi->i2c);
@@ -283,7 +285,7 @@  int msm_hdmi_modeset_init(struct hdmi *hdmi,
 		goto fail;
 	}
 
-	hdmi->connector = msm_hdmi_connector_init(hdmi);
+	hdmi->connector = drm_bridge_connector_init(hdmi->dev, encoder);
 	if (IS_ERR(hdmi->connector)) {
 		ret = PTR_ERR(hdmi->connector);
 		DRM_DEV_ERROR(dev->dev, "failed to create HDMI connector: %d\n", ret);
@@ -291,6 +293,8 @@  int msm_hdmi_modeset_init(struct hdmi *hdmi,
 		goto fail;
 	}
 
+	drm_connector_attach_encoder(hdmi->connector, hdmi->encoder);
+
 	hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
 	if (hdmi->irq < 0) {
 		ret = hdmi->irq;
@@ -307,7 +311,9 @@  int msm_hdmi_modeset_init(struct hdmi *hdmi,
 		goto fail;
 	}
 
-	ret = msm_hdmi_hpd_enable(hdmi->connector);
+	drm_bridge_connector_enable_hpd(hdmi->connector);
+
+	ret = msm_hdmi_hpd_enable(hdmi->bridge);
 	if (ret < 0) {
 		DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
 		goto fail;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 82261078c6b1..736f348befb3 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -114,6 +114,13 @@  struct hdmi_platform_config {
 	struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO];
 };
 
+struct hdmi_bridge {
+	struct drm_bridge base;
+	struct hdmi *hdmi;
+	struct work_struct hpd_work;
+};
+#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
+
 void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on);
 
 static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data)
@@ -230,13 +237,11 @@  void msm_hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate);
 struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi);
 void msm_hdmi_bridge_destroy(struct drm_bridge *bridge);
 
-/*
- * hdmi connector:
- */
-
-void msm_hdmi_connector_irq(struct drm_connector *connector);
-struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi);
-int msm_hdmi_hpd_enable(struct drm_connector *connector);
+void msm_hdmi_hpd_irq(struct drm_bridge *bridge);
+enum drm_connector_status msm_hdmi_bridge_detect(
+		struct drm_bridge *bridge);
+int msm_hdmi_hpd_enable(struct drm_bridge *bridge);
+void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge);
 
 /*
  * i2c adapter for ddc:
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index f04eb4a70f0d..211b73dddf65 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -5,17 +5,16 @@ 
  */
 
 #include <linux/delay.h>
+#include <drm/drm_bridge_connector.h>
 
+#include "msm_kms.h"
 #include "hdmi.h"
 
-struct hdmi_bridge {
-	struct drm_bridge base;
-	struct hdmi *hdmi;
-};
-#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
-
 void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)
 {
+	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+
+	msm_hdmi_hpd_disable(hdmi_bridge);
 }
 
 static void msm_hdmi_power_on(struct drm_bridge *bridge)
@@ -251,14 +250,76 @@  static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge,
 		msm_hdmi_audio_update(hdmi);
 }
 
+static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge *bridge,
+		struct drm_connector *connector)
+{
+	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+	struct hdmi *hdmi = hdmi_bridge->hdmi;
+	struct edid *edid;
+	uint32_t hdmi_ctrl;
+
+	hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
+	hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
+
+	edid = drm_get_edid(connector, hdmi->i2c);
+
+	hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
+
+	hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
+
+	return edid;
+}
+
+static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
+		const struct drm_display_info *info,
+		const struct drm_display_mode *mode)
+{
+	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+	struct hdmi *hdmi = hdmi_bridge->hdmi;
+	const struct hdmi_platform_config *config = hdmi->config;
+	struct msm_drm_private *priv = bridge->dev->dev_private;
+	struct msm_kms *kms = priv->kms;
+	long actual, requested;
+
+	requested = 1000 * mode->clock;
+	actual = kms->funcs->round_pixclk(kms,
+			requested, hdmi_bridge->hdmi->encoder);
+
+	/* for mdp5/apq8074, we manage our own pixel clk (as opposed to
+	 * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
+	 * instead):
+	 */
+	if (config->pwr_clk_cnt > 0)
+		actual = clk_round_rate(hdmi->pwr_clks[0], actual);
+
+	DBG("requested=%ld, actual=%ld", requested, actual);
+
+	if (actual != requested)
+		return MODE_CLOCK_RANGE;
+
+	return 0;
+}
+
 static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
 		.pre_enable = msm_hdmi_bridge_pre_enable,
 		.enable = msm_hdmi_bridge_enable,
 		.disable = msm_hdmi_bridge_disable,
 		.post_disable = msm_hdmi_bridge_post_disable,
 		.mode_set = msm_hdmi_bridge_mode_set,
+		.mode_valid = msm_hdmi_bridge_mode_valid,
+		.get_edid = msm_hdmi_bridge_get_edid,
+		.detect = msm_hdmi_bridge_detect,
 };
 
+static void
+msm_hdmi_hotplug_work(struct work_struct *work)
+{
+	struct hdmi_bridge *hdmi_bridge =
+		container_of(work, struct hdmi_bridge, hpd_work);
+	struct drm_bridge *bridge = &hdmi_bridge->base;
+
+	drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge));
+}
 
 /* initialize bridge */
 struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
@@ -275,11 +336,17 @@  struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
 	}
 
 	hdmi_bridge->hdmi = hdmi;
+	INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);
 
 	bridge = &hdmi_bridge->base;
 	bridge->funcs = &msm_hdmi_bridge_funcs;
+	bridge->ddc = hdmi->i2c;
+	bridge->type = DRM_MODE_CONNECTOR_HDMIA;
+	bridge->ops = DRM_BRIDGE_OP_HPD |
+		DRM_BRIDGE_OP_DETECT |
+		DRM_BRIDGE_OP_EDID;
 
-	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, 0);
+	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
similarity index 62%
rename from drivers/gpu/drm/msm/hdmi/hdmi_connector.c
rename to drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
index a7f729cdec7b..1cda7bf23b3b 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c
@@ -11,13 +11,6 @@ 
 #include "msm_kms.h"
 #include "hdmi.h"
 
-struct hdmi_connector {
-	struct drm_connector base;
-	struct hdmi *hdmi;
-	struct work_struct hpd_work;
-};
-#define to_hdmi_connector(x) container_of(x, struct hdmi_connector, base)
-
 static void msm_hdmi_phy_reset(struct hdmi *hdmi)
 {
 	unsigned int val;
@@ -139,10 +132,10 @@  static void enable_hpd_clocks(struct hdmi *hdmi, bool enable)
 	}
 }
 
-int msm_hdmi_hpd_enable(struct drm_connector *connector)
+int msm_hdmi_hpd_enable(struct drm_bridge *bridge)
 {
-	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
-	struct hdmi *hdmi = hdmi_connector->hdmi;
+	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+	struct hdmi *hdmi = hdmi_bridge->hdmi;
 	const struct hdmi_platform_config *config = hdmi->config;
 	struct device *dev = &hdmi->pdev->dev;
 	uint32_t hpd_ctrl;
@@ -199,9 +192,9 @@  int msm_hdmi_hpd_enable(struct drm_connector *connector)
 	return ret;
 }
 
-static void hdp_disable(struct hdmi_connector *hdmi_connector)
+void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge)
 {
-	struct hdmi *hdmi = hdmi_connector->hdmi;
+	struct hdmi *hdmi = hdmi_bridge->hdmi;
 	const struct hdmi_platform_config *config = hdmi->config;
 	struct device *dev = &hdmi->pdev->dev;
 	int ret;
@@ -227,19 +220,10 @@  static void hdp_disable(struct hdmi_connector *hdmi_connector)
 		dev_warn(dev, "failed to disable hpd regulator: %d\n", ret);
 }
 
-static void
-msm_hdmi_hotplug_work(struct work_struct *work)
-{
-	struct hdmi_connector *hdmi_connector =
-		container_of(work, struct hdmi_connector, hpd_work);
-	struct drm_connector *connector = &hdmi_connector->base;
-	drm_helper_hpd_irq_event(connector->dev);
-}
-
-void msm_hdmi_connector_irq(struct drm_connector *connector)
+void msm_hdmi_hpd_irq(struct drm_bridge *bridge)
 {
-	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
-	struct hdmi *hdmi = hdmi_connector->hdmi;
+	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+	struct hdmi *hdmi = hdmi_bridge->hdmi;
 	uint32_t hpd_int_status, hpd_int_ctrl;
 
 	/* Process HPD: */
@@ -262,7 +246,7 @@  void msm_hdmi_connector_irq(struct drm_connector *connector)
 			hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
 		hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
 
-		queue_work(hdmi->workq, &hdmi_connector->hpd_work);
+		queue_work(hdmi->workq, &hdmi_bridge->hpd_work);
 	}
 }
 
@@ -293,11 +277,11 @@  static enum drm_connector_status detect_gpio(struct hdmi *hdmi)
 			connector_status_disconnected;
 }
 
-static enum drm_connector_status hdmi_connector_detect(
-		struct drm_connector *connector, bool force)
+enum drm_connector_status msm_hdmi_bridge_detect(
+		struct drm_bridge *bridge)
 {
-	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
-	struct hdmi *hdmi = hdmi_connector->hdmi;
+	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
+	struct hdmi *hdmi = hdmi_bridge->hdmi;
 	const struct hdmi_platform_config *config = hdmi->config;
 	struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX];
 	enum drm_connector_status stat_gpio, stat_reg;
@@ -331,115 +315,3 @@  static enum drm_connector_status hdmi_connector_detect(
 
 	return stat_gpio;
 }
-
-static void hdmi_connector_destroy(struct drm_connector *connector)
-{
-	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
-
-	hdp_disable(hdmi_connector);
-
-	drm_connector_cleanup(connector);
-
-	kfree(hdmi_connector);
-}
-
-static int msm_hdmi_connector_get_modes(struct drm_connector *connector)
-{
-	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
-	struct hdmi *hdmi = hdmi_connector->hdmi;
-	struct edid *edid;
-	uint32_t hdmi_ctrl;
-	int ret = 0;
-
-	hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
-	hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
-
-	edid = drm_get_edid(connector, hdmi->i2c);
-
-	hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
-
-	hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
-	drm_connector_update_edid_property(connector, edid);
-
-	if (edid) {
-		ret = drm_add_edid_modes(connector, edid);
-		kfree(edid);
-	}
-
-	return ret;
-}
-
-static int msm_hdmi_connector_mode_valid(struct drm_connector *connector,
-				 struct drm_display_mode *mode)
-{
-	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
-	struct hdmi *hdmi = hdmi_connector->hdmi;
-	const struct hdmi_platform_config *config = hdmi->config;
-	struct msm_drm_private *priv = connector->dev->dev_private;
-	struct msm_kms *kms = priv->kms;
-	long actual, requested;
-
-	requested = 1000 * mode->clock;
-	actual = kms->funcs->round_pixclk(kms,
-			requested, hdmi_connector->hdmi->encoder);
-
-	/* for mdp5/apq8074, we manage our own pixel clk (as opposed to
-	 * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
-	 * instead):
-	 */
-	if (config->pwr_clk_cnt > 0)
-		actual = clk_round_rate(hdmi->pwr_clks[0], actual);
-
-	DBG("requested=%ld, actual=%ld", requested, actual);
-
-	if (actual != requested)
-		return MODE_CLOCK_RANGE;
-
-	return 0;
-}
-
-static const struct drm_connector_funcs hdmi_connector_funcs = {
-	.detect = hdmi_connector_detect,
-	.fill_modes = drm_helper_probe_single_connector_modes,
-	.destroy = hdmi_connector_destroy,
-	.reset = drm_atomic_helper_connector_reset,
-	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-static const struct drm_connector_helper_funcs msm_hdmi_connector_helper_funcs = {
-	.get_modes = msm_hdmi_connector_get_modes,
-	.mode_valid = msm_hdmi_connector_mode_valid,
-};
-
-/* initialize connector */
-struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
-{
-	struct drm_connector *connector = NULL;
-	struct hdmi_connector *hdmi_connector;
-
-	hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
-	if (!hdmi_connector)
-		return ERR_PTR(-ENOMEM);
-
-	hdmi_connector->hdmi = hdmi;
-	INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);
-
-	connector = &hdmi_connector->base;
-
-	drm_connector_init_with_ddc(hdmi->dev, connector,
-				    &hdmi_connector_funcs,
-				    DRM_MODE_CONNECTOR_HDMIA,
-				    hdmi->i2c);
-	drm_connector_helper_add(connector, &msm_hdmi_connector_helper_funcs);
-
-	connector->polled = DRM_CONNECTOR_POLL_CONNECT |
-			DRM_CONNECTOR_POLL_DISCONNECT;
-
-	connector->interlace_allowed = 0;
-	connector->doublescan_allowed = 0;
-
-	drm_connector_attach_encoder(connector, hdmi->encoder);
-
-	return connector;
-}