diff mbox series

[8/8] drm/ingenic: Attach bridge chain to encoders

Message ID 20210808134526.119198-9-paul@crapouillou.net (mailing list archive)
State New, archived
Headers show
Series gpu/drm: ingenic-drm: Various improvements | expand

Commit Message

Paul Cercueil Aug. 8, 2021, 1:45 p.m. UTC
Attach a top-level bridge to each encoder, which will be used for
negociating the bus format and flags.

All the bridges are now attached with DRM_BRIDGE_ATTACH_NO_CONNECTOR.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
---
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 92 +++++++++++++++++------
 1 file changed, 70 insertions(+), 22 deletions(-)

Comments

H. Nikolaus Schaller Aug. 8, 2021, 6:57 p.m. UTC | #1
Hi Paul,
all other patches apply cleanly but this one fails on top of v5.14-rc4.
What base are you using?
BR and thanks,
Nikolaus


> Am 08.08.2021 um 15:45 schrieb Paul Cercueil <paul@crapouillou.net>:
> 
> Attach a top-level bridge to each encoder, which will be used for
> negociating the bus format and flags.
> 
> All the bridges are now attached with DRM_BRIDGE_ATTACH_NO_CONNECTOR.
> 
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
> ---
> drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 92 +++++++++++++++++------
> 1 file changed, 70 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
> index 7ae48ead3ab6..09d5dd298078 100644
> --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
> +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
> @@ -21,6 +21,7 @@
> #include <drm/drm_atomic.h>
> #include <drm/drm_atomic_helper.h>
> #include <drm/drm_bridge.h>
> +#include <drm/drm_bridge_connector.h>
> #include <drm/drm_color_mgmt.h>
> #include <drm/drm_crtc.h>
> #include <drm/drm_crtc_helper.h>
> @@ -107,6 +108,19 @@ struct ingenic_drm {
> 	struct drm_private_obj private_obj;
> };
> 
> +struct ingenic_drm_bridge {
> +	struct drm_encoder encoder;
> +	struct drm_bridge bridge, *next_bridge;
> +
> +	struct drm_bus_cfg bus_cfg;
> +};
> +
> +static inline struct ingenic_drm_bridge *
> +to_ingenic_drm_bridge(struct drm_encoder *encoder)
> +{
> +	return container_of(encoder, struct ingenic_drm_bridge, encoder);
> +}
> +
> static inline struct ingenic_drm_private_state *
> to_ingenic_drm_priv_state(struct drm_private_state *state)
> {
> @@ -679,11 +693,10 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
> {
> 	struct ingenic_drm *priv = drm_device_get_priv(encoder->dev);
> 	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
> -	struct drm_connector *conn = conn_state->connector;
> -	struct drm_display_info *info = &conn->display_info;
> +	struct ingenic_drm_bridge *bridge = to_ingenic_drm_bridge(encoder);
> 	unsigned int cfg, rgbcfg = 0;
> 
> -	priv->panel_is_sharp = info->bus_flags & DRM_BUS_FLAG_SHARP_SIGNALS;
> +	priv->panel_is_sharp = bridge->bus_cfg.flags & DRM_BUS_FLAG_SHARP_SIGNALS;
> 
> 	if (priv->panel_is_sharp) {
> 		cfg = JZ_LCD_CFG_MODE_SPECIAL_TFT_1 | JZ_LCD_CFG_REV_POLARITY;
> @@ -696,19 +709,19 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
> 		cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
> 	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
> 		cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
> -	if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
> +	if (bridge->bus_cfg.flags & DRM_BUS_FLAG_DE_LOW)
> 		cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
> -	if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
> +	if (bridge->bus_cfg.flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
> 		cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
> 
> 	if (!priv->panel_is_sharp) {
> -		if (conn->connector_type == DRM_MODE_CONNECTOR_TV) {
> +		if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV) {
> 			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
> 				cfg |= JZ_LCD_CFG_MODE_TV_OUT_I;
> 			else
> 				cfg |= JZ_LCD_CFG_MODE_TV_OUT_P;
> 		} else {
> -			switch (*info->bus_formats) {
> +			switch (bridge->bus_cfg.format) {
> 			case MEDIA_BUS_FMT_RGB565_1X16:
> 				cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT;
> 				break;
> @@ -734,20 +747,29 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
> 	regmap_write(priv->map, JZ_REG_LCD_RGBC, rgbcfg);
> }
> 
> -static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder,
> -					    struct drm_crtc_state *crtc_state,
> -					    struct drm_connector_state *conn_state)
> +static int ingenic_drm_bridge_attach(struct drm_bridge *bridge,
> +				     enum drm_bridge_attach_flags flags)
> +{
> +	struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder);
> +
> +	return drm_bridge_attach(bridge->encoder, ib->next_bridge,
> +				 &ib->bridge, flags);
> +}
> +
> +static int ingenic_drm_bridge_atomic_check(struct drm_bridge *bridge,
> +					   struct drm_bridge_state *bridge_state,
> +					   struct drm_crtc_state *crtc_state,
> +					   struct drm_connector_state *conn_state)
> {
> -	struct drm_display_info *info = &conn_state->connector->display_info;
> 	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
> +	struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder);
> 
> -	if (info->num_bus_formats != 1)
> -		return -EINVAL;
> +	ib->bus_cfg = bridge_state->output_bus_cfg;
> 
> 	if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV)
> 		return 0;
> 
> -	switch (*info->bus_formats) {
> +	switch (bridge_state->output_bus_cfg.format) {
> 	case MEDIA_BUS_FMT_RGB888_3X8:
> 	case MEDIA_BUS_FMT_RGB888_3X8_DELTA:
> 		/*
> @@ -911,8 +933,16 @@ static const struct drm_crtc_helper_funcs ingenic_drm_crtc_helper_funcs = {
> };
> 
> static const struct drm_encoder_helper_funcs ingenic_drm_encoder_helper_funcs = {
> -	.atomic_mode_set	= ingenic_drm_encoder_atomic_mode_set,
> -	.atomic_check		= ingenic_drm_encoder_atomic_check,
> +	.atomic_mode_set        = ingenic_drm_encoder_atomic_mode_set,
> +};
> +
> +static const struct drm_bridge_funcs ingenic_drm_bridge_funcs = {
> +	.attach			= ingenic_drm_bridge_attach,
> +	.atomic_check		= ingenic_drm_bridge_atomic_check,
> +	.atomic_reset		= drm_atomic_helper_bridge_reset,
> +	.atomic_duplicate_state	= drm_atomic_helper_bridge_duplicate_state,
> +	.atomic_destroy_state	= drm_atomic_helper_bridge_destroy_state,
> +	.atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
> };
> 
> static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = {
> @@ -958,7 +988,9 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
> 	struct drm_plane *primary;
> 	struct drm_bridge *bridge;
> 	struct drm_panel *panel;
> +	struct drm_connector *connector;
> 	struct drm_encoder *encoder;
> +	struct ingenic_drm_bridge *ib;
> 	struct drm_device *drm;
> 	void __iomem *base;
> 	long parent_rate;
> @@ -1146,20 +1178,36 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
> 			bridge = devm_drm_panel_bridge_add_typed(dev, panel,
> 								 DRM_MODE_CONNECTOR_DPI);
> 
> -		encoder = drmm_plain_encoder_alloc(drm, NULL, DRM_MODE_ENCODER_DPI, NULL);
> -		if (IS_ERR(encoder)) {
> -			ret = PTR_ERR(encoder);
> +		ib = drmm_encoder_alloc(drm, struct ingenic_drm_bridge, encoder,
> +					NULL, DRM_MODE_ENCODER_DPI, NULL);
> +		if (IS_ERR(ib)) {
> +			ret = PTR_ERR(ib);
> 			dev_err(dev, "Failed to init encoder: %d\n", ret);
> 			return ret;
> 		}
> 
> -		encoder->possible_crtcs = 1;
> +		encoder = &ib->encoder;
> +		encoder->possible_crtcs = drm_crtc_mask(&priv->crtc);
> 
> 		drm_encoder_helper_add(encoder, &ingenic_drm_encoder_helper_funcs);
> 
> -		ret = drm_bridge_attach(encoder, bridge, NULL, 0);
> -		if (ret)
> +		ib->bridge.funcs = &ingenic_drm_bridge_funcs;
> +		ib->next_bridge = bridge;
> +
> +		ret = drm_bridge_attach(encoder, &ib->bridge, NULL,
> +					DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> +		if (ret) {
> +			dev_err(dev, "Unable to attach bridge\n");
> 			return ret;
> +		}
> +
> +		connector = drm_bridge_connector_init(drm, encoder);
> +		if (IS_ERR(connector)) {
> +			dev_err(dev, "Unable to init connector\n");
> +			return PTR_ERR(connector);
> +		}
> +
> +		drm_connector_attach_encoder(connector, encoder);
> 	}
> 
> 	drm_for_each_encoder(encoder, drm) {
> -- 
> 2.30.2
>
Paul Cercueil Aug. 8, 2021, 7:04 p.m. UTC | #2
Hi Nikolaus,

Le dim., août 8 2021 at 20:57:09 +0200, H. Nikolaus Schaller 
<hns@goldelico.com> a écrit :
> Hi Paul,
> all other patches apply cleanly but this one fails on top of 
> v5.14-rc4.
> What base are you using?
> BR and thanks,
> Nikolaus

The base is drm-misc (https://cgit.freedesktop.org/drm/drm-misc), 
branch drm-misc-next.

Cheers,
-Paul


>>  Am 08.08.2021 um 15:45 schrieb Paul Cercueil <paul@crapouillou.net>:
>> 
>>  Attach a top-level bridge to each encoder, which will be used for
>>  negociating the bus format and flags.
>> 
>>  All the bridges are now attached with 
>> DRM_BRIDGE_ATTACH_NO_CONNECTOR.
>> 
>>  Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>>  ---
>>  drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 92 
>> +++++++++++++++++------
>>  1 file changed, 70 insertions(+), 22 deletions(-)
>> 
>>  diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
>> b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
>>  index 7ae48ead3ab6..09d5dd298078 100644
>>  --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
>>  +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
>>  @@ -21,6 +21,7 @@
>>  #include <drm/drm_atomic.h>
>>  #include <drm/drm_atomic_helper.h>
>>  #include <drm/drm_bridge.h>
>>  +#include <drm/drm_bridge_connector.h>
>>  #include <drm/drm_color_mgmt.h>
>>  #include <drm/drm_crtc.h>
>>  #include <drm/drm_crtc_helper.h>
>>  @@ -107,6 +108,19 @@ struct ingenic_drm {
>>  	struct drm_private_obj private_obj;
>>  };
>> 
>>  +struct ingenic_drm_bridge {
>>  +	struct drm_encoder encoder;
>>  +	struct drm_bridge bridge, *next_bridge;
>>  +
>>  +	struct drm_bus_cfg bus_cfg;
>>  +};
>>  +
>>  +static inline struct ingenic_drm_bridge *
>>  +to_ingenic_drm_bridge(struct drm_encoder *encoder)
>>  +{
>>  +	return container_of(encoder, struct ingenic_drm_bridge, encoder);
>>  +}
>>  +
>>  static inline struct ingenic_drm_private_state *
>>  to_ingenic_drm_priv_state(struct drm_private_state *state)
>>  {
>>  @@ -679,11 +693,10 @@ static void 
>> ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
>>  {
>>  	struct ingenic_drm *priv = drm_device_get_priv(encoder->dev);
>>  	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
>>  -	struct drm_connector *conn = conn_state->connector;
>>  -	struct drm_display_info *info = &conn->display_info;
>>  +	struct ingenic_drm_bridge *bridge = 
>> to_ingenic_drm_bridge(encoder);
>>  	unsigned int cfg, rgbcfg = 0;
>> 
>>  -	priv->panel_is_sharp = info->bus_flags & 
>> DRM_BUS_FLAG_SHARP_SIGNALS;
>>  +	priv->panel_is_sharp = bridge->bus_cfg.flags & 
>> DRM_BUS_FLAG_SHARP_SIGNALS;
>> 
>>  	if (priv->panel_is_sharp) {
>>  		cfg = JZ_LCD_CFG_MODE_SPECIAL_TFT_1 | JZ_LCD_CFG_REV_POLARITY;
>>  @@ -696,19 +709,19 @@ static void 
>> ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
>>  		cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
>>  	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
>>  		cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
>>  -	if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
>>  +	if (bridge->bus_cfg.flags & DRM_BUS_FLAG_DE_LOW)
>>  		cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
>>  -	if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
>>  +	if (bridge->bus_cfg.flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
>>  		cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
>> 
>>  	if (!priv->panel_is_sharp) {
>>  -		if (conn->connector_type == DRM_MODE_CONNECTOR_TV) {
>>  +		if (conn_state->connector->connector_type == 
>> DRM_MODE_CONNECTOR_TV) {
>>  			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
>>  				cfg |= JZ_LCD_CFG_MODE_TV_OUT_I;
>>  			else
>>  				cfg |= JZ_LCD_CFG_MODE_TV_OUT_P;
>>  		} else {
>>  -			switch (*info->bus_formats) {
>>  +			switch (bridge->bus_cfg.format) {
>>  			case MEDIA_BUS_FMT_RGB565_1X16:
>>  				cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT;
>>  				break;
>>  @@ -734,20 +747,29 @@ static void 
>> ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
>>  	regmap_write(priv->map, JZ_REG_LCD_RGBC, rgbcfg);
>>  }
>> 
>>  -static int ingenic_drm_encoder_atomic_check(struct drm_encoder 
>> *encoder,
>>  -					    struct drm_crtc_state *crtc_state,
>>  -					    struct drm_connector_state *conn_state)
>>  +static int ingenic_drm_bridge_attach(struct drm_bridge *bridge,
>>  +				     enum drm_bridge_attach_flags flags)
>>  +{
>>  +	struct ingenic_drm_bridge *ib = 
>> to_ingenic_drm_bridge(bridge->encoder);
>>  +
>>  +	return drm_bridge_attach(bridge->encoder, ib->next_bridge,
>>  +				 &ib->bridge, flags);
>>  +}
>>  +
>>  +static int ingenic_drm_bridge_atomic_check(struct drm_bridge 
>> *bridge,
>>  +					   struct drm_bridge_state *bridge_state,
>>  +					   struct drm_crtc_state *crtc_state,
>>  +					   struct drm_connector_state *conn_state)
>>  {
>>  -	struct drm_display_info *info = 
>> &conn_state->connector->display_info;
>>  	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
>>  +	struct ingenic_drm_bridge *ib = 
>> to_ingenic_drm_bridge(bridge->encoder);
>> 
>>  -	if (info->num_bus_formats != 1)
>>  -		return -EINVAL;
>>  +	ib->bus_cfg = bridge_state->output_bus_cfg;
>> 
>>  	if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV)
>>  		return 0;
>> 
>>  -	switch (*info->bus_formats) {
>>  +	switch (bridge_state->output_bus_cfg.format) {
>>  	case MEDIA_BUS_FMT_RGB888_3X8:
>>  	case MEDIA_BUS_FMT_RGB888_3X8_DELTA:
>>  		/*
>>  @@ -911,8 +933,16 @@ static const struct drm_crtc_helper_funcs 
>> ingenic_drm_crtc_helper_funcs = {
>>  };
>> 
>>  static const struct drm_encoder_helper_funcs 
>> ingenic_drm_encoder_helper_funcs = {
>>  -	.atomic_mode_set	= ingenic_drm_encoder_atomic_mode_set,
>>  -	.atomic_check		= ingenic_drm_encoder_atomic_check,
>>  +	.atomic_mode_set        = ingenic_drm_encoder_atomic_mode_set,
>>  +};
>>  +
>>  +static const struct drm_bridge_funcs ingenic_drm_bridge_funcs = {
>>  +	.attach			= ingenic_drm_bridge_attach,
>>  +	.atomic_check		= ingenic_drm_bridge_atomic_check,
>>  +	.atomic_reset		= drm_atomic_helper_bridge_reset,
>>  +	.atomic_duplicate_state	= 
>> drm_atomic_helper_bridge_duplicate_state,
>>  +	.atomic_destroy_state	= drm_atomic_helper_bridge_destroy_state,
>>  +	.atomic_get_input_bus_fmts = 
>> drm_atomic_helper_bridge_propagate_bus_fmt,
>>  };
>> 
>>  static const struct drm_mode_config_funcs 
>> ingenic_drm_mode_config_funcs = {
>>  @@ -958,7 +988,9 @@ static int ingenic_drm_bind(struct device *dev, 
>> bool has_components)
>>  	struct drm_plane *primary;
>>  	struct drm_bridge *bridge;
>>  	struct drm_panel *panel;
>>  +	struct drm_connector *connector;
>>  	struct drm_encoder *encoder;
>>  +	struct ingenic_drm_bridge *ib;
>>  	struct drm_device *drm;
>>  	void __iomem *base;
>>  	long parent_rate;
>>  @@ -1146,20 +1178,36 @@ static int ingenic_drm_bind(struct device 
>> *dev, bool has_components)
>>  			bridge = devm_drm_panel_bridge_add_typed(dev, panel,
>>  								 DRM_MODE_CONNECTOR_DPI);
>> 
>>  -		encoder = drmm_plain_encoder_alloc(drm, NULL, 
>> DRM_MODE_ENCODER_DPI, NULL);
>>  -		if (IS_ERR(encoder)) {
>>  -			ret = PTR_ERR(encoder);
>>  +		ib = drmm_encoder_alloc(drm, struct ingenic_drm_bridge, encoder,
>>  +					NULL, DRM_MODE_ENCODER_DPI, NULL);
>>  +		if (IS_ERR(ib)) {
>>  +			ret = PTR_ERR(ib);
>>  			dev_err(dev, "Failed to init encoder: %d\n", ret);
>>  			return ret;
>>  		}
>> 
>>  -		encoder->possible_crtcs = 1;
>>  +		encoder = &ib->encoder;
>>  +		encoder->possible_crtcs = drm_crtc_mask(&priv->crtc);
>> 
>>  		drm_encoder_helper_add(encoder, 
>> &ingenic_drm_encoder_helper_funcs);
>> 
>>  -		ret = drm_bridge_attach(encoder, bridge, NULL, 0);
>>  -		if (ret)
>>  +		ib->bridge.funcs = &ingenic_drm_bridge_funcs;
>>  +		ib->next_bridge = bridge;
>>  +
>>  +		ret = drm_bridge_attach(encoder, &ib->bridge, NULL,
>>  +					DRM_BRIDGE_ATTACH_NO_CONNECTOR);
>>  +		if (ret) {
>>  +			dev_err(dev, "Unable to attach bridge\n");
>>  			return ret;
>>  +		}
>>  +
>>  +		connector = drm_bridge_connector_init(drm, encoder);
>>  +		if (IS_ERR(connector)) {
>>  +			dev_err(dev, "Unable to init connector\n");
>>  +			return PTR_ERR(connector);
>>  +		}
>>  +
>>  +		drm_connector_attach_encoder(connector, encoder);
>>  	}
>> 
>>  	drm_for_each_encoder(encoder, drm) {
>>  --
>>  2.30.2
>> 
>
H. Nikolaus Schaller Aug. 8, 2021, 7:06 p.m. UTC | #3
> Am 08.08.2021 um 21:04 schrieb Paul Cercueil <paul@crapouillou.net>:
> 
> Hi Nikolaus,
> 
> Le dim., août 8 2021 at 20:57:09 +0200, H. Nikolaus Schaller <hns@goldelico.com> a écrit :
>> Hi Paul,
>> all other patches apply cleanly but this one fails on top of v5.14-rc4.
>> What base are you using?
>> BR and thanks,
>> Nikolaus
> 
> The base is drm-misc (https://cgit.freedesktop.org/drm/drm-misc), branch drm-misc-next.

Ok, fine!

BR and thanks,
Nikolaus

> 
> Cheers,
> -Paul
> 
> 
>>> Am 08.08.2021 um 15:45 schrieb Paul Cercueil <paul@crapouillou.net>:
>>> Attach a top-level bridge to each encoder, which will be used for
>>> negociating the bus format and flags.
>>> All the bridges are now attached with DRM_BRIDGE_ATTACH_NO_CONNECTOR.
>>> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>>> ---
>>> drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 92 +++++++++++++++++------
>>> 1 file changed, 70 insertions(+), 22 deletions(-)
>>> diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
>>> index 7ae48ead3ab6..09d5dd298078 100644
>>> --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
>>> +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
>>> @@ -21,6 +21,7 @@
>>> #include <drm/drm_atomic.h>
>>> #include <drm/drm_atomic_helper.h>
>>> #include <drm/drm_bridge.h>
>>> +#include <drm/drm_bridge_connector.h>
>>> #include <drm/drm_color_mgmt.h>
>>> #include <drm/drm_crtc.h>
>>> #include <drm/drm_crtc_helper.h>
>>> @@ -107,6 +108,19 @@ struct ingenic_drm {
>>> 	struct drm_private_obj private_obj;
>>> };
>>> +struct ingenic_drm_bridge {
>>> +	struct drm_encoder encoder;
>>> +	struct drm_bridge bridge, *next_bridge;
>>> +
>>> +	struct drm_bus_cfg bus_cfg;
>>> +};
>>> +
>>> +static inline struct ingenic_drm_bridge *
>>> +to_ingenic_drm_bridge(struct drm_encoder *encoder)
>>> +{
>>> +	return container_of(encoder, struct ingenic_drm_bridge, encoder);
>>> +}
>>> +
>>> static inline struct ingenic_drm_private_state *
>>> to_ingenic_drm_priv_state(struct drm_private_state *state)
>>> {
>>> @@ -679,11 +693,10 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
>>> {
>>> 	struct ingenic_drm *priv = drm_device_get_priv(encoder->dev);
>>> 	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
>>> -	struct drm_connector *conn = conn_state->connector;
>>> -	struct drm_display_info *info = &conn->display_info;
>>> +	struct ingenic_drm_bridge *bridge = to_ingenic_drm_bridge(encoder);
>>> 	unsigned int cfg, rgbcfg = 0;
>>> -	priv->panel_is_sharp = info->bus_flags & DRM_BUS_FLAG_SHARP_SIGNALS;
>>> +	priv->panel_is_sharp = bridge->bus_cfg.flags & DRM_BUS_FLAG_SHARP_SIGNALS;
>>> 	if (priv->panel_is_sharp) {
>>> 		cfg = JZ_LCD_CFG_MODE_SPECIAL_TFT_1 | JZ_LCD_CFG_REV_POLARITY;
>>> @@ -696,19 +709,19 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
>>> 		cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
>>> 	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
>>> 		cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
>>> -	if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
>>> +	if (bridge->bus_cfg.flags & DRM_BUS_FLAG_DE_LOW)
>>> 		cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
>>> -	if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
>>> +	if (bridge->bus_cfg.flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
>>> 		cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
>>> 	if (!priv->panel_is_sharp) {
>>> -		if (conn->connector_type == DRM_MODE_CONNECTOR_TV) {
>>> +		if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV) {
>>> 			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
>>> 				cfg |= JZ_LCD_CFG_MODE_TV_OUT_I;
>>> 			else
>>> 				cfg |= JZ_LCD_CFG_MODE_TV_OUT_P;
>>> 		} else {
>>> -			switch (*info->bus_formats) {
>>> +			switch (bridge->bus_cfg.format) {
>>> 			case MEDIA_BUS_FMT_RGB565_1X16:
>>> 				cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT;
>>> 				break;
>>> @@ -734,20 +747,29 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
>>> 	regmap_write(priv->map, JZ_REG_LCD_RGBC, rgbcfg);
>>> }
>>> -static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder,
>>> -					    struct drm_crtc_state *crtc_state,
>>> -					    struct drm_connector_state *conn_state)
>>> +static int ingenic_drm_bridge_attach(struct drm_bridge *bridge,
>>> +				     enum drm_bridge_attach_flags flags)
>>> +{
>>> +	struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder);
>>> +
>>> +	return drm_bridge_attach(bridge->encoder, ib->next_bridge,
>>> +				 &ib->bridge, flags);
>>> +}
>>> +
>>> +static int ingenic_drm_bridge_atomic_check(struct drm_bridge *bridge,
>>> +					   struct drm_bridge_state *bridge_state,
>>> +					   struct drm_crtc_state *crtc_state,
>>> +					   struct drm_connector_state *conn_state)
>>> {
>>> -	struct drm_display_info *info = &conn_state->connector->display_info;
>>> 	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
>>> +	struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder);
>>> -	if (info->num_bus_formats != 1)
>>> -		return -EINVAL;
>>> +	ib->bus_cfg = bridge_state->output_bus_cfg;
>>> 	if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV)
>>> 		return 0;
>>> -	switch (*info->bus_formats) {
>>> +	switch (bridge_state->output_bus_cfg.format) {
>>> 	case MEDIA_BUS_FMT_RGB888_3X8:
>>> 	case MEDIA_BUS_FMT_RGB888_3X8_DELTA:
>>> 		/*
>>> @@ -911,8 +933,16 @@ static const struct drm_crtc_helper_funcs ingenic_drm_crtc_helper_funcs = {
>>> };
>>> static const struct drm_encoder_helper_funcs ingenic_drm_encoder_helper_funcs = {
>>> -	.atomic_mode_set	= ingenic_drm_encoder_atomic_mode_set,
>>> -	.atomic_check		= ingenic_drm_encoder_atomic_check,
>>> +	.atomic_mode_set        = ingenic_drm_encoder_atomic_mode_set,
>>> +};
>>> +
>>> +static const struct drm_bridge_funcs ingenic_drm_bridge_funcs = {
>>> +	.attach			= ingenic_drm_bridge_attach,
>>> +	.atomic_check		= ingenic_drm_bridge_atomic_check,
>>> +	.atomic_reset		= drm_atomic_helper_bridge_reset,
>>> +	.atomic_duplicate_state	= drm_atomic_helper_bridge_duplicate_state,
>>> +	.atomic_destroy_state	= drm_atomic_helper_bridge_destroy_state,
>>> +	.atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
>>> };
>>> static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = {
>>> @@ -958,7 +988,9 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
>>> 	struct drm_plane *primary;
>>> 	struct drm_bridge *bridge;
>>> 	struct drm_panel *panel;
>>> +	struct drm_connector *connector;
>>> 	struct drm_encoder *encoder;
>>> +	struct ingenic_drm_bridge *ib;
>>> 	struct drm_device *drm;
>>> 	void __iomem *base;
>>> 	long parent_rate;
>>> @@ -1146,20 +1178,36 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
>>> 			bridge = devm_drm_panel_bridge_add_typed(dev, panel,
>>> 								 DRM_MODE_CONNECTOR_DPI);
>>> -		encoder = drmm_plain_encoder_alloc(drm, NULL, DRM_MODE_ENCODER_DPI, NULL);
>>> -		if (IS_ERR(encoder)) {
>>> -			ret = PTR_ERR(encoder);
>>> +		ib = drmm_encoder_alloc(drm, struct ingenic_drm_bridge, encoder,
>>> +					NULL, DRM_MODE_ENCODER_DPI, NULL);
>>> +		if (IS_ERR(ib)) {
>>> +			ret = PTR_ERR(ib);
>>> 			dev_err(dev, "Failed to init encoder: %d\n", ret);
>>> 			return ret;
>>> 		}
>>> -		encoder->possible_crtcs = 1;
>>> +		encoder = &ib->encoder;
>>> +		encoder->possible_crtcs = drm_crtc_mask(&priv->crtc);
>>> 		drm_encoder_helper_add(encoder, &ingenic_drm_encoder_helper_funcs);
>>> -		ret = drm_bridge_attach(encoder, bridge, NULL, 0);
>>> -		if (ret)
>>> +		ib->bridge.funcs = &ingenic_drm_bridge_funcs;
>>> +		ib->next_bridge = bridge;
>>> +
>>> +		ret = drm_bridge_attach(encoder, &ib->bridge, NULL,
>>> +					DRM_BRIDGE_ATTACH_NO_CONNECTOR);
>>> +		if (ret) {
>>> +			dev_err(dev, "Unable to attach bridge\n");
>>> 			return ret;
>>> +		}
>>> +
>>> +		connector = drm_bridge_connector_init(drm, encoder);
>>> +		if (IS_ERR(connector)) {
>>> +			dev_err(dev, "Unable to init connector\n");
>>> +			return PTR_ERR(connector);
>>> +		}
>>> +
>>> +		drm_connector_attach_encoder(connector, encoder);
>>> 	}
>>> 	drm_for_each_encoder(encoder, drm) {
>>> --
>>> 2.30.2
> 
>
H. Nikolaus Schaller Aug. 8, 2021, 7:12 p.m. UTC | #4
> Am 08.08.2021 um 21:06 schrieb H. Nikolaus Schaller <hns@goldelico.com>:
> 
> 
> 
>> Am 08.08.2021 um 21:04 schrieb Paul Cercueil <paul@crapouillou.net>:
>> 
>> Hi Nikolaus,
>> 
>> Le dim., août 8 2021 at 20:57:09 +0200, H. Nikolaus Schaller <hns@goldelico.com> a écrit :
>>> Hi Paul,
>>> all other patches apply cleanly but this one fails on top of v5.14-rc4.
>>> What base are you using?
>>> BR and thanks,
>>> Nikolaus
>> 
>> The base is drm-misc (https://cgit.freedesktop.org/drm/drm-misc), branch drm-misc-next.
> 
> Ok, fine!

Contains 3 patches for drm/ingenic and after taking them first, I can apply the series.

Again, BR and thanks,
Nikolaus
H. Nikolaus Schaller Aug. 9, 2021, 11:14 a.m. UTC | #5
Hi Paul,
quick feedback: our HDMI on top compiles fine after fixing 2 merge conflicts, but dos not yet work.
Will need some spare time with access to the CI20 board to research the issue, i.e. can not give feedback immediately.
BR and thanks,
Nikolaus

> Am 08.08.2021 um 21:12 schrieb H. Nikolaus Schaller <hns@goldelico.com>:
> 
> 
> 
>> Am 08.08.2021 um 21:06 schrieb H. Nikolaus Schaller <hns@goldelico.com>:
>> 
>> 
>> 
>>> Am 08.08.2021 um 21:04 schrieb Paul Cercueil <paul@crapouillou.net>:
>>> 
>>> Hi Nikolaus,
>>> 
>>> Le dim., août 8 2021 at 20:57:09 +0200, H. Nikolaus Schaller <hns@goldelico.com> a écrit :
>>>> Hi Paul,
>>>> all other patches apply cleanly but this one fails on top of v5.14-rc4.
>>>> What base are you using?
>>>> BR and thanks,
>>>> Nikolaus
>>> 
>>> The base is drm-misc (https://cgit.freedesktop.org/drm/drm-misc), branch drm-misc-next.
>> 
>> Ok, fine!
> 
> Contains 3 patches for drm/ingenic and after taking them first, I can apply the series.
> 
> Again, BR and thanks,
> Nikolaus
> 
> _______________________________________________
> https://projects.goldelico.com/p/gta04-kernel/
> Letux-kernel mailing list
> Letux-kernel@openphoenux.org
> http://lists.goldelico.com/mailman/listinfo.cgi/letux-kernel
Paul Cercueil Aug. 9, 2021, 4:22 p.m. UTC | #6
Hi Nikolaus,

Le lun., août 9 2021 at 13:14:03 +0200, H. Nikolaus Schaller 
<hns@goldelico.com> a écrit :
> Hi Paul,
> quick feedback: our HDMI on top compiles fine after fixing 2 merge 
> conflicts, but dos not yet work.
> Will need some spare time with access to the CI20 board to research 
> the issue, i.e. can not give feedback immediately.

Alright, no problem. I'll be back home in about 2 weeks and then I can 
test on my CI20 as well.

Cheers,
-Paul

> BR and thanks,
> Nikolaus
> 
>>  Am 08.08.2021 um 21:12 schrieb H. Nikolaus Schaller 
>> <hns@goldelico.com>:
>> 
>> 
>> 
>>>  Am 08.08.2021 um 21:06 schrieb H. Nikolaus Schaller 
>>> <hns@goldelico.com>:
>>> 
>>> 
>>> 
>>>>  Am 08.08.2021 um 21:04 schrieb Paul Cercueil 
>>>> <paul@crapouillou.net>:
>>>> 
>>>>  Hi Nikolaus,
>>>> 
>>>>  Le dim., août 8 2021 at 20:57:09 +0200, H. Nikolaus Schaller 
>>>> <hns@goldelico.com> a écrit :
>>>>>  Hi Paul,
>>>>>  all other patches apply cleanly but this one fails on top of 
>>>>> v5.14-rc4.
>>>>>  What base are you using?
>>>>>  BR and thanks,
>>>>>  Nikolaus
>>>> 
>>>>  The base is drm-misc (https://cgit.freedesktop.org/drm/drm-misc), 
>>>> branch drm-misc-next.
>>> 
>>>  Ok, fine!
>> 
>>  Contains 3 patches for drm/ingenic and after taking them first, I 
>> can apply the series.
>> 
>>  Again, BR and thanks,
>>  Nikolaus
>> 
>>  _______________________________________________
>>  https://projects.goldelico.com/p/gta04-kernel/
>>  Letux-kernel mailing list
>>  Letux-kernel@openphoenux.org
>>  http://lists.goldelico.com/mailman/listinfo.cgi/letux-kernel
>
Paul Boddie Aug. 9, 2021, 11:17 p.m. UTC | #7
On Monday, 9 August 2021 18:22:12 CEST Paul Cercueil wrote:
> 
> Le lun., août 9 2021 at 13:14:03 +0200, H. Nikolaus Schaller 
<hns@goldelico.com> a écrit :
> >
> > quick feedback: our HDMI on top compiles fine after fixing 2 merge
> > conflicts, but dos not yet work.
> > Will need some spare time with access to the CI20 board to research
> > the issue, i.e. can not give feedback immediately.
> 
> Alright, no problem. I'll be back home in about 2 weeks and then I can
> test on my CI20 as well.

Just for reference, I looked into this initialisation failure. The HDMI 
peripheral driver gets initialised satisfactorily...

dw-hdmi-ingenic 10180000.hdmi: Detected HDMI TX controller v1.31a with HDCP 
(DWC HDMI 3D TX PHY)
dw-hdmi-ingenic 10180000.hdmi: registered DesignWare HDMI I2C bus driver

But then the reported error occurs in the DRM driver:

ingenic-drm 13050000.lcdc0: Unable to init connector
ingenic-drm: probe of 13050000.lcdc0 failed with error -22

This originates in a call to drm_bridge_connector_init from ingenic_drm_bind:

connector = drm_bridge_connector_init(drm, encoder);

The invoked function iterates over the registered bridges, one of which seems 
to be the HDMI peripheral (it has bridge operations defined identically to 
those specified in the Synopsys driver), but the type member of the drm_bridge 
structure is set to 0 (DRM_MODE_CONNECTOR_Unknown).

I might expect the bridge to expose a type acquired from its connector, but I 
don't see this propagation occurring in the Synopsys driver: dw_hdmi_probe 
sets the bridge operations and other members of the drm_bridge structure, but 
it doesn't set the type.

Also, it might be possible that dw_hdmi_connector_detect (exposed as the 
detect operation) is not getting called, and this would explain why the 
bridge's connector member does not have the connector_type set, either (since 
it is also set to 0).

Paul
Paul Cercueil Aug. 10, 2021, 7:52 a.m. UTC | #8
Hi Paul,

Le mar., août 10 2021 at 01:17:20 +0200, Paul Boddie 
<paul@boddie.org.uk> a écrit :
> On Monday, 9 August 2021 18:22:12 CEST Paul Cercueil wrote:
>> 
>>  Le lun., août 9 2021 at 13:14:03 +0200, H. Nikolaus Schaller
> <hns@goldelico.com> a écrit :
>>  >
>>  > quick feedback: our HDMI on top compiles fine after fixing 2 merge
>>  > conflicts, but dos not yet work.
>>  > Will need some spare time with access to the CI20 board to 
>> research
>>  > the issue, i.e. can not give feedback immediately.
>> 
>>  Alright, no problem. I'll be back home in about 2 weeks and then I 
>> can
>>  test on my CI20 as well.
> 
> Just for reference, I looked into this initialisation failure. The 
> HDMI
> peripheral driver gets initialised satisfactorily...
> 
> dw-hdmi-ingenic 10180000.hdmi: Detected HDMI TX controller v1.31a 
> with HDCP
> (DWC HDMI 3D TX PHY)
> dw-hdmi-ingenic 10180000.hdmi: registered DesignWare HDMI I2C bus 
> driver
> 
> But then the reported error occurs in the DRM driver:
> 
> ingenic-drm 13050000.lcdc0: Unable to init connector
> ingenic-drm: probe of 13050000.lcdc0 failed with error -22
> 
> This originates in a call to drm_bridge_connector_init from 
> ingenic_drm_bind:
> 
> connector = drm_bridge_connector_init(drm, encoder);
> 
> The invoked function iterates over the registered bridges, one of 
> which seems
> to be the HDMI peripheral (it has bridge operations defined 
> identically to
> those specified in the Synopsys driver), but the type member of the 
> drm_bridge
> structure is set to 0 (DRM_MODE_CONNECTOR_Unknown).
> 
> I might expect the bridge to expose a type acquired from its 
> connector, but I
> don't see this propagation occurring in the Synopsys driver: 
> dw_hdmi_probe
> sets the bridge operations and other members of the drm_bridge 
> structure, but
> it doesn't set the type.
> 
> Also, it might be possible that dw_hdmi_connector_detect (exposed as 
> the
> detect operation) is not getting called, and this would explain why 
> the
> bridge's connector member does not have the connector_type set, 
> either (since
> it is also set to 0).

 From what I understand the last bridge in the chained list is supposed 
to set the connector type. The HDMI driver's probe function should get 
a pointer to the next bridge in the queue and attach it (see how 
ite-it66121.c does it). The last bridge in the queue should be 
"hdmi-connector" (display-connector.c) which will effectively set the 
connector type.

Cheers,
-Paul
Paul Boddie Aug. 10, 2021, 9:15 p.m. UTC | #9
On Tuesday, 10 August 2021 09:52:36 CEST Paul Cercueil wrote:
> 
> Le mar., août 10 2021 at 01:17:20 +0200, Paul Boddie <paul@boddie.org.uk> a 
écrit :
> > 
> > But then the reported error occurs in the DRM driver:
> > 
> > ingenic-drm 13050000.lcdc0: Unable to init connector
> > ingenic-drm: probe of 13050000.lcdc0 failed with error -22
> > 
> > This originates in a call to drm_bridge_connector_init from
> > ingenic_drm_bind:
> > 
> > connector = drm_bridge_connector_init(drm, encoder);
> > 
> > The invoked function iterates over the registered bridges, one of
> > which seems to be the HDMI peripheral (it has bridge operations defined
> > identically to those specified in the Synopsys driver), but the type
> > member of the drm_bridge structure is set to 0
> > (DRM_MODE_CONNECTOR_Unknown).

Although I had fancy ideas about finding the connector node in the device tree 
and populating the necessary type details on the bridge, I decided to just add 
the following to the Synopsys driver's dw_hdmi_probe function:

hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;

This then lets the above invocation succeed and the Ingenic DRM driver 
initialises. However, I get "Input Not Supported" on my display.

Conveniently, when indicating the necessary boot arguments...

env set bootargs ... drm.debug=0x3f

...as suggested to me on a previous occasion, the /sys/kernel/debug/dri/0/
state file indicates the following:

plane[31]: plane-0
        crtc=crtc-0
        fb=36   
                allocated by = Xorg
                refcount=2
                format=XR24 little-endian (0x34325258)
                modifier=0x0
                size=1280x1024
                layers: 
                        size[0]=1280x1024
                        pitch[0]=5120
                        offset[0]=0
                        obj[0]: 
                                name=0
                                refcount=3
                                start=00010000
                                size=5242880
                                imported=no
                                paddr=0x00c00000
                                vaddr=3eb0c080
        crtc-pos=1280x1024+0+0
        src-pos=1280.000000x1024.000000+0.000000+0.000000
        rotation=1
        normalized-zpos=0
        color-encoding=ITU-R BT.601 YCbCr
        color-range=YCbCr limited range
plane[33]: plane-1
        crtc=(null)
        fb=0
        crtc-pos=0x0+0+0
        src-pos=0.000000x0.000000+0.000000+0.000000
        rotation=1
        normalized-zpos=0
        color-encoding=ITU-R BT.601 YCbCr
        color-range=YCbCr limited range
crtc[32]: crtc-0
        enable=1
        active=1
        self_refresh_active=0
        planes_changed=0
        mode_changed=0
        active_changed=0
        connectors_changed=0
        color_mgmt_changed=0
        plane_mask=1
        connector_mask=1
        encoder_mask=1
        mode: "": 60 108000 1280 1328 1440 1688 1024 1025 1028 1066 0x0 0x5
connector[35]: HDMI-A-1
        crtc=crtc-0
        self_refresh_aware=0

I suspect that we may be dealing with an incompatible bus format again, but I 
may be quite wrong about that, too.

Here is the result of running modetest using...

sudo ./modetest -D /dev/dri/card0 -M ingenic-drm

Encoders:
id      crtc    type    possible crtcs  possible clones
34      32      DPI     0x00000001      0x00000001

Connectors:
id      encoder status          name            size (mm)       modes   
encoders
35      34      connected       HDMI-A-1        340x270         17      34
  modes:
        index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot)
  #0 1280x1024 60.02 1280 1328 1440 1688 1024 1025 1028 1066 108000 flags: 
phsync, pvsync; type: preferred, driver
  #1 1280x1024 75.02 1280 1296 1440 1688 1024 1025 1028 1066 135000 flags: 
phsync, pvsync; type: driver
  #2 1280x960 60.00 1280 1376 1488 1800 960 961 964 1000 108000 flags: phsync, 
pvsync; type: driver
  #3 1152x864 75.00 1152 1216 1344 1600 864 865 868 900 108000 flags: phsync, 
pvsync; type: driver
  #4 1024x768 75.03 1024 1040 1136 1312 768 769 772 800 78750 flags: phsync, 
pvsync; type: driver
  #5 1024x768 70.07 1024 1048 1184 1328 768 771 777 806 75000 flags: nhsync, 
nvsync; type: driver
  #6 1024x768 60.00 1024 1048 1184 1344 768 771 777 806 65000 flags: nhsync, 
nvsync; type: driver
  #7 832x624 74.55 832 864 928 1152 624 625 628 667 57284 flags: nhsync, 
nvsync; type: driver
  #8 800x600 75.00 800 816 896 1056 600 601 604 625 49500 flags: phsync, 
pvsync; type: driver
  #9 800x600 72.19 800 856 976 1040 600 637 643 666 50000 flags: phsync, 
pvsync; type: driver
  #10 800x600 60.32 800 840 968 1056 600 601 605 628 40000 flags: phsync, 
pvsync; type: driver
  #11 800x600 56.25 800 824 896 1024 600 601 603 625 36000 flags: phsync, 
pvsync; type: driver
  #12 640x480 75.00 640 656 720 840 480 481 484 500 31500 flags: nhsync, 
nvsync; type: driver
  #13 640x480 72.81 640 664 704 832 480 489 492 520 31500 flags: nhsync, 
nvsync; type: driver
  #14 640x480 66.67 640 704 768 864 480 483 486 525 30240 flags: nhsync, 
nvsync; type: driver
  #15 640x480 59.94 640 656 752 800 480 490 492 525 25175 flags: nhsync, 
nvsync; type: driver
  #16 720x400 70.08 720 738 846 900 400 412 414 449 28320 flags: nhsync, 
pvsync; type: driver
  props:
        1 EDID: 
                flags: immutable blob
                blobs:

                value:  
                        00ffffffffffff00047232ad01010101
                        2d0e010380221b782aaea5a6544c9926
                        145054bfef0081808140714f01010101
                        010101010101302a009851002a403070
                        1300520e1100001e000000ff00343435
                        3030353444454330300a000000fc0041
                        4c313731350a202020202020000000fd
                        00384c1e520e000a2020202020200051
        2 DPMS: 
                flags: enum
                enums: On=0 Standby=1 Suspend=2 Off=3
                value: 3
        5 link-status:
                flags: enum
                enums: Good=0 Bad=1
                value: 0
        6 non-desktop:
                flags: immutable range
                values: 0 1
                value: 0
        4 TILE: 
                flags: immutable blob
                blobs:

                value:
        20 CRTC_ID:
                flags: object
                value: 32

CRTCs:
id      fb      pos     size
32      36      (0,0)   (1280x1024)
  #0  60.02 1280 1328 1440 1688 1024 1025 1028 1066 108000 flags: phsync, 
pvsync; type:
  props:
        22 ACTIVE:
                flags: range
                values: 0 1
                value: 0
        23 MODE_ID:
                flags: blob
                blobs:

                value:  
                        e0a5010000053005a005980600000004
                        010404042a0400003c00000005000000
                        00000000000000000000000000000000
                        00000000000000000000000000000000
                        00000000
        19 OUT_FENCE_PTR:
                flags: range
                values: 0 18446744073709551615
                value: 0
        24 VRR_ENABLED:
                flags: range
                values: 0 1
                value: 0
        28 GAMMA_LUT:
                flags: blob
                blobs:

                value:
        29 GAMMA_LUT_SIZE:
                flags: immutable range
                values: 0 4294967295
                value: 256

Planes:
id      crtc    fb      CRTC x,y        x,y     gamma size      possible crtcs
31      32      36      0,0             0,0     0               0x00000001
  formats: XR15 RG16 RG24 XR24 XR30
  props:
        8 type: 
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 1
        17 FB_ID:
                flags: object
                value: 36
        18 IN_FENCE_FD:
                flags: signed range
                values: -1 2147483647
                value: -1
        20 CRTC_ID:
                flags: object
                value: 32
        13 CRTC_X:
                flags: signed range
                values: -2147483648 2147483647
                value: 0
        14 CRTC_Y:
                flags: signed range
                values: -2147483648 2147483647
                value: 0
        15 CRTC_W:
                flags: range
                values: 0 2147483647
                value: 1280
        16 CRTC_H:
                flags: range
                values: 0 2147483647
                value: 1024
        9 SRC_X:
                flags: range
                values: 0 4294967295
                value: 0
        10 SRC_Y:
                flags: range
                values: 0 4294967295
                value: 0
        11 SRC_W:
                flags: range
                values: 0 4294967295
                value: 83886080
        12 SRC_H:
                flags: range
                values: 0 4294967295
                value: 67108864
33      0       0       0,0             0,0     0               0x00000001
  formats: C8   XR15 RG16 RG24 XR24 XR30
  props:
        8 type: 
                flags: immutable enum
                enums: Overlay=0 Primary=1 Cursor=2
                value: 0
        17 FB_ID:
                flags: object
                value: 0
        18 IN_FENCE_FD:
                flags: signed range
                values: -1 2147483647
                value: -1
        20 CRTC_ID:
                flags: object
                value: 0
        13 CRTC_X:
                flags: signed range
                values: -2147483648 2147483647
                value: 0
        14 CRTC_Y:
                flags: signed range
                values: -2147483648 2147483647
                value: 0
        15 CRTC_W:
                flags: range
                values: 0 2147483647
                value: 0
        16 CRTC_H:
                flags: range
                values: 0 2147483647
                value: 0
        9 SRC_X:
                flags: range
                values: 0 4294967295
                value: 0
        10 SRC_Y:
                flags: range
                values: 0 4294967295
                value: 0
        11 SRC_W:
                flags: range
                values: 0 4294967295
                value: 0
        12 SRC_H:
                flags: range
                values: 0 4294967295
                value: 0

Frame buffers:
id      size    pitch

Just in case that means anything to anyone.

Paul
Paul Cercueil Aug. 10, 2021, 9:54 p.m. UTC | #10
Hi Paul,
[...]

> Encoders:
> id      crtc    type    possible crtcs  possible clones
> 34      32      DPI     0x00000001      0x00000001
> 
> Connectors:
> id      encoder status          name            size (mm)       modes
> encoders
> 35      34      connected       HDMI-A-1        340x270         17    
>   34
>   modes:
>         index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot)
>   #0 1280x1024 60.02 1280 1328 1440 1688 1024 1025 1028 1066 108000 
> flags:
> phsync, pvsync; type: preferred, driver
>   #1 1280x1024 75.02 1280 1296 1440 1688 1024 1025 1028 1066 135000 
> flags:
> phsync, pvsync; type: driver
>   #2 1280x960 60.00 1280 1376 1488 1800 960 961 964 1000 108000 
> flags: phsync,
> pvsync; type: driver
>   #3 1152x864 75.00 1152 1216 1344 1600 864 865 868 900 108000 flags: 
> phsync,
> pvsync; type: driver
>   #4 1024x768 75.03 1024 1040 1136 1312 768 769 772 800 78750 flags: 
> phsync,
> pvsync; type: driver
>   #5 1024x768 70.07 1024 1048 1184 1328 768 771 777 806 75000 flags: 
> nhsync,
> nvsync; type: driver
>   #6 1024x768 60.00 1024 1048 1184 1344 768 771 777 806 65000 flags: 
> nhsync,
> nvsync; type: driver
>   #7 832x624 74.55 832 864 928 1152 624 625 628 667 57284 flags: 
> nhsync,
> nvsync; type: driver
>   #8 800x600 75.00 800 816 896 1056 600 601 604 625 49500 flags: 
> phsync,
> pvsync; type: driver
>   #9 800x600 72.19 800 856 976 1040 600 637 643 666 50000 flags: 
> phsync,
> pvsync; type: driver
>   #10 800x600 60.32 800 840 968 1056 600 601 605 628 40000 flags: 
> phsync,
> pvsync; type: driver
>   #11 800x600 56.25 800 824 896 1024 600 601 603 625 36000 flags: 
> phsync,
> pvsync; type: driver
>   #12 640x480 75.00 640 656 720 840 480 481 484 500 31500 flags: 
> nhsync,
> nvsync; type: driver
>   #13 640x480 72.81 640 664 704 832 480 489 492 520 31500 flags: 
> nhsync,
> nvsync; type: driver
>   #14 640x480 66.67 640 704 768 864 480 483 486 525 30240 flags: 
> nhsync,
> nvsync; type: driver
>   #15 640x480 59.94 640 656 752 800 480 490 492 525 25175 flags: 
> nhsync,
> nvsync; type: driver
>   #16 720x400 70.08 720 738 846 900 400 412 414 449 28320 flags: 
> nhsync,
> pvsync; type: driver
>   props:
>         1 EDID:
>                 flags: immutable blob
>                 blobs:
> 
>                 value:
>                         00ffffffffffff00047232ad01010101
>                         2d0e010380221b782aaea5a6544c9926
>                         145054bfef0081808140714f01010101
>                         010101010101302a009851002a403070
>                         1300520e1100001e000000ff00343435
>                         3030353444454330300a000000fc0041
>                         4c313731350a202020202020000000fd
>                         00384c1e520e000a2020202020200051
>         2 DPMS:
>                 flags: enum
>                 enums: On=0 Standby=1 Suspend=2 Off=3
>                 value: 3
>         5 link-status:
>                 flags: enum
>                 enums: Good=0 Bad=1
>                 value: 0
>         6 non-desktop:
>                 flags: immutable range
>                 values: 0 1
>                 value: 0
>         4 TILE:
>                 flags: immutable blob
>                 blobs:
> 
>                 value:
>         20 CRTC_ID:
>                 flags: object
>                 value: 32
> 
> CRTCs:
> id      fb      pos     size
> 32      36      (0,0)   (1280x1024)
>   #0  60.02 1280 1328 1440 1688 1024 1025 1028 1066 108000 flags: 
> phsync,
> pvsync; type:
>   props:
>         22 ACTIVE:
>                 flags: range
>                 values: 0 1
>                 value: 0
>         23 MODE_ID:
>                 flags: blob
>                 blobs:
> 
>                 value:
>                         e0a5010000053005a005980600000004
>                         010404042a0400003c00000005000000
>                         00000000000000000000000000000000
>                         00000000000000000000000000000000
>                         00000000
>         19 OUT_FENCE_PTR:
>                 flags: range
>                 values: 0 18446744073709551615
>                 value: 0
>         24 VRR_ENABLED:
>                 flags: range
>                 values: 0 1
>                 value: 0
>         28 GAMMA_LUT:
>                 flags: blob
>                 blobs:
> 
>                 value:
>         29 GAMMA_LUT_SIZE:
>                 flags: immutable range
>                 values: 0 4294967295
>                 value: 256
> 
> Planes:
> id      crtc    fb      CRTC x,y        x,y     gamma size      
> possible crtcs
> 31      32      36      0,0             0,0     0               
> 0x00000001
>   formats: XR15 RG16 RG24 XR24 XR30
>   props:
>         8 type:
>                 flags: immutable enum
>                 enums: Overlay=0 Primary=1 Cursor=2
>                 value: 1
>         17 FB_ID:
>                 flags: object
>                 value: 36
>         18 IN_FENCE_FD:
>                 flags: signed range
>                 values: -1 2147483647
>                 value: -1
>         20 CRTC_ID:
>                 flags: object
>                 value: 32
>         13 CRTC_X:
>                 flags: signed range
>                 values: -2147483648 2147483647
>                 value: 0
>         14 CRTC_Y:
>                 flags: signed range
>                 values: -2147483648 2147483647
>                 value: 0
>         15 CRTC_W:
>                 flags: range
>                 values: 0 2147483647
>                 value: 1280
>         16 CRTC_H:
>                 flags: range
>                 values: 0 2147483647
>                 value: 1024
>         9 SRC_X:
>                 flags: range
>                 values: 0 4294967295
>                 value: 0
>         10 SRC_Y:
>                 flags: range
>                 values: 0 4294967295
>                 value: 0
>         11 SRC_W:
>                 flags: range
>                 values: 0 4294967295
>                 value: 83886080
>         12 SRC_H:
>                 flags: range
>                 values: 0 4294967295
>                 value: 67108864
> 33      0       0       0,0             0,0     0               
> 0x00000001
>   formats: C8   XR15 RG16 RG24 XR24 XR30
>   props:
>         8 type:
>                 flags: immutable enum
>                 enums: Overlay=0 Primary=1 Cursor=2
>                 value: 0
>         17 FB_ID:
>                 flags: object
>                 value: 0
>         18 IN_FENCE_FD:
>                 flags: signed range
>                 values: -1 2147483647
>                 value: -1
>         20 CRTC_ID:
>                 flags: object
>                 value: 0
>         13 CRTC_X:
>                 flags: signed range
>                 values: -2147483648 2147483647
>                 value: 0
>         14 CRTC_Y:
>                 flags: signed range
>                 values: -2147483648 2147483647
>                 value: 0
>         15 CRTC_W:
>                 flags: range
>                 values: 0 2147483647
>                 value: 0
>         16 CRTC_H:
>                 flags: range
>                 values: 0 2147483647
>                 value: 0
>         9 SRC_X:
>                 flags: range
>                 values: 0 4294967295
>                 value: 0
>         10 SRC_Y:
>                 flags: range
>                 values: 0 4294967295
>                 value: 0
>         11 SRC_W:
>                 flags: range
>                 values: 0 4294967295
>                 value: 0
>         12 SRC_H:
>                 flags: range
>                 values: 0 4294967295
>                 value: 0
> 
> Frame buffers:
> id      size    pitch
> 
> Just in case that means anything to anyone.

Everything looks good to me. Maybe add some debug in ingenic-drm to see 
what bus flags and format it ends up choosing.

Cheers,
-Paul
diff mbox series

Patch

diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 7ae48ead3ab6..09d5dd298078 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -21,6 +21,7 @@ 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_bridge.h>
+#include <drm/drm_bridge_connector.h>
 #include <drm/drm_color_mgmt.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
@@ -107,6 +108,19 @@  struct ingenic_drm {
 	struct drm_private_obj private_obj;
 };
 
+struct ingenic_drm_bridge {
+	struct drm_encoder encoder;
+	struct drm_bridge bridge, *next_bridge;
+
+	struct drm_bus_cfg bus_cfg;
+};
+
+static inline struct ingenic_drm_bridge *
+to_ingenic_drm_bridge(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct ingenic_drm_bridge, encoder);
+}
+
 static inline struct ingenic_drm_private_state *
 to_ingenic_drm_priv_state(struct drm_private_state *state)
 {
@@ -679,11 +693,10 @@  static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
 {
 	struct ingenic_drm *priv = drm_device_get_priv(encoder->dev);
 	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
-	struct drm_connector *conn = conn_state->connector;
-	struct drm_display_info *info = &conn->display_info;
+	struct ingenic_drm_bridge *bridge = to_ingenic_drm_bridge(encoder);
 	unsigned int cfg, rgbcfg = 0;
 
-	priv->panel_is_sharp = info->bus_flags & DRM_BUS_FLAG_SHARP_SIGNALS;
+	priv->panel_is_sharp = bridge->bus_cfg.flags & DRM_BUS_FLAG_SHARP_SIGNALS;
 
 	if (priv->panel_is_sharp) {
 		cfg = JZ_LCD_CFG_MODE_SPECIAL_TFT_1 | JZ_LCD_CFG_REV_POLARITY;
@@ -696,19 +709,19 @@  static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
 		cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
 	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
 		cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
-	if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
+	if (bridge->bus_cfg.flags & DRM_BUS_FLAG_DE_LOW)
 		cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
-	if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
+	if (bridge->bus_cfg.flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
 		cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
 
 	if (!priv->panel_is_sharp) {
-		if (conn->connector_type == DRM_MODE_CONNECTOR_TV) {
+		if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV) {
 			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 				cfg |= JZ_LCD_CFG_MODE_TV_OUT_I;
 			else
 				cfg |= JZ_LCD_CFG_MODE_TV_OUT_P;
 		} else {
-			switch (*info->bus_formats) {
+			switch (bridge->bus_cfg.format) {
 			case MEDIA_BUS_FMT_RGB565_1X16:
 				cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT;
 				break;
@@ -734,20 +747,29 @@  static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
 	regmap_write(priv->map, JZ_REG_LCD_RGBC, rgbcfg);
 }
 
-static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder,
-					    struct drm_crtc_state *crtc_state,
-					    struct drm_connector_state *conn_state)
+static int ingenic_drm_bridge_attach(struct drm_bridge *bridge,
+				     enum drm_bridge_attach_flags flags)
+{
+	struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder);
+
+	return drm_bridge_attach(bridge->encoder, ib->next_bridge,
+				 &ib->bridge, flags);
+}
+
+static int ingenic_drm_bridge_atomic_check(struct drm_bridge *bridge,
+					   struct drm_bridge_state *bridge_state,
+					   struct drm_crtc_state *crtc_state,
+					   struct drm_connector_state *conn_state)
 {
-	struct drm_display_info *info = &conn_state->connector->display_info;
 	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
+	struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder);
 
-	if (info->num_bus_formats != 1)
-		return -EINVAL;
+	ib->bus_cfg = bridge_state->output_bus_cfg;
 
 	if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV)
 		return 0;
 
-	switch (*info->bus_formats) {
+	switch (bridge_state->output_bus_cfg.format) {
 	case MEDIA_BUS_FMT_RGB888_3X8:
 	case MEDIA_BUS_FMT_RGB888_3X8_DELTA:
 		/*
@@ -911,8 +933,16 @@  static const struct drm_crtc_helper_funcs ingenic_drm_crtc_helper_funcs = {
 };
 
 static const struct drm_encoder_helper_funcs ingenic_drm_encoder_helper_funcs = {
-	.atomic_mode_set	= ingenic_drm_encoder_atomic_mode_set,
-	.atomic_check		= ingenic_drm_encoder_atomic_check,
+	.atomic_mode_set        = ingenic_drm_encoder_atomic_mode_set,
+};
+
+static const struct drm_bridge_funcs ingenic_drm_bridge_funcs = {
+	.attach			= ingenic_drm_bridge_attach,
+	.atomic_check		= ingenic_drm_bridge_atomic_check,
+	.atomic_reset		= drm_atomic_helper_bridge_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_bridge_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_bridge_destroy_state,
+	.atomic_get_input_bus_fmts = drm_atomic_helper_bridge_propagate_bus_fmt,
 };
 
 static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = {
@@ -958,7 +988,9 @@  static int ingenic_drm_bind(struct device *dev, bool has_components)
 	struct drm_plane *primary;
 	struct drm_bridge *bridge;
 	struct drm_panel *panel;
+	struct drm_connector *connector;
 	struct drm_encoder *encoder;
+	struct ingenic_drm_bridge *ib;
 	struct drm_device *drm;
 	void __iomem *base;
 	long parent_rate;
@@ -1146,20 +1178,36 @@  static int ingenic_drm_bind(struct device *dev, bool has_components)
 			bridge = devm_drm_panel_bridge_add_typed(dev, panel,
 								 DRM_MODE_CONNECTOR_DPI);
 
-		encoder = drmm_plain_encoder_alloc(drm, NULL, DRM_MODE_ENCODER_DPI, NULL);
-		if (IS_ERR(encoder)) {
-			ret = PTR_ERR(encoder);
+		ib = drmm_encoder_alloc(drm, struct ingenic_drm_bridge, encoder,
+					NULL, DRM_MODE_ENCODER_DPI, NULL);
+		if (IS_ERR(ib)) {
+			ret = PTR_ERR(ib);
 			dev_err(dev, "Failed to init encoder: %d\n", ret);
 			return ret;
 		}
 
-		encoder->possible_crtcs = 1;
+		encoder = &ib->encoder;
+		encoder->possible_crtcs = drm_crtc_mask(&priv->crtc);
 
 		drm_encoder_helper_add(encoder, &ingenic_drm_encoder_helper_funcs);
 
-		ret = drm_bridge_attach(encoder, bridge, NULL, 0);
-		if (ret)
+		ib->bridge.funcs = &ingenic_drm_bridge_funcs;
+		ib->next_bridge = bridge;
+
+		ret = drm_bridge_attach(encoder, &ib->bridge, NULL,
+					DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+		if (ret) {
+			dev_err(dev, "Unable to attach bridge\n");
 			return ret;
+		}
+
+		connector = drm_bridge_connector_init(drm, encoder);
+		if (IS_ERR(connector)) {
+			dev_err(dev, "Unable to init connector\n");
+			return PTR_ERR(connector);
+		}
+
+		drm_connector_attach_encoder(connector, encoder);
 	}
 
 	drm_for_each_encoder(encoder, drm) {