Re: [PATCH v1 1/2] drm/msm/dp: Fix support of LTTPR handling

2025-03-11 Thread Abel Vesa
On 25-03-10 22:05:51, Aleksandrs Vinarskis wrote:
> Take into account LTTPR capabilities when selecting maximum allowed
> link rate, number of data lines. Initialize LTTPR before
> msm_dp_panel_read_sink_caps, as
> a) Link params computation need to take into account LTTPR's caps
> b) It appears DPTX shall (re)read DPRX caps after LTTPR detection
> 
> Return lttpr_count to prepare for per-segment link training.
> 
> Signed-off-by: Aleksandrs Vinarskis 
> ---
>  drivers/gpu/drm/msm/dp/dp_display.c | 31 +++--
>  drivers/gpu/drm/msm/dp/dp_panel.c   | 30 +++-
>  drivers/gpu/drm/msm/dp/dp_panel.h   |  2 ++
>  3 files changed, 44 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
> b/drivers/gpu/drm/msm/dp/dp_display.c
> index bbc47d86ae9e..2edbc6adfde5 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -108,6 +108,8 @@ struct msm_dp_display_private {
>   struct msm_dp_event event_list[DP_EVENT_Q_MAX];
>   spinlock_t event_lock;
>  
> + u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE];
> +
>   bool wide_bus_supported;
>  
>   struct msm_dp_audio *audio;
> @@ -367,17 +369,21 @@ static int msm_dp_display_send_hpd_notification(struct 
> msm_dp_display_private *d
>   return 0;
>  }
>  
> -static void msm_dp_display_lttpr_init(struct msm_dp_display_private *dp)
> +static int msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 
> *dpcd)
>  {
> - u8 lttpr_caps[DP_LTTPR_COMMON_CAP_SIZE];
> - int rc;
> + int rc, lttpr_count;
>  
> - if (drm_dp_read_lttpr_common_caps(dp->aux, dp->panel->dpcd, lttpr_caps))
> - return;
> + if (drm_dp_read_lttpr_common_caps(dp->aux, dpcd, dp->lttpr_common_caps))
> + return 0;
>  
> - rc = drm_dp_lttpr_init(dp->aux, drm_dp_lttpr_count(lttpr_caps));
> - if (rc)
> - DRM_ERROR("failed to set LTTPRs transparency mode, rc=%d\n", 
> rc);
> + lttpr_count = drm_dp_lttpr_count(dp->lttpr_common_caps);
> + rc = drm_dp_lttpr_init(dp->aux, lttpr_count);
> + if (rc) {
> + DRM_ERROR("fialed to set LTTPRs transparency mode, rc=%d\n", 
> rc);

Nitpick: failed

With that fixed, LGTM:

Reviewed-by: Abel Vesa 

> + return 0;
> + }
> +
> + return lttpr_count;
>  }
>  
>  static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp)
> @@ -385,12 +391,17 @@ static int msm_dp_display_process_hpd_high(struct 
> msm_dp_display_private *dp)
>   struct drm_connector *connector = dp->msm_dp_display.connector;
>   const struct drm_display_info *info = &connector->display_info;
>   int rc = 0;
> + u8 dpcd[DP_RECEIVER_CAP_SIZE];
>  
> - rc = msm_dp_panel_read_sink_caps(dp->panel, connector);
> + rc = drm_dp_read_dpcd_caps(dp->aux, dpcd);
>   if (rc)
>   goto end;
>  
> - msm_dp_display_lttpr_init(dp);
> + msm_dp_display_lttpr_init(dp, dpcd);
> +
> + rc = msm_dp_panel_read_sink_caps(dp->panel, dp->lttpr_common_caps, 
> connector);
> + if (rc)
> + goto end;
>  
>   msm_dp_link_process_request(dp->link);
>  
> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c 
> b/drivers/gpu/drm/msm/dp/dp_panel.c
> index 92415bf8aa16..f41b4cf7002e 100644
> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
> @@ -45,9 +45,12 @@ static void msm_dp_panel_read_psr_cap(struct 
> msm_dp_panel_private *panel)
>   }
>  }
>  
> -static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel)
> +static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel,
> +   const u8 
> lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE])
>  {
>   int rc;
> + int max_sink_lanes, max_source_lanes, max_lttpr_lanes;
> + int max_sink_rate, max_source_rate, max_lttpr_rate;
>   struct msm_dp_panel_private *panel;
>   struct msm_dp_link_info *link_info;
>   u8 *dpcd, major, minor;
> @@ -64,16 +67,24 @@ static int msm_dp_panel_read_dpcd(struct msm_dp_panel 
> *msm_dp_panel)
>   major = (link_info->revision >> 4) & 0x0f;
>   minor = link_info->revision & 0x0f;
>  
> - link_info->rate = drm_dp_max_link_rate(dpcd);
> - link_info->num_lanes = drm_dp_max_lane_count(dpcd);
> + max_source_lanes = msm_dp_panel->max_dp_lanes;
> + max_source_rate = msm_dp_panel->max_dp_link_rate;
>  
> - /* Limit data lanes from data-lanes of endpoint property of dtsi */
> - if (link_info->num_lanes > msm_dp_panel->max_dp_lanes)
> - link_info->num_lanes = msm_dp_panel->max_dp_lanes;
> + max_sink_lanes = drm_dp_max_lane_count(dpcd);
> + max_sink_rate = drm_dp_max_link_rate(dpcd);
> +
> + max_lttpr_lanes = drm_dp_lttpr_max_lane_count(lttpr_common_caps);
> + max_lttpr_rate = drm_dp_lttpr_max_link_rate(lttpr_common_caps);
>  
> + if (max_lttpr_lanes)
> + max_sink_lanes = min(max_sink_lan

Re: [PATCH v5 1/2] drm/bridge: split HDMI Audio from DRM_BRIDGE_OP_HDMI

2025-03-11 Thread Maxime Ripard
On Mon, Mar 10, 2025 at 08:42:29PM +0200, Dmitry Baryshkov wrote:
> On Mon, 10 Mar 2025 at 16:55, Maxime Ripard  wrote:
> >
> > Hi,
> >
> > On Fri, Mar 07, 2025 at 07:55:52AM +0200, Dmitry Baryshkov wrote:
> > > From: Dmitry Baryshkov 
> > >
> > > As pointed out by Laurent, OP bits are supposed to describe operations.
> > > Split DRM_BRIDGE_OP_HDMI_AUDIO from DRM_BRIDGE_OP_HDMI instead of
> > > overloading DRM_BRIDGE_OP_HDMI.
> > >
> > > Signed-off-by: Dmitry Baryshkov 
> > > ---
> > >  drivers/gpu/drm/bridge/lontium-lt9611.c|  2 +-
> > >  drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c   |  1 +
> > >  drivers/gpu/drm/display/drm_bridge_connector.c | 59 
> > > +-
> > >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c |  1 +
> > >  include/drm/drm_bridge.h   | 23 --
> > >  5 files changed, 61 insertions(+), 25 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c 
> > > b/drivers/gpu/drm/bridge/lontium-lt9611.c
> > > index 
> > > 026803034231f78c17f619dc04119bdd9b2b6679..3b93c17e25c18ae0d13e9bb74553cf21dcc39f9d
> > >  100644
> > > --- a/drivers/gpu/drm/bridge/lontium-lt9611.c
> > > +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
> > > @@ -1130,7 +1130,7 @@ static int lt9611_probe(struct i2c_client *client)
> > >   lt9611->bridge.of_node = client->dev.of_node;
> > >   lt9611->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
> > >DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES |
> > > -  DRM_BRIDGE_OP_HDMI;
> > > +  DRM_BRIDGE_OP_HDMI | DRM_BRIDGE_OP_HDMI_AUDIO;
> > >   lt9611->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
> > >   lt9611->bridge.vendor = "Lontium";
> > >   lt9611->bridge.product = "LT9611";
> > > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c 
> > > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> > > index 
> > > 6166f197e37b552cb8a52b7b0d23ffc632f54557..5e5f8c2f95be1f5c4633f1093b17a00f9425bb37
> > >  100644
> > > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> > > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> > > @@ -1077,6 +1077,7 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct 
> > > platform_device *pdev,
> > >   hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT |
> > >  DRM_BRIDGE_OP_EDID |
> > >  DRM_BRIDGE_OP_HDMI |
> > > +DRM_BRIDGE_OP_HDMI_AUDIO |
> > >  DRM_BRIDGE_OP_HPD;
> > >   hdmi->bridge.of_node = pdev->dev.of_node;
> > >   hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
> > > diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c 
> > > b/drivers/gpu/drm/display/drm_bridge_connector.c
> > > index 
> > > 30c736fc0067e31a97db242e5b16ea8a5b4cf359..030f98d454608a63154827c65d4822d378df3b4c
> > >  100644
> > > --- a/drivers/gpu/drm/display/drm_bridge_connector.c
> > > +++ b/drivers/gpu/drm/display/drm_bridge_connector.c
> > > @@ -98,6 +98,13 @@ struct drm_bridge_connector {
> > >* HDMI connector infrastructure, if any (see &DRM_BRIDGE_OP_HDMI).
> > >*/
> > >   struct drm_bridge *bridge_hdmi;
> > > + /**
> > > +  * @bridge_hdmi_audio:
> > > +  *
> > > +  * The bridge in the chain that implements necessary support for the
> > > +  * HDMI Audio infrastructure, if any (see 
> > > &DRM_BRIDGE_OP_HDMI_AUDIO).
> > > +  */
> > > + struct drm_bridge *bridge_hdmi_audio;
> > >  };
> > >
> > >  #define to_drm_bridge_connector(x) \
> > > @@ -433,7 +440,7 @@ static int drm_bridge_connector_audio_startup(struct 
> > > drm_connector *connector)
> > >   to_drm_bridge_connector(connector);
> > >   struct drm_bridge *bridge;
> > >
> > > - bridge = bridge_connector->bridge_hdmi;
> > > + bridge = bridge_connector->bridge_hdmi_audio;
> > >   if (!bridge)
> > >   return -EINVAL;
> > >
> > > @@ -451,7 +458,7 @@ static int drm_bridge_connector_audio_prepare(struct 
> > > drm_connector *connector,
> > >   to_drm_bridge_connector(connector);
> > >   struct drm_bridge *bridge;
> > >
> > > - bridge = bridge_connector->bridge_hdmi;
> > > + bridge = bridge_connector->bridge_hdmi_audio;
> > >   if (!bridge)
> > >   return -EINVAL;
> > >
> > > @@ -464,7 +471,7 @@ static void 
> > > drm_bridge_connector_audio_shutdown(struct drm_connector *connector)
> > >   to_drm_bridge_connector(connector);
> > >   struct drm_bridge *bridge;
> > >
> > > - bridge = bridge_connector->bridge_hdmi;
> > > + bridge = bridge_connector->bridge_hdmi_audio;
> > >   if (!bridge)
> > >   return;
> > >
> > > @@ -478,7 +485,7 @@ static int 
> > > drm_bridge_connector_audio_mute_stream(struct drm_connector *connecto
> > >   to_drm_bridge_connector(connector);
> > >   struct drm_bridge *bridge;
> > >
> > > - bridge = bridge_connector->bridge_hdmi;
> > > + bridge = bridge_c

Re: [PATCH v1 2/2] drm/msm/dp: Introduce link training per-segment for LTTPRs

2025-03-11 Thread Johan Hovold
Hi Aleksandrs,

Just a drive-by comment.

On Mon, Mar 10, 2025 at 10:05:52PM +0100, Aleksandrs Vinarskis wrote:

> @@ -1084,10 +1091,13 @@ static int msm_dp_ctrl_update_vx_px(struct 
> msm_dp_ctrl_private *ctrl)
>  }
>  
>  static bool msm_dp_ctrl_train_pattern_set(struct msm_dp_ctrl_private *ctrl,
> - u8 pattern)
> + u8 pattern, enum drm_dp_phy dp_phy)
>  {
>   u8 buf;
>   int ret = 0;
> + int reg = dp_phy == DP_PHY_DPRX ?
> + DP_TRAINING_PATTERN_SET :
> + DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy);

This is hardly readable; avoid using the ternary operator and split
declaration from non-trivial initialisation.

Johan


[PATCH v1 1/2] drm/msm/dp: Fix support of LTTPR handling

2025-03-11 Thread Aleksandrs Vinarskis
Take into account LTTPR capabilities when selecting maximum allowed
link rate, number of data lines. Initialize LTTPR before
msm_dp_panel_read_sink_caps, as
a) Link params computation need to take into account LTTPR's caps
b) It appears DPTX shall (re)read DPRX caps after LTTPR detection

Return lttpr_count to prepare for per-segment link training.

Signed-off-by: Aleksandrs Vinarskis 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 31 +++--
 drivers/gpu/drm/msm/dp/dp_panel.c   | 30 +++-
 drivers/gpu/drm/msm/dp/dp_panel.h   |  2 ++
 3 files changed, 44 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index bbc47d86ae9e..2edbc6adfde5 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -108,6 +108,8 @@ struct msm_dp_display_private {
struct msm_dp_event event_list[DP_EVENT_Q_MAX];
spinlock_t event_lock;
 
+   u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE];
+
bool wide_bus_supported;
 
struct msm_dp_audio *audio;
@@ -367,17 +369,21 @@ static int msm_dp_display_send_hpd_notification(struct 
msm_dp_display_private *d
return 0;
 }
 
-static void msm_dp_display_lttpr_init(struct msm_dp_display_private *dp)
+static int msm_dp_display_lttpr_init(struct msm_dp_display_private *dp, u8 
*dpcd)
 {
-   u8 lttpr_caps[DP_LTTPR_COMMON_CAP_SIZE];
-   int rc;
+   int rc, lttpr_count;
 
-   if (drm_dp_read_lttpr_common_caps(dp->aux, dp->panel->dpcd, lttpr_caps))
-   return;
+   if (drm_dp_read_lttpr_common_caps(dp->aux, dpcd, dp->lttpr_common_caps))
+   return 0;
 
-   rc = drm_dp_lttpr_init(dp->aux, drm_dp_lttpr_count(lttpr_caps));
-   if (rc)
-   DRM_ERROR("failed to set LTTPRs transparency mode, rc=%d\n", 
rc);
+   lttpr_count = drm_dp_lttpr_count(dp->lttpr_common_caps);
+   rc = drm_dp_lttpr_init(dp->aux, lttpr_count);
+   if (rc) {
+   DRM_ERROR("fialed to set LTTPRs transparency mode, rc=%d\n", 
rc);
+   return 0;
+   }
+
+   return lttpr_count;
 }
 
 static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp)
@@ -385,12 +391,17 @@ static int msm_dp_display_process_hpd_high(struct 
msm_dp_display_private *dp)
struct drm_connector *connector = dp->msm_dp_display.connector;
const struct drm_display_info *info = &connector->display_info;
int rc = 0;
+   u8 dpcd[DP_RECEIVER_CAP_SIZE];
 
-   rc = msm_dp_panel_read_sink_caps(dp->panel, connector);
+   rc = drm_dp_read_dpcd_caps(dp->aux, dpcd);
if (rc)
goto end;
 
-   msm_dp_display_lttpr_init(dp);
+   msm_dp_display_lttpr_init(dp, dpcd);
+
+   rc = msm_dp_panel_read_sink_caps(dp->panel, dp->lttpr_common_caps, 
connector);
+   if (rc)
+   goto end;
 
msm_dp_link_process_request(dp->link);
 
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c 
b/drivers/gpu/drm/msm/dp/dp_panel.c
index 92415bf8aa16..f41b4cf7002e 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -45,9 +45,12 @@ static void msm_dp_panel_read_psr_cap(struct 
msm_dp_panel_private *panel)
}
 }
 
-static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel)
+static int msm_dp_panel_read_dpcd(struct msm_dp_panel *msm_dp_panel,
+ const u8 
lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE])
 {
int rc;
+   int max_sink_lanes, max_source_lanes, max_lttpr_lanes;
+   int max_sink_rate, max_source_rate, max_lttpr_rate;
struct msm_dp_panel_private *panel;
struct msm_dp_link_info *link_info;
u8 *dpcd, major, minor;
@@ -64,16 +67,24 @@ static int msm_dp_panel_read_dpcd(struct msm_dp_panel 
*msm_dp_panel)
major = (link_info->revision >> 4) & 0x0f;
minor = link_info->revision & 0x0f;
 
-   link_info->rate = drm_dp_max_link_rate(dpcd);
-   link_info->num_lanes = drm_dp_max_lane_count(dpcd);
+   max_source_lanes = msm_dp_panel->max_dp_lanes;
+   max_source_rate = msm_dp_panel->max_dp_link_rate;
 
-   /* Limit data lanes from data-lanes of endpoint property of dtsi */
-   if (link_info->num_lanes > msm_dp_panel->max_dp_lanes)
-   link_info->num_lanes = msm_dp_panel->max_dp_lanes;
+   max_sink_lanes = drm_dp_max_lane_count(dpcd);
+   max_sink_rate = drm_dp_max_link_rate(dpcd);
+
+   max_lttpr_lanes = drm_dp_lttpr_max_lane_count(lttpr_common_caps);
+   max_lttpr_rate = drm_dp_lttpr_max_link_rate(lttpr_common_caps);
 
+   if (max_lttpr_lanes)
+   max_sink_lanes = min(max_sink_lanes, max_lttpr_lanes);
+   if (max_lttpr_rate)
+   max_sink_rate = min(max_sink_rate, max_lttpr_rate);
+
+   /* Limit data lanes from data-lanes of endpoint property of dtsi */
+   link_info->num_lanes = min(max_sink_lanes, max_

Re: [PATCH v5 1/2] drm/bridge: split HDMI Audio from DRM_BRIDGE_OP_HDMI

2025-03-11 Thread Maxime Ripard
On Tue, Mar 11, 2025 at 05:50:09PM +0200, Dmitry Baryshkov wrote:
> On Tue, Mar 11, 2025 at 09:36:37AM +0100, Maxime Ripard wrote:
> > On Mon, Mar 10, 2025 at 08:42:29PM +0200, Dmitry Baryshkov wrote:
> > > On Mon, 10 Mar 2025 at 16:55, Maxime Ripard  wrote:
> > > >
> > > > Hi,
> > > >
> > > > On Fri, Mar 07, 2025 at 07:55:52AM +0200, Dmitry Baryshkov wrote:
> > > > > From: Dmitry Baryshkov 
> > > > >
> > > > > As pointed out by Laurent, OP bits are supposed to describe 
> > > > > operations.
> > > > > Split DRM_BRIDGE_OP_HDMI_AUDIO from DRM_BRIDGE_OP_HDMI instead of
> > > > > overloading DRM_BRIDGE_OP_HDMI.
> > > > >
> > > > > Signed-off-by: Dmitry Baryshkov 
> > > > > ---
> > > > >  drivers/gpu/drm/bridge/lontium-lt9611.c|  2 +-
> > > > >  drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c   |  1 +
> > > > >  drivers/gpu/drm/display/drm_bridge_connector.c | 59 
> > > > > +-
> > > > >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c |  1 +
> > > > >  include/drm/drm_bridge.h   | 23 --
> > > > >  5 files changed, 61 insertions(+), 25 deletions(-)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c 
> > > > > b/drivers/gpu/drm/bridge/lontium-lt9611.c
> > > > > index 
> > > > > 026803034231f78c17f619dc04119bdd9b2b6679..3b93c17e25c18ae0d13e9bb74553cf21dcc39f9d
> > > > >  100644
> > > > > --- a/drivers/gpu/drm/bridge/lontium-lt9611.c
> > > > > +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
> > > > > @@ -1130,7 +1130,7 @@ static int lt9611_probe(struct i2c_client 
> > > > > *client)
> > > > >   lt9611->bridge.of_node = client->dev.of_node;
> > > > >   lt9611->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
> > > > >DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES |
> > > > > -  DRM_BRIDGE_OP_HDMI;
> > > > > +  DRM_BRIDGE_OP_HDMI | 
> > > > > DRM_BRIDGE_OP_HDMI_AUDIO;
> > > > >   lt9611->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
> > > > >   lt9611->bridge.vendor = "Lontium";
> > > > >   lt9611->bridge.product = "LT9611";
> > > > > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c 
> > > > > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> > > > > index 
> > > > > 6166f197e37b552cb8a52b7b0d23ffc632f54557..5e5f8c2f95be1f5c4633f1093b17a00f9425bb37
> > > > >  100644
> > > > > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> > > > > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> > > > > @@ -1077,6 +1077,7 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct 
> > > > > platform_device *pdev,
> > > > >   hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT |
> > > > >  DRM_BRIDGE_OP_EDID |
> > > > >  DRM_BRIDGE_OP_HDMI |
> > > > > +DRM_BRIDGE_OP_HDMI_AUDIO |
> > > > >  DRM_BRIDGE_OP_HPD;
> > > > >   hdmi->bridge.of_node = pdev->dev.of_node;
> > > > >   hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
> > > > > diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c 
> > > > > b/drivers/gpu/drm/display/drm_bridge_connector.c
> > > > > index 
> > > > > 30c736fc0067e31a97db242e5b16ea8a5b4cf359..030f98d454608a63154827c65d4822d378df3b4c
> > > > >  100644
> > > > > --- a/drivers/gpu/drm/display/drm_bridge_connector.c
> > > > > +++ b/drivers/gpu/drm/display/drm_bridge_connector.c
> > > > > @@ -98,6 +98,13 @@ struct drm_bridge_connector {
> > > > >* HDMI connector infrastructure, if any (see 
> > > > > &DRM_BRIDGE_OP_HDMI).
> > > > >*/
> > > > >   struct drm_bridge *bridge_hdmi;
> > > > > + /**
> > > > > +  * @bridge_hdmi_audio:
> > > > > +  *
> > > > > +  * The bridge in the chain that implements necessary support 
> > > > > for the
> > > > > +  * HDMI Audio infrastructure, if any (see 
> > > > > &DRM_BRIDGE_OP_HDMI_AUDIO).
> > > > > +  */
> > > > > + struct drm_bridge *bridge_hdmi_audio;
> > > > >  };
> > > > >
> > > > >  #define to_drm_bridge_connector(x) \
> > > > > @@ -433,7 +440,7 @@ static int 
> > > > > drm_bridge_connector_audio_startup(struct drm_connector *connector)
> > > > >   to_drm_bridge_connector(connector);
> > > > >   struct drm_bridge *bridge;
> > > > >
> > > > > - bridge = bridge_connector->bridge_hdmi;
> > > > > + bridge = bridge_connector->bridge_hdmi_audio;
> > > > >   if (!bridge)
> > > > >   return -EINVAL;
> > > > >
> > > > > @@ -451,7 +458,7 @@ static int 
> > > > > drm_bridge_connector_audio_prepare(struct drm_connector *connector,
> > > > >   to_drm_bridge_connector(connector);
> > > > >   struct drm_bridge *bridge;
> > > > >
> > > > > - bridge = bridge_connector->bridge_hdmi;
> > > > > + bridge = bridge_connector->bridge_hdmi_audio;
> > > > >   if (!bridge)
> > > > >   return -EINVAL;
> > > > >
> > > > > @@ -464,7 +471,7 @@ static void 
> > > > > drm_bridge_connector_audio_shutdown(struct drm_connector 

Re: [PATCH v2 09/10] drm/bridge: anx7625: update bridge_ops and sink detect logic

2025-03-11 Thread Dmitry Baryshkov
On Tue, Mar 11, 2025 at 05:54:44PM +0530, Ayushi Makhija wrote:
> The anx7625_link_bridge() checks if a device is not a panel
> bridge and add DRM_BRIDGE_OP_HPD and DRM_BRIDGE_OP_DETECT to
> the bridge operations. However, on port 1 of the anx7625
> bridge, any device added is always treated as a panel
> bridge, preventing connector_detect function from being
> called. To resolve this, instead of just checking if it is a
> panel bridge, verify the type of panel bridge
> whether it is a DisplayPort or eDP panel. If the panel
> bridge is not of the eDP type, add DRM_BRIDGE_OP_HPD and
> DRM_BRIDGE_OP_DETECT to the bridge operations.

Are/were there any devices using anx7625, eDP panel _and_ not using the
AUX bus? It would be better to use the precence of the 'aux' node to
determine whether it is an eDP or a DP configuration.

> 
> In the anx7625_sink_detect(), the device is checked to see
> if it is a panel bridge, and it always sends a "connected"
> status to the connector. When adding the DP port on port 1 of the
> anx7625, it incorrectly treats it as a panel bridge and sends an
> always "connected" status. Instead of checking the status on the
> panel bridge, it's better to check the hpd_status for connectors
> like DisplayPort. This way, it verifies the hpd_status variable
> before sending the status to the connector.
> 
> Signed-off-by: Ayushi Makhija 
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 10 --
>  1 file changed, 4 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
> b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index 764da1c1dc11..ad99ad19653f 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -1814,9 +1814,6 @@ static enum drm_connector_status 
> anx7625_sink_detect(struct anx7625_data *ctx)
>  
>   DRM_DEV_DEBUG_DRIVER(dev, "sink detect\n");
>  
> - if (ctx->pdata.panel_bridge)
> - return connector_status_connected;
> -
>   return ctx->hpd_status ? connector_status_connected :
>connector_status_disconnected;
>  }
> @@ -2608,9 +2605,10 @@ static int anx7625_link_bridge(struct drm_dp_aux *aux)
>   platform->bridge.of_node = dev->of_node;
>   if (!anx7625_of_panel_on_aux_bus(dev))
>   platform->bridge.ops |= DRM_BRIDGE_OP_EDID;
> - if (!platform->pdata.panel_bridge)
> - platform->bridge.ops |= DRM_BRIDGE_OP_HPD |
> - DRM_BRIDGE_OP_DETECT;
> + if (!platform->pdata.panel_bridge ||
> + platform->pdata.panel_bridge->type != DRM_MODE_CONNECTOR_eDP) {
> + platform->bridge.ops |= DRM_BRIDGE_OP_HPD | 
> DRM_BRIDGE_OP_DETECT;
> + }
>   platform->bridge.type = platform->pdata.panel_bridge ?
>   DRM_MODE_CONNECTOR_eDP :
>   DRM_MODE_CONNECTOR_DisplayPort;
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry


[PATCH v4 04/25] drm/gem-shmem: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch to a multiple of 8.

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/drm_gem_shmem_helper.c | 16 +---
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c 
b/drivers/gpu/drm/drm_gem_shmem_helper.c
index d99dee67353a..849ee2cde990 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -514,18 +515,11 @@ EXPORT_SYMBOL(drm_gem_shmem_purge);
 int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev,
  struct drm_mode_create_dumb *args)
 {
-   u32 min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+   int ret;
 
-   if (!args->pitch || !args->size) {
-   args->pitch = min_pitch;
-   args->size = PAGE_ALIGN(args->pitch * args->height);
-   } else {
-   /* ensure sane minimum values */
-   if (args->pitch < min_pitch)
-   args->pitch = min_pitch;
-   if (args->size < args->pitch * args->height)
-   args->size = PAGE_ALIGN(args->pitch * args->height);
-   }
+   ret = drm_mode_size_dumb(dev, args, SZ_8, 0);
+   if (ret)
+   return ret;
 
return drm_gem_shmem_create_with_handle(file, dev, args->size, 
&args->handle);
 }
-- 
2.48.1



[PATCH v4 21/25] drm/virtio: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch to a multiple of 4.

Signed-off-by: Thomas Zimmermann 
Cc: David Airlie 
Cc: Gerd Hoffmann 
Cc: Gurchetan Singh 
Cc: Chia-I Wu 
---
 drivers/gpu/drm/virtio/virtgpu_gem.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c 
b/drivers/gpu/drm/virtio/virtgpu_gem.c
index dde8fc1a3689..5e5e38d53990 100644
--- a/drivers/gpu/drm/virtio/virtgpu_gem.c
+++ b/drivers/gpu/drm/virtio/virtgpu_gem.c
@@ -23,6 +23,7 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include 
 #include 
 #include 
 
@@ -66,15 +67,14 @@ int virtio_gpu_mode_dumb_create(struct drm_file *file_priv,
struct virtio_gpu_object_params params = { 0 };
struct virtio_gpu_device *vgdev = dev->dev_private;
int ret;
-   uint32_t pitch;
+
+   ret = drm_mode_size_dumb(dev, args, SZ_4, 0);
+   if (ret)
+   return ret;
 
if (args->bpp != 32)
return -EINVAL;
 
-   pitch = args->width * 4;
-   args->size = pitch * args->height;
-   args->size = ALIGN(args->size, PAGE_SIZE);
-
params.format = virtio_gpu_translate_format(DRM_FORMAT_HOST_XRGB);
params.width = args->width;
params.height = args->height;
@@ -92,7 +92,6 @@ int virtio_gpu_mode_dumb_create(struct drm_file *file_priv,
if (ret)
goto fail;
 
-   args->pitch = pitch;
return ret;
 
 fail:
-- 
2.48.1



[PATCH v4 03/25] drm/gem-dma: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch to a multiple of 8.

Push the current calculation into the only direct caller imx. Imx's
hardware requires the framebuffer width to be aligned to 8. The
driver's current approach is actually incorrect, as it only guarantees
this implicitly and requires bpp to be a multiple of 8 already. A
later commit will fix this problem by aligning the scanline pitch
such that an aligned width still fits into each scanline's memory.

A number of other drivers are build on top of gem-dma helpers and
implement their own dumb-buffer allocation. These drivers invoke
drm_gem_dma_dumb_create_internal(), which is not affected by this
commit.

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/drm_gem_dma_helper.c | 7 +--
 drivers/gpu/drm/imx/ipuv3/imx-drm-core.c | 2 ++
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_dma_helper.c 
b/drivers/gpu/drm/drm_gem_dma_helper.c
index b7f033d4352a..49be9b033610 100644
--- a/drivers/gpu/drm/drm_gem_dma_helper.c
+++ b/drivers/gpu/drm/drm_gem_dma_helper.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -304,9 +305,11 @@ int drm_gem_dma_dumb_create(struct drm_file *file_priv,
struct drm_mode_create_dumb *args)
 {
struct drm_gem_dma_object *dma_obj;
+   int ret;
 
-   args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
-   args->size = args->pitch * args->height;
+   ret = drm_mode_size_dumb(drm, args, SZ_8, 0);
+   if (ret)
+   return ret;
 
dma_obj = drm_gem_dma_create_with_handle(file_priv, drm, args->size,
 &args->handle);
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c 
b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
index ec5fd9a01f1e..e7025df7b978 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
@@ -145,6 +145,8 @@ static int imx_drm_dumb_create(struct drm_file *file_priv,
int ret;
 
args->width = ALIGN(width, 8);
+   args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+   args->size = args->pitch * args->height;
 
ret = drm_gem_dma_dumb_create(file_priv, drm, args);
if (ret)
-- 
2.48.1



[PATCH v4 12/25] drm/mediatek: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch to a multiple of 8.

Signed-off-by: Thomas Zimmermann 
Cc: Chun-Kuang Hu 
Cc: Philipp Zabel 
Cc: Matthias Brugger 
Cc: AngeloGioacchino Del Regno 
---
 drivers/gpu/drm/mediatek/mtk_gem.c | 13 -
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_gem.c 
b/drivers/gpu/drm/mediatek/mtk_gem.c
index a172456d1d7b..21e08fabfd7f 100644
--- a/drivers/gpu/drm/mediatek/mtk_gem.c
+++ b/drivers/gpu/drm/mediatek/mtk_gem.c
@@ -8,6 +8,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -124,15 +125,9 @@ int mtk_gem_dumb_create(struct drm_file *file_priv, struct 
drm_device *dev,
struct mtk_gem_obj *mtk_gem;
int ret;
 
-   args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
-
-   /*
-* Multiply 2 variables of different types,
-* for example: args->size = args->spacing * args->height;
-* may cause coverity issue with unintentional overflow.
-*/
-   args->size = args->pitch;
-   args->size *= args->height;
+   ret = drm_mode_size_dumb(dev, args, SZ_8, 0);
+   if (ret)
+   return ret;
 
mtk_gem = mtk_gem_create(dev, args->size, false);
if (IS_ERR(mtk_gem))
-- 
2.48.1



[PATCH v4 10/25] drm/imx/ipuv3: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. The hardware requires the framebuffer width to be a
multiple of 8. The scanline pitch has be large enough to support
this. Therefore compute the byte size of 8 pixels in the given color
mode and align the pitch accordingly.

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Philipp Zabel 
Cc: Philipp Zabel 
Cc: Shawn Guo 
Cc: Sascha Hauer 
Cc: Pengutronix Kernel Team 
Cc: Fabio Estevam 
---
 drivers/gpu/drm/imx/ipuv3/imx-drm-core.c | 31 ++--
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c 
b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
index e7025df7b978..465b5a6ad5bb 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
@@ -17,7 +17,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -141,19 +143,32 @@ static int imx_drm_dumb_create(struct drm_file *file_priv,
   struct drm_device *drm,
   struct drm_mode_create_dumb *args)
 {
-   u32 width = args->width;
+   u32 fourcc;
+   const struct drm_format_info *info;
+   u64 pitch_align;
int ret;
 
-   args->width = ALIGN(width, 8);
-   args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
-   args->size = args->pitch * args->height;
-
-   ret = drm_gem_dma_dumb_create(file_priv, drm, args);
+   /*
+* Hardware requires the framebuffer width to be aligned to
+* multiples of 8. The mode-setting code handles this, but
+* the buffer pitch has to be aligned as well. Set the pitch
+* alignment accordingly, so that the each scanline fits into
+* the allocated buffer.
+*/
+   fourcc = drm_driver_color_mode_format(drm, args->bpp);
+   if (fourcc == DRM_FORMAT_INVALID)
+   return -EINVAL;
+   info = drm_format_info(fourcc);
+   if (!info)
+   return -EINVAL;
+   pitch_align = drm_format_info_min_pitch(info, 0, SZ_8);
+   if (!pitch_align || pitch_align > U32_MAX)
+   return -EINVAL;
+   ret = drm_mode_size_dumb(drm, args, pitch_align, 0);
if (ret)
return ret;
 
-   args->width = width;
-   return ret;
+   return drm_gem_dma_dumb_create(file_priv, drm, args);
 }
 
 static const struct drm_driver imx_drm_driver = {
-- 
2.48.1



[PATCH v4 25/25] drm/xlnx: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch according to hardware requirements.

Signed-off-by: Thomas Zimmermann 
Cc: Laurent Pinchart 
Cc: Tomi Valkeinen 
---
 drivers/gpu/drm/xlnx/zynqmp_kms.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.c 
b/drivers/gpu/drm/xlnx/zynqmp_kms.c
index b47463473472..7ea0cd4f71d3 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_kms.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_kms.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -363,10 +364,12 @@ static int zynqmp_dpsub_dumb_create(struct drm_file 
*file_priv,
struct drm_mode_create_dumb *args)
 {
struct zynqmp_dpsub *dpsub = to_zynqmp_dpsub(drm);
-   unsigned int pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+   int ret;
 
/* Enforce the alignment constraints of the DMA engine. */
-   args->pitch = ALIGN(pitch, dpsub->dma_align);
+   ret = drm_mode_size_dumb(drm, args, dpsub->dma_align, 0);
+   if (ret)
+   return ret;
 
return drm_gem_dma_dumb_create_internal(file_priv, drm, args);
 }
-- 
2.48.1



[PATCH v4 20/25] drm/tegra: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch according to hardware requirements.

Signed-off-by: Thomas Zimmermann 
Acked-by: Thierry Reding 
Cc: Thierry Reding 
Cc: Mikko Perttunen 
---
 drivers/gpu/drm/tegra/gem.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index ace3e5a805cf..4d88e71192fb 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -16,6 +16,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 
@@ -543,12 +544,13 @@ void tegra_bo_free_object(struct drm_gem_object *gem)
 int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
 struct drm_mode_create_dumb *args)
 {
-   unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
struct tegra_drm *tegra = drm->dev_private;
struct tegra_bo *bo;
+   int ret;
 
-   args->pitch = round_up(min_pitch, tegra->pitch_align);
-   args->size = args->pitch * args->height;
+   ret = drm_mode_size_dumb(drm, args, tegra->pitch_align, 0);
+   if (ret)
+   return ret;
 
bo = tegra_bo_create_with_handle(file, drm, args->size, 0,
 &args->handle);
-- 
2.48.1



[PATCH v4 16/25] drm/qxl: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch
and buffer size. No alignment required.

Signed-off-by: Thomas Zimmermann 
Cc: Dave Airlie 
Cc: Gerd Hoffmann 
---
 drivers/gpu/drm/qxl/qxl_dumb.c | 17 -
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c
index 17df5c7ccf69..1200946767ce 100644
--- a/drivers/gpu/drm/qxl/qxl_dumb.c
+++ b/drivers/gpu/drm/qxl/qxl_dumb.c
@@ -23,6 +23,8 @@
  *  Alon Levy
  */
 
+#include 
+
 #include "qxl_drv.h"
 #include "qxl_object.h"
 
@@ -35,14 +37,13 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
struct qxl_device *qdev = to_qxl(dev);
struct qxl_bo *qobj;
struct drm_gem_object *gobj;
-   uint32_t handle;
int r;
struct qxl_surface surf;
-   uint32_t pitch, format;
+   u32 format;
 
-   pitch = args->width * ((args->bpp + 1) / 8);
-   args->size = pitch * args->height;
-   args->size = ALIGN(args->size, PAGE_SIZE);
+   r = drm_mode_size_dumb(dev, args, 0, 0);
+   if (r)
+   return r;
 
switch (args->bpp) {
case 16:
@@ -57,20 +58,18 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
 
surf.width = args->width;
surf.height = args->height;
-   surf.stride = pitch;
+   surf.stride = args->pitch;
surf.format = format;
surf.data = 0;
 
r = qxl_gem_object_create_with_handle(qdev, file_priv,
  QXL_GEM_DOMAIN_CPU,
  args->size, &surf, &gobj,
- &handle);
+ &args->handle);
if (r)
return r;
qobj = gem_to_qxl_bo(gobj);
qobj->is_dumb = true;
drm_gem_object_put(gobj);
-   args->pitch = pitch;
-   args->handle = handle;
return 0;
 }
-- 
2.48.1



Re: [PATCH v5 2/2] drm/msm/dp: reuse generic HDMI codec implementation

2025-03-11 Thread Dmitry Baryshkov
On Tue, Mar 11, 2025 at 09:41:13AM +0100, Maxime Ripard wrote:
> Hi,
> 
> On Mon, Mar 10, 2025 at 08:53:24PM +0200, Dmitry Baryshkov wrote:
> > On Mon, 10 Mar 2025 at 17:08, Maxime Ripard  wrote:
> > >
> > > On Fri, Mar 07, 2025 at 07:55:53AM +0200, Dmitry Baryshkov wrote:
> > > > From: Dmitry Baryshkov 
> > > >
> > > > The MSM DisplayPort driver implements several HDMI codec functions
> > > > in the driver, e.g. it manually manages HDMI codec device registration,
> > > > returning ELD and plugged_cb support. In order to reduce code
> > > > duplication reuse drm_hdmi_audio_* helpers and drm_bridge_connector
> > > > integration.
> > > >
> > > > Signed-off-by: Dmitry Baryshkov 
> > > > ---
> > > >  drivers/gpu/drm/msm/Kconfig |   1 +
> > > >  drivers/gpu/drm/msm/dp/dp_audio.c   | 131 
> > > > 
> > > >  drivers/gpu/drm/msm/dp/dp_audio.h   |  27 ++--
> > > >  drivers/gpu/drm/msm/dp/dp_display.c |  28 ++--
> > > >  drivers/gpu/drm/msm/dp/dp_display.h |   6 --
> > > >  drivers/gpu/drm/msm/dp/dp_drm.c |   8 +++
> > > >  6 files changed, 31 insertions(+), 170 deletions(-)
> > > >

[...]

> > > >
> > > >  static int msm_edp_bridge_atomic_check(struct drm_bridge *drm_bridge,
> > > > @@ -320,9 +324,13 @@ int msm_dp_bridge_init(struct msm_dp 
> > > > *msm_dp_display, struct drm_device *dev,
> > > >*/
> > > >   if (!msm_dp_display->is_edp) {
> > > >   bridge->ops =
> > > > + DRM_BRIDGE_OP_HDMI_AUDIO |
> > > >   DRM_BRIDGE_OP_DETECT |
> > > >   DRM_BRIDGE_OP_HPD |
> > > >   DRM_BRIDGE_OP_MODES;
> > > > + bridge->hdmi_audio_dev = &msm_dp_display->pdev->dev;
> > > > + bridge->hdmi_audio_max_i2s_playback_channels = 8;
> > > > + bridge->hdmi_audio_dai_port = -1;
> > > >   }
> > >
> > > I think I'd prefer the toggle to be OP_DP_AUDIO, even if the
> > > implementation is exactly the same. That way, we'll be able to condition
> > > it to the DP support when that arrives, and we have the latitude to
> > > rework it to accomodate some DP subtleties without affecting the drivers
> > > later on.
> > 
> > I don't think that there is a point in having OP_DP_AUDIO. There is
> > not so much difference in the driver. Also currently OP_HDMI_AUDIO
> > follows existing approach (which was pointed out by Laurent) - that
> > OP_foo should guard a particular set of callbacks. From this
> > perspective, OP_HDMI_AUDIO is fine - it guards usage of
> > hdmi_audio_foo(). OP_DP_AUDIO would duplicate that.
> 
> HDMI and DP are two competing standards, with different governing
> bodies. I don't think either have claimed that they will strictly adhere
> to what the other is doing, and I don't have the will to cross-check
> every given audio feature in both HDMI and DP right now.

Hmm. Currently (or before the first hdmi_audio patchset) everybody has
been plumbing hdmi-codec directly from the driver (even for DP audio).

> However, I think we should really have the flexibility to deal with that
> situation if it happens, and without having to do any major refactoring.
> That means providing an API that is consistent to the drivers, and
> provides what the driver needs. Here, it needs DP audio support, not
> HDMI's.

Would OP_HDMI_CODEC be a better name for the OP? (we can rename the
existing callbacks to be hdmi_codec instead of hdmi_audio too).

> How we plumb it is an implementation detail, and I do agree we can use
> the same functions under the hood right now. But the driver is a DP
> driver, it wants DP infrastructure and DP audio support.

Would OP_DP_AUDIO require a different set of callbacks on the bridge
level? I don't want to end up with too much of duplication. Maybe we
should the cdns bridges which implement both HDMI and DP functionality
IIRC.


-- 
With best wishes
Dmitry


Re: [PATCH v5 1/2] drm/bridge: split HDMI Audio from DRM_BRIDGE_OP_HDMI

2025-03-11 Thread Dmitry Baryshkov
On Tue, Mar 11, 2025 at 09:36:37AM +0100, Maxime Ripard wrote:
> On Mon, Mar 10, 2025 at 08:42:29PM +0200, Dmitry Baryshkov wrote:
> > On Mon, 10 Mar 2025 at 16:55, Maxime Ripard  wrote:
> > >
> > > Hi,
> > >
> > > On Fri, Mar 07, 2025 at 07:55:52AM +0200, Dmitry Baryshkov wrote:
> > > > From: Dmitry Baryshkov 
> > > >
> > > > As pointed out by Laurent, OP bits are supposed to describe operations.
> > > > Split DRM_BRIDGE_OP_HDMI_AUDIO from DRM_BRIDGE_OP_HDMI instead of
> > > > overloading DRM_BRIDGE_OP_HDMI.
> > > >
> > > > Signed-off-by: Dmitry Baryshkov 
> > > > ---
> > > >  drivers/gpu/drm/bridge/lontium-lt9611.c|  2 +-
> > > >  drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c   |  1 +
> > > >  drivers/gpu/drm/display/drm_bridge_connector.c | 59 
> > > > +-
> > > >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c |  1 +
> > > >  include/drm/drm_bridge.h   | 23 --
> > > >  5 files changed, 61 insertions(+), 25 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c 
> > > > b/drivers/gpu/drm/bridge/lontium-lt9611.c
> > > > index 
> > > > 026803034231f78c17f619dc04119bdd9b2b6679..3b93c17e25c18ae0d13e9bb74553cf21dcc39f9d
> > > >  100644
> > > > --- a/drivers/gpu/drm/bridge/lontium-lt9611.c
> > > > +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
> > > > @@ -1130,7 +1130,7 @@ static int lt9611_probe(struct i2c_client *client)
> > > >   lt9611->bridge.of_node = client->dev.of_node;
> > > >   lt9611->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
> > > >DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES |
> > > > -  DRM_BRIDGE_OP_HDMI;
> > > > +  DRM_BRIDGE_OP_HDMI | 
> > > > DRM_BRIDGE_OP_HDMI_AUDIO;
> > > >   lt9611->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
> > > >   lt9611->bridge.vendor = "Lontium";
> > > >   lt9611->bridge.product = "LT9611";
> > > > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c 
> > > > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> > > > index 
> > > > 6166f197e37b552cb8a52b7b0d23ffc632f54557..5e5f8c2f95be1f5c4633f1093b17a00f9425bb37
> > > >  100644
> > > > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> > > > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> > > > @@ -1077,6 +1077,7 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct 
> > > > platform_device *pdev,
> > > >   hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT |
> > > >  DRM_BRIDGE_OP_EDID |
> > > >  DRM_BRIDGE_OP_HDMI |
> > > > +DRM_BRIDGE_OP_HDMI_AUDIO |
> > > >  DRM_BRIDGE_OP_HPD;
> > > >   hdmi->bridge.of_node = pdev->dev.of_node;
> > > >   hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
> > > > diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c 
> > > > b/drivers/gpu/drm/display/drm_bridge_connector.c
> > > > index 
> > > > 30c736fc0067e31a97db242e5b16ea8a5b4cf359..030f98d454608a63154827c65d4822d378df3b4c
> > > >  100644
> > > > --- a/drivers/gpu/drm/display/drm_bridge_connector.c
> > > > +++ b/drivers/gpu/drm/display/drm_bridge_connector.c
> > > > @@ -98,6 +98,13 @@ struct drm_bridge_connector {
> > > >* HDMI connector infrastructure, if any (see 
> > > > &DRM_BRIDGE_OP_HDMI).
> > > >*/
> > > >   struct drm_bridge *bridge_hdmi;
> > > > + /**
> > > > +  * @bridge_hdmi_audio:
> > > > +  *
> > > > +  * The bridge in the chain that implements necessary support for 
> > > > the
> > > > +  * HDMI Audio infrastructure, if any (see 
> > > > &DRM_BRIDGE_OP_HDMI_AUDIO).
> > > > +  */
> > > > + struct drm_bridge *bridge_hdmi_audio;
> > > >  };
> > > >
> > > >  #define to_drm_bridge_connector(x) \
> > > > @@ -433,7 +440,7 @@ static int 
> > > > drm_bridge_connector_audio_startup(struct drm_connector *connector)
> > > >   to_drm_bridge_connector(connector);
> > > >   struct drm_bridge *bridge;
> > > >
> > > > - bridge = bridge_connector->bridge_hdmi;
> > > > + bridge = bridge_connector->bridge_hdmi_audio;
> > > >   if (!bridge)
> > > >   return -EINVAL;
> > > >
> > > > @@ -451,7 +458,7 @@ static int 
> > > > drm_bridge_connector_audio_prepare(struct drm_connector *connector,
> > > >   to_drm_bridge_connector(connector);
> > > >   struct drm_bridge *bridge;
> > > >
> > > > - bridge = bridge_connector->bridge_hdmi;
> > > > + bridge = bridge_connector->bridge_hdmi_audio;
> > > >   if (!bridge)
> > > >   return -EINVAL;
> > > >
> > > > @@ -464,7 +471,7 @@ static void 
> > > > drm_bridge_connector_audio_shutdown(struct drm_connector *connector)
> > > >   to_drm_bridge_connector(connector);
> > > >   struct drm_bridge *bridge;
> > > >
> > > > - bridge = bridge_connector->bridge_hdmi;
> > > > + bridge = bridge_connector->bridge_hdmi_audio;
> > > >   if (!bridge)
> > > >   return;
> 

Re: [PATCH v2 06/10] arm64: dts: qcom: sa8775p: add Display Serial Interface device nodes

2025-03-11 Thread Dmitry Baryshkov
On Tue, Mar 11, 2025 at 05:54:41PM +0530, Ayushi Makhija wrote:
> Add device tree nodes for the DSI0 and DSI1 controllers
> with their corresponding PHYs found on Qualcomm SA8775P SoC.
> 
> Signed-off-by: Ayushi Makhija 
> ---
>  arch/arm64/boot/dts/qcom/sa8775p.dtsi | 186 +-
>  1 file changed, 185 insertions(+), 1 deletion(-)
> 

Reviewed-by: Dmitry Baryshkov 

-- 
With best wishes
Dmitry


Re: [PATCH v2 08/10] drm/bridge: anx7625: enable HPD interrupts

2025-03-11 Thread Dmitry Baryshkov
On Tue, Mar 11, 2025 at 05:54:43PM +0530, Ayushi Makhija wrote:
> When device enters the suspend state, it prevents
> HPD interrupts from occurring. To address this,
> add an additional PM runtime vote in hpd_enable().
> This vote is removed in hpd_disable().

Is it really enough to toggle the HPD interrupts? Is there any kind of
programming that should be moved to .hpd_enable() too (so that by
default the bridge doesn't generate HPD interrupts)?

> 
> Signed-off-by: Ayushi Makhija 
> ---
>  drivers/gpu/drm/bridge/analogix/anx7625.c | 18 ++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
> b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index 4be34d5c7a3b..764da1c1dc11 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -2474,6 +2474,22 @@ static const struct drm_edid 
> *anx7625_bridge_edid_read(struct drm_bridge *bridge
>   return anx7625_edid_read(ctx);
>  }
>  
> +static void anx7625_bridge_hpd_enable(struct drm_bridge *bridge)
> +{
> + struct anx7625_data *ctx = bridge_to_anx7625(bridge);
> + struct device *dev = ctx->dev;
> +
> + pm_runtime_get_sync(dev);
> +}
> +
> +static void anx7625_bridge_hpd_disable(struct drm_bridge *bridge)
> +{
> + struct anx7625_data *ctx = bridge_to_anx7625(bridge);
> + struct device *dev = ctx->dev;
> +
> + pm_runtime_put_sync(dev);
> +}
> +
>  static const struct drm_bridge_funcs anx7625_bridge_funcs = {
>   .attach = anx7625_bridge_attach,
>   .detach = anx7625_bridge_detach,
> @@ -2487,6 +2503,8 @@ static const struct drm_bridge_funcs 
> anx7625_bridge_funcs = {
>   .atomic_reset = drm_atomic_helper_bridge_reset,
>   .detect = anx7625_bridge_detect,
>   .edid_read = anx7625_bridge_edid_read,
> + .hpd_enable = anx7625_bridge_hpd_enable,
> + .hpd_disable = anx7625_bridge_hpd_disable,
>  };
>  
>  static int anx7625_register_i2c_dummy_clients(struct anx7625_data *ctx,
> -- 
> 2.34.1
> 

-- 
With best wishes
Dmitry


Re: [PATCH v2 04/10] drm/msm/dsi: add DSI PHY configuration on SA8775P

2025-03-11 Thread Dmitry Baryshkov
On Tue, Mar 11, 2025 at 05:54:39PM +0530, Ayushi Makhija wrote:
> The SA8775P SoC uses the 5nm (v4.2) DSI PHY driver with
> different enable regulator load.
> 
> Signed-off-by: Ayushi Makhija 
> ---
>  drivers/gpu/drm/msm/dsi/phy/dsi_phy.c |  2 ++
>  drivers/gpu/drm/msm/dsi/phy/dsi_phy.h |  1 +
>  drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 27 +++
>  3 files changed, 30 insertions(+)
> 

Reviewed-by: Dmitry Baryshkov 

-- 
With best wishes
Dmitry


Re: [PATCH v2 05/10] drm/msm/dsi: add DSI support for SA8775P

2025-03-11 Thread Dmitry Baryshkov
On Tue, Mar 11, 2025 at 05:54:40PM +0530, Ayushi Makhija wrote:
> Add DSI Controller v2.5.1 support for SA8775P SoC.
> 
> Signed-off-by: Ayushi Makhija 
> ---
>  drivers/gpu/drm/msm/dsi/dsi_cfg.c | 18 ++
>  drivers/gpu/drm/msm/dsi/dsi_cfg.h |  1 +
>  2 files changed, 19 insertions(+)
> 

Reviewed-by: Dmitry Baryshkov 

-- 
With best wishes
Dmitry


[bug report] drm/msm/a6xx: Introduce GMU wrapper support

2025-03-11 Thread Dan Carpenter
Hello Konrad Dybcio,

Commit 5a903a44a984 ("drm/msm/a6xx: Introduce GMU wrapper support")
from Jun 16, 2023 (linux-next), leads to the following Smatch static
checker warning:

drivers/gpu/drm/msm/adreno/a6xx_gmu.c:1844 a6xx_gmu_wrapper_init()
warn: 'gmu->cxpd' can also be NULL

drivers/gpu/drm/msm/adreno/a6xx_gmu.c
1790 int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct 
device_node *node)
1791 {
1792 struct platform_device *pdev = of_find_device_by_node(node);
1793 struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
1794 int ret;
1795 
1796 if (!pdev)
1797 return -ENODEV;
1798 
1799 gmu->dev = &pdev->dev;
1800 
1801 ret = of_dma_configure(gmu->dev, node, true);
1802 if (ret)
1803 return ret;
1804 
1805 pm_runtime_enable(gmu->dev);
1806 
1807 /* Mark legacy for manual SPTPRAC control */
1808 gmu->legacy = true;
1809 
1810 /* Map the GMU registers */
1811 gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");
1812 if (IS_ERR(gmu->mmio)) {
1813 ret = PTR_ERR(gmu->mmio);
1814 goto err_mmio;
1815 }
1816 
1817 gmu->cxpd = dev_pm_domain_attach_by_name(gmu->dev, "cx");

dev_pm_domain_attach_by_name() sure seemse like it can return NULL.

1818 if (IS_ERR(gmu->cxpd)) {
1819 ret = PTR_ERR(gmu->cxpd);
1820 goto err_mmio;
1821 }
1822 
1823 if (!device_link_add(gmu->dev, gmu->cxpd, DL_FLAG_PM_RUNTIME)) 
{

If it did then device_link_add() then this would fail

1824 ret = -ENODEV;
1825 goto detach_cxpd;
1826 }
1827 
1828 init_completion(&gmu->pd_gate);
1829 complete_all(&gmu->pd_gate);
1830 gmu->pd_nb.notifier_call = cxpd_notifier_cb;
1831 
1832 /* Get a link to the GX power domain to reset the GPU */
1833 gmu->gxpd = dev_pm_domain_attach_by_name(gmu->dev, "gx");
1834 if (IS_ERR(gmu->gxpd)) {
1835 ret = PTR_ERR(gmu->gxpd);
1836 goto err_mmio;
1837 }
1838 
1839 gmu->initialized = true;
1840 
1841 return 0;
1842 
1843 detach_cxpd:
--> 1844 dev_pm_domain_detach(gmu->cxpd, false);
  ^
And this would crash.

1845 
1846 err_mmio:
1847 iounmap(gmu->mmio);
1848 
1849 /* Drop reference taken in of_find_device_by_node */
1850 put_device(gmu->dev);
1851 
1852 return ret;
1853 }

regards,
dan carpenter


[PATCH v4 00/25] drm/dumb-buffers: Fix and improve buffer-size calculation

2025-03-11 Thread Thomas Zimmermann
Dumb-buffer pitch and size is specified by width, height, bits-per-pixel
plus various hardware-specific alignments. The calculation of these
values is inconsistent and duplicated among drivers. The results for
formats with bpp < 8 are sometimes incorrect.

This series fixes this for most drivers. Default scanline pitch and
buffer size are now calculated with the existing 4CC helpers. There is
a new helper drm_mode_size_dumb() that calculates scanline pitch and
buffer size according to driver requirements.

The series fixes the common GEM implementations for DMA, SHMEM and
VRAM. It further changes most implementations of dumb_create to use
the new helper. A small number of drivers has more complicated
calculations and will be updated by a later patches.

v4:
- improve UAPI documentation
- document bpp special cases
- use drm_warn_once()
- add TODO lists
- armada: fix pitch alignment
v3:
- document UAPI semantics
- fall back to bpp-based allocation for unknown color modes
- cleanups
v2:
- rewrite series
- convert many individual drivers besides the shared GEM helpers

Thomas Zimmermann (25):
  drm/dumb-buffers: Sanitize output on errors
  drm/dumb-buffers: Provide helper to set pitch and size
  drm/gem-dma: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/gem-shmem: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/gem-vram: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/armada: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/exynos: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/gma500: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/hibmc: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/imx/ipuv3: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/loongson: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/mediatek: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/msm: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/nouveau: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/omapdrm: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/qxl: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/renesas/rcar-du: Compute dumb-buffer sizes with
drm_mode_size_dumb()
  drm/renesas/rz-du: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/rockchip: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/tegra: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/virtio: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/vmwgfx: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/xe: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/xen: Compute dumb-buffer sizes with drm_mode_size_dumb()
  drm/xlnx: Compute dumb-buffer sizes with drm_mode_size_dumb()

 Documentation/gpu/todo.rst|  28 +++
 drivers/gpu/drm/armada/armada_gem.c   |  16 +-
 drivers/gpu/drm/drm_dumb_buffers.c| 172 --
 drivers/gpu/drm/drm_gem_dma_helper.c  |   7 +-
 drivers/gpu/drm/drm_gem_shmem_helper.c|  16 +-
 drivers/gpu/drm/drm_gem_vram_helper.c |  89 +++--
 drivers/gpu/drm/exynos/exynos_drm_gem.c   |   8 +-
 drivers/gpu/drm/gma500/gem.c  |  21 +--
 .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   |  25 ++-
 drivers/gpu/drm/imx/ipuv3/imx-drm-core.c  |  29 ++-
 drivers/gpu/drm/loongson/lsdc_gem.c   |  29 +--
 drivers/gpu/drm/mediatek/mtk_gem.c|  13 +-
 drivers/gpu/drm/msm/msm_gem.c |  27 ++-
 drivers/gpu/drm/nouveau/nouveau_display.c |   7 +-
 drivers/gpu/drm/omapdrm/omap_gem.c|  15 +-
 drivers/gpu/drm/qxl/qxl_dumb.c|  17 +-
 drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c |   7 +-
 drivers/gpu/drm/renesas/rz-du/rzg2l_du_kms.c  |   7 +-
 drivers/gpu/drm/rockchip/rockchip_drm_gem.c   |  12 +-
 drivers/gpu/drm/tegra/gem.c   |   8 +-
 drivers/gpu/drm/virtio/virtgpu_gem.c  |  11 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_surface.c   |  21 +--
 drivers/gpu/drm/xe/xe_bo.c|   8 +-
 drivers/gpu/drm/xen/xen_drm_front.c   |   7 +-
 drivers/gpu/drm/xlnx/zynqmp_kms.c |   7 +-
 include/drm/drm_dumb_buffers.h|  14 ++
 include/drm/drm_gem_vram_helper.h |   6 -
 include/uapi/drm/drm_mode.h   |  50 -
 28 files changed, 449 insertions(+), 228 deletions(-)
 create mode 100644 include/drm/drm_dumb_buffers.h

-- 
2.48.1



[PATCH v4 02/25] drm/dumb-buffers: Provide helper to set pitch and size

2025-03-11 Thread Thomas Zimmermann
Add drm_modes_size_dumb(), a helper to calculate the dumb-buffer
scanline pitch and allocation size. Implementations of struct
drm_driver.dumb_create can call the new helper for their size
computations.

There is currently quite a bit of code duplication among DRM's
memory managers. Each calculates scanline pitch and buffer size
from the given arguments, but the implementations are inconsistent
in how they treat alignment and format support. Later patches will
unify this code on top of drm_mode_size_dumb() as much as possible.

drm_mode_size_dumb() uses existing 4CC format helpers to interpret
the given color mode. This makes the dumb-buffer interface behave
similar the kernel's video= parameter. Current per-driver implementations
again likely have subtle differences or bugs in how they support color
modes.

The dumb-buffer UAPI is only specified for known color modes. These
values describe linear, single-plane RGB color formats or legacy index
formats. Other values should not be specified. But some user space
still does. So for unknown color modes, there are a number of known
exceptions for which drm_mode_size_dumb() calculates the pitch from
the bpp value, as before. All other values work the same but print
an error.

v4:
- use %u conversion specifier (Geert)
- list DRM_FORMAT_Dn in UAPI docs (Geert)
- avoid dmesg spamming with drm_warn_once() (Sima)
- add more information about bpp special case (Sima)
- clarify parameters for hardware alignment
- add a TODO item for DUMB_CREATE2
v3:
- document the UAPI semantics
- compute scanline pitch from for unknown color modes (Andy, Tomi)

Signed-off-by: Thomas Zimmermann 
---
 Documentation/gpu/todo.rst |  28 ++
 drivers/gpu/drm/drm_dumb_buffers.c | 132 +
 include/drm/drm_dumb_buffers.h |  14 +++
 include/uapi/drm/drm_mode.h|  50 ++-
 4 files changed, 223 insertions(+), 1 deletion(-)
 create mode 100644 include/drm/drm_dumb_buffers.h

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index c5a24e03..f1bd741b06dc 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -515,6 +515,34 @@ Contact: Douglas Anderson 
 
 Level: Starter
 
+Implement a new DUMB_CREATE2 ioctl
+--
+
+The current DUMB_CREATE ioctl is not well defined. Instead of a pixel and
+framebuffer format, it only accepts a color mode of vague semantics. Assuming
+a linear framebuffer, the color mode gives and idea of the supported pixel
+format. But userspace effectively has to guess the correct values. It really
+only works reliable with framebuffers in XRGB. Userspace has begun to
+workaround these limitations by computing arbitrary format's buffer sizes and
+calculating their sizes in terms of XRGB pixels.
+
+One possible solution is a new ioctl DUMB_CREATE2. It should accept a DRM
+format and a format modifier to resolve the color mode's ambiguity. As
+framebuffers can be multi-planar, the new ioctl has to return the buffer size,
+pitch and GEM handle for each individual color plane.
+
+In the first step, the new ioctl can be limited to the current features of
+the existing DUMB_CREATE. Individual drivers can then be extended to support
+multi-planar formats. Rockchip might require this and would be a good 
candidate.
+
+In addition to the kernel implementation, there must be user-space support
+for the new ioctl. There's code in Mesa that might be able to use the new
+call.
+
+Contact: Thomas Zimmermann 
+
+Level: Advanced
+
 
 Core refactorings
 =
diff --git a/drivers/gpu/drm/drm_dumb_buffers.c 
b/drivers/gpu/drm/drm_dumb_buffers.c
index 9916aaf5b3f2..97cd3dcb79f1 100644
--- a/drivers/gpu/drm/drm_dumb_buffers.c
+++ b/drivers/gpu/drm/drm_dumb_buffers.c
@@ -25,6 +25,8 @@
 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 
@@ -57,6 +59,136 @@
  * a hardware-specific ioctl to allocate suitable buffer objects.
  */
 
+static int drm_mode_align_dumb(struct drm_mode_create_dumb *args,
+  unsigned long hw_pitch_align,
+  unsigned long hw_size_align)
+{
+   u32 pitch = args->pitch;
+   u32 size;
+
+   if (!pitch)
+   return -EINVAL;
+
+   if (hw_pitch_align)
+   pitch = roundup(pitch, hw_pitch_align);
+
+   /* overflow checks for 32bit size calculations */
+   if (args->height > U32_MAX / pitch)
+   return -EINVAL;
+
+   if (!hw_size_align)
+   hw_size_align = PAGE_SIZE;
+   else if (!IS_ALIGNED(hw_size_align, PAGE_SIZE))
+   return -EINVAL; /* TODO: handle this if necessary */
+
+   size = ALIGN(args->height * pitch, hw_size_align);
+   if (!size)
+   return -EINVAL;
+
+   args->pitch = pitch;
+   args->size = size;
+
+   return 0;
+}
+
+/**
+ * drm_mode_size_dumb - Calculates the scanline and buffer sizes for dumb 
buffers
+ * @dev: DRM device
+ * @args

[PATCH v4 01/25] drm/dumb-buffers: Sanitize output on errors

2025-03-11 Thread Thomas Zimmermann
The ioctls MODE_CREATE_DUMB and MODE_MAP_DUMB return results into a
memory buffer supplied by user space. On errors, it is possible that
intermediate values are being returned. The exact semantics depends
on the DRM driver's implementation of these ioctls. Although this is
most-likely not a security problem in practice, avoid any uncertainty
by clearing the memory to 0 on errors.

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/drm_dumb_buffers.c | 40 ++
 1 file changed, 29 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_dumb_buffers.c 
b/drivers/gpu/drm/drm_dumb_buffers.c
index 70032bba1c97..9916aaf5b3f2 100644
--- a/drivers/gpu/drm/drm_dumb_buffers.c
+++ b/drivers/gpu/drm/drm_dumb_buffers.c
@@ -99,7 +99,30 @@ int drm_mode_create_dumb(struct drm_device *dev,
 int drm_mode_create_dumb_ioctl(struct drm_device *dev,
   void *data, struct drm_file *file_priv)
 {
-   return drm_mode_create_dumb(dev, data, file_priv);
+   struct drm_mode_create_dumb *args = data;
+   int err;
+
+   err = drm_mode_create_dumb(dev, args, file_priv);
+   if (err) {
+   args->handle = 0;
+   args->pitch = 0;
+   args->size = 0;
+   }
+   return err;
+}
+
+static int drm_mode_mmap_dumb(struct drm_device *dev, struct drm_mode_map_dumb 
*args,
+ struct drm_file *file_priv)
+{
+   if (!dev->driver->dumb_create)
+   return -ENOSYS;
+
+   if (dev->driver->dumb_map_offset)
+   return dev->driver->dumb_map_offset(file_priv, dev, 
args->handle,
+   &args->offset);
+   else
+   return drm_gem_dumb_map_offset(file_priv, dev, args->handle,
+  &args->offset);
 }
 
 /**
@@ -120,17 +143,12 @@ int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
 void *data, struct drm_file *file_priv)
 {
struct drm_mode_map_dumb *args = data;
+   int err;
 
-   if (!dev->driver->dumb_create)
-   return -ENOSYS;
-
-   if (dev->driver->dumb_map_offset)
-   return dev->driver->dumb_map_offset(file_priv, dev,
-   args->handle,
-   &args->offset);
-   else
-   return drm_gem_dumb_map_offset(file_priv, dev, args->handle,
-  &args->offset);
+   err = drm_mode_mmap_dumb(dev, args, file_priv);
+   if (err)
+   args->offset = 0;
+   return err;
 }
 
 int drm_mode_destroy_dumb(struct drm_device *dev, u32 handle,
-- 
2.48.1



[PATCH v4 07/25] drm/exynos: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. No alignment required.

Signed-off-by: Thomas Zimmermann 
Cc: Inki Dae 
Cc: Seung-Woo Kim 
Cc: Kyungmin Park 
Cc: Krzysztof Kozlowski 
Cc: Alim Akhtar 
---
 drivers/gpu/drm/exynos/exynos_drm_gem.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c 
b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 4787fee4696f..ffa1c02b4b1e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -330,15 +331,16 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
unsigned int flags;
int ret;
 
+   ret = drm_mode_size_dumb(dev, args, 0, 0);
+   if (ret)
+   return ret;
+
/*
 * allocate memory to be used for framebuffer.
 * - this callback would be called by user application
 *  with DRM_IOCTL_MODE_CREATE_DUMB command.
 */
 
-   args->pitch = args->width * ((args->bpp + 7) / 8);
-   args->size = args->pitch * args->height;
-
if (is_drm_iommu_supported(dev))
flags = EXYNOS_BO_NONCONTIG | EXYNOS_BO_WC;
else
-- 
2.48.1



[PATCH v4 13/25] drm/msm: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch
and buffer size. Alignment is specified in bytes, but the hardware
requires the scanline pitch to be a multiple of 32 pixels. Therefore
compute the byte size of 32 pixels in the given color mode and align
the pitch accordingly. This replaces the existing code in the driver's
align_pitch() helper.

v3:
- clarify pitch alignment in commit message (Dmitry)

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Dmitry Baryshkov 
Cc: Rob Clark 
Cc: Abhinav Kumar 
Cc: Dmitry Baryshkov 
Cc: Sean Paul 
Cc: Marijn Suijten 
---
 drivers/gpu/drm/msm/msm_gem.c | 27 +--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index ebc9ba66efb8..a956905f1ef2 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -11,8 +11,10 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -700,8 +702,29 @@ void msm_gem_unpin_iova(struct drm_gem_object *obj,
 int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
struct drm_mode_create_dumb *args)
 {
-   args->pitch = align_pitch(args->width, args->bpp);
-   args->size  = PAGE_ALIGN(args->pitch * args->height);
+   u32 fourcc;
+   const struct drm_format_info *info;
+   u64 pitch_align;
+   int ret;
+
+   /*
+* Adreno needs pitch aligned to 32 pixels. Compute the number
+* of bytes for a block of 32 pixels at the given color format.
+* Use the result as pitch alignment.
+*/
+   fourcc = drm_driver_color_mode_format(dev, args->bpp);
+   if (fourcc == DRM_FORMAT_INVALID)
+   return -EINVAL;
+   info = drm_format_info(fourcc);
+   if (!info)
+   return -EINVAL;
+   pitch_align = drm_format_info_min_pitch(info, 0, SZ_32);
+   if (!pitch_align || pitch_align > U32_MAX)
+   return -EINVAL;
+   ret = drm_mode_size_dumb(dev, args, pitch_align, 0);
+   if (ret)
+   return ret;
+
return msm_gem_new_handle(dev, file, args->size,
MSM_BO_SCANOUT | MSM_BO_WC, &args->handle, "dumb");
 }
-- 
2.48.1



[PATCH v4 14/25] drm/nouveau: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch to a multiple of 256.

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Lyude Paul 
Cc: Karol Herbst 
Cc: Lyude Paul 
Cc: Danilo Krummrich 
---
 drivers/gpu/drm/nouveau/nouveau_display.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c
index add006fc8d81..daa2528f9c9a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -808,9 +809,9 @@ nouveau_display_dumb_create(struct drm_file *file_priv, 
struct drm_device *dev,
uint32_t domain;
int ret;
 
-   args->pitch = roundup(args->width * (args->bpp / 8), 256);
-   args->size = args->pitch * args->height;
-   args->size = roundup(args->size, PAGE_SIZE);
+   ret = drm_mode_size_dumb(dev, args, SZ_256, 0);
+   if (ret)
+   return ret;
 
/* Use VRAM if there is any ; otherwise fallback to system memory */
if (nouveau_drm(dev)->client.device.info.ram_size != 0)
-- 
2.48.1



[PATCH v4 09/25] drm/hibmc: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch to a multiple of 128.

The hibmc driver's new hibmc_dumb_create() is similar to the one
in GEM VRAM helpers. The driver was the only caller of
drm_gem_vram_fill_create_dumb(). Remove the now unused helper.

Signed-off-by: Thomas Zimmermann 
Cc: Xinliang Liu 
Cc: Tian Tao 
Cc: Xinwei Kong 
Cc: Sumit Semwal 
Cc: Yongqin Liu 
Cc: John Stultz 
---
 drivers/gpu/drm/drm_gem_vram_helper.c | 65 ---
 .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 25 ++-
 include/drm/drm_gem_vram_helper.h |  6 --
 3 files changed, 24 insertions(+), 72 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c 
b/drivers/gpu/drm/drm_gem_vram_helper.c
index 15cd564cbeac..b4cf8134df6d 100644
--- a/drivers/gpu/drm/drm_gem_vram_helper.c
+++ b/drivers/gpu/drm/drm_gem_vram_helper.c
@@ -444,71 +444,6 @@ void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo,
 }
 EXPORT_SYMBOL(drm_gem_vram_vunmap);
 
-/**
- * drm_gem_vram_fill_create_dumb() - Helper for implementing
- *  &struct drm_driver.dumb_create
- *
- * @file:  the DRM file
- * @dev:   the DRM device
- * @pg_align:  the buffer's alignment in multiples of the page size
- * @pitch_align:   the scanline's alignment in powers of 2
- * @args:  the arguments as provided to
- * &struct drm_driver.dumb_create
- *
- * This helper function fills &struct drm_mode_create_dumb, which is used
- * by &struct drm_driver.dumb_create. Implementations of this interface
- * should forwards their arguments to this helper, plus the driver-specific
- * parameters.
- *
- * Returns:
- * 0 on success, or
- * a negative error code otherwise.
- */
-int drm_gem_vram_fill_create_dumb(struct drm_file *file,
- struct drm_device *dev,
- unsigned long pg_align,
- unsigned long pitch_align,
- struct drm_mode_create_dumb *args)
-{
-   size_t pitch, size;
-   struct drm_gem_vram_object *gbo;
-   int ret;
-   u32 handle;
-
-   pitch = args->width * DIV_ROUND_UP(args->bpp, 8);
-   if (pitch_align) {
-   if (WARN_ON_ONCE(!is_power_of_2(pitch_align)))
-   return -EINVAL;
-   pitch = ALIGN(pitch, pitch_align);
-   }
-   size = pitch * args->height;
-
-   size = roundup(size, PAGE_SIZE);
-   if (!size)
-   return -EINVAL;
-
-   gbo = drm_gem_vram_create(dev, size, pg_align);
-   if (IS_ERR(gbo))
-   return PTR_ERR(gbo);
-
-   ret = drm_gem_handle_create(file, &gbo->bo.base, &handle);
-   if (ret)
-   goto err_drm_gem_object_put;
-
-   drm_gem_object_put(&gbo->bo.base);
-
-   args->pitch = pitch;
-   args->size = size;
-   args->handle = handle;
-
-   return 0;
-
-err_drm_gem_object_put:
-   drm_gem_object_put(&gbo->bo.base);
-   return ret;
-}
-EXPORT_SYMBOL(drm_gem_vram_fill_create_dumb);
-
 /*
  * Helpers for struct ttm_device_funcs
  */
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c 
b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index e6de6d5edf6b..81768577871f 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -18,10 +18,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -54,7 +56,28 @@ static irqreturn_t hibmc_interrupt(int irq, void *arg)
 static int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
 struct drm_mode_create_dumb *args)
 {
-   return drm_gem_vram_fill_create_dumb(file, dev, 0, 128, args);
+   struct drm_gem_vram_object *gbo;
+   int ret;
+
+   ret = drm_mode_size_dumb(dev, args, SZ_128, 0);
+   if (ret)
+   return ret;
+
+   gbo = drm_gem_vram_create(dev, args->size, 0);
+   if (IS_ERR(gbo))
+   return PTR_ERR(gbo);
+
+   ret = drm_gem_handle_create(file, &gbo->bo.base, &args->handle);
+   if (ret)
+   goto err_drm_gem_object_put;
+
+   drm_gem_object_put(&gbo->bo.base);
+
+   return 0;
+
+err_drm_gem_object_put:
+   drm_gem_object_put(&gbo->bo.base);
+   return ret;
 }
 
 static const struct drm_driver hibmc_driver = {
diff --git a/include/drm/drm_gem_vram_helper.h 
b/include/drm/drm_gem_vram_helper.h
index 00830b49a3ff..b6e821f5dd03 100644
--- a/include/drm/drm_gem_vram_helper.h
+++ b/include/drm/drm_gem_vram_helper.h
@@ -100,12 +100,6 @@ int drm_gem_vram_vmap(struct drm_gem_vram_object *gbo, 
struct iosys_map *map);
 void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo,
 struct iosys_map *map);
 
-int drm_gem_vram_fill_create_dumb(struct drm_file *file,
-   

[PATCH v4 11/25] drm/loongson: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch according to hardware requirements.

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Sui Jingfeng 
Cc: Sui Jingfeng 
---
 drivers/gpu/drm/loongson/lsdc_gem.c | 29 -
 1 file changed, 8 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/loongson/lsdc_gem.c 
b/drivers/gpu/drm/loongson/lsdc_gem.c
index a720d8f53209..9f982b85301f 100644
--- a/drivers/gpu/drm/loongson/lsdc_gem.c
+++ b/drivers/gpu/drm/loongson/lsdc_gem.c
@@ -6,6 +6,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -204,45 +205,31 @@ int lsdc_dumb_create(struct drm_file *file, struct 
drm_device *ddev,
const struct lsdc_desc *descp = ldev->descp;
u32 domain = LSDC_GEM_DOMAIN_VRAM;
struct drm_gem_object *gobj;
-   size_t size;
-   u32 pitch;
-   u32 handle;
int ret;
 
-   if (!args->width || !args->height)
-   return -EINVAL;
-
-   if (args->bpp != 32 && args->bpp != 16)
-   return -EINVAL;
-
-   pitch = args->width * args->bpp / 8;
-   pitch = ALIGN(pitch, descp->pitch_align);
-   size = pitch * args->height;
-   size = ALIGN(size, PAGE_SIZE);
+   ret = drm_mode_size_dumb(ddev, args, descp->pitch_align, 0);
+   if (ret)
+   return ret;
 
/* Maximum single bo size allowed is the half vram size available */
-   if (size > ldev->vram_size / 2) {
-   drm_err(ddev, "Requesting(%zuMiB) failed\n", size >> 20);
+   if (args->size > ldev->vram_size / 2) {
+   drm_err(ddev, "Requesting(%zuMiB) failed\n", 
(size_t)(args->size >> PAGE_SHIFT));
return -ENOMEM;
}
 
-   gobj = lsdc_gem_object_create(ddev, domain, size, false, NULL, NULL);
+   gobj = lsdc_gem_object_create(ddev, domain, args->size, false, NULL, 
NULL);
if (IS_ERR(gobj)) {
drm_err(ddev, "Failed to create gem object\n");
return PTR_ERR(gobj);
}
 
-   ret = drm_gem_handle_create(file, gobj, &handle);
+   ret = drm_gem_handle_create(file, gobj, &args->handle);
 
/* drop reference from allocate, handle holds it now */
drm_gem_object_put(gobj);
if (ret)
return ret;
 
-   args->pitch = pitch;
-   args->size = size;
-   args->handle = handle;
-
return 0;
 }
 
-- 
2.48.1



[PATCH v4 05/25] drm/gem-vram: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Inline code from drm_gem_vram_fill_create_dumb() without
the existing size computation. Align the pitch to a multiple of 8.

Only hibmc and vboxvideo use gem-vram. Hibmc invokes the call to
drm_gem_vram_fill_create_dumb() directly and is therefore not affected.

Signed-off-by: Thomas Zimmermann 
---
 drivers/gpu/drm/drm_gem_vram_helper.c | 24 +++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c 
b/drivers/gpu/drm/drm_gem_vram_helper.c
index 22b1fe9c03b8..15cd564cbeac 100644
--- a/drivers/gpu/drm/drm_gem_vram_helper.c
+++ b/drivers/gpu/drm/drm_gem_vram_helper.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -582,10 +583,31 @@ int drm_gem_vram_driver_dumb_create(struct drm_file *file,
struct drm_device *dev,
struct drm_mode_create_dumb *args)
 {
+   struct drm_gem_vram_object *gbo;
+   int ret;
+
if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
return -EINVAL;
 
-   return drm_gem_vram_fill_create_dumb(file, dev, 0, 0, args);
+   ret = drm_mode_size_dumb(dev, args, SZ_8, 0);
+   if (ret)
+   return ret;
+
+   gbo = drm_gem_vram_create(dev, args->size, 0);
+   if (IS_ERR(gbo))
+   return PTR_ERR(gbo);
+
+   ret = drm_gem_handle_create(file, &gbo->bo.base, &args->handle);
+   if (ret)
+   goto err_drm_gem_object_put;
+
+   drm_gem_object_put(&gbo->bo.base);
+
+   return 0;
+
+err_drm_gem_object_put:
+   drm_gem_object_put(&gbo->bo.base);
+   return ret;
 }
 EXPORT_SYMBOL(drm_gem_vram_driver_dumb_create);
 
-- 
2.48.1



[PATCH v4 06/25] drm/armada: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch to a multiple of 128.

v4:
- align pitch to 128 bytes (Russell)

Signed-off-by: Thomas Zimmermann 
Cc: Russell King 
---
 drivers/gpu/drm/armada/armada_gem.c | 16 +++-
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_gem.c 
b/drivers/gpu/drm/armada/armada_gem.c
index 1a1680d71486..a767c4edd5c8 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -9,6 +9,7 @@
 #include 
 
 #include 
+#include 
 #include 
 
 #include "armada_drm.h"
@@ -244,14 +245,13 @@ int armada_gem_dumb_create(struct drm_file *file, struct 
drm_device *dev,
struct drm_mode_create_dumb *args)
 {
struct armada_gem_object *dobj;
-   u32 handle;
-   size_t size;
int ret;
 
-   args->pitch = armada_pitch(args->width, args->bpp);
-   args->size = size = args->pitch * args->height;
+   ret = drm_mode_size_dumb(dev, args, SZ_128, 0);
+   if (ret)
+   return ret;
 
-   dobj = armada_gem_alloc_private_object(dev, size);
+   dobj = armada_gem_alloc_private_object(dev, args->size);
if (dobj == NULL)
return -ENOMEM;
 
@@ -259,14 +259,12 @@ int armada_gem_dumb_create(struct drm_file *file, struct 
drm_device *dev,
if (ret)
goto err;
 
-   ret = drm_gem_handle_create(file, &dobj->obj, &handle);
+   ret = drm_gem_handle_create(file, &dobj->obj, &args->handle);
if (ret)
goto err;
 
-   args->handle = handle;
-
/* drop reference from allocate - handle holds it now */
-   DRM_DEBUG_DRIVER("obj %p size %zu handle %#x\n", dobj, size, handle);
+   DRM_DEBUG_DRIVER("obj %p size %llu handle %#x\n", dobj, args->size, 
args->handle);
  err:
drm_gem_object_put(&dobj->obj);
return ret;
-- 
2.48.1



[PATCH v4 08/25] drm/gma500: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch to a multiple of 64.

Signed-off-by: Thomas Zimmermann 
Cc: Patrik Jakobsson 
---
 drivers/gpu/drm/gma500/gem.c | 21 ++---
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c
index 4b7627a72637..fc337db0a948 100644
--- a/drivers/gpu/drm/gma500/gem.c
+++ b/drivers/gpu/drm/gma500/gem.c
@@ -16,6 +16,7 @@
 #include 
 
 #include 
+#include 
 #include 
 
 #include "gem.h"
@@ -199,35 +200,25 @@ psb_gem_create(struct drm_device *dev, u64 size, const 
char *name, bool stolen,
 int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
struct drm_mode_create_dumb *args)
 {
-   size_t pitch, size;
struct psb_gem_object *pobj;
struct drm_gem_object *obj;
-   u32 handle;
int ret;
 
-   pitch = args->width * DIV_ROUND_UP(args->bpp, 8);
-   pitch = ALIGN(pitch, 64);
-
-   size = pitch * args->height;
-   size = roundup(size, PAGE_SIZE);
-   if (!size)
-   return -EINVAL;
+   ret = drm_mode_size_dumb(dev, args, SZ_64, 0);
+   if (ret)
+   return ret;
 
-   pobj = psb_gem_create(dev, size, "gem", false, PAGE_SIZE);
+   pobj = psb_gem_create(dev, args->size, "gem", false, PAGE_SIZE);
if (IS_ERR(pobj))
return PTR_ERR(pobj);
obj = &pobj->base;
 
-   ret = drm_gem_handle_create(file, obj, &handle);
+   ret = drm_gem_handle_create(file, obj, &args->handle);
if (ret)
goto err_drm_gem_object_put;
 
drm_gem_object_put(obj);
 
-   args->pitch = pitch;
-   args->size = size;
-   args->handle = handle;
-
return 0;
 
 err_drm_gem_object_put:
-- 
2.48.1



[PATCH v4 17/25] drm/renesas/rcar-du: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch according to hardware requirements.

Signed-off-by: Thomas Zimmermann 
Cc: Laurent Pinchart 
Cc: Kieran Bingham 
---
 drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c 
b/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
index 70d8ad065bfa..32c8307da522 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -407,8 +408,8 @@ int rcar_du_dumb_create(struct drm_file *file, struct 
drm_device *dev,
struct drm_mode_create_dumb *args)
 {
struct rcar_du_device *rcdu = to_rcar_du_device(dev);
-   unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
unsigned int align;
+   int ret;
 
/*
 * The R8A7779 DU requires a 16 pixels pitch alignment as documented,
@@ -419,7 +420,9 @@ int rcar_du_dumb_create(struct drm_file *file, struct 
drm_device *dev,
else
align = 16 * args->bpp / 8;
 
-   args->pitch = roundup(min_pitch, align);
+   ret = drm_mode_size_dumb(dev, args, align, 0);
+   if (ret)
+   return ret;
 
return drm_gem_dma_dumb_create_internal(file, dev, args);
 }
-- 
2.48.1



[PATCH v4 24/25] drm/xen: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch
and buffer size. Align the pitch to a multiple of 8.

Signed-off-by: Thomas Zimmermann 
Cc: Oleksandr Andrushchenko 
---
 drivers/gpu/drm/xen/xen_drm_front.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xen/xen_drm_front.c 
b/drivers/gpu/drm/xen/xen_drm_front.c
index 1bda7ef606cc..fd2f250fbc33 100644
--- a/drivers/gpu/drm/xen/xen_drm_front.c
+++ b/drivers/gpu/drm/xen/xen_drm_front.c
@@ -14,6 +14,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -414,8 +415,10 @@ static int xen_drm_drv_dumb_create(struct drm_file *filp,
 * object without pages etc.
 * For details also see drm_gem_handle_create
 */
-   args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
-   args->size = args->pitch * args->height;
+
+   ret = drm_mode_size_dumb(dev, args, SZ_8, 0);
+   if (ret)
+   return ret;
 
obj = xen_drm_front_gem_create(dev, args->size);
if (IS_ERR(obj)) {
-- 
2.48.1



[PATCH v4 23/25] drm/xe: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch
and buffer size. Align the pitch to a multiple of 8. Align the
buffer size according to hardware requirements.

Xe's internal calculation allowed for 64-bit wide buffer sizes, but
the ioctl's internal checks always verified against 32-bit wide limits.
Hance, it is safe to limit the driver code to 32-bit calculations as
well.

v3:
- mention 32-bit calculation in commit description (Matthew)

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Matthew Auld 
Cc: Lucas De Marchi 
Cc: "Thomas Hellström" 
Cc: Rodrigo Vivi 
---
 drivers/gpu/drm/xe/xe_bo.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index 64f9c936eea0..471aab61176e 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -9,6 +9,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -2910,14 +2911,13 @@ int xe_bo_dumb_create(struct drm_file *file_priv,
struct xe_device *xe = to_xe_device(dev);
struct xe_bo *bo;
uint32_t handle;
-   int cpp = DIV_ROUND_UP(args->bpp, 8);
int err;
u32 page_size = max_t(u32, PAGE_SIZE,
xe->info.vram_flags & XE_VRAM_FLAGS_NEED64K ? SZ_64K : SZ_4K);
 
-   args->pitch = ALIGN(args->width * cpp, 64);
-   args->size = ALIGN(mul_u32_u32(args->pitch, args->height),
-  page_size);
+   err = drm_mode_size_dumb(dev, args, SZ_64, page_size);
+   if (err)
+   return err;
 
bo = xe_bo_create_user(xe, NULL, NULL, args->size,
   DRM_XE_GEM_CPU_CACHING_WC,
-- 
2.48.1



[PATCH v4 19/25] drm/rockchip: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch to a multiple of 64.

Signed-off-by: Thomas Zimmermann 
Acked-by: Heiko Stuebner 
Cc: Sandy Huang 
Cc: "Heiko Stübner" 
Cc: Andy Yan 
---
 drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index 6330b883efc3..3bd06202e232 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -9,6 +9,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -403,13 +404,12 @@ int rockchip_gem_dumb_create(struct drm_file *file_priv,
 struct drm_mode_create_dumb *args)
 {
struct rockchip_gem_object *rk_obj;
-   int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+   int ret;
 
-   /*
-* align to 64 bytes since Mali requires it.
-*/
-   args->pitch = ALIGN(min_pitch, 64);
-   args->size = args->pitch * args->height;
+   /* 64-byte alignment required by Mali */
+   ret = drm_mode_size_dumb(dev, args, SZ_64, 0);
+   if (ret)
+   return ret;
 
rk_obj = rockchip_gem_create_with_handle(file_priv, dev, args->size,
 &args->handle);
-- 
2.48.1



[PATCH v4 22/25] drm/vmwgfx: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch
and buffer size. No alignment required.

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Zack Rusin 
Cc: Zack Rusin 
Cc: Broadcom internal kernel review list 
---
 drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 21 -
 1 file changed, 4 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index 02ab65cc63ec..c3a4ea713559 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -15,6 +15,7 @@
 #include "vmw_surface_cache.h"
 #include "device_include/svga3d_surfacedefs.h"
 
+#include 
 #include 
 
 #define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32)
@@ -2270,23 +2271,9 @@ int vmw_dumb_create(struct drm_file *file_priv,
 * contents is going to be rendered guest side.
 */
if (!dev_priv->has_mob || !vmw_supports_3d(dev_priv)) {
-   int cpp = DIV_ROUND_UP(args->bpp, 8);
-
-   switch (cpp) {
-   case 1: /* DRM_FORMAT_C8 */
-   case 2: /* DRM_FORMAT_RGB565 */
-   case 4: /* DRM_FORMAT_XRGB */
-   break;
-   default:
-   /*
-* Dumb buffers don't allow anything else.
-* This is tested via IGT's dumb_buffers
-*/
-   return -EINVAL;
-   }
-
-   args->pitch = args->width * cpp;
-   args->size = ALIGN(args->pitch * args->height, PAGE_SIZE);
+   ret = drm_mode_size_dumb(dev, args, 0, 0);
+   if (ret)
+   return ret;
 
ret = vmw_gem_object_create_with_handle(dev_priv, file_priv,
args->size, 
&args->handle,
-- 
2.48.1



[PATCH v4 18/25] drm/renesas/rz-du: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch according to hardware requirements.

Signed-off-by: Thomas Zimmermann 
Cc: Biju Das 
---
 drivers/gpu/drm/renesas/rz-du/rzg2l_du_kms.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_kms.c 
b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_kms.c
index 90c6269ccd29..f752369cd52f 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_kms.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_kms.c
@@ -75,10 +75,11 @@ const struct rzg2l_du_format_info *rzg2l_du_format_info(u32 
fourcc)
 int rzg2l_du_dumb_create(struct drm_file *file, struct drm_device *dev,
 struct drm_mode_create_dumb *args)
 {
-   unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
-   unsigned int align = 16 * args->bpp / 8;
+   int ret;
 
-   args->pitch = roundup(min_pitch, align);
+   ret = drm_mode_size_dumb(dev, args, 16 * args->bpp / 8, 0);
+   if (ret)
+   return ret;
 
return drm_gem_dma_dumb_create_internal(file, dev, args);
 }
-- 
2.48.1



[PATCH v4 15/25] drm/omapdrm: Compute dumb-buffer sizes with drm_mode_size_dumb()

2025-03-11 Thread Thomas Zimmermann
Call drm_mode_size_dumb() to compute dumb-buffer scanline pitch and
buffer size. Align the pitch to a multiple of 8.

Signed-off-by: Thomas Zimmermann 
Reviewed-by: Tomi Valkeinen 
Cc: Tomi Valkeinen 
---
 drivers/gpu/drm/omapdrm/omap_gem.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c 
b/drivers/gpu/drm/omapdrm/omap_gem.c
index b9c67e4ca360..b8413a2dcdeb 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 
@@ -583,15 +584,13 @@ static int omap_gem_object_mmap(struct drm_gem_object 
*obj, struct vm_area_struc
 int omap_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
struct drm_mode_create_dumb *args)
 {
-   union omap_gem_size gsize;
-
-   args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
-
-   args->size = PAGE_ALIGN(args->pitch * args->height);
+   union omap_gem_size gsize = { };
+   int ret;
 
-   gsize = (union omap_gem_size){
-   .bytes = args->size,
-   };
+   ret = drm_mode_size_dumb(dev, args, SZ_8, 0);
+   if (ret)
+   return ret;
+   gsize.bytes = args->size;
 
return omap_gem_new_handle(dev, file, gsize,
OMAP_BO_SCANOUT | OMAP_BO_WC, &args->handle);
-- 
2.48.1



Re: [PATCH v3 18/21] drm/msm/dpu: Implement 10-bit color alpha for v12.0 DPU

2025-03-11 Thread Krzysztof Kozlowski
On 21/02/2025 17:25, Dmitry Baryshkov wrote:
>> -static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer,
>> -struct dpu_plane_state *pstate, const struct msm_format *format)
>> +static void _dpu_crtc_setup_blend_cfg(const struct dpu_hw_ctl *ctl,
>> +  struct dpu_crtc_mixer *mixer,
>> +  struct dpu_plane_state *pstate,
>> +  const struct msm_format *format)
>>  {
>>  struct dpu_hw_mixer *lm = mixer->hw_lm;
>>  uint32_t blend_op;
>> -uint32_t fg_alpha, bg_alpha;
>> +uint32_t fg_alpha, bg_alpha, max_alpha;
>>  
>>  fg_alpha = pstate->base.alpha >> 8;
>> -bg_alpha = 0xff - fg_alpha;
>> +if (ctl->mdss_ver->core_major_ver < 12)
>> +max_alpha = 0xff;
>> +else
>> +max_alpha = 0x3ff;
> 
> So, CTL is passed only to get struct dpu_mdss_version? It can either be
> passed directly or fetched via dpu_kms->catalog->mdss_ver

Ack.

> 
>> +bg_alpha = max_alpha - fg_alpha;
>>  
>>  /* default to opaque blending */
>>  if (pstate->base.pixel_blend_mode == DRM_MODE_BLEND_PIXEL_NONE ||
>> @@ -337,7 +343,7 @@ static void _dpu_crtc_setup_blend_cfg(struct 
>> dpu_crtc_mixer *mixer,
>>  } else if (pstate->base.pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) {
>>  blend_op = DPU_BLEND_FG_ALPHA_FG_CONST |
>>  DPU_BLEND_BG_ALPHA_FG_PIXEL;
>> -if (fg_alpha != 0xff) {
>> +if (fg_alpha != max_alpha) {
>>  bg_alpha = fg_alpha;
>>  blend_op |= DPU_BLEND_BG_MOD_ALPHA |
>>  DPU_BLEND_BG_INV_MOD_ALPHA;
>> @@ -348,7 +354,7 @@ static void _dpu_crtc_setup_blend_cfg(struct 
>> dpu_crtc_mixer *mixer,
>>  /* coverage blending */
>>  blend_op = DPU_BLEND_FG_ALPHA_FG_PIXEL |
>>  DPU_BLEND_BG_ALPHA_FG_PIXEL;
>> -if (fg_alpha != 0xff) {
>> +if (fg_alpha != max_alpha) {
>>  bg_alpha = fg_alpha;
>>  blend_op |= DPU_BLEND_FG_MOD_ALPHA |
>>  DPU_BLEND_FG_INV_MOD_ALPHA |
>> @@ -482,7 +488,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc 
>> *crtc,
>>  
>>  /* blend config update */
>>  for (lm_idx = 0; lm_idx < cstate->num_mixers; lm_idx++) {
>> -_dpu_crtc_setup_blend_cfg(mixer + lm_idx, pstate, 
>> format);
>> +_dpu_crtc_setup_blend_cfg(ctl, mixer + lm_idx, pstate, 
>> format);
>>  
>>  if (bg_alpha_enable && !format->alpha_enable)
>>  mixer[lm_idx].mixer_op_mode = 0;
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
>> index 
>> 3bfb61cb83672dca4236bdbbbfb1e442223576d2..75bf3521b03c8e243ccfe1fc226aa71f23b296df
>>  100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
>> @@ -19,12 +19,20 @@
>>  
>>  /* These register are offset to mixer base + stage base */
>>  #define LM_BLEND0_OP 0x00
>> +
>> +/* >  #define LM_BLEND0_CONST_ALPHA0x04
>>  #define LM_FG_COLOR_FILL_COLOR_0 0x08
>>  #define LM_FG_COLOR_FILL_COLOR_1 0x0C
> 
> lowercase hex

Ack

> 
>>  #define LM_FG_COLOR_FILL_SIZE0x10
>>  #define LM_FG_COLOR_FILL_XY  0x14
>>  
>> +/* >= v12 DPU */
>> +#define LM_BORDER_COLOR_0_V12   0x1C
> 
> lowercase hex
> 
>> +#define LM_BORDER_COLOR_1_V12   0x20
>> +
>> +/* >= v12 DPU with offset to mixer base + stage base */
>> +#define LM_BLEND0_CONST_ALPHA_V12   0x08
> 
> This doesn't seem to be aligned properly

That's only patch view... because I used tabs. I think existing code
uses spaces, so I will switch to spaces.


Best regards,
Krzysztof


Re: [PATCH 3/4] drm/vc4: use new helper to get ACR values

2025-03-11 Thread Maxime Ripard
On Mon, Mar 10, 2025 at 10:18:04PM +0200, Dmitry Baryshkov wrote:
> On Mon, Mar 10, 2025 at 03:51:53PM +0100, Maxime Ripard wrote:
> > On Sun, Mar 09, 2025 at 10:13:58AM +0200, Dmitry Baryshkov wrote:
> > > From: Dmitry Baryshkov 
> > > 
> > > Use drm_hdmi_acr_get_n_cts() helper instead of calculating N and CTS
> > > values in the VC4 driver.
> > > 
> > > Signed-off-by: Dmitry Baryshkov 
> > > ---
> > >  drivers/gpu/drm/vc4/vc4_hdmi.c | 10 +++---
> > >  drivers/gpu/drm/vc4/vc4_hdmi.h |  7 +++
> > >  2 files changed, 10 insertions(+), 7 deletions(-)
> > > 
> 
> > > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h 
> > > b/drivers/gpu/drm/vc4/vc4_hdmi.h
> > > index 
> > > e3d989ca302b72533c374dfa3fd0d5bd7fe64a82..0a775dbfe99d45521f3d0a2016555aefa81d7934
> > >  100644
> > > --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> > > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> > > @@ -211,6 +211,13 @@ struct vc4_hdmi {
> > >* KMS hooks. Protected by @mutex.
> > >*/
> > >   enum hdmi_colorspace output_format;
> > > +
> > > + /**
> > > +  * @tmds_char_rate: Copy of
> > > +  * @drm_connector_state.hdmi.tmds_char_rate for use outside of
> > > +  * KMS hooks. Protected by @mutex.
> > > +  */
> > > + unsigned long long tmds_char_rate;
> > >  };
> > 
> > This should be in drm_connector_hdmi if it's useful
> 
> That would mean bringing the state to a non-state structure on the
> framework level. Is it fine from your POV?

Sorry, I'm changing my mind a little bit, but it's pretty much the same
case than for accessing the infoframes from debugfs: we want to get some
information stored in the state from outside of KMS.

What we did for the infoframes is that we're actually just taking the
connection_mutex from the DRM device and access the drm_connector->state
pointer.

I guess it would also work for ALSA?

Maxime


signature.asc
Description: PGP signature


Re: [PATCH v5 2/2] drm/msm/dp: reuse generic HDMI codec implementation

2025-03-11 Thread Maxime Ripard
Hi,

On Mon, Mar 10, 2025 at 08:53:24PM +0200, Dmitry Baryshkov wrote:
> On Mon, 10 Mar 2025 at 17:08, Maxime Ripard  wrote:
> >
> > On Fri, Mar 07, 2025 at 07:55:53AM +0200, Dmitry Baryshkov wrote:
> > > From: Dmitry Baryshkov 
> > >
> > > The MSM DisplayPort driver implements several HDMI codec functions
> > > in the driver, e.g. it manually manages HDMI codec device registration,
> > > returning ELD and plugged_cb support. In order to reduce code
> > > duplication reuse drm_hdmi_audio_* helpers and drm_bridge_connector
> > > integration.
> > >
> > > Signed-off-by: Dmitry Baryshkov 
> > > ---
> > >  drivers/gpu/drm/msm/Kconfig |   1 +
> > >  drivers/gpu/drm/msm/dp/dp_audio.c   | 131 
> > > 
> > >  drivers/gpu/drm/msm/dp/dp_audio.h   |  27 ++--
> > >  drivers/gpu/drm/msm/dp/dp_display.c |  28 ++--
> > >  drivers/gpu/drm/msm/dp/dp_display.h |   6 --
> > >  drivers/gpu/drm/msm/dp/dp_drm.c |   8 +++
> > >  6 files changed, 31 insertions(+), 170 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
> > > index 
> > > 974bc7c0ea761147d3326bdce9039d6f26f290d0..7f127e2ae44292f8f5c7ff6a9251c3d7ec8c9f58
> > >  100644
> > > --- a/drivers/gpu/drm/msm/Kconfig
> > > +++ b/drivers/gpu/drm/msm/Kconfig
> > > @@ -104,6 +104,7 @@ config DRM_MSM_DPU
> > >  config DRM_MSM_DP
> > >   bool "Enable DisplayPort support in MSM DRM driver"
> > >   depends on DRM_MSM
> > > + select DRM_DISPLAY_HDMI_AUDIO_HELPER
> > >   select RATIONAL
> > >   default y
> > >   help
> > > diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c 
> > > b/drivers/gpu/drm/msm/dp/dp_audio.c
> > > index 
> > > 70fdc9fe228a7149546accd8479a9e4397f3d5dd..f8bfb908f9b4bf93ad5480f0785e3aed23dde160
> > >  100644
> > > --- a/drivers/gpu/drm/msm/dp/dp_audio.c
> > > +++ b/drivers/gpu/drm/msm/dp/dp_audio.c
> > > @@ -13,13 +13,13 @@
> > >
> > >  #include "dp_catalog.h"
> > >  #include "dp_audio.h"
> > > +#include "dp_drm.h"
> > >  #include "dp_panel.h"
> > >  #include "dp_reg.h"
> > >  #include "dp_display.h"
> > >  #include "dp_utils.h"
> > >
> > >  struct msm_dp_audio_private {
> > > - struct platform_device *audio_pdev;
> > >   struct platform_device *pdev;
> > >   struct drm_device *drm_dev;
> > >   struct msm_dp_catalog *catalog;
> > > @@ -160,24 +160,11 @@ static void msm_dp_audio_enable(struct 
> > > msm_dp_audio_private *audio, bool enable)
> > >   msm_dp_catalog_audio_enable(catalog, enable);
> > >  }
> > >
> > > -static struct msm_dp_audio_private *msm_dp_audio_get_data(struct 
> > > platform_device *pdev)
> > > +static struct msm_dp_audio_private *msm_dp_audio_get_data(struct msm_dp 
> > > *msm_dp_display)
> > >  {
> > >   struct msm_dp_audio *msm_dp_audio;
> > > - struct msm_dp *msm_dp_display;
> > > -
> > > - if (!pdev) {
> > > - DRM_ERROR("invalid input\n");
> > > - return ERR_PTR(-ENODEV);
> > > - }
> > > -
> > > - msm_dp_display = platform_get_drvdata(pdev);
> > > - if (!msm_dp_display) {
> > > - DRM_ERROR("invalid input\n");
> > > - return ERR_PTR(-ENODEV);
> > > - }
> > >
> > >   msm_dp_audio = msm_dp_display->msm_dp_audio;
> > > -
> > >   if (!msm_dp_audio) {
> > >   DRM_ERROR("invalid msm_dp_audio data\n");
> > >   return ERR_PTR(-EINVAL);
> > > @@ -186,68 +173,16 @@ static struct msm_dp_audio_private 
> > > *msm_dp_audio_get_data(struct platform_device
> > >   return container_of(msm_dp_audio, struct msm_dp_audio_private, 
> > > msm_dp_audio);
> > >  }
> > >
> > > -static int msm_dp_audio_hook_plugged_cb(struct device *dev, void *data,
> > > - hdmi_codec_plugged_cb fn,
> > > - struct device *codec_dev)
> > > -{
> > > -
> > > - struct platform_device *pdev;
> > > - struct msm_dp *msm_dp_display;
> > > -
> > > - pdev = to_platform_device(dev);
> > > - if (!pdev) {
> > > - pr_err("invalid input\n");
> > > - return -ENODEV;
> > > - }
> > > -
> > > - msm_dp_display = platform_get_drvdata(pdev);
> > > - if (!msm_dp_display) {
> > > - pr_err("invalid input\n");
> > > - return -ENODEV;
> > > - }
> > > -
> > > - return msm_dp_display_set_plugged_cb(msm_dp_display, fn, codec_dev);
> > > -}
> > > -
> > > -static int msm_dp_audio_get_eld(struct device *dev,
> > > - void *data, uint8_t *buf, size_t len)
> > > -{
> > > - struct platform_device *pdev;
> > > - struct msm_dp *msm_dp_display;
> > > -
> > > - pdev = to_platform_device(dev);
> > > -
> > > - if (!pdev) {
> > > - DRM_ERROR("invalid input\n");
> > > - return -ENODEV;
> > > - }
> > > -
> > > - msm_dp_display = platform_get_drvdata(pdev);
> > > - if (!msm_dp_display) {
> > > - DRM_ERROR("invalid input\n");
> > > - return -ENODEV;
> > > - }
> > > -
> > > - mutex_lock(&msm_

Re: [PATCH 1/4] drm/display: hdmi: provide central data authority for ACR params

2025-03-11 Thread Maxime Ripard
On Mon, Mar 10, 2025 at 10:14:52PM +0200, Dmitry Baryshkov wrote:
> On Mon, Mar 10, 2025 at 03:46:33PM +0100, Maxime Ripard wrote:
> > On Sun, Mar 09, 2025 at 10:13:56AM +0200, Dmitry Baryshkov wrote:
> > > From: Dmitry Baryshkov 
> > > 
> > > HDMI standard defines recommended N and CTS values for Audio Clock
> > > Regeneration. Currently each driver implements those, frequently in
> > > somewhat unique way. Provide a generic helper for getting those values
> > > to be used by the HDMI drivers.
> > > 
> > > The helper is added to drm_hdmi_helper.c rather than drm_hdmi_audio.c
> > > since HDMI drivers can be using this helper function even without
> > > switching to DRM HDMI Audio helpers.
> > > 
> > > Note: currently this only handles the values per HDMI 1.4b Section 7.2
> > > and HDMI 2.0 Section 9.2.1. Later the table can be expanded to
> > > accommodate for Deep Color TMDS char rates per HDMI 1.4 Appendix D
> > > and/or HDMI 2.0 / 2.1 Appendix C).
> > > 
> > > Signed-off-by: Dmitry Baryshkov 
> > > ---
> > >  drivers/gpu/drm/display/drm_hdmi_helper.c | 164 
> > > ++
> > >  include/drm/display/drm_hdmi_helper.h |   6 ++
> > >  2 files changed, 170 insertions(+)
> > > 
> > > diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c 
> > > b/drivers/gpu/drm/display/drm_hdmi_helper.c
> > > index 
> > > 74dd4d01dd9bb2c9e69ec1c60b0056bd69417e8a..89d25571bfd21c56c6835821d2272a12c816a76e
> > >  100644
> > > --- a/drivers/gpu/drm/display/drm_hdmi_helper.c
> > > +++ b/drivers/gpu/drm/display/drm_hdmi_helper.c
> > > @@ -256,3 +256,167 @@ drm_hdmi_compute_mode_clock(const struct 
> > > drm_display_mode *mode,
> > >   return DIV_ROUND_CLOSEST_ULL(clock * bpc, 8);
> > >  }
> > >  EXPORT_SYMBOL(drm_hdmi_compute_mode_clock);
> > > +
> > > +struct drm_hdmi_acr_n_cts_entry {
> > > + unsigned int n;
> > > + unsigned int cts;
> > > +};
> > > +
> > > +struct drm_hdmi_acr_data {
> > > + unsigned long tmds_clock_khz;
> > > + struct drm_hdmi_acr_n_cts_entry n_cts_32k,
> > > + n_cts_44k1,
> > > + n_cts_48k;
> > > +};
> > > +
> > > +static const struct drm_hdmi_acr_data hdmi_acr_n_cts[] = {
> > > + {
> > > + /* "Other" entry */
> > > + .n_cts_32k =  { .n = 4096, },
> > > + .n_cts_44k1 = { .n = 6272, },
> > > + .n_cts_48k =  { .n = 6144, },
> > > + }, {
> > > + .tmds_clock_khz = 25175,
> > > + .n_cts_32k =  { .n = 4576,  .cts = 28125, },
> > > + .n_cts_44k1 = { .n = 7007,  .cts = 31250, },
> > > + .n_cts_48k =  { .n = 6864,  .cts = 28125, },
> > > + }, {
> > > + .tmds_clock_khz = 25200,
> > > + .n_cts_32k =  { .n = 4096,  .cts = 25200, },
> > > + .n_cts_44k1 = { .n = 6272,  .cts = 28000, },
> > > + .n_cts_48k =  { .n = 6144,  .cts = 25200, },
> > > + }, {
> > > + .tmds_clock_khz = 27000,
> > > + .n_cts_32k =  { .n = 4096,  .cts = 27000, },
> > > + .n_cts_44k1 = { .n = 6272,  .cts = 3, },
> > > + .n_cts_48k =  { .n = 6144,  .cts = 27000, },
> > > + }, {
> > > + .tmds_clock_khz = 27027,
> > > + .n_cts_32k =  { .n = 4096,  .cts = 27027, },
> > > + .n_cts_44k1 = { .n = 6272,  .cts = 30030, },
> > > + .n_cts_48k =  { .n = 6144,  .cts = 27027, },
> > > + }, {
> > > + .tmds_clock_khz = 54000,
> > > + .n_cts_32k =  { .n = 4096,  .cts = 54000, },
> > > + .n_cts_44k1 = { .n = 6272,  .cts = 6, },
> > > + .n_cts_48k =  { .n = 6144,  .cts = 54000, },
> > > + }, {
> > > + .tmds_clock_khz = 54054,
> > > + .n_cts_32k =  { .n = 4096,  .cts = 54054, },
> > > + .n_cts_44k1 = { .n = 6272,  .cts = 60060, },
> > > + .n_cts_48k =  { .n = 6144,  .cts = 54054, },
> > > + }, {
> > > + .tmds_clock_khz = 74176,
> > > + .n_cts_32k =  { .n = 11648, .cts = 210937, }, /* and 210938 */
> > > + .n_cts_44k1 = { .n = 17836, .cts = 234375, },
> > > + .n_cts_48k =  { .n = 11648, .cts = 140625, },
> > > + }, {
> > > + .tmds_clock_khz = 74250,
> > > + .n_cts_32k =  { .n = 4096,  .cts = 74250, },
> > > + .n_cts_44k1 = { .n = 6272,  .cts = 82500, },
> > > + .n_cts_48k =  { .n = 6144,  .cts = 74250, },
> > > + }, {
> > > + .tmds_clock_khz = 148352,
> > > + .n_cts_32k =  { .n = 11648, .cts = 421875, },
> > > + .n_cts_44k1 = { .n = 8918,  .cts = 234375, },
> > > + .n_cts_48k =  { .n = 5824,  .cts = 140625, },
> > > + }, {
> > > + .tmds_clock_khz = 148500,
> > > + .n_cts_32k =  { .n = 4096,  .cts = 148500, },
> > > + .n_cts_44k1 = { .n = 6272,  .cts = 165000, },
> > > + .n_cts_48k =  { .n = 6144,  .cts = 148500, },
> > > + }, {
> > > + .tmds_clock_khz = 296703,
> > > + .n_cts_32k =  { .n = 5824,  .cts = 421875, },
> > > + .n_cts_44k1 = { .n = 4459,  .cts = 234375, },
> > > + .n_cts_48k =  { .n = 582

Re: [PATCH v1 2/2] drm/msm/dp: Introduce link training per-segment for LTTPRs

2025-03-11 Thread Abel Vesa
On 25-03-10 22:05:52, Aleksandrs Vinarskis wrote:
> DisplayPort requires per-segment link training when LTTPR are switched
> to non-transparent mode, starting with LTTPR closest to the source.
> Only when each segment is trained individually, source can link train
> to sink.
> 
> Implement per-segment link traning when LTTPR(s) are detected, to
> support external docking stations. On higher level, changes are:
> 
> *  Pass phy being trained down to all required helpers
> *  Run CR, EQ link training per phy
> *  Set voltage swing, pre-emphasis levels per phy
> 
> This ensures successful link training both when connected directly to
> the monitor (single LTTPR onboard most X1E laptops) and via the docking
> station (at least two LTTPRs). This does not address/resolve underlying
> mainlink initialization issues.
> 
> Signed-off-by: Aleksandrs Vinarskis 

Reviewed-by: Abel Vesa 

> ---
>  drivers/gpu/drm/msm/dp/dp_ctrl.c| 136 +++-
>  drivers/gpu/drm/msm/dp/dp_ctrl.h|   2 +-
>  drivers/gpu/drm/msm/dp/dp_display.c |   4 +-
>  3 files changed, 98 insertions(+), 44 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c 
> b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> index d8633a596f8d..20f07ef46ef3 100644
> --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
> +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> @@ -79,6 +79,8 @@ struct msm_dp_ctrl_private {
>   struct msm_dp_link *link;
>   struct msm_dp_catalog *catalog;
>  
> + int *lttpr_count;
> +
>   struct phy *phy;
>  
>   unsigned int num_core_clks;
> @@ -1034,7 +1036,8 @@ static int msm_dp_ctrl_set_vx_px(struct 
> msm_dp_ctrl_private *ctrl,
>   return 0;
>  }
>  
> -static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl)
> +static int msm_dp_ctrl_update_phy_vx_px(struct msm_dp_ctrl_private *ctrl,
> + enum drm_dp_phy dp_phy)
>  {
>   struct msm_dp_link *link = ctrl->link;
>   int ret = 0, lane, lane_cnt;
> @@ -1075,8 +1078,12 @@ static int msm_dp_ctrl_update_vx_px(struct 
> msm_dp_ctrl_private *ctrl)
>  
>   drm_dbg_dp(ctrl->drm_dev, "sink: p|v=0x%x\n",
>   voltage_swing_level | pre_emphasis_level);
> - ret = drm_dp_dpcd_write(ctrl->aux, DP_TRAINING_LANE0_SET,
> - buf, lane_cnt);
> +
> + int reg = dp_phy == DP_PHY_DPRX ?
> + DP_TRAINING_LANE0_SET :
> + DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy);
> +
> + ret = drm_dp_dpcd_write(ctrl->aux, reg, buf, lane_cnt);
>   if (ret == lane_cnt)
>   ret = 0;
>  
> @@ -1084,10 +1091,13 @@ static int msm_dp_ctrl_update_vx_px(struct 
> msm_dp_ctrl_private *ctrl)
>  }
>  
>  static bool msm_dp_ctrl_train_pattern_set(struct msm_dp_ctrl_private *ctrl,
> - u8 pattern)
> + u8 pattern, enum drm_dp_phy dp_phy)
>  {
>   u8 buf;
>   int ret = 0;
> + int reg = dp_phy == DP_PHY_DPRX ?
> + DP_TRAINING_PATTERN_SET :
> + DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy);
>  
>   drm_dbg_dp(ctrl->drm_dev, "sink: pattern=%x\n", pattern);
>  
> @@ -1096,7 +1106,7 @@ static bool msm_dp_ctrl_train_pattern_set(struct 
> msm_dp_ctrl_private *ctrl,
>   if (pattern && pattern != DP_TRAINING_PATTERN_4)
>   buf |= DP_LINK_SCRAMBLING_DISABLE;
>  
> - ret = drm_dp_dpcd_writeb(ctrl->aux, DP_TRAINING_PATTERN_SET, buf);
> + ret = drm_dp_dpcd_writeb(ctrl->aux, reg, buf);
>   return ret == 1;
>  }
>  
> @@ -1115,12 +1125,16 @@ static int msm_dp_ctrl_read_link_status(struct 
> msm_dp_ctrl_private *ctrl,
>  }
>  
>  static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl,
> - int *training_step)
> + int *training_step, enum drm_dp_phy dp_phy)
>  {
> + int delay_us;
>   int tries, old_v_level, ret = 0;
>   u8 link_status[DP_LINK_STATUS_SIZE];
>   int const maximum_retries = 4;
>  
> + delay_us = drm_dp_read_clock_recovery_delay(ctrl->aux,
> + ctrl->panel->dpcd, dp_phy, false);
> +
>   msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
>  
>   *training_step = DP_TRAINING_1;
> @@ -1129,18 +1143,19 @@ static int msm_dp_ctrl_link_train_1(struct 
> msm_dp_ctrl_private *ctrl,
>   if (ret)
>   return ret;
>   msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 |
> - DP_LINK_SCRAMBLING_DISABLE);
> + DP_LINK_SCRAMBLING_DISABLE, dp_phy);
>  
> - ret = msm_dp_ctrl_update_vx_px(ctrl);
> + msm_dp_link_reset_phy_params_vx_px(ctrl->link);
> + ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy);
>   if (ret)
>   return ret;
>  
>   tries = 0;
>   old_v_level = ctrl->link->phy_params.v_level;
>   for (tries = 0; tries < maximum_retries; tries++) {
> - drm_dp_link_train_clock_recovery_delay(ctrl->aux, 
> ctrl->panel->dpcd);
> + fsleep(delay_u

[PATCH v2 02/10] dt-bindings: msm: dsi-controller-main: document the SA8775P DSI CTRL

2025-03-11 Thread Ayushi Makhija
Document the DSI CTRL on the SA8775P Platform.

Signed-off-by: Ayushi Makhija 
---
 .../devicetree/bindings/display/msm/dsi-controller-main.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git 
a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml 
b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
index ffbd1dc9470e..3621e3f12b65 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
@@ -23,6 +23,7 @@ properties:
   - qcom,msm8996-dsi-ctrl
   - qcom,msm8998-dsi-ctrl
   - qcom,qcm2290-dsi-ctrl
+  - qcom,sa8775p-dsi-ctrl
   - qcom,sc7180-dsi-ctrl
   - qcom,sc7280-dsi-ctrl
   - qcom,sdm660-dsi-ctrl
-- 
2.34.1



[PATCH v2 10/10] drm/bridge: anx7625: change the gpiod_set_value API

2025-03-11 Thread Ayushi Makhija
Use gpiod_set_value_cansleep() instead of gpiod_set_value()
to fix the below call trace in the boot log:

[5.690534] Call trace:
[5.690536]  gpiod_set_value+0x40/0xa4
[5.690540]  anx7625_runtime_pm_resume+0xa0/0x324 [anx7625]
[5.690545]  __rpm_callback+0x48/0x1d8
[5.690549]  rpm_callback+0x6c/0x78

Certain GPIO controllers require access via message-based buses
such as I2C or SPI, which may cause the GPIOs to enter a sleep
state. Therefore, use the gpiod_set_value_cansleep().

Signed-off-by: Ayushi Makhija 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
b/drivers/gpu/drm/bridge/analogix/anx7625.c
index ad99ad19653f..310c9b598fbf 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -1257,10 +1257,10 @@ static void anx7625_power_on(struct anx7625_data *ctx)
usleep_range(11000, 12000);
 
/* Power on pin enable */
-   gpiod_set_value(ctx->pdata.gpio_p_on, 1);
+   gpiod_set_value_cansleep(ctx->pdata.gpio_p_on, 1);
usleep_range(1, 11000);
/* Power reset pin enable */
-   gpiod_set_value(ctx->pdata.gpio_reset, 1);
+   gpiod_set_value_cansleep(ctx->pdata.gpio_reset, 1);
usleep_range(1, 11000);
 
DRM_DEV_DEBUG_DRIVER(dev, "power on !\n");
@@ -1280,9 +1280,9 @@ static void anx7625_power_standby(struct anx7625_data 
*ctx)
return;
}
 
-   gpiod_set_value(ctx->pdata.gpio_reset, 0);
+   gpiod_set_value_cansleep(ctx->pdata.gpio_reset, 0);
usleep_range(1000, 1100);
-   gpiod_set_value(ctx->pdata.gpio_p_on, 0);
+   gpiod_set_value_cansleep(ctx->pdata.gpio_p_on, 0);
usleep_range(1000, 1100);
 
ret = regulator_bulk_disable(ARRAY_SIZE(ctx->pdata.supplies),
-- 
2.34.1



[PATCH v2 08/10] drm/bridge: anx7625: enable HPD interrupts

2025-03-11 Thread Ayushi Makhija
When device enters the suspend state, it prevents
HPD interrupts from occurring. To address this,
add an additional PM runtime vote in hpd_enable().
This vote is removed in hpd_disable().

Signed-off-by: Ayushi Makhija 
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 4be34d5c7a3b..764da1c1dc11 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -2474,6 +2474,22 @@ static const struct drm_edid 
*anx7625_bridge_edid_read(struct drm_bridge *bridge
return anx7625_edid_read(ctx);
 }
 
+static void anx7625_bridge_hpd_enable(struct drm_bridge *bridge)
+{
+   struct anx7625_data *ctx = bridge_to_anx7625(bridge);
+   struct device *dev = ctx->dev;
+
+   pm_runtime_get_sync(dev);
+}
+
+static void anx7625_bridge_hpd_disable(struct drm_bridge *bridge)
+{
+   struct anx7625_data *ctx = bridge_to_anx7625(bridge);
+   struct device *dev = ctx->dev;
+
+   pm_runtime_put_sync(dev);
+}
+
 static const struct drm_bridge_funcs anx7625_bridge_funcs = {
.attach = anx7625_bridge_attach,
.detach = anx7625_bridge_detach,
@@ -2487,6 +2503,8 @@ static const struct drm_bridge_funcs anx7625_bridge_funcs 
= {
.atomic_reset = drm_atomic_helper_bridge_reset,
.detect = anx7625_bridge_detect,
.edid_read = anx7625_bridge_edid_read,
+   .hpd_enable = anx7625_bridge_hpd_enable,
+   .hpd_disable = anx7625_bridge_hpd_disable,
 };
 
 static int anx7625_register_i2c_dummy_clients(struct anx7625_data *ctx,
-- 
2.34.1



[PATCH v2 07/10] arm64: dts: qcom: sa8775p-ride: add anx7625 DSI to DP bridge nodes

2025-03-11 Thread Ayushi Makhija
Add anx7625 DSI to DP bridge device nodes.

Signed-off-by: Ayushi Makhija 
---
 arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi | 208 -
 1 file changed, 207 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi 
b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi
index 175f8b1e3b2d..77d86c1d8aa6 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi
@@ -28,6 +28,13 @@ chosen {
stdout-path = "serial0:115200n8";
};
 
+   vph_pwr: vph-pwr-regulator {
+   compatible = "regulator-fixed";
+   regulator-name = "vph_pwr";
+   regulator-always-on;
+   regulator-boot-on;
+   };
+
vreg_conn_1p8: vreg_conn_1p8 {
compatible = "regulator-fixed";
regulator-name = "vreg_conn_1p8";
@@ -128,6 +135,30 @@ dp1_connector_in: endpoint {
};
};
};
+
+   dp-dsi0-connector {
+   compatible = "dp-connector";
+   label = "DSI0";
+   type = "full-size";
+
+   port {
+   dp_dsi0_connector_in: endpoint {
+   remote-endpoint = <&anx7625_1_out>;
+   };
+   };
+   };
+
+   dp-dsi1-connector {
+   compatible = "dp-connector";
+   label = "DSI1";
+   type = "full-size";
+
+   port {
+   dp_dsi1_connector_in: endpoint {
+   remote-endpoint = <&anx7625_2_out>;
+   };
+   };
+   };
 };
 
 &apps_rsc {
@@ -517,9 +548,135 @@ &i2c11 {
 
 &i2c18 {
clock-frequency = <40>;
-   pinctrl-0 = <&qup_i2c18_default>;
+   pinctrl-0 = <&qup_i2c18_default>,
+   <&io_expander_intr_active>,
+   <&io_expander_reset_active>;
pinctrl-names = "default";
+
status = "okay";
+
+   io_expander: gpio@74 {
+   compatible = "ti,tca9539";
+   reg = <0x74>;
+   interrupts-extended = <&tlmm 98 IRQ_TYPE_EDGE_BOTH>;
+   gpio-controller;
+   #gpio-cells = <2>;
+   interrupt-controller;
+   #interrupt-cells = <2>;
+
+   gpio2-hog {
+   gpio-hog;
+   gpios = <2 GPIO_ACTIVE_HIGH>;
+   input;
+   line-name = "dsi0_int_pin";
+   };
+
+   gpio3-hog {
+   gpio-hog;
+   gpios = <3 GPIO_ACTIVE_LOW>;
+   output-high;
+   line-name = "dsi0_cbl_det_pin";
+   };
+
+   gpio10-hog {
+   gpio-hog;
+   gpios = <10 GPIO_ACTIVE_HIGH>;
+   input;
+   line-name = "dsi1_int_pin";
+   };
+
+   gpio11-hog {
+   gpio-hog;
+   gpios = <11 GPIO_ACTIVE_LOW>;
+   output-high;
+   line-name = "dsi1_cbl_det_pin";
+   };
+   };
+
+   i2c-mux@70 {
+   compatible = "nxp,pca9543";
+   #address-cells = <1>;
+
+   #size-cells = <0>;
+   reg = <0x70>;
+
+   i2c@0 {
+   reg = <0>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   anx_bridge1: anx7625@58 {
+   compatible = "analogix,anx7625";
+   reg = <0x58>;
+   interrupts-extended = <&io_expander 2 
IRQ_TYPE_EDGE_FALLING>;
+   enable-gpios = <&io_expander 1 
GPIO_ACTIVE_HIGH>;
+   reset-gpios = <&io_expander 0 GPIO_ACTIVE_HIGH>;
+   vdd10-supply = <&vph_pwr>;
+   vdd18-supply = <&vph_pwr>;
+   vdd33-supply = <&vph_pwr>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   dsi2dp_bridge_1_in: port@0 {
+   reg = <0>;
+
+   anx7625_1_in: endpoint {
+   remote-endpoint = 
<&mdss0_dsi0_out>;
+   };
+   };
+
+   dsi2dp_bridge_1_out: port@1 {
+   reg = <1>;
+
+   anx7625_1_out: endpoint {
+

[PATCH v2 03/10] dt-bindings: display: msm: document DSI controller and phy on SA8775P

2025-03-11 Thread Ayushi Makhija
Document DSI controller and phy on SA8775P platform.

Signed-off-by: Ayushi Makhija 
---
 .../display/msm/qcom,sa8775p-mdss.yaml| 188 ++
 1 file changed, 188 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml 
b/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml
index a90a8b3f1a9e..628ca68871f4 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml
@@ -52,6 +52,26 @@ patternProperties:
 items:
   - const: qcom,sa8775p-dp
 
+  "^dsi@[0-9a-f]+$":
+type: object
+additionalProperties: true
+
+properties:
+  compatible:
+items:
+  - const: qcom,sa8775p-dsi-ctrl
+  - const: qcom,mdss-dsi-ctrl
+
+  "^phy@[0-9a-f]+$":
+type: object
+additionalProperties: true
+
+properties:
+  compatible:
+enum:
+  - qcom,sa8775p-dsi-phy-5nm
+  - qcom,sa8775p-edp-phy
+
 required:
   - compatible
 
@@ -131,6 +151,20 @@ examples:
 remote-endpoint = <&mdss0_dp0_in>;
 };
 };
+
+port@1 {
+reg = <1>;
+dpu_intf1_out: endpoint {
+remote-endpoint = <&mdss0_dsi0_in>;
+};
+};
+
+port@2 {
+reg = <2>;
+dpu_intf2_out: endpoint {
+remote-endpoint = <&mdss0_dsi1_in>;
+};
+};
 };
 
 mdss0_mdp_opp_table: opp-table {
@@ -158,6 +192,160 @@ examples:
 };
 };
 
+dsi@ae94000 {
+compatible = "qcom,sa8775p-dsi-ctrl", "qcom,mdss-dsi-ctrl";
+reg = <0x0ae94000 0x400>;
+reg-names = "dsi_ctrl";
+
+interrupt-parent = <&mdss>;
+interrupts = <4>;
+
+clocks = <&dispc_byte_clk>,
+ <&dispcc_intf_clk>,
+ <&dispcc_pclk>,
+ <&dispcc_esc_clk>,
+ <&dispcc_ahb_clk>,
+ <&gcc_bus_clk>;
+clock-names = "byte",
+  "byte_intf",
+  "pixel",
+  "core",
+  "iface",
+  "bus";
+assigned-clocks = <&dispcc_byte_clk>,
+  <&dispcc_pclk>;
+assigned-clock-parents = <&mdss0_dsi0_phy 0>, <&mdss0_dsi0_phy 1>;
+phys = <&mdss0_dsi0_phy>;
+
+operating-points-v2 = <&dsi0_opp_table>;
+power-domains = <&rpmhpd SA8775P_MMCX>;
+
+#address-cells = <1>;
+#size-cells = <0>;
+
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+
+port@0 {
+reg = <0>;
+mdss0_dsi0_in: endpoint {
+remote-endpoint = <&dpu_intf1_out>;
+};
+};
+
+port@1 {
+reg = <1>;
+mdss0_dsi0_out: endpoint { };
+};
+};
+
+dsi0_opp_table: opp-table {
+compatible = "operating-points-v2";
+
+opp-35800 {
+opp-hz = /bits/ 64 <35800>;
+required-opps = <&rpmhpd_opp_svs_l1>;
+};
+};
+};
+
+mdss0_dsi0_phy: phy@ae94400 {
+compatible = "qcom,sa8775p-dsi-phy-5nm";
+reg = <0x0ae94400 0x200>,
+  <0x0ae94600 0x280>,
+  <0x0ae94900 0x27c>;
+reg-names = "dsi_phy",
+"dsi_phy_lane",
+"dsi_pll";
+
+#clock-cells = <1>;
+#phy-cells = <0>;
+
+clocks = <&dispcc_iface_clk>,
+ <&rpmhcc_ref_clk>;
+clock-names = "iface", "ref";
+
+vdds-supply = <&vreg_dsi_supply>;
+};
+
+dsi@ae96000 {
+compatible = "qcom,sa8775p-dsi-ctrl", "qcom,mdss-dsi-ctrl";
+reg = <0x0ae96000 0x400>;
+reg-names = "dsi_ctrl";
+
+interrupt-parent = <&mdss>;
+interrupts = <4>;
+
+clocks = <&dispc_byte_clk>,
+ <&dispcc_intf_clk>,
+ <&dispcc_pclk>,
+ <&dispcc_esc_clk>,
+ <&dispcc_ahb_clk>,
+ <&gcc_bus_clk>;
+clock-names = "byte",
+  "byte_intf",
+  "pixel",
+  "core",
+  "iface",
+  "bus";
+assigned-clocks = <&dispcc_byte_clk>,
+  <&dispcc_pclk>;
+

[PATCH v2 05/10] drm/msm/dsi: add DSI support for SA8775P

2025-03-11 Thread Ayushi Makhija
Add DSI Controller v2.5.1 support for SA8775P SoC.

Signed-off-by: Ayushi Makhija 
---
 drivers/gpu/drm/msm/dsi/dsi_cfg.c | 18 ++
 drivers/gpu/drm/msm/dsi/dsi_cfg.h |  1 +
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c 
b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
index 7754dcec33d0..7675558ae2e5 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -221,6 +221,22 @@ static const struct msm_dsi_config sc7280_dsi_cfg = {
},
 };
 
+static const struct regulator_bulk_data sa8775p_dsi_regulators[] = {
+   { .supply = "vdda", .init_load_uA = 8300 },/* 1.2 V */
+   { .supply = "refgen" },
+};
+
+static const struct msm_dsi_config sa8775p_dsi_cfg = {
+   .io_offset = DSI_6G_REG_SHIFT,
+   .regulator_data = sa8775p_dsi_regulators,
+   .num_regulators = ARRAY_SIZE(sa8775p_dsi_regulators),
+   .bus_clk_names = dsi_v2_4_clk_names,
+   .num_bus_clks = ARRAY_SIZE(dsi_v2_4_clk_names),
+   .io_start = {
+   { 0xae94000, 0xae96000 },
+   },
+};
+
 static const struct msm_dsi_host_cfg_ops msm_dsi_v2_host_ops = {
.link_clk_set_rate = dsi_link_clk_set_rate_v2,
.link_clk_enable = dsi_link_clk_enable_v2,
@@ -294,6 +310,8 @@ static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] 
= {
&sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_5_0,
&sc7280_dsi_cfg, &msm_dsi_6g_v2_host_ops},
+   {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_5_1,
+   &sa8775p_dsi_cfg, &msm_dsi_6g_v2_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_6_0,
&sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_7_0,
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h 
b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
index 120cb65164c1..65b0705fac0e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
@@ -27,6 +27,7 @@
 #define MSM_DSI_6G_VER_MINOR_V2_4_00x2004
 #define MSM_DSI_6G_VER_MINOR_V2_4_10x20040001
 #define MSM_DSI_6G_VER_MINOR_V2_5_00x2005
+#define MSM_DSI_6G_VER_MINOR_V2_5_10x20050001
 #define MSM_DSI_6G_VER_MINOR_V2_6_00x2006
 #define MSM_DSI_6G_VER_MINOR_V2_7_00x2007
 #define MSM_DSI_6G_VER_MINOR_V2_8_00x2008
-- 
2.34.1



[PATCH v2 01/10] dt-bindings: display: msm-dsi-phy-7nm: document the SA8775P DSI PHY

2025-03-11 Thread Ayushi Makhija
Document the DSI PHY on the SA8775P Platform.

Signed-off-by: Ayushi Makhija 
---
 Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml 
b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
index 321470435e65..fd5728f3e89f 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
@@ -17,6 +17,7 @@ properties:
 enum:
   - qcom,dsi-phy-7nm
   - qcom,dsi-phy-7nm-8150
+  - qcom,sa8775p-dsi-phy-5nm
   - qcom,sc7280-dsi-phy-7nm
   - qcom,sm6375-dsi-phy-7nm
   - qcom,sm8350-dsi-phy-5nm
-- 
2.34.1



[PATCH v2 06/10] arm64: dts: qcom: sa8775p: add Display Serial Interface device nodes

2025-03-11 Thread Ayushi Makhija
Add device tree nodes for the DSI0 and DSI1 controllers
with their corresponding PHYs found on Qualcomm SA8775P SoC.

Signed-off-by: Ayushi Makhija 
---
 arch/arm64/boot/dts/qcom/sa8775p.dtsi | 186 +-
 1 file changed, 185 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi 
b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
index 3394ae2d1300..edc5130f4bae 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
@@ -6,6 +6,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -3890,6 +3891,22 @@ dpu_intf4_out: endpoint {
remote-endpoint = 
<&mdss0_dp1_in>;
};
};
+
+   port@2 {
+   reg = <2>;
+
+   dpu_intf1_out: endpoint {
+   remote-endpoint = 
<&mdss0_dsi0_in>;
+   };
+   };
+
+   port@3 {
+   reg = <3>;
+
+   dpu_intf2_out: endpoint {
+   remote-endpoint = 
<&mdss0_dsi1_in>;
+   };
+   };
};
 
mdss0_mdp_opp_table: opp-table {
@@ -3917,6 +3934,170 @@ opp-65000 {
};
};
 
+   mdss0_dsi0: dsi@ae94000 {
+   compatible = "qcom,sa8775p-dsi-ctrl", 
"qcom,mdss-dsi-ctrl";
+   reg = <0x0 0x0ae94000 0x0 0x400>;
+   reg-names = "dsi_ctrl";
+
+   interrupt-parent = <&mdss0>;
+   interrupts = <4>;
+
+   clocks = <&dispcc0 MDSS_DISP_CC_MDSS_BYTE0_CLK>,
+<&dispcc0 
MDSS_DISP_CC_MDSS_BYTE0_INTF_CLK>,
+<&dispcc0 MDSS_DISP_CC_MDSS_PCLK0_CLK>,
+<&dispcc0 MDSS_DISP_CC_MDSS_ESC0_CLK>,
+<&dispcc0 MDSS_DISP_CC_MDSS_AHB_CLK>,
+<&gcc GCC_DISP_HF_AXI_CLK>;
+   clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+   assigned-clocks = <&dispcc0 
MDSS_DISP_CC_MDSS_BYTE0_CLK_SRC>,
+ <&dispcc0 
MDSS_DISP_CC_MDSS_PCLK0_CLK_SRC>;
+   assigned-clock-parents = <&mdss0_dsi0_phy 
DSI_BYTE_PLL_CLK>,
+<&mdss0_dsi0_phy 
DSI_PIXEL_PLL_CLK>;
+   phys = <&mdss0_dsi0_phy>;
+
+   operating-points-v2 = <&dsi0_opp_table>;
+   power-domains = <&rpmhpd SA8775P_MMCX>;
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   status = "disabled";
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port@0 {
+   reg = <0>;
+
+   mdss0_dsi0_in: endpoint {
+   remote-endpoint = 
<&dpu_intf1_out>;
+   };
+   };
+
+   port@1 {
+   reg = <1>;
+
+   mdss0_dsi0_out: endpoint{ };
+   };
+   };
+
+   dsi0_opp_table: opp-table {
+   compatible = "operating-points-v2";
+
+   opp-35800 {
+   opp-hz = /bits/ 64 <35800>;
+   required-opps = 
<&rpmhpd_opp_svs_l1>;
+   };
+   };
+   };
+
+   md

[PATCH v1 2/2] drm/msm/dp: Introduce link training per-segment for LTTPRs

2025-03-11 Thread Aleksandrs Vinarskis
DisplayPort requires per-segment link training when LTTPR are switched
to non-transparent mode, starting with LTTPR closest to the source.
Only when each segment is trained individually, source can link train
to sink.

Implement per-segment link traning when LTTPR(s) are detected, to
support external docking stations. On higher level, changes are:

*  Pass phy being trained down to all required helpers
*  Run CR, EQ link training per phy
*  Set voltage swing, pre-emphasis levels per phy

This ensures successful link training both when connected directly to
the monitor (single LTTPR onboard most X1E laptops) and via the docking
station (at least two LTTPRs). This does not address/resolve underlying
mainlink initialization issues.

Signed-off-by: Aleksandrs Vinarskis 
---
 drivers/gpu/drm/msm/dp/dp_ctrl.c| 136 +++-
 drivers/gpu/drm/msm/dp/dp_ctrl.h|   2 +-
 drivers/gpu/drm/msm/dp/dp_display.c |   4 +-
 3 files changed, 98 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index d8633a596f8d..20f07ef46ef3 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -79,6 +79,8 @@ struct msm_dp_ctrl_private {
struct msm_dp_link *link;
struct msm_dp_catalog *catalog;
 
+   int *lttpr_count;
+
struct phy *phy;
 
unsigned int num_core_clks;
@@ -1034,7 +1036,8 @@ static int msm_dp_ctrl_set_vx_px(struct 
msm_dp_ctrl_private *ctrl,
return 0;
 }
 
-static int msm_dp_ctrl_update_vx_px(struct msm_dp_ctrl_private *ctrl)
+static int msm_dp_ctrl_update_phy_vx_px(struct msm_dp_ctrl_private *ctrl,
+   enum drm_dp_phy dp_phy)
 {
struct msm_dp_link *link = ctrl->link;
int ret = 0, lane, lane_cnt;
@@ -1075,8 +1078,12 @@ static int msm_dp_ctrl_update_vx_px(struct 
msm_dp_ctrl_private *ctrl)
 
drm_dbg_dp(ctrl->drm_dev, "sink: p|v=0x%x\n",
voltage_swing_level | pre_emphasis_level);
-   ret = drm_dp_dpcd_write(ctrl->aux, DP_TRAINING_LANE0_SET,
-   buf, lane_cnt);
+
+   int reg = dp_phy == DP_PHY_DPRX ?
+   DP_TRAINING_LANE0_SET :
+   DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy);
+
+   ret = drm_dp_dpcd_write(ctrl->aux, reg, buf, lane_cnt);
if (ret == lane_cnt)
ret = 0;
 
@@ -1084,10 +1091,13 @@ static int msm_dp_ctrl_update_vx_px(struct 
msm_dp_ctrl_private *ctrl)
 }
 
 static bool msm_dp_ctrl_train_pattern_set(struct msm_dp_ctrl_private *ctrl,
-   u8 pattern)
+   u8 pattern, enum drm_dp_phy dp_phy)
 {
u8 buf;
int ret = 0;
+   int reg = dp_phy == DP_PHY_DPRX ?
+   DP_TRAINING_PATTERN_SET :
+   DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy);
 
drm_dbg_dp(ctrl->drm_dev, "sink: pattern=%x\n", pattern);
 
@@ -1096,7 +1106,7 @@ static bool msm_dp_ctrl_train_pattern_set(struct 
msm_dp_ctrl_private *ctrl,
if (pattern && pattern != DP_TRAINING_PATTERN_4)
buf |= DP_LINK_SCRAMBLING_DISABLE;
 
-   ret = drm_dp_dpcd_writeb(ctrl->aux, DP_TRAINING_PATTERN_SET, buf);
+   ret = drm_dp_dpcd_writeb(ctrl->aux, reg, buf);
return ret == 1;
 }
 
@@ -1115,12 +1125,16 @@ static int msm_dp_ctrl_read_link_status(struct 
msm_dp_ctrl_private *ctrl,
 }
 
 static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl,
-   int *training_step)
+   int *training_step, enum drm_dp_phy dp_phy)
 {
+   int delay_us;
int tries, old_v_level, ret = 0;
u8 link_status[DP_LINK_STATUS_SIZE];
int const maximum_retries = 4;
 
+   delay_us = drm_dp_read_clock_recovery_delay(ctrl->aux,
+   ctrl->panel->dpcd, dp_phy, false);
+
msm_dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);
 
*training_step = DP_TRAINING_1;
@@ -1129,18 +1143,19 @@ static int msm_dp_ctrl_link_train_1(struct 
msm_dp_ctrl_private *ctrl,
if (ret)
return ret;
msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 |
-   DP_LINK_SCRAMBLING_DISABLE);
+   DP_LINK_SCRAMBLING_DISABLE, dp_phy);
 
-   ret = msm_dp_ctrl_update_vx_px(ctrl);
+   msm_dp_link_reset_phy_params_vx_px(ctrl->link);
+   ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy);
if (ret)
return ret;
 
tries = 0;
old_v_level = ctrl->link->phy_params.v_level;
for (tries = 0; tries < maximum_retries; tries++) {
-   drm_dp_link_train_clock_recovery_delay(ctrl->aux, 
ctrl->panel->dpcd);
+   fsleep(delay_us);
 
-   ret = msm_dp_ctrl_read_link_status(ctrl, link_status);
+   ret = drm_dp_dpcd_read_phy_link_status(ctrl->aux, dp_phy, 
link_status);
if (ret)
return r

[PATCH v2 04/10] drm/msm/dsi: add DSI PHY configuration on SA8775P

2025-03-11 Thread Ayushi Makhija
The SA8775P SoC uses the 5nm (v4.2) DSI PHY driver with
different enable regulator load.

Signed-off-by: Ayushi Makhija 
---
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c |  2 ++
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h |  1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 27 +++
 3 files changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index c0bcc6828963..92be08ac5f65 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -581,6 +581,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
  .data = &dsi_phy_7nm_cfgs },
{ .compatible = "qcom,dsi-phy-7nm-8150",
  .data = &dsi_phy_7nm_8150_cfgs },
+   { .compatible = "qcom,sa8775p-dsi-phy-5nm",
+ .data = &dsi_phy_5nm_8775p_cfgs },
{ .compatible = "qcom,sc7280-dsi-phy-7nm",
  .data = &dsi_phy_7nm_7280_cfgs },
{ .compatible = "qcom,sm6375-dsi-phy-7nm",
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 8985818bb2e0..22f23a5b9fa0 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -58,6 +58,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_7nm_7280_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8775p_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs;
 
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
index 798168180c1a..598ea183c746 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -1146,6 +1146,10 @@ static const struct regulator_bulk_data 
dsi_phy_7nm_37750uA_regulators[] = {
{ .supply = "vdds", .init_load_uA = 37550 },
 };
 
+static const struct regulator_bulk_data dsi_phy_7nm_48000uA_regulators[] = {
+   { .supply = "vdds", .init_load_uA = 48000 },
+};
+
 static const struct regulator_bulk_data dsi_phy_7nm_98000uA_regulators[] = {
{ .supply = "vdds", .init_load_uA = 98000 },
 };
@@ -1288,6 +1292,29 @@ const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs = {
.quirks = DSI_PHY_7NM_QUIRK_V4_3,
 };
 
+const struct msm_dsi_phy_cfg dsi_phy_5nm_8775p_cfgs = {
+   .has_phy_lane = true,
+   .regulator_data = dsi_phy_7nm_48000uA_regulators,
+   .num_regulators = ARRAY_SIZE(dsi_phy_7nm_48000uA_regulators),
+   .ops = {
+   .enable = dsi_7nm_phy_enable,
+   .disable = dsi_7nm_phy_disable,
+   .pll_init = dsi_pll_7nm_init,
+   .save_pll_state = dsi_7nm_pll_save_state,
+   .restore_pll_state = dsi_7nm_pll_restore_state,
+   .set_continuous_clock = dsi_7nm_set_continuous_clock,
+   },
+   .min_pll_rate = 6UL,
+#ifdef CONFIG_64BIT
+   .max_pll_rate = 50UL,
+#else
+   .max_pll_rate = ULONG_MAX,
+#endif
+   .io_start = { 0xae94400, 0xae96400 },
+   .num_dsi_phy = 2,
+   .quirks = DSI_PHY_7NM_QUIRK_V4_2,
+};
+
 const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs = {
.has_phy_lane = true,
.regulator_data = dsi_phy_7nm_98400uA_regulators,
-- 
2.34.1



[PATCH v1 0/2] drm/msm/dp: Introduce link training per-segment for LTTPRs

2025-03-11 Thread Aleksandrs Vinarskis
Recently added Initial LTTPR support in msm/dp has configured LTTPR(s)
to non-transparent mode to enable video output on X1E-based devices
that come with LTTPR on the motherboards. However, video would not work
if additional LTTPR(s) are present between sink and source, which is
the case for USB Type-C docks (eg. Dell WD19TB/WD22TB4), and at least
some universal Thunderbolt/USB Type-C monitors (eg. Dell U2725QE).

First, take into account LTTPR capabilities when computing max link
rate, number of lanes. Take into account previous discussion on the
lists - exit early if reading DPCD caps failed. This also fixes
"*ERROR* panel edid read failed" on some monitors which seems to be
caused by msm_dp_panel_read_sink_caps running before LTTPR(s) are
initialized.

Finally, implement link training per-segment. Pass lttpr_count to all
required helpers. This seems to also partially improve UI hanging when
changing external display's link parameters (resolution, framerate):
* Prior to this series, via direct USB Type-C to display connection,
  attempt to change resolution or framerate hangs the UI, setting does
  not stick. Some back and forth replugging finally sets desired
  parameters.
* With this series, via direct USB Type-C to display connection,
  changing parameters works most of the time, without UI freezing. Via
  docking station/multiple LTTPRs the setting works when increasing
  bandwith (eg. change framerate from 60hz to 100hz), but in all other
  cases the setting again does not stick.

These appear to be mainlink initialization related, as in all cases LT
passes successfully.

Test matrix:
* Dell XPS 9345
* Left USB Type-C, Right USB Type-C
* Direct monitor connection, Dell WD19TB, Dell WD22TB4
* Dell AW3423DWF, Samsung LS24A600, dual Samsung LS24A600 (one
  monitor per USB Type-C connector)
* Dell XPS 9345
* Left USB Type-C, Right USB Type-C
* Direct monitor connection
* Dell U2725QE (universal Thunderbolt/DP Alt mode, probes with
  LTTPR when in DP Alt mode)

In both cases, "Thunderbot Support"/"USB4 PCIE Tunneling" was disabled
in UEFI to force universal Thunderbolt/DP Alt mode devices to work in
DP Alt mode.
In both cases laptops had HBR3 patches applied [1], resulting in
maximum successful link with 3440x1440@100hz and 4k@60hz respectively.
When using WD22TB4/U2725QE, USB Type-C pin assigment D got enabled, and
USB3.0 devices were working in parallel to video ouput.

Known issues:
* As mentioned above, mainlink parameters changing is not stable, but
  appears to be unrelated to this series, and works better than before.
* In a very particular combination of Dell XPS 9345 + Dell AW3423DWF at
  max resolution, right USB Type-C connector does not always work:
  following successful link training, mainlink is not starting. When
  switching monitor to PIP/PBP mode, the issue is gone. I am unable to
  reproduce this issue in any other combination of devices/modes, so
  perhaps its an edge case of either the monitor (Dell AW3423DWF) or
  the docking station (Dell WD19TB/WD22TB4) specifically.


Due to lack of access to official DisplayPort specfication, changes
were primarily inspired by/reverse engineered from Intel's i915 driver.

[1] https://lore.kernel.org/all/20250226231436.16138-2-alex.vinars...@gmail.com/

Aleksandrs Vinarskis (2):
  drm/msm/dp: Fix support of LTTPR handling
  drm/msm/dp: Introduce link training per-segment for LTTPRs

 drivers/gpu/drm/msm/dp/dp_ctrl.c| 136 +++-
 drivers/gpu/drm/msm/dp/dp_ctrl.h|   2 +-
 drivers/gpu/drm/msm/dp/dp_display.c |  33 +--
 drivers/gpu/drm/msm/dp/dp_panel.c   |  30 --
 drivers/gpu/drm/msm/dp/dp_panel.h   |   2 +
 5 files changed, 141 insertions(+), 62 deletions(-)

-- 
2.45.2



Re: [PATCH 05/10] dt-bindings: display/msm: Add Qualcomm SAR2130P

2025-03-11 Thread Krzysztof Kozlowski
On Sat, Mar 08, 2025 at 03:42:23AM +0200, Dmitry Baryshkov wrote:
> +patternProperties:
> +  "^display-controller@[0-9a-f]+$":
> +type: object
> +additionalProperties: true
> +

Drop blank line

> +properties:
> +  compatible:
> +const: qcom,sar2130p-dpu
> +
> +  "^displayport-controller@[0-9a-f]+$":
> +type: object
> +additionalProperties: true
> +

Drop blank line

> +properties:
> +  compatible:
> +items:
> +  - const: qcom,sar2130p-dp
> +  - const: qcom,sm8350-dp
> +
> +  "^dsi@[0-9a-f]+$":
> +type: object
> +additionalProperties: true
> +

Drop blank line

> +properties:
> +  compatible:
> +items:
> +  - const: qcom,sar2130p-dsi-ctrl
> +  - const: qcom,mdss-dsi-ctrl

Drop last compatible here and use contains (see v3 of my sm8750)

> +
> +  "^phy@[0-9a-f]+$":
> +type: object
> +additionalProperties: true
> +

Drop blank line

> +properties:
> +  compatible:
> +const: qcom,sar2130p-dsi-phy-5nm
> +
> +required:
> +  - compatible

Reviewed-by: Krzysztof Kozlowski 

Best regards,
Krzysztof



Re: [PATCH v5 1/2] drm/bridge: split HDMI Audio from DRM_BRIDGE_OP_HDMI

2025-03-11 Thread Maxime Ripard
Hi,

On Fri, Mar 07, 2025 at 07:55:52AM +0200, Dmitry Baryshkov wrote:
> From: Dmitry Baryshkov 
> 
> As pointed out by Laurent, OP bits are supposed to describe operations.
> Split DRM_BRIDGE_OP_HDMI_AUDIO from DRM_BRIDGE_OP_HDMI instead of
> overloading DRM_BRIDGE_OP_HDMI.
> 
> Signed-off-by: Dmitry Baryshkov 
> ---
>  drivers/gpu/drm/bridge/lontium-lt9611.c|  2 +-
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c   |  1 +
>  drivers/gpu/drm/display/drm_bridge_connector.c | 59 
> +-
>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c |  1 +
>  include/drm/drm_bridge.h   | 23 --
>  5 files changed, 61 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c 
> b/drivers/gpu/drm/bridge/lontium-lt9611.c
> index 
> 026803034231f78c17f619dc04119bdd9b2b6679..3b93c17e25c18ae0d13e9bb74553cf21dcc39f9d
>  100644
> --- a/drivers/gpu/drm/bridge/lontium-lt9611.c
> +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
> @@ -1130,7 +1130,7 @@ static int lt9611_probe(struct i2c_client *client)
>   lt9611->bridge.of_node = client->dev.of_node;
>   lt9611->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
>DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES |
> -  DRM_BRIDGE_OP_HDMI;
> +  DRM_BRIDGE_OP_HDMI | DRM_BRIDGE_OP_HDMI_AUDIO;
>   lt9611->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
>   lt9611->bridge.vendor = "Lontium";
>   lt9611->bridge.product = "LT9611";
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c 
> b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> index 
> 6166f197e37b552cb8a52b7b0d23ffc632f54557..5e5f8c2f95be1f5c4633f1093b17a00f9425bb37
>  100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> @@ -1077,6 +1077,7 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct 
> platform_device *pdev,
>   hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT |
>  DRM_BRIDGE_OP_EDID |
>  DRM_BRIDGE_OP_HDMI |
> +DRM_BRIDGE_OP_HDMI_AUDIO |
>  DRM_BRIDGE_OP_HPD;
>   hdmi->bridge.of_node = pdev->dev.of_node;
>   hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
> diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c 
> b/drivers/gpu/drm/display/drm_bridge_connector.c
> index 
> 30c736fc0067e31a97db242e5b16ea8a5b4cf359..030f98d454608a63154827c65d4822d378df3b4c
>  100644
> --- a/drivers/gpu/drm/display/drm_bridge_connector.c
> +++ b/drivers/gpu/drm/display/drm_bridge_connector.c
> @@ -98,6 +98,13 @@ struct drm_bridge_connector {
>* HDMI connector infrastructure, if any (see &DRM_BRIDGE_OP_HDMI).
>*/
>   struct drm_bridge *bridge_hdmi;
> + /**
> +  * @bridge_hdmi_audio:
> +  *
> +  * The bridge in the chain that implements necessary support for the
> +  * HDMI Audio infrastructure, if any (see &DRM_BRIDGE_OP_HDMI_AUDIO).
> +  */
> + struct drm_bridge *bridge_hdmi_audio;
>  };
>  
>  #define to_drm_bridge_connector(x) \
> @@ -433,7 +440,7 @@ static int drm_bridge_connector_audio_startup(struct 
> drm_connector *connector)
>   to_drm_bridge_connector(connector);
>   struct drm_bridge *bridge;
>  
> - bridge = bridge_connector->bridge_hdmi;
> + bridge = bridge_connector->bridge_hdmi_audio;
>   if (!bridge)
>   return -EINVAL;
>  
> @@ -451,7 +458,7 @@ static int drm_bridge_connector_audio_prepare(struct 
> drm_connector *connector,
>   to_drm_bridge_connector(connector);
>   struct drm_bridge *bridge;
>  
> - bridge = bridge_connector->bridge_hdmi;
> + bridge = bridge_connector->bridge_hdmi_audio;
>   if (!bridge)
>   return -EINVAL;
>  
> @@ -464,7 +471,7 @@ static void drm_bridge_connector_audio_shutdown(struct 
> drm_connector *connector)
>   to_drm_bridge_connector(connector);
>   struct drm_bridge *bridge;
>  
> - bridge = bridge_connector->bridge_hdmi;
> + bridge = bridge_connector->bridge_hdmi_audio;
>   if (!bridge)
>   return;
>  
> @@ -478,7 +485,7 @@ static int drm_bridge_connector_audio_mute_stream(struct 
> drm_connector *connecto
>   to_drm_bridge_connector(connector);
>   struct drm_bridge *bridge;
>  
> - bridge = bridge_connector->bridge_hdmi;
> + bridge = bridge_connector->bridge_hdmi_audio;
>   if (!bridge)
>   return -EINVAL;
>  
> @@ -576,6 +583,21 @@ struct drm_connector *drm_bridge_connector_init(struct 
> drm_device *drm,
>   max_bpc = bridge->max_bpc;
>   }
>  
> + if (bridge->ops & DRM_BRIDGE_OP_HDMI_AUDIO) {
> + if (bridge_connector->bridge_hdmi_audio)
> + return ERR_PTR(-EBUSY);
> +
> + if (!bridge->hdmi_audio_max_i2s_playback_channels &&
> +   

Re: [PATCH 3/4] drm/vc4: use new helper to get ACR values

2025-03-11 Thread Dmitry Baryshkov
On Mon, Mar 10, 2025 at 03:51:53PM +0100, Maxime Ripard wrote:
> On Sun, Mar 09, 2025 at 10:13:58AM +0200, Dmitry Baryshkov wrote:
> > From: Dmitry Baryshkov 
> > 
> > Use drm_hdmi_acr_get_n_cts() helper instead of calculating N and CTS
> > values in the VC4 driver.
> > 
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> >  drivers/gpu/drm/vc4/vc4_hdmi.c | 10 +++---
> >  drivers/gpu/drm/vc4/vc4_hdmi.h |  7 +++
> >  2 files changed, 10 insertions(+), 7 deletions(-)
> > 

> > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> > index 
> > e3d989ca302b72533c374dfa3fd0d5bd7fe64a82..0a775dbfe99d45521f3d0a2016555aefa81d7934
> >  100644
> > --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> > @@ -211,6 +211,13 @@ struct vc4_hdmi {
> >  * KMS hooks. Protected by @mutex.
> >  */
> > enum hdmi_colorspace output_format;
> > +
> > +   /**
> > +* @tmds_char_rate: Copy of
> > +* @drm_connector_state.hdmi.tmds_char_rate for use outside of
> > +* KMS hooks. Protected by @mutex.
> > +*/
> > +   unsigned long long tmds_char_rate;
> >  };
> 
> This should be in drm_connector_hdmi if it's useful

That would mean bringing the state to a non-state structure on the
framework level. Is it fine from your POV? Is it also fine to use
drm_connector.mutex for protecting this? Or should we be using something
like drm_connector_hdmi.infoframes.mutex (maybe after moving it from
.infoframes to the top level)?

-- 
With best wishes
Dmitry


Re: [PATCH 03/11] dt-bindings: power: qcom,kpss-acc-v2: Add MSM8916 compatible

2025-03-11 Thread Dmitry Baryshkov
On Thu, Mar 06, 2025 at 07:11:15PM +0100, Konrad Dybcio wrote:
> From: Konrad Dybcio 
> 
> MSM8916 seems to reuse the same hardware as MSM8974 and friends (for
> whom this binding document was created). Add a new compatible for it.

Ok, I should have read dt-bindigns before sending a comment. But this
commit doesn't explain, why do you need an extra compat string.

> 
> Signed-off-by: Konrad Dybcio 
> ---
>  Documentation/devicetree/bindings/power/qcom,kpss-acc-v2.yaml | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/power/qcom,kpss-acc-v2.yaml 
> b/Documentation/devicetree/bindings/power/qcom,kpss-acc-v2.yaml
> index 
> 202a5d51ee88c7190805efe8f1bf493bdb69ec45..27dae49163fa0790ceb6fda8a5c674f739d4a41a
>  100644
> --- a/Documentation/devicetree/bindings/power/qcom,kpss-acc-v2.yaml
> +++ b/Documentation/devicetree/bindings/power/qcom,kpss-acc-v2.yaml
> @@ -18,7 +18,9 @@ description:
>  
>  properties:
>compatible:
> -const: qcom,kpss-acc-v2
> +enum:
> +  - qcom,msm8916-kpss-acc
> +  - qcom,kpss-acc-v2
>  
>reg:
>  items:
> 
> -- 
> 2.48.1
> 

-- 
With best wishes
Dmitry


[PATCH v2 09/10] drm/bridge: anx7625: update bridge_ops and sink detect logic

2025-03-11 Thread Ayushi Makhija
The anx7625_link_bridge() checks if a device is not a panel
bridge and add DRM_BRIDGE_OP_HPD and DRM_BRIDGE_OP_DETECT to
the bridge operations. However, on port 1 of the anx7625
bridge, any device added is always treated as a panel
bridge, preventing connector_detect function from being
called. To resolve this, instead of just checking if it is a
panel bridge, verify the type of panel bridge
whether it is a DisplayPort or eDP panel. If the panel
bridge is not of the eDP type, add DRM_BRIDGE_OP_HPD and
DRM_BRIDGE_OP_DETECT to the bridge operations.

In the anx7625_sink_detect(), the device is checked to see
if it is a panel bridge, and it always sends a "connected"
status to the connector. When adding the DP port on port 1 of the
anx7625, it incorrectly treats it as a panel bridge and sends an
always "connected" status. Instead of checking the status on the
panel bridge, it's better to check the hpd_status for connectors
like DisplayPort. This way, it verifies the hpd_status variable
before sending the status to the connector.

Signed-off-by: Ayushi Makhija 
---
 drivers/gpu/drm/bridge/analogix/anx7625.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 764da1c1dc11..ad99ad19653f 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -1814,9 +1814,6 @@ static enum drm_connector_status 
anx7625_sink_detect(struct anx7625_data *ctx)
 
DRM_DEV_DEBUG_DRIVER(dev, "sink detect\n");
 
-   if (ctx->pdata.panel_bridge)
-   return connector_status_connected;
-
return ctx->hpd_status ? connector_status_connected :
 connector_status_disconnected;
 }
@@ -2608,9 +2605,10 @@ static int anx7625_link_bridge(struct drm_dp_aux *aux)
platform->bridge.of_node = dev->of_node;
if (!anx7625_of_panel_on_aux_bus(dev))
platform->bridge.ops |= DRM_BRIDGE_OP_EDID;
-   if (!platform->pdata.panel_bridge)
-   platform->bridge.ops |= DRM_BRIDGE_OP_HPD |
-   DRM_BRIDGE_OP_DETECT;
+   if (!platform->pdata.panel_bridge ||
+   platform->pdata.panel_bridge->type != DRM_MODE_CONNECTOR_eDP) {
+   platform->bridge.ops |= DRM_BRIDGE_OP_HPD | 
DRM_BRIDGE_OP_DETECT;
+   }
platform->bridge.type = platform->pdata.panel_bridge ?
DRM_MODE_CONNECTOR_eDP :
DRM_MODE_CONNECTOR_DisplayPort;
-- 
2.34.1



Re: [PATCH 02/10] dt-bindings: display/msm: dsi-controller-main: describe SAR2130P

2025-03-11 Thread Krzysztof Kozlowski
On Sat, Mar 08, 2025 at 03:42:20AM +0200, Dmitry Baryshkov wrote:
> From: Dmitry Baryshkov 
> 
> Describe MIPI DSI controller present on Qualcomm SAR2130P platform.
> 
> Signed-off-by: Dmitry Baryshkov 
> ---
>  Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml | 2 ++
>  1 file changed, 2 insertions(+)

Reviewed-by: Krzysztof Kozlowski 

Best regards,
Krzysztof



[PATCH 08/11] arm64: dts: qcom: sc8180x: Rename AOSS_QMP to power-management

2025-03-11 Thread Konrad Dybcio
From: Konrad Dybcio 

The node is currently named power-controller, which requires the device
underneath is a power domain provider. Rename it to align with other
SoCs and resolve this sort of warnings:

power-controller@c31: '#power-domain-cells' is a required property

Fixes: 8575f197b077 ("arm64: dts: qcom: Introduce the SC8180x platform")
Signed-off-by: Konrad Dybcio 
---
 arch/arm64/boot/dts/qcom/sc8180x.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/sc8180x.dtsi 
b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
index 
28693a3bfc7fefd883a7dee69a406235317c3047..f142eb63b8d7f443a8df2334cf3c205353762893
 100644
--- a/arch/arm64/boot/dts/qcom/sc8180x.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
@@ -3524,7 +3524,7 @@ tsens1: thermal-sensor@c265000 {
#thermal-sensor-cells = <1>;
};
 
-   aoss_qmp: power-controller@c30 {
+   aoss_qmp: power-management@c30 {
compatible = "qcom,sc8180x-aoss-qmp", "qcom,aoss-qmp";
reg = <0x0 0x0c30 0x0 0x400>;
interrupts = ;

-- 
2.48.1



Re: [PATCH v3 19/21] drm/msm/dpu: Implement CTL_PIPE_ACTIVE for v12.0 DPU

2025-03-11 Thread Krzysztof Kozlowski
On 21/02/2025 17:26, Dmitry Baryshkov wrote:
> Minot nit below
> 
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> index 
>> 43a254cf57da571e2ec8aad38028477652f9283c..3e0bdd1100ebb0d302a852ceeaf8af86835e69a1
>>  100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> @@ -40,6 +40,7 @@
>>  #define   CTL_INTF_FLUSH0x110
>>  #define   CTL_CDM_FLUSH0x114
>>  #define   CTL_PERIPH_FLUSH  0x128
>> +#define   CTL_PIPE_ACTIVE   0x12C
> 
> lowercase hex, please.
Ack

Best regards,
Krzysztof


Re: [PATCH v2 03/10] dt-bindings: display: msm: document DSI controller and phy on SA8775P

2025-03-11 Thread Dmitry Baryshkov
On Tue, Mar 11, 2025 at 05:54:38PM +0530, Ayushi Makhija wrote:
> Document DSI controller and phy on SA8775P platform.
> 
> Signed-off-by: Ayushi Makhija 
> ---
>  .../display/msm/qcom,sa8775p-mdss.yaml| 188 ++
>  1 file changed, 188 insertions(+)
> 
> diff --git 
> a/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml 
> b/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml
> index a90a8b3f1a9e..628ca68871f4 100644
> --- a/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml
> +++ b/Documentation/devicetree/bindings/display/msm/qcom,sa8775p-mdss.yaml
> @@ -52,6 +52,26 @@ patternProperties:
>  items:
>- const: qcom,sa8775p-dp
>  
> +  "^dsi@[0-9a-f]+$":
> +type: object
> +additionalProperties: true
> +
> +properties:
> +  compatible:
> +items:
> +  - const: qcom,sa8775p-dsi-ctrl
> +  - const: qcom,mdss-dsi-ctrl
> +
> +  "^phy@[0-9a-f]+$":
> +type: object
> +additionalProperties: true
> +
> +properties:
> +  compatible:
> +enum:
> +  - qcom,sa8775p-dsi-phy-5nm
> +  - qcom,sa8775p-edp-phy

This does more than is written in the commit message: it also adds eDP
PHY as a possible child. Please expand the commit message to account for
that.

> +
>  required:
>- compatible
>  
> @@ -131,6 +151,20 @@ examples:
>  remote-endpoint = <&mdss0_dp0_in>;
>  };
>  };
> +
> +port@1 {
> +reg = <1>;
> +dpu_intf1_out: endpoint {
> +remote-endpoint = <&mdss0_dsi0_in>;
> +};
> +};
> +
> +port@2 {
> +reg = <2>;
> +dpu_intf2_out: endpoint {
> +remote-endpoint = <&mdss0_dsi1_in>;
> +};
> +};
>  };
>  
>  mdss0_mdp_opp_table: opp-table {
> @@ -158,6 +192,160 @@ examples:
>  };
>  };
>  
> +dsi@ae94000 {
> +compatible = "qcom,sa8775p-dsi-ctrl", "qcom,mdss-dsi-ctrl";
> +reg = <0x0ae94000 0x400>;
> +reg-names = "dsi_ctrl";
> +
> +interrupt-parent = <&mdss>;
> +interrupts = <4>;
> +
> +clocks = <&dispc_byte_clk>,
> + <&dispcc_intf_clk>,
> + <&dispcc_pclk>,
> + <&dispcc_esc_clk>,
> + <&dispcc_ahb_clk>,
> + <&gcc_bus_clk>;
> +clock-names = "byte",
> +  "byte_intf",
> +  "pixel",
> +  "core",
> +  "iface",
> +  "bus";
> +assigned-clocks = <&dispcc_byte_clk>,
> +  <&dispcc_pclk>;
> +assigned-clock-parents = <&mdss0_dsi0_phy 0>, <&mdss0_dsi0_phy 
> 1>;
> +phys = <&mdss0_dsi0_phy>;
> +
> +operating-points-v2 = <&dsi0_opp_table>;
> +power-domains = <&rpmhpd SA8775P_MMCX>;
> +
> +#address-cells = <1>;
> +#size-cells = <0>;
> +
> +ports {
> +#address-cells = <1>;
> +#size-cells = <0>;
> +
> +port@0 {
> +reg = <0>;
> +mdss0_dsi0_in: endpoint {
> +remote-endpoint = <&dpu_intf1_out>;
> +};
> +};
> +
> +port@1 {
> +reg = <1>;
> +mdss0_dsi0_out: endpoint { };
> +};
> +};
> +
> +dsi0_opp_table: opp-table {
> +compatible = "operating-points-v2";
> +
> +opp-35800 {
> +opp-hz = /bits/ 64 <35800>;
> +required-opps = <&rpmhpd_opp_svs_l1>;
> +};
> +};
> +};
> +
> +mdss0_dsi0_phy: phy@ae94400 {
> +compatible = "qcom,sa8775p-dsi-phy-5nm";
> +reg = <0x0ae94400 0x200>,
> +  <0x0ae94600 0x280>,
> +  <0x0ae94900 0x27c>;
> +reg-names = "dsi_phy",
> +"dsi_phy_lane",
> +"dsi_pll";
> +
> +#clock-cells = <1>;
> +#phy-cells = <0>;
> +
> +clocks = <&dispcc_iface_clk>,
> + <&rpmhcc_ref_clk>;
> +clock-names = "iface", "ref";
> +
> +vdds-supply = <&vreg_dsi_supply>;
> +};
> +
> +dsi@ae96000 {
> +compatible = "qcom,sa8775p-dsi-ctrl", "qcom,mdss-dsi-ctrl";
> +reg = <0x0ae96000 0x400>;
> +reg-names = "dsi_ctrl";
> +
> +interrupt-parent = <&mdss>;
> +interrupts = <4>;
> +
> +clocks = <&dispc_byte_clk>,
> 

Re: [PATCH 1/4] drm/display: hdmi: provide central data authority for ACR params

2025-03-11 Thread Dmitry Baryshkov
On Tue, Mar 11, 2025 at 08:59:45AM +0100, Maxime Ripard wrote:
> On Mon, Mar 10, 2025 at 10:14:52PM +0200, Dmitry Baryshkov wrote:
> > On Mon, Mar 10, 2025 at 03:46:33PM +0100, Maxime Ripard wrote:
> > > On Sun, Mar 09, 2025 at 10:13:56AM +0200, Dmitry Baryshkov wrote:
> > > > From: Dmitry Baryshkov 
> > > > 
> > > > HDMI standard defines recommended N and CTS values for Audio Clock
> > > > Regeneration. Currently each driver implements those, frequently in
> > > > somewhat unique way. Provide a generic helper for getting those values
> > > > to be used by the HDMI drivers.
> > > > 
> > > > The helper is added to drm_hdmi_helper.c rather than drm_hdmi_audio.c
> > > > since HDMI drivers can be using this helper function even without
> > > > switching to DRM HDMI Audio helpers.
> > > > 
> > > > Note: currently this only handles the values per HDMI 1.4b Section 7.2
> > > > and HDMI 2.0 Section 9.2.1. Later the table can be expanded to
> > > > accommodate for Deep Color TMDS char rates per HDMI 1.4 Appendix D
> > > > and/or HDMI 2.0 / 2.1 Appendix C).
> > > > 
> > > > Signed-off-by: Dmitry Baryshkov 
> > > > ---
> > > >  drivers/gpu/drm/display/drm_hdmi_helper.c | 164 
> > > > ++
> > > >  include/drm/display/drm_hdmi_helper.h |   6 ++
> > > >  2 files changed, 170 insertions(+)
> > > > 
> > > > diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c 
> > > > b/drivers/gpu/drm/display/drm_hdmi_helper.c
> > > > index 
> > > > 74dd4d01dd9bb2c9e69ec1c60b0056bd69417e8a..89d25571bfd21c56c6835821d2272a12c816a76e
> > > >  100644
> > > > --- a/drivers/gpu/drm/display/drm_hdmi_helper.c
> > > > +++ b/drivers/gpu/drm/display/drm_hdmi_helper.c
> > > > @@ -256,3 +256,167 @@ drm_hdmi_compute_mode_clock(const struct 
> > > > drm_display_mode *mode,
> > > > return DIV_ROUND_CLOSEST_ULL(clock * bpc, 8);
> > > >  }
> > > >  EXPORT_SYMBOL(drm_hdmi_compute_mode_clock);
> > > > +
> > > > +struct drm_hdmi_acr_n_cts_entry {
> > > > +   unsigned int n;
> > > > +   unsigned int cts;
> > > > +};
> > > > +
> > > > +struct drm_hdmi_acr_data {
> > > > +   unsigned long tmds_clock_khz;
> > > > +   struct drm_hdmi_acr_n_cts_entry n_cts_32k,
> > > > +   n_cts_44k1,
> > > > +   n_cts_48k;
> > > > +};
> > > > +
> > > > +static const struct drm_hdmi_acr_data hdmi_acr_n_cts[] = {
> > > > +   {
> > > > +   /* "Other" entry */
> > > > +   .n_cts_32k =  { .n = 4096, },
> > > > +   .n_cts_44k1 = { .n = 6272, },
> > > > +   .n_cts_48k =  { .n = 6144, },
> > > > +   }, {
> > > > +   .tmds_clock_khz = 25175,
> > > > +   .n_cts_32k =  { .n = 4576,  .cts = 28125, },
> > > > +   .n_cts_44k1 = { .n = 7007,  .cts = 31250, },
> > > > +   .n_cts_48k =  { .n = 6864,  .cts = 28125, },
> > > > +   }, {
> > > > +   .tmds_clock_khz = 25200,
> > > > +   .n_cts_32k =  { .n = 4096,  .cts = 25200, },
> > > > +   .n_cts_44k1 = { .n = 6272,  .cts = 28000, },
> > > > +   .n_cts_48k =  { .n = 6144,  .cts = 25200, },
> > > > +   }, {
> > > > +   .tmds_clock_khz = 27000,
> > > > +   .n_cts_32k =  { .n = 4096,  .cts = 27000, },
> > > > +   .n_cts_44k1 = { .n = 6272,  .cts = 3, },
> > > > +   .n_cts_48k =  { .n = 6144,  .cts = 27000, },
> > > > +   }, {
> > > > +   .tmds_clock_khz = 27027,
> > > > +   .n_cts_32k =  { .n = 4096,  .cts = 27027, },
> > > > +   .n_cts_44k1 = { .n = 6272,  .cts = 30030, },
> > > > +   .n_cts_48k =  { .n = 6144,  .cts = 27027, },
> > > > +   }, {
> > > > +   .tmds_clock_khz = 54000,
> > > > +   .n_cts_32k =  { .n = 4096,  .cts = 54000, },
> > > > +   .n_cts_44k1 = { .n = 6272,  .cts = 6, },
> > > > +   .n_cts_48k =  { .n = 6144,  .cts = 54000, },
> > > > +   }, {
> > > > +   .tmds_clock_khz = 54054,
> > > > +   .n_cts_32k =  { .n = 4096,  .cts = 54054, },
> > > > +   .n_cts_44k1 = { .n = 6272,  .cts = 60060, },
> > > > +   .n_cts_48k =  { .n = 6144,  .cts = 54054, },
> > > > +   }, {
> > > > +   .tmds_clock_khz = 74176,
> > > > +   .n_cts_32k =  { .n = 11648, .cts = 210937, }, /* and 
> > > > 210938 */
> > > > +   .n_cts_44k1 = { .n = 17836, .cts = 234375, },
> > > > +   .n_cts_48k =  { .n = 11648, .cts = 140625, },
> > > > +   }, {
> > > > +   .tmds_clock_khz = 74250,
> > > > +   .n_cts_32k =  { .n = 4096,  .cts = 74250, },
> > > > +   .n_cts_44k1 = { .n = 6272,  .cts = 82500, },
> > > > +   .n_cts_48k =  { .n = 6144,  .cts = 74250, },
> > > > +   }, {
> > > > +   .tmds_clock_khz = 148352,
> > > > +   .n_cts_32k =  { .n = 11648, 

Re: [PATCH 3/4] drm/vc4: use new helper to get ACR values

2025-03-11 Thread Dmitry Baryshkov
On Tue, Mar 11, 2025 at 09:07:10AM +0100, Maxime Ripard wrote:
> On Mon, Mar 10, 2025 at 10:18:04PM +0200, Dmitry Baryshkov wrote:
> > On Mon, Mar 10, 2025 at 03:51:53PM +0100, Maxime Ripard wrote:
> > > On Sun, Mar 09, 2025 at 10:13:58AM +0200, Dmitry Baryshkov wrote:
> > > > From: Dmitry Baryshkov 
> > > > 
> > > > Use drm_hdmi_acr_get_n_cts() helper instead of calculating N and CTS
> > > > values in the VC4 driver.
> > > > 
> > > > Signed-off-by: Dmitry Baryshkov 
> > > > ---
> > > >  drivers/gpu/drm/vc4/vc4_hdmi.c | 10 +++---
> > > >  drivers/gpu/drm/vc4/vc4_hdmi.h |  7 +++
> > > >  2 files changed, 10 insertions(+), 7 deletions(-)
> > > > 
> > 
> > > > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h 
> > > > b/drivers/gpu/drm/vc4/vc4_hdmi.h
> > > > index 
> > > > e3d989ca302b72533c374dfa3fd0d5bd7fe64a82..0a775dbfe99d45521f3d0a2016555aefa81d7934
> > > >  100644
> > > > --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> > > > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> > > > @@ -211,6 +211,13 @@ struct vc4_hdmi {
> > > >  * KMS hooks. Protected by @mutex.
> > > >  */
> > > > enum hdmi_colorspace output_format;
> > > > +
> > > > +   /**
> > > > +* @tmds_char_rate: Copy of
> > > > +* @drm_connector_state.hdmi.tmds_char_rate for use outside of
> > > > +* KMS hooks. Protected by @mutex.
> > > > +*/
> > > > +   unsigned long long tmds_char_rate;
> > > >  };
> > > 
> > > This should be in drm_connector_hdmi if it's useful
> > 
> > That would mean bringing the state to a non-state structure on the
> > framework level. Is it fine from your POV?
> 
> Sorry, I'm changing my mind a little bit, but it's pretty much the same
> case than for accessing the infoframes from debugfs: we want to get some
> information stored in the state from outside of KMS.
> 
> What we did for the infoframes is that we're actually just taking the
> connection_mutex from the DRM device and access the drm_connector->state
> pointer.
> 
> I guess it would also work for ALSA?

I'd really prefer to follow the drm_connector.infoframes.audio. It makes
sense to group all ALSA-related functionality together. Maybe I should
refactor it to:

struct drm_connector {
struct {
struct mutex lock;
struct drm_connector_hdmi_infoframe audio_infoframe;
unsigned long long tmds_char_rate;
} audio;
};

WDYT? If that doesn't sound appealing, I'll go the connetion_mutex and
drm_connector_state way.

-- 
With best wishes
Dmitry


[PATCH v2 00/10] Add DSI display support for SA8775P target

2025-03-11 Thread Ayushi Makhija
This series enables the support for DSI to DP bridge ports
(labled as DSI0 and DSI1) of the Qualcomm's SA8775P Ride platform.

SA8775P SoC has DSI controller v2.5.1 and DSI PHY v4.2.
The Ride platform is having ANX7625 DSI to DP bridge chip from Analogix.

---
This patch depends on following series:
https://lore.kernel.org/linux-arm-msm/20250127-dts-qcom-dsi-phy-clocks-v1-0-9d8ddbcb1...@linaro.org/
(ARM / arm64: dts: qcom: Use the header with DSI phy clock IDs)

Changes in v2: Fixed review comments from Rob, konard, Dmitry and  Krzysztof
- Added additionalProperities in dsi and phy patternProperties in patch 3. 
[Rob's bot]
- Updated example in qcom,sa8775p-mdss.yaml of patch 3:
- Added port1 and port2 inside mdss0 ports.
- Renamed dsi ports from mdss_dsi0_in to mdss0_dsi0_in and mdss_dsi1_in 
to mdss0_dsi1_in.
- Updated the init load value for vdds supply of DSI PHY from
  15uA to 48000uA as per chipset power grid in patch 4. [Dmitry]
- Updated the init load value for vdda supply for DSI ctrl
  from 30100uA to 8300uA as per chipset power grid in patch 5. [Dmitry]
- Rebase the series to use the header with DSI phy clock IDs to make code 
more
  readable in patch 6. [konard]
- Added the interrupts-extended in patch 7. [konard]
- Fixed the warning from DT checker against DT binding in patch 7. 
[Krzysztof]
- Changed the connector node name from dsi0-connector to dp-dsi0-connector 
and dsi1-connector to dp-dsi1-connector
  respectively in patch 7. [Dmitry]
- Added the vph_pwr for anx7625 vdda10, vdds18 and vdda33 supply to fix the 
warnings from DT checker in
  patch 7. [Rob's bot]
- Addressed device tree comments in patch 7. [Konard]
- Squash the DT patch 8 into DT patch 7. [Dmitry]
- Added hpd_enable() and hpd_disable() bridge funcs in patch 9. [Dmitry]
- Update hpd detection bridge op flags logic based on eDP connector in 
patch 10. [Dmitry]
- Link to v1 : 
https://lore.kernel.org/linux-arm-msm/20250225121824.3869719-1-quic_amakh...@quicinc.com/

---

Ayushi Makhija (10):
  dt-bindings: display: msm-dsi-phy-7nm: document the SA8775P DSI PHY
  dt-bindings: msm: dsi-controller-main: document the SA8775P DSI CTRL
  dt-bindings: display: msm: document DSI controller and phy on SA8775P
  drm/msm/dsi: add DSI PHY configuration on SA8775P
  drm/msm/dsi: add DSI support for SA8775P
  arm64: dts: qcom: sa8775p: add Display Serial Interface device nodes
  arm64: dts: qcom: sa8775p-ride: add anx7625 DSI to DP bridge nodes
  drm/bridge: anx7625: enable HPD interrupts
  drm/bridge: anx7625: update bridge_ops and sink detect logic
  drm/bridge: anx7625: change the gpiod_set_value API

 .../display/msm/dsi-controller-main.yaml  |   1 +
 .../bindings/display/msm/dsi-phy-7nm.yaml |   1 +
 .../display/msm/qcom,sa8775p-mdss.yaml| 188 
 arch/arm64/boot/dts/qcom/sa8775p-ride.dtsi| 208 +-
 arch/arm64/boot/dts/qcom/sa8775p.dtsi | 186 +++-
 drivers/gpu/drm/bridge/analogix/anx7625.c |  36 ++-
 drivers/gpu/drm/msm/dsi/dsi_cfg.c |  18 ++
 drivers/gpu/drm/msm/dsi/dsi_cfg.h |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c |   2 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c |  27 +++
 11 files changed, 657 insertions(+), 12 deletions(-)

-- 
2.34.1



Re: [PATCH v5 1/2] drm/bridge: split HDMI Audio from DRM_BRIDGE_OP_HDMI

2025-03-11 Thread Dmitry Baryshkov
On Tue, Mar 11, 2025 at 04:58:59PM +0100, Maxime Ripard wrote:
> On Tue, Mar 11, 2025 at 05:50:09PM +0200, Dmitry Baryshkov wrote:
> > On Tue, Mar 11, 2025 at 09:36:37AM +0100, Maxime Ripard wrote:
> > > On Mon, Mar 10, 2025 at 08:42:29PM +0200, Dmitry Baryshkov wrote:
> > > > On Mon, 10 Mar 2025 at 16:55, Maxime Ripard  wrote:
> > > > >
> > > > > Hi,
> > > > >
> > > > > On Fri, Mar 07, 2025 at 07:55:52AM +0200, Dmitry Baryshkov wrote:
> > > > > > From: Dmitry Baryshkov 
> > > > > >
> > > > > > As pointed out by Laurent, OP bits are supposed to describe 
> > > > > > operations.
> > > > > > Split DRM_BRIDGE_OP_HDMI_AUDIO from DRM_BRIDGE_OP_HDMI instead of
> > > > > > overloading DRM_BRIDGE_OP_HDMI.
> > > > > >
> > > > > > Signed-off-by: Dmitry Baryshkov 
> > > > > > ---
> > > > > >  drivers/gpu/drm/bridge/lontium-lt9611.c|  2 +-
> > > > > >  drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c   |  1 +
> > > > > >  drivers/gpu/drm/display/drm_bridge_connector.c | 59 
> > > > > > +-
> > > > > >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c |  1 +
> > > > > >  include/drm/drm_bridge.h   | 23 --
> > > > > >  5 files changed, 61 insertions(+), 25 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c 
> > > > > > b/drivers/gpu/drm/bridge/lontium-lt9611.c
> > > > > > index 
> > > > > > 026803034231f78c17f619dc04119bdd9b2b6679..3b93c17e25c18ae0d13e9bb74553cf21dcc39f9d
> > > > > >  100644
> > > > > > --- a/drivers/gpu/drm/bridge/lontium-lt9611.c
> > > > > > +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
> > > > > > @@ -1130,7 +1130,7 @@ static int lt9611_probe(struct i2c_client 
> > > > > > *client)
> > > > > >   lt9611->bridge.of_node = client->dev.of_node;
> > > > > >   lt9611->bridge.ops = DRM_BRIDGE_OP_DETECT | 
> > > > > > DRM_BRIDGE_OP_EDID |
> > > > > >DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES |
> > > > > > -  DRM_BRIDGE_OP_HDMI;
> > > > > > +  DRM_BRIDGE_OP_HDMI | 
> > > > > > DRM_BRIDGE_OP_HDMI_AUDIO;
> > > > > >   lt9611->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
> > > > > >   lt9611->bridge.vendor = "Lontium";
> > > > > >   lt9611->bridge.product = "LT9611";
> > > > > > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c 
> > > > > > b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> > > > > > index 
> > > > > > 6166f197e37b552cb8a52b7b0d23ffc632f54557..5e5f8c2f95be1f5c4633f1093b17a00f9425bb37
> > > > > >  100644
> > > > > > --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> > > > > > +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
> > > > > > @@ -1077,6 +1077,7 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct 
> > > > > > platform_device *pdev,
> > > > > >   hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT |
> > > > > >  DRM_BRIDGE_OP_EDID |
> > > > > >  DRM_BRIDGE_OP_HDMI |
> > > > > > +DRM_BRIDGE_OP_HDMI_AUDIO |
> > > > > >  DRM_BRIDGE_OP_HPD;
> > > > > >   hdmi->bridge.of_node = pdev->dev.of_node;
> > > > > >   hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
> > > > > > diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c 
> > > > > > b/drivers/gpu/drm/display/drm_bridge_connector.c
> > > > > > index 
> > > > > > 30c736fc0067e31a97db242e5b16ea8a5b4cf359..030f98d454608a63154827c65d4822d378df3b4c
> > > > > >  100644
> > > > > > --- a/drivers/gpu/drm/display/drm_bridge_connector.c
> > > > > > +++ b/drivers/gpu/drm/display/drm_bridge_connector.c
> > > > > > @@ -98,6 +98,13 @@ struct drm_bridge_connector {
> > > > > >* HDMI connector infrastructure, if any (see 
> > > > > > &DRM_BRIDGE_OP_HDMI).
> > > > > >*/
> > > > > >   struct drm_bridge *bridge_hdmi;
> > > > > > + /**
> > > > > > +  * @bridge_hdmi_audio:
> > > > > > +  *
> > > > > > +  * The bridge in the chain that implements necessary support 
> > > > > > for the
> > > > > > +  * HDMI Audio infrastructure, if any (see 
> > > > > > &DRM_BRIDGE_OP_HDMI_AUDIO).
> > > > > > +  */
> > > > > > + struct drm_bridge *bridge_hdmi_audio;
> > > > > >  };
> > > > > >
> > > > > >  #define to_drm_bridge_connector(x) \
> > > > > > @@ -433,7 +440,7 @@ static int 
> > > > > > drm_bridge_connector_audio_startup(struct drm_connector *connector)
> > > > > >   to_drm_bridge_connector(connector);
> > > > > >   struct drm_bridge *bridge;
> > > > > >
> > > > > > - bridge = bridge_connector->bridge_hdmi;
> > > > > > + bridge = bridge_connector->bridge_hdmi_audio;
> > > > > >   if (!bridge)
> > > > > >   return -EINVAL;
> > > > > >
> > > > > > @@ -451,7 +458,7 @@ static int 
> > > > > > drm_bridge_connector_audio_prepare(struct drm_connector *connector,
> > > > > >   to_drm_bridge_connector(connector);
> > > > > >   struct drm_bridge *bridge;
> > > > > >
> > > > > > - bridge = bridge_c

[PATCH v4 05/19] dt-bindings: display/msm: qcom,sm8750-mdss: Add SM8750

2025-03-11 Thread Krzysztof Kozlowski
Add MDSS/MDP display subsystem for Qualcomm SM8750 SoC, next generation
with two revisions up of the IP block comparing to SM8650.

Reviewed-by: Rob Herring (Arm) 
Signed-off-by: Krzysztof Kozlowski 
---

Changes in v3:
1. Properly described interconnects
2. Use only one compatible and contains for the sub-blocks (Rob)
---
 .../bindings/display/msm/qcom,sm8750-mdss.yaml | 470 +
 1 file changed, 470 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/msm/qcom,sm8750-mdss.yaml 
b/Documentation/devicetree/bindings/display/msm/qcom,sm8750-mdss.yaml
new file mode 100644
index 
..72c70edc1fb01c61f8aad24fdb58bfb4f62a6e34
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8750-mdss.yaml
@@ -0,0 +1,470 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sm8750-mdss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SM8750 Display MDSS
+
+maintainers:
+  - Krzysztof Kozlowski 
+
+description:
+  SM8650 MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks like
+  DPU display controller, DSI and DP interfaces etc.
+
+$ref: /schemas/display/msm/mdss-common.yaml#
+
+properties:
+  compatible:
+const: qcom,sm8750-mdss
+
+  clocks:
+items:
+  - description: Display AHB
+  - description: Display hf AXI
+  - description: Display core
+
+  iommus:
+maxItems: 1
+
+  interconnects:
+items:
+  - description: Interconnect path from mdp0 port to the data bus
+  - description: Interconnect path from CPU to the reg bus
+
+  interconnect-names:
+items:
+  - const: mdp0-mem
+  - const: cpu-cfg
+
+patternProperties:
+  "^display-controller@[0-9a-f]+$":
+type: object
+additionalProperties: true
+properties:
+  compatible:
+const: qcom,sm8750-dpu
+
+  "^displayport-controller@[0-9a-f]+$":
+type: object
+additionalProperties: true
+properties:
+  compatible:
+contains:
+  const: qcom,sm8750-dp
+
+  "^dsi@[0-9a-f]+$":
+type: object
+additionalProperties: true
+properties:
+  compatible:
+contains:
+  const: qcom,sm8750-dsi-ctrl
+
+  "^phy@[0-9a-f]+$":
+type: object
+additionalProperties: true
+properties:
+  compatible:
+const: qcom,sm8750-dsi-phy-3nm
+
+required:
+  - compatible
+
+unevaluatedProperties: false
+
+examples:
+  - |
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+display-subsystem@ae0 {
+compatible = "qcom,sm8750-mdss";
+reg = <0x0ae0 0x1000>;
+reg-names = "mdss";
+
+interrupts = ;
+
+clocks = <&disp_cc_mdss_ahb_clk>,
+ <&gcc_disp_hf_axi_clk>,
+ <&disp_cc_mdss_mdp_clk>;
+
+interconnects = <&mmss_noc MASTER_MDP QCOM_ICC_TAG_ALWAYS
+ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>,
+<&gem_noc MASTER_APPSS_PROC 
QCOM_ICC_TAG_ACTIVE_ONLY
+ &config_noc SLAVE_DISPLAY_CFG 
QCOM_ICC_TAG_ACTIVE_ONLY>;
+interconnect-names = "mdp0-mem",
+ "cpu-cfg";
+
+resets = <&disp_cc_mdss_core_bcr>;
+
+power-domains = <&mdss_gdsc>;
+
+iommus = <&apps_smmu 0x800 0x2>;
+
+interrupt-controller;
+#interrupt-cells = <1>;
+
+#address-cells = <1>;
+#size-cells = <1>;
+ranges;
+
+display-controller@ae01000 {
+compatible = "qcom,sm8750-dpu";
+reg = <0x0ae01000 0x93000>,
+  <0x0aeb 0x2008>;
+reg-names = "mdp",
+"vbif";
+
+interrupts-extended = <&mdss 0>;
+
+clocks = <&gcc_disp_hf_axi_clk>,
+ <&disp_cc_mdss_ahb_clk>,
+ <&disp_cc_mdss_mdp_lut_clk>,
+ <&disp_cc_mdss_mdp_clk>,
+ <&disp_cc_mdss_vsync_clk>;
+clock-names = "nrt_bus",
+  "iface",
+  "lut",
+  "core",
+  "vsync";
+
+assigned-clocks = <&disp_cc_mdss_vsync_clk>;
+assigned-clock-rates = <1920>;
+
+operating-points-v2 = <&mdp_opp_table>;
+
+power-domains = <&rpmhpd RPMHPD_MMCX>;
+
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+
+port@0 {
+reg = <0>;
+
+dpu_intf1_out: endpoint {
+remote-endpoint = <&mdss_dsi0_in>;
+};
+};

[PATCH v4 06/19] drm/msm/dpu: Add missing "fetch" name to set_active_pipes()

2025-03-11 Thread Krzysztof Kozlowski
The set_active_pipes() callback configures CTL_FETCH_PIPE_ACTIVE and
newer DPU v12.0 comes with CTL_PIPE_ACTIVE, thus rename it to
set_active_fetch_pipes() to better match the purpose.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Jessica Zhang 
Signed-off-by: Krzysztof Kozlowski 
---

Changes in v2:
1. New patch
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c   | 12 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c |  6 +++---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h |  2 +-
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 
0714936d883523e5c53bfb42f932234db76c58db..2d7af6fff2708c12520a78cc6c979b9930dffc95
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -445,9 +445,9 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc 
*crtc,
 
uint32_t lm_idx;
bool bg_alpha_enable = false;
-   DECLARE_BITMAP(fetch_active, SSPP_MAX);
+   DECLARE_BITMAP(active_fetch, SSPP_MAX);
 
-   memset(fetch_active, 0, sizeof(fetch_active));
+   memset(active_fetch, 0, sizeof(active_fetch));
drm_atomic_crtc_for_each_plane(plane, crtc) {
state = plane->state;
if (!state)
@@ -464,7 +464,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc 
*crtc,
if (pstate->stage == DPU_STAGE_BASE && format->alpha_enable)
bg_alpha_enable = true;
 
-   set_bit(pstate->pipe.sspp->idx, fetch_active);
+   set_bit(pstate->pipe.sspp->idx, active_fetch);
_dpu_crtc_blend_setup_pipe(crtc, plane,
   mixer, cstate->num_mixers,
   pstate->stage,
@@ -472,7 +472,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc 
*crtc,
   &pstate->pipe, 0, stage_cfg);
 
if (pstate->r_pipe.sspp) {
-   set_bit(pstate->r_pipe.sspp->idx, fetch_active);
+   set_bit(pstate->r_pipe.sspp->idx, active_fetch);
_dpu_crtc_blend_setup_pipe(crtc, plane,
   mixer, cstate->num_mixers,
   pstate->stage,
@@ -492,8 +492,8 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc 
*crtc,
}
}
 
-   if (ctl->ops.set_active_pipes)
-   ctl->ops.set_active_pipes(ctl, fetch_active);
+   if (ctl->ops.set_active_fetch_pipes)
+   ctl->ops.set_active_fetch_pipes(ctl, active_fetch);
 
_dpu_crtc_program_lm_output_roi(crtc);
 }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 
216dfcabcb92d410ce185c0d34db69c99930d2b8..951d5dccab6faf34a519d06683514aea1ee6ef60
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -698,8 +698,8 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl 
*ctx,
}
 }
 
-static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx,
-   unsigned long *fetch_active)
+static void dpu_hw_ctl_set_active_fetch_pipes(struct dpu_hw_ctl *ctx,
+ unsigned long *fetch_active)
 {
int i;
u32 val = 0;
@@ -787,7 +787,7 @@ struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev,
c->ops.update_pending_flush_dspp = 
dpu_hw_ctl_update_pending_flush_dspp;
 
if (mdss_ver->core_major_ver >= 7)
-   c->ops.set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active;
+   c->ops.set_active_fetch_pipes = 
dpu_hw_ctl_set_active_fetch_pipes;
 
c->idx = cfg->id;
c->mixer_count = mixer_count;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index 
aa560df698ed4e57a25e4a893d7333e19b065fe8..1b40d8cc92865e31e5ac4a8c3ee8fac8c5499bbd
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -254,7 +254,7 @@ struct dpu_hw_ctl_ops {
void (*setup_blendstage)(struct dpu_hw_ctl *ctx,
enum dpu_lm lm, struct dpu_hw_stage_cfg *cfg);
 
-   void (*set_active_pipes)(struct dpu_hw_ctl *ctx,
+   void (*set_active_fetch_pipes)(struct dpu_hw_ctl *ctx,
unsigned long *fetch_active);
 };
 

-- 
2.43.0



[PATCH v4 03/19] dt-bindings: display/msm: dp-controller: Add SM8750

2025-03-11 Thread Krzysztof Kozlowski
Add DisplayPort controller for Qualcomm SM8750 SoC which so far looks
fully compatible with earlier SM8650 variant - both are of version
v1.5.1 of the IP block.  Datasheet also mentions that both support 4x
MST for DPTX0 and 2x MST for DPTX1.

Acked-by: Rob Herring (Arm) 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Krzysztof Kozlowski 
---

Changes in v3:
1. Extend commit msg
---
 Documentation/devicetree/bindings/display/msm/dp-controller.yaml | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml 
b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
index 
e00b88332f2fed2fc33f6d72c5cc3d827cd7594e..a4bf9e07a28355c0391d1757fab16ebe5ff14a44
 100644
--- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
@@ -37,6 +37,10 @@ properties:
   - qcom,sm8450-dp
   - qcom,sm8550-dp
   - const: qcom,sm8350-dp
+  - items:
+  - enum:
+  - qcom,sm8750-dp
+  - const: qcom,sm8650-dp
 
   reg:
 minItems: 4

-- 
2.43.0



[PATCH v4 04/19] dt-bindings: display/msm: qcom,sm8650-dpu: Add SM8750

2025-03-11 Thread Krzysztof Kozlowski
Add DPU for Qualcomm SM8750 SoC which has several differences, new
blocks and changes in registers, making it incompatible with SM8650.

Acked-by: Rob Herring (Arm) 
Signed-off-by: Krzysztof Kozlowski 
---
 Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml 
b/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml
index 
01cf79bd754b491349c52c5aef49ba06e835d0bf..0a46120dd8680371ed031f7773859716f49c3aa1
 100644
--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8650-dpu.yaml
@@ -16,6 +16,7 @@ properties:
 enum:
   - qcom,sa8775p-dpu
   - qcom,sm8650-dpu
+  - qcom,sm8750-dpu
   - qcom,x1e80100-dpu
 
   reg:

-- 
2.43.0



[PATCH v4 02/19] dt-bindings: display/msm: dsi-controller-main: Add SM8750

2025-03-11 Thread Krzysztof Kozlowski
Add DSI controller for Qualcomm SM8750 SoC which is quite different from
previous (SM8650) generation.

It does not allow the display clock controller clocks like "byte" and
"pixel" to be reparented to DSI PHY PLLs while the DSI PHY PLL is not
configured (not prepared, rate not set).  Therefore
assigned-clock-parents are not working here and driver is responsible
for reparenting clocks with proper procedure.  These clocks are now
inputs to the DSI controller device.

Except that SM8750 DSI comes with several differences, new blocks and
changes in registers, making it incompatible with SM8650.

Reviewed-by: Rob Herring (Arm) 
Signed-off-by: Krzysztof Kozlowski 
---
 .../bindings/display/msm/dsi-controller-main.yaml  | 54 --
 1 file changed, 49 insertions(+), 5 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml 
b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
index 
2aab33cd0017cd4a0c915b7297bb3952e62561fa..8ecb2d8e296edf555df7380eac284b41a3f000a5
 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
@@ -40,6 +40,7 @@ properties:
   - qcom,sm8450-dsi-ctrl
   - qcom,sm8550-dsi-ctrl
   - qcom,sm8650-dsi-ctrl
+  - qcom,sm8750-dsi-ctrl
   - const: qcom,mdss-dsi-ctrl
   - enum:
   - qcom,dsi-ctrl-6g-qcm2290
@@ -68,11 +69,11 @@ properties:
- mnoc:: MNOC clock
- pixel:: Display pixel clock.
 minItems: 3
-maxItems: 9
+maxItems: 12
 
   clock-names:
 minItems: 3
-maxItems: 9
+maxItems: 12
 
   phys:
 maxItems: 1
@@ -107,7 +108,8 @@ properties:
 minItems: 2
 maxItems: 4
 description: |
-  Parents of "byte" and "pixel" for the given platform.
+  For DSI on SM8650 and older: parents of "byte" and "pixel" for the given
+  platform.
   For DSIv2 platforms this should contain "byte", "esc", "src" and
   "pixel_src" clocks.
 
@@ -216,8 +218,6 @@ required:
   - clocks
   - clock-names
   - phys
-  - assigned-clocks
-  - assigned-clock-parents
   - ports
 
 allOf:
@@ -242,6 +242,9 @@ allOf:
 - const: byte
 - const: pixel
 - const: core
+  required:
+- assigned-clocks
+- assigned-clock-parents
 
   - if:
   properties:
@@ -264,6 +267,9 @@ allOf:
 - const: byte
 - const: pixel
 - const: core
+  required:
+- assigned-clocks
+- assigned-clock-parents
 
   - if:
   properties:
@@ -286,6 +292,9 @@ allOf:
 - const: pixel
 - const: core
 - const: core_mmss
+  required:
+- assigned-clocks
+- assigned-clock-parents
 
   - if:
   properties:
@@ -307,6 +316,9 @@ allOf:
 - const: core_mmss
 - const: pixel
 - const: core
+  required:
+- assigned-clocks
+- assigned-clock-parents
 
   - if:
   properties:
@@ -342,6 +354,35 @@ allOf:
 - const: core
 - const: iface
 - const: bus
+  required:
+- assigned-clocks
+- assigned-clock-parents
+
+  - if:
+  properties:
+compatible:
+  contains:
+enum:
+  - qcom,sm8750-dsi-ctrl
+then:
+  properties:
+clocks:
+  minItems: 12
+  maxItems: 12
+clock-names:
+  items:
+- const: byte
+- const: byte_intf
+- const: pixel
+- const: core
+- const: iface
+- const: bus
+- const: dsi_pll_pixel
+- const: dsi_pll_byte
+- const: esync
+- const: osc
+- const: byte_src
+- const: pixel_src
 
   - if:
   properties:
@@ -365,6 +406,9 @@ allOf:
 - const: core_mmss
 - const: pixel
 - const: core
+  required:
+- assigned-clocks
+- assigned-clock-parents
 
 unevaluatedProperties: false
 

-- 
2.43.0



[PATCH v4 00/19] drm/msm: Add support for SM8750

2025-03-11 Thread Krzysztof Kozlowski
Hi,

Dependency / Rabased on top of
==
https://lore.kernel.org/all/20241214-dpu-drop-features-v1-0-988f0662c...@linaro.org/

Merging
===
DSI pieces here might not be ready - I got modetest writeback working,
but DSI panel on MTP8750 still shows darkness.  Therefore we discussed
that DPU/catalog things could be applied first.

Changes in v4
=
- Add ack/rb tags
- Implement Dmitry's feedback (lower-case hex, indentation, pass
  mdss_ver instead of ctl), patches:
  drm/msm/dpu: Implement 10-bit color alpha for v12.0 DPU
  drm/msm/dpu: Implement CTL_PIPE_ACTIVE for v12.0 DPU

- Rebase on latest next
- Drop applied two first patches
- Link to v3: 
https://lore.kernel.org/r/20250221-b4-sm8750-display-v3-0-3ea95b163...@linaro.org

Changes in v3
=
- Add ack/rb tags
- #5: dt-bindings: display/msm: dp-controller: Add SM8750:
  Extend commit msg

- #7: dt-bindings: display/msm: qcom,sm8750-mdss: Add SM8750:
  - Properly described interconnects
  - Use only one compatible and contains for the sub-blocks (Rob)

- #12: drm/msm/dsi: Add support for SM8750:
  Drop 'struct msm_dsi_config sm8750_dsi_cfg' and use sm8650 one.
- drm/msm/dpu: Implement new v12.0 DPU differences
  Split into several patches
- Link to v2: 
https://lore.kernel.org/r/20250217-b4-sm8750-display-v2-0-d201dcdda...@linaro.org

Changes in v2
=
- Implement LM crossbar, 10-bit alpha and active layer changes:
  New patch: drm/msm/dpu: Implement new v12.0 DPU differences
- New patch: drm/msm/dpu: Add missing "fetch" name to set_active_pipes()
- Add CDM
- Split some DPU patch pieces into separate patches:
  drm/msm/dpu: Drop useless comments
  drm/msm/dpu: Add LM_7, DSC_[67], PP_[67] and MERGE_3D_5
  drm/msm/dpu: Add handling of LM_6 and LM_7 bits in pending flush mask
- Split DSI and DSI PHY patches
- Mention CLK_OPS_PARENT_ENABLE in DSI commit
- Mention DSI PHY PLL work:
  https://patchwork.freedesktop.org/patch/542000/?series=119177&rev=1
- DPU: Drop SSPP_VIG4 comments
- DPU: Add CDM
- Link to v1: 
https://lore.kernel.org/r/20250109-b4-sm8750-display-v1-0-b3f15faf4...@linaro.org

Best regards,
Krzysztof

---
Krzysztof Kozlowski (19):
  dt-bindings: display/msm: dsi-phy-7nm: Add SM8750
  dt-bindings: display/msm: dsi-controller-main: Add SM8750
  dt-bindings: display/msm: dp-controller: Add SM8750
  dt-bindings: display/msm: qcom,sm8650-dpu: Add SM8750
  dt-bindings: display/msm: qcom,sm8750-mdss: Add SM8750
  drm/msm/dpu: Add missing "fetch" name to set_active_pipes()
  drm/msm/dpu: Clear CTL_FETCH_PIPE_ACTIVE on mixer reset
  drm/msm/dpu: Clear CTL_FETCH_PIPE_ACTIVE on ctl_path reset
  drm/msm/dpu: Clear CTL_FETCH_PIPE_ACTIVE before blend setup
  drm/msm/dpu: Drop useless comments
  drm/msm/dpu: Add LM_7, DSC_[67], PP_[67] and MERGE_3D_5
  drm/msm/dpu: Add handling of LM_6 and LM_7 bits in pending flush mask
  drm/msm/dsi/phy: Add support for SM8750
  drm/msm/dsi: Add support for SM8750
  drm/msm/dpu: Add support for SM8750
  drm/msm/dpu: Implement 10-bit color alpha for v12.0 DPU
  drm/msm/dpu: Implement CTL_PIPE_ACTIVE for v12.0 DPU
  drm/msm/dpu: Implement LM crossbar for v12.0 DPU
  drm/msm/mdss: Add support for SM8750

 .../bindings/display/msm/dp-controller.yaml|   4 +
 .../bindings/display/msm/dsi-controller-main.yaml  |  54 ++-
 .../bindings/display/msm/dsi-phy-7nm.yaml  |   1 +
 .../bindings/display/msm/qcom,sm8650-dpu.yaml  |   1 +
 .../bindings/display/msm/qcom,sm8750-mdss.yaml | 470 +++
 .../drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h| 496 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c   |  58 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c|  12 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c |  35 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c |  71 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h |  19 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c  | 210 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h  |  18 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h|   6 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c|   1 +
 drivers/gpu/drm/msm/dsi/dsi.h  |   2 +
 drivers/gpu/drm/msm/dsi/dsi_cfg.c  |  14 +
 drivers/gpu/drm/msm/dsi/dsi_cfg.h  |   1 +
 drivers/gpu/drm/msm/dsi/dsi_host.c |  80 
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c  |   2 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h  |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c  |  79 +++-
 drivers/gpu/drm/msm/msm_mdss.c |  33 ++
 drivers/gpu/drm/msm/msm_mdss.h |   1 +
 .../gpu/drm/msm/registers/display/dsi_phy_7nm.xml  |  14 +
 26 files changed, 1643 insertions(+), 41 deletions(-)
---
base-commit: 3772cd6a20f716117ce666721c9f08

[PATCH v4 07/19] drm/msm/dpu: Clear CTL_FETCH_PIPE_ACTIVE on mixer reset

2025-03-11 Thread Krzysztof Kozlowski
Resetting mixers should also include resetting active fetch pipes.

Fixes: ae4d721ce100 ("drm/msm/dpu: add an API to reset the encoder related hw 
blocks")
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Krzysztof Kozlowski 
---

Changes in v3:
1. New patch, split from previous big DPU v12.0.
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 
284e69bb47c179ba62363b2df2cebd5172c44f8a..ccf492f27140a2841b454d413e885e4bbd9ee497
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2188,6 +2188,9 @@ static void dpu_encoder_helper_reset_mixers(struct 
dpu_encoder_phys *phys_enc)
/* clear all blendstages */
if (ctl->ops.setup_blendstage)
ctl->ops.setup_blendstage(ctl, hw_mixer[i]->idx, NULL);
+
+   if (ctl->ops.set_active_fetch_pipes)
+   ctl->ops.set_active_fetch_pipes(ctl, NULL);
}
 }
 

-- 
2.43.0



[PATCH v4 01/19] dt-bindings: display/msm: dsi-phy-7nm: Add SM8750

2025-03-11 Thread Krzysztof Kozlowski
Add DSI PHY v7.0 for Qualcomm SM8750 SoC which is quite different from
previous (SM8650) generation.

Acked-by: Rob Herring (Arm) 
Signed-off-by: Krzysztof Kozlowski 
---
 Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml 
b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
index 
321470435e654f1d569fc54f6a810e3f70fb168c..4ac262d3feb1293c65633f3b804b4f34c518400c
 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-7nm.yaml
@@ -23,6 +23,7 @@ properties:
   - qcom,sm8450-dsi-phy-5nm
   - qcom,sm8550-dsi-phy-4nm
   - qcom,sm8650-dsi-phy-4nm
+  - qcom,sm8750-dsi-phy-3nm
 
   reg:
 items:

-- 
2.43.0



[PATCH v4 18/19] drm/msm/dpu: Implement LM crossbar for v12.0 DPU

2025-03-11 Thread Krzysztof Kozlowski
v12.0 DPU on SM8750 comes with new LM crossbar that requires each pipe
rectangle to be programmed separately in blend stage.  Implement support
for this along with a new CTL_LAYER_ACTIVE register and setting the
blend stage in layer mixer code.

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Krzysztof Kozlowski 
---

Changes in v4:
1. Lowercase hex
2. Add Dmitry's tag

Changes in v3:
1. New patch, split from previous big DPU v12.0.
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c|  18 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |   6 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c  |  27 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h  |   9 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c   | 126 
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h   |  18 
 6 files changed, 201 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 
3135e5ab9e8121f3dbd93dde9458f007ae45392a..bde87533b4b39ac8740f7ec6cc59ea96e705
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -524,6 +524,7 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
struct dpu_hw_ctl *ctl;
struct dpu_hw_mixer *lm;
struct dpu_hw_stage_cfg stage_cfg;
+   DECLARE_BITMAP(active_lms, LM_MAX);
int i;
 
DRM_DEBUG_ATOMIC("%s\n", dpu_crtc->name);
@@ -537,10 +538,14 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)

mixer[i].lm_ctl->ops.set_active_fetch_pipes(mixer[i].lm_ctl, NULL);
if (mixer[i].lm_ctl->ops.set_active_pipes)
mixer[i].lm_ctl->ops.set_active_pipes(mixer[i].lm_ctl, 
NULL);
+
+   if (mixer[i].hw_lm->ops.clear_all_blendstages)
+   
mixer[i].hw_lm->ops.clear_all_blendstages(mixer[i].hw_lm);
}
 
/* initialize stage cfg */
memset(&stage_cfg, 0, sizeof(struct dpu_hw_stage_cfg));
+   memset(active_lms, 0, sizeof(active_lms));
 
_dpu_crtc_blend_setup_mixer(crtc, dpu_crtc, mixer, &stage_cfg);
 
@@ -554,13 +559,22 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
ctl->ops.update_pending_flush_mixer(ctl,
mixer[i].hw_lm->idx);
 
+   set_bit(lm->idx, active_lms);
+   if (ctl->ops.set_active_lms)
+   ctl->ops.set_active_lms(ctl, active_lms);
+
DRM_DEBUG_ATOMIC("lm %d, op_mode 0x%X, ctl %d\n",
mixer[i].hw_lm->idx - LM_0,
mixer[i].mixer_op_mode,
ctl->idx - CTL_0);
 
-   ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
-   &stage_cfg);
+   if (ctl->ops.setup_blendstage)
+   ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
+ &stage_cfg);
+
+   if (lm->ops.setup_blendstage)
+   lm->ops.setup_blendstage(lm, mixer[i].hw_lm->idx,
+&stage_cfg);
}
 }
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 
aec71a86f809afedc2660d66d2cbf4109c302067..b36b8d7d6cda53c31d3aafd5050c98b01b48f458
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2189,6 +2189,12 @@ static void dpu_encoder_helper_reset_mixers(struct 
dpu_encoder_phys *phys_enc)
if (ctl->ops.setup_blendstage)
ctl->ops.setup_blendstage(ctl, hw_mixer[i]->idx, NULL);
 
+   if (hw_mixer[i]->ops.clear_all_blendstages)
+   hw_mixer[i]->ops.clear_all_blendstages(hw_mixer[i]);
+
+   if (ctl->ops.set_active_lms)
+   ctl->ops.set_active_lms(ctl, NULL);
+
if (ctl->ops.set_active_fetch_pipes)
ctl->ops.set_active_fetch_pipes(ctl, NULL);
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 
c9c65d5e9d36d3a4ce2aef9f57da631f2acd9123..2f9713227c287ffcfd6bedff7bad14cf8df6eb30
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -43,6 +43,7 @@
 #define   CTL_CDM_FLUSH0x114
 #define   CTL_PERIPH_FLUSH  0x128
 #define   CTL_PIPE_ACTIVE   0x12c
+#define   CTL_LAYER_ACTIVE  0x130
 #define   CTL_INTF_MASTER   0x134
 #define   CTL_DSPP_n_FLUSH(n)   ((0x13C) + ((n) * 4))
 
@@ -65,6 +66,8 @@ static const u32 fetch_tbl[SSPP_MAX] = {CTL_INVALID_BIT, 16, 
17, 18, 19,
CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, 0,
1, 2, 3, 4, 5};
 
+static const u32 lm_tbl[LM_MAX] = {CTL_INVALID_BIT, 0, 1, 2, 3, 4, 5, 6, 7};
+
 static int _mixer_

[PATCH v4 19/19] drm/msm/mdss: Add support for SM8750

2025-03-11 Thread Krzysztof Kozlowski
Add support for the Qualcomm SM8750 platform.

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Krzysztof Kozlowski 
---
 drivers/gpu/drm/msm/msm_mdss.c | 33 +
 drivers/gpu/drm/msm/msm_mdss.h |  1 +
 2 files changed, 34 insertions(+)

diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index 
dcb49fd30402b80edd2cb5971f95a78eaad6081f..3f00eb6de3a9d2bee7637c6f516efff78b7d872b
 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -222,6 +222,24 @@ static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss 
*msm_mdss)
}
 }
 
+static void msm_mdss_setup_ubwc_dec_50(struct msm_mdss *msm_mdss)
+{
+   const struct msm_mdss_data *data = msm_mdss->mdss_data;
+   u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) |
+   MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit);
+
+   if (data->ubwc_bank_spread)
+   value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD;
+
+   if (data->macrotile_mode)
+   value |= MDSS_UBWC_STATIC_MACROTILE_MODE;
+
+   writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC);
+
+   writel_relaxed(4, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
+   writel_relaxed(1, msm_mdss->mmio + REG_MDSS_UBWC_PREDICTION_MODE);
+}
+
 #define MDSS_HW_MAJ_MIN\
(MDSS_HW_VERSION_MAJOR__MASK | MDSS_HW_VERSION_MINOR__MASK)
 
@@ -339,6 +357,9 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss)
case UBWC_4_3:
msm_mdss_setup_ubwc_dec_40(msm_mdss);
break;
+   case UBWC_5_0:
+   msm_mdss_setup_ubwc_dec_50(msm_mdss);
+   break;
default:
dev_err(msm_mdss->dev, "Unsupported UBWC decoder version %x\n",
msm_mdss->mdss_data->ubwc_dec_version);
@@ -722,6 +743,17 @@ static const struct msm_mdss_data sm8550_data = {
.reg_bus_bw = 57000,
 };
 
+static const struct msm_mdss_data sm8750_data = {
+   .ubwc_enc_version = UBWC_5_0,
+   .ubwc_dec_version = UBWC_5_0,
+   .ubwc_swizzle = 6,
+   .ubwc_bank_spread = true,
+   /* TODO: highest_bank_bit = 2 for LP_DDR4 */
+   .highest_bank_bit = 3,
+   .macrotile_mode = true,
+   .reg_bus_bw = 57000,
+};
+
 static const struct msm_mdss_data x1e80100_data = {
.ubwc_enc_version = UBWC_4_0,
.ubwc_dec_version = UBWC_4_3,
@@ -756,6 +788,7 @@ static const struct of_device_id mdss_dt_match[] = {
{ .compatible = "qcom,sm8450-mdss", .data = &sm8350_data },
{ .compatible = "qcom,sm8550-mdss", .data = &sm8550_data },
{ .compatible = "qcom,sm8650-mdss", .data = &sm8550_data},
+   { .compatible = "qcom,sm8750-mdss", .data = &sm8750_data},
{ .compatible = "qcom,x1e80100-mdss", .data = &x1e80100_data},
{}
 };
diff --git a/drivers/gpu/drm/msm/msm_mdss.h b/drivers/gpu/drm/msm/msm_mdss.h
index 
14dc53704314558841ee1fe08d93309fd2233812..dd0160c6ba1a297cea5b87cd8b03895b2aa08213
 100644
--- a/drivers/gpu/drm/msm/msm_mdss.h
+++ b/drivers/gpu/drm/msm/msm_mdss.h
@@ -22,6 +22,7 @@ struct msm_mdss_data {
 #define UBWC_3_0 0x3000
 #define UBWC_4_0 0x4000
 #define UBWC_4_3 0x4003
+#define UBWC_5_0 0x5000
 
 const struct msm_mdss_data *msm_mdss_get_mdss_data(struct device *dev);
 

-- 
2.43.0



[PATCH v4 17/19] drm/msm/dpu: Implement CTL_PIPE_ACTIVE for v12.0 DPU

2025-03-11 Thread Krzysztof Kozlowski
v12.0 DPU on SM8750 comes with new CTL_PIPE_ACTIVE register for
selective activation of pipes, which replaces earlier
dpu_hw_ctl_setup_blendstage() code path for newer devices.

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Krzysztof Kozlowski 
---

Changes in v4:
1. Lowercase hex
2. Add Dmitry's tag

Changes in v3:
1. New patch, split from previous big DPU v12.0.
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c|  9 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  3 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c  | 29 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h  |  8 
 4 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 
90f47fc15ee5708795701d78a1380f4ab01c1427..3135e5ab9e8121f3dbd93dde9458f007ae45392a
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -452,8 +452,10 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc 
*crtc,
uint32_t lm_idx;
bool bg_alpha_enable = false;
DECLARE_BITMAP(active_fetch, SSPP_MAX);
+   DECLARE_BITMAP(active_pipes, SSPP_MAX);
 
memset(active_fetch, 0, sizeof(active_fetch));
+   memset(active_pipes, 0, sizeof(active_pipes));
drm_atomic_crtc_for_each_plane(plane, crtc) {
state = plane->state;
if (!state)
@@ -471,6 +473,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc 
*crtc,
bg_alpha_enable = true;
 
set_bit(pstate->pipe.sspp->idx, active_fetch);
+   set_bit(pstate->pipe.sspp->idx, active_pipes);
_dpu_crtc_blend_setup_pipe(crtc, plane,
   mixer, cstate->num_mixers,
   pstate->stage,
@@ -479,6 +482,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc 
*crtc,
 
if (pstate->r_pipe.sspp) {
set_bit(pstate->r_pipe.sspp->idx, active_fetch);
+   set_bit(pstate->r_pipe.sspp->idx, active_pipes);
_dpu_crtc_blend_setup_pipe(crtc, plane,
   mixer, cstate->num_mixers,
   pstate->stage,
@@ -502,6 +506,9 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc 
*crtc,
if (ctl->ops.set_active_fetch_pipes)
ctl->ops.set_active_fetch_pipes(ctl, active_fetch);
 
+   if (ctl->ops.set_active_pipes)
+   ctl->ops.set_active_pipes(ctl, active_pipes);
+
_dpu_crtc_program_lm_output_roi(crtc);
 }
 
@@ -528,6 +535,8 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
mixer[i].lm_ctl);
if (mixer[i].lm_ctl->ops.set_active_fetch_pipes)

mixer[i].lm_ctl->ops.set_active_fetch_pipes(mixer[i].lm_ctl, NULL);
+   if (mixer[i].lm_ctl->ops.set_active_pipes)
+   mixer[i].lm_ctl->ops.set_active_pipes(mixer[i].lm_ctl, 
NULL);
}
 
/* initialize stage cfg */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 
ccf492f27140a2841b454d413e885e4bbd9ee497..aec71a86f809afedc2660d66d2cbf4109c302067
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2191,6 +2191,9 @@ static void dpu_encoder_helper_reset_mixers(struct 
dpu_encoder_phys *phys_enc)
 
if (ctl->ops.set_active_fetch_pipes)
ctl->ops.set_active_fetch_pipes(ctl, NULL);
+
+   if (ctl->ops.set_active_pipes)
+   ctl->ops.set_active_pipes(ctl, NULL);
}
 }
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 
3e5e1e09e9d00ade74371489b2b4e50e648e2d16..c9c65d5e9d36d3a4ce2aef9f57da631f2acd9123
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -42,6 +42,7 @@
 #define   CTL_INTF_FLUSH0x110
 #define   CTL_CDM_FLUSH0x114
 #define   CTL_PERIPH_FLUSH  0x128
+#define   CTL_PIPE_ACTIVE   0x12c
 #define   CTL_INTF_MASTER   0x134
 #define   CTL_DSPP_n_FLUSH(n)   ((0x13C) + ((n) * 4))
 
@@ -676,6 +677,9 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl 
*ctx,
if (ctx->ops.set_active_fetch_pipes)
ctx->ops.set_active_fetch_pipes(ctx, NULL);
 
+   if (ctx->ops.set_active_pipes)
+   ctx->ops.set_active_pipes(ctx, NULL);
+
if (cfg->intf) {
intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
intf_active &= ~BIT(cfg->intf - INTF_0);
@@ -724,6 +728,23 @@ static void dpu_hw_ctl_set_active_fetch_pipes(struct 
dpu_hw_ctl *c

[PATCH v4 14/19] drm/msm/dsi: Add support for SM8750

2025-03-11 Thread Krzysztof Kozlowski
Add support for DSI on Qualcomm SM8750 SoC with notable difference:

DSI PHY PLLs, the parents of pixel and byte clocks, cannot be used as
parents before DSI PHY is configured and the PLLs are prepared with
initial rate is set.  Therefore assigned-clock-parents are not working
here and driver is responsible for reparenting clocks with proper
procedure: see dsi_clk_init_6g_v2_9().

Part of the change is exactly the same as CLK_OPS_PARENT_ENABLE, however
CLK_OPS_PARENT_ENABLE won't work here because assigned-clock-parents are
executed way too early - before DSI PHY is configured.

Signed-off-by: Krzysztof Kozlowski 

---

Changes in v3:
1. Drop 'struct msm_dsi_config sm8750_dsi_cfg' and use sm8650 one.

SM8750 DSI PHY also needs Dmitry's patch:
https://patchwork.freedesktop.org/patch/542000/?series=119177&rev=1
(or some other way of correct early setting of the DSI PHY PLL rate)
---
 drivers/gpu/drm/msm/dsi/dsi.h  |  2 +
 drivers/gpu/drm/msm/dsi/dsi_cfg.c  | 14 +++
 drivers/gpu/drm/msm/dsi/dsi_cfg.h  |  1 +
 drivers/gpu/drm/msm/dsi/dsi_host.c | 80 ++
 4 files changed, 97 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 
87496db203d6c7582eadcb74e94eb56a219df292..93c028a122f3a59b1632da76472e0a3e781c6ae8
 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -98,6 +98,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi);
 int msm_dsi_runtime_suspend(struct device *dev);
 int msm_dsi_runtime_resume(struct device *dev);
 int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host);
+int dsi_link_clk_set_rate_6g_v2_9(struct msm_dsi_host *msm_host);
 int dsi_link_clk_set_rate_v2(struct msm_dsi_host *msm_host);
 int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host);
 int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host);
@@ -115,6 +116,7 @@ int dsi_dma_base_get_6g(struct msm_dsi_host *msm_host, 
uint64_t *iova);
 int dsi_dma_base_get_v2(struct msm_dsi_host *msm_host, uint64_t *iova);
 int dsi_clk_init_v2(struct msm_dsi_host *msm_host);
 int dsi_clk_init_6g_v2(struct msm_dsi_host *msm_host);
+int dsi_clk_init_6g_v2_9(struct msm_dsi_host *msm_host);
 int dsi_calc_clk_rate_v2(struct msm_dsi_host *msm_host, bool is_bonded_dsi);
 int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi);
 void msm_dsi_host_snapshot(struct msm_disp_state *disp_state, struct 
mipi_dsi_host *host);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c 
b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
index 
7754dcec33d06e3d6eb8a9d55e53f24af073adb9..7f8a8de0897a579a525b466fd01bbcd95454c614
 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -257,6 +257,18 @@ static const struct msm_dsi_host_cfg_ops 
msm_dsi_6g_v2_host_ops = {
.calc_clk_rate = dsi_calc_clk_rate_6g,
 };
 
+static const struct msm_dsi_host_cfg_ops msm_dsi_6g_v2_9_host_ops = {
+   .link_clk_set_rate = dsi_link_clk_set_rate_6g_v2_9,
+   .link_clk_enable = dsi_link_clk_enable_6g,
+   .link_clk_disable = dsi_link_clk_disable_6g,
+   .clk_init_ver = dsi_clk_init_6g_v2_9,
+   .tx_buf_alloc = dsi_tx_buf_alloc_6g,
+   .tx_buf_get = dsi_tx_buf_get_6g,
+   .tx_buf_put = dsi_tx_buf_put_6g,
+   .dma_base_get = dsi_dma_base_get_6g,
+   .calc_clk_rate = dsi_calc_clk_rate_6g,
+};
+
 static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
{MSM_DSI_VER_MAJOR_V2, MSM_DSI_V2_VER_MINOR_8064,
&apq8064_dsi_cfg, &msm_dsi_v2_host_ops},
@@ -300,6 +312,8 @@ static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] 
= {
&sm8550_dsi_cfg, &msm_dsi_6g_v2_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_8_0,
&sm8650_dsi_cfg, &msm_dsi_6g_v2_host_ops},
+   {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_9_0,
+   &sm8650_dsi_cfg, &msm_dsi_6g_v2_9_host_ops},
 };
 
 const struct msm_dsi_cfg_handler *msm_dsi_cfg_get(u32 major, u32 minor)
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h 
b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
index 
120cb65164c1ba1deb9acb513e5f073bd560c496..859c279afbb0377d16f8406f3e6b083640aff5a1
 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
@@ -30,6 +30,7 @@
 #define MSM_DSI_6G_VER_MINOR_V2_6_00x2006
 #define MSM_DSI_6G_VER_MINOR_V2_7_00x2007
 #define MSM_DSI_6G_VER_MINOR_V2_8_00x2008
+#define MSM_DSI_6G_VER_MINOR_V2_9_00x2009
 
 #define MSM_DSI_V2_VER_MINOR_8064  0x0
 
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 
4d75529c0e858160761f5eb55db65e5d7565c27b..8ebcfd307779b8dfd35c64d3fea34123a5d0751b
 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -119,6 +119,15 @@ struct msm_dsi_host {
struct clk *pixel_clk;
struct clk *byte_intf_clk;
 
+   /*
+* Clocks which needs to be properly parented between DISPCC and DSI PH

[PATCH v4 15/19] drm/msm/dpu: Add support for SM8750

2025-03-11 Thread Krzysztof Kozlowski
Add DPU version v12.0 support for the Qualcomm SM8750 platform.

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Krzysztof Kozlowski 
---

Changes in v2:
1. Add CDM
---
 .../drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h| 496 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c |  29 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c|   1 +
 4 files changed, 527 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h 
b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h
new file mode 100644
index 
..1f883b9f8b8b29e3a8c2fe254b78594a413dc2a1
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_12_0_sm8750.h
@@ -0,0 +1,496 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 Linaro Limited
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2015-2018, 2020 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DPU_12_0_SM8750_H
+#define _DPU_12_0_SM8750_H
+
+static const struct dpu_caps sm8750_dpu_caps = {
+   .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+   .max_mixer_blendstages = 0xb,
+   .has_src_split = true,
+   .has_dim_layer = true,
+   .has_idle_pc = true,
+   .has_3d_merge = true,
+   .max_linewidth = 8192,
+   .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+};
+
+static const struct dpu_mdp_cfg sm8750_mdp = {
+   .name = "top_0",
+   .base = 0, .len = 0x494,
+   .clk_ctrls = {
+   [DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20 },
+   },
+};
+
+static const struct dpu_ctl_cfg sm8750_ctl[] = {
+   {
+   .name = "ctl_0", .id = CTL_0,
+   .base = 0x15000, .len = 0x1000,
+   .has_split_display = 1,
+   .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),
+   }, {
+   .name = "ctl_1", .id = CTL_1,
+   .base = 0x16000, .len = 0x1000,
+   .has_split_display = 1,
+   .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),
+   }, {
+   .name = "ctl_2", .id = CTL_2,
+   .base = 0x17000, .len = 0x1000,
+   .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),
+   }, {
+   .name = "ctl_3", .id = CTL_3,
+   .base = 0x18000, .len = 0x1000,
+   .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 12),
+   }, {
+   .name = "ctl_4", .id = CTL_4,
+   .base = 0x19000, .len = 0x1000,
+   .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 13),
+   }, {
+   .name = "ctl_5", .id = CTL_5,
+   .base = 0x1a000, .len = 0x1000,
+   .intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 23),
+   },
+};
+
+static const struct dpu_sspp_cfg sm8750_sspp[] = {
+   {
+   .name = "sspp_0", .id = SSPP_VIG0,
+   .base = 0x4000, .len = 0x344,
+   .features = VIG_SDM845_MASK_SDMA,
+   .sblk = &dpu_vig_sblk_qseed3_3_4,
+   .xin_id = 0,
+   .type = SSPP_TYPE_VIG,
+   }, {
+   .name = "sspp_1", .id = SSPP_VIG1,
+   .base = 0x6000, .len = 0x344,
+   .features = VIG_SDM845_MASK_SDMA,
+   .sblk = &dpu_vig_sblk_qseed3_3_4,
+   .xin_id = 4,
+   .type = SSPP_TYPE_VIG,
+   }, {
+   .name = "sspp_2", .id = SSPP_VIG2,
+   .base = 0x8000, .len = 0x344,
+   .features = VIG_SDM845_MASK_SDMA,
+   .sblk = &dpu_vig_sblk_qseed3_3_4,
+   .xin_id = 8,
+   .type = SSPP_TYPE_VIG,
+   }, {
+   .name = "sspp_3", .id = SSPP_VIG3,
+   .base = 0xa000, .len = 0x344,
+   .features = VIG_SDM845_MASK_SDMA,
+   .sblk = &dpu_vig_sblk_qseed3_3_4,
+   .xin_id = 12,
+   .type = SSPP_TYPE_VIG,
+   }, {
+   .name = "sspp_8", .id = SSPP_DMA0,
+   .base = 0x24000, .len = 0x344,
+   .features = DMA_SDM845_MASK_SDMA,
+   .sblk = &dpu_dma_sblk,
+   .xin_id = 1,
+   .type = SSPP_TYPE_DMA,
+   }, {
+   .name = "sspp_9", .id = SSPP_DMA1,
+   .base = 0x26000, .len = 0x344,
+   .features = DMA_SDM845_MASK_SDMA,
+   .sblk = &dpu_dma_sblk,
+   .xin_id = 5,
+   .type = SSPP_TYPE_DMA,
+   }, {
+   .name = "sspp_10", .id = SSPP_DMA2,
+   .base = 0x28000, .len = 0x344,
+   .features = DMA_SDM845_MASK_SDMA,
+   .sblk = &dpu_dma_sblk,
+   .xin_id = 9,
+   .type = SSPP_TYPE_DMA,
+   }, {
+   .name = "sspp_11", .id = SSPP_DMA3,
+   .base = 0x2a000, .len = 0x344,
+   .features = DMA_SDM845_MASK_S

[PATCH v4 13/19] drm/msm/dsi/phy: Add support for SM8750

2025-03-11 Thread Krzysztof Kozlowski
Add support for DSI PHY v7.0 on Qualcomm SM8750 SoC which comes with an
incompatible hardware interface change:

ICODE_ACCUM_STATUS_LOW and ALOG_OBSV_BUS_STATUS_1 registers - their
offsets were just switched.  Currently these registers are not used in
the driver, so the easiest is to document both but keep them commented
out to avoid conflict.

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Krzysztof Kozlowski 
---

Changes in v2:
1. Fix pll freq check for clock inverters
   16000ULL -> 16300ULL
---
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c  |  2 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h  |  1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c  | 79 --
 .../gpu/drm/msm/registers/display/dsi_phy_7nm.xml  | 14 
 4 files changed, 90 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index 
c0bcc68289633fd7506ce4f1f963655d862e8f08..60571237efc4d332959ac76ff1d6d6245f688469
 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -593,6 +593,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
  .data = &dsi_phy_4nm_8550_cfgs },
{ .compatible = "qcom,sm8650-dsi-phy-4nm",
  .data = &dsi_phy_4nm_8650_cfgs },
+   { .compatible = "qcom,sm8750-dsi-phy-3nm",
+ .data = &dsi_phy_3nm_8750_cfgs },
 #endif
{}
 };
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 
1925418da24263d6621299cae78f1fb9455c..7541ffde65218a28d4dde7cfc8246c0715b53ec6
 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -61,6 +61,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8350_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_5nm_8450_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8550_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_4nm_8650_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_3nm_8750_cfgs;
 
 struct msm_dsi_dphy_timing {
u32 clk_zero;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
index 
a92decbee5b5433853ed973747f7705d9079068d..b077d00e4c5dfcc81040fe3ec71c43607749f26b
 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c
@@ -51,6 +51,8 @@
 #define DSI_PHY_7NM_QUIRK_V4_3 BIT(3)
 /* Hardware is V5.2 */
 #define DSI_PHY_7NM_QUIRK_V5_2 BIT(4)
+/* Hardware is V7.0 */
+#define DSI_PHY_7NM_QUIRK_V7_0 BIT(5)
 
 struct dsi_pll_config {
bool enable_ssc;
@@ -129,9 +131,30 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll, 
struct dsi_pll_config
dec_multiple = div_u64(pll_freq * multiplier, divider);
dec = div_u64_rem(dec_multiple, multiplier, &frac);
 
-   if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1)
+   if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1) {
config->pll_clock_inverters = 0x28;
-   else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) {
+   } else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) {
+   if (pll_freq < 16300ULL)
+   config->pll_clock_inverters = 0xa0;
+   else if (pll_freq < 17500ULL)
+   config->pll_clock_inverters = 0x20;
+   else if (pll_freq < 32500ULL)
+   config->pll_clock_inverters = 0xa0;
+   else if (pll_freq < 35000ULL)
+   config->pll_clock_inverters = 0x20;
+   else if (pll_freq < 65000ULL)
+   config->pll_clock_inverters = 0xa0;
+   else if (pll_freq < 7ULL)
+   config->pll_clock_inverters = 0x20;
+   else if (pll_freq < 13ULL)
+   config->pll_clock_inverters = 0xa0;
+   else if (pll_freq < 25ULL)
+   config->pll_clock_inverters = 0x20;
+   else if (pll_freq < 40ULL)
+   config->pll_clock_inverters = 0x00;
+   else
+   config->pll_clock_inverters = 0x40;
+   } else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) {
if (pll_freq <= 13ULL)
config->pll_clock_inverters = 0xa0;
else if (pll_freq <= 25ULL)
@@ -250,7 +273,8 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm 
*pll)
vco_config_1 = 0x01;
}
 
-   if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) {
+   if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) ||
+   (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) {
if (pll->vco_current_rate < 155700ULL)
vco_config_1 = 0x08;
else
@@ -620,6 +644,7 @@ static int dsi_7nm_pll_restore_st

[PATCH v4 08/19] drm/msm/dpu: Clear CTL_FETCH_PIPE_ACTIVE on ctl_path reset

2025-03-11 Thread Krzysztof Kozlowski
Resetting entire CTL path should also include resetting active fetch
pipes.

Fixes: e1a950eec256 ("drm/msm/dpu: add reset_intf_cfg operation for dpu_hw_ctl")
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Krzysztof Kozlowski 
---

Changes in v3:
1. New patch, split from previous big DPU v12.0.
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 
951d5dccab6faf34a519d06683514aea1ee6ef60..2ce59ba50ffa0d14eaa07e993fadf0f218390ef1
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -667,6 +667,9 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl 
*ctx,
 
dpu_hw_ctl_clear_all_blendstages(ctx);
 
+   if (ctx->ops.set_active_fetch_pipes)
+   ctx->ops.set_active_fetch_pipes(ctx, NULL);
+
if (cfg->intf) {
intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
intf_active &= ~BIT(cfg->intf - INTF_0);

-- 
2.43.0



[PATCH v4 11/19] drm/msm/dpu: Add LM_7, DSC_[67], PP_[67] and MERGE_3D_5

2025-03-11 Thread Krzysztof Kozlowski
Add IDs for new blocks present in MDSS/MDP v12 for LM, DSC, PINGPONG and
MERGE_3D blocks.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Jessica Zhang 
Signed-off-by: Krzysztof Kozlowski 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index 
8d820cd1b5545d247515763039b341184e814e32..175639c8bfbb9bbd02ed35f1780bcbd869f08c36
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -125,6 +125,7 @@ enum dpu_lm {
LM_4,
LM_5,
LM_6,
+   LM_7,
LM_MAX
 };
 
@@ -169,6 +170,8 @@ enum dpu_dsc {
DSC_3,
DSC_4,
DSC_5,
+   DSC_6,
+   DSC_7,
DSC_MAX
 };
 
@@ -185,6 +188,8 @@ enum dpu_pingpong {
PINGPONG_3,
PINGPONG_4,
PINGPONG_5,
+   PINGPONG_6,
+   PINGPONG_7,
PINGPONG_CWB_0,
PINGPONG_CWB_1,
PINGPONG_CWB_2,
@@ -199,6 +204,7 @@ enum dpu_merge_3d {
MERGE_3D_2,
MERGE_3D_3,
MERGE_3D_4,
+   MERGE_3D_5,
MERGE_3D_MAX
 };
 

-- 
2.43.0



[PATCH v4 16/19] drm/msm/dpu: Implement 10-bit color alpha for v12.0 DPU

2025-03-11 Thread Krzysztof Kozlowski
v12.0 DPU on SM8750 comes with 10-bit color alpha.  Add register
differences and new implementations of setup_alpha_out,
setup_border_color and so one for this.

Signed-off-by: Krzysztof Kozlowski 

---

Changes in v4:
1. Lowercase hex, use spaces for define indentation
2. _dpu_crtc_setup_blend_cfg(): pass mdss_ver instead of ctl

Changes in v3:
1. New patch, split from previous big DPU v12.0.
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  | 19 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 84 +--
 2 files changed, 94 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 
a4b0fe0d9899b32141928f0b6a16503a49b3c27a..90f47fc15ee5708795701d78a1380f4ab01c1427
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -320,14 +320,20 @@ static bool dpu_crtc_get_scanout_position(struct drm_crtc 
*crtc,
 }
 
 static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer,
-   struct dpu_plane_state *pstate, const struct msm_format *format)
+ struct dpu_plane_state *pstate,
+ const struct msm_format *format,
+ const struct dpu_mdss_version *mdss_ver)
 {
struct dpu_hw_mixer *lm = mixer->hw_lm;
uint32_t blend_op;
-   uint32_t fg_alpha, bg_alpha;
+   uint32_t fg_alpha, bg_alpha, max_alpha;
 
fg_alpha = pstate->base.alpha >> 8;
-   bg_alpha = 0xff - fg_alpha;
+   if (mdss_ver->core_major_ver < 12)
+   max_alpha = 0xff;
+   else
+   max_alpha = 0x3ff;
+   bg_alpha = max_alpha - fg_alpha;
 
/* default to opaque blending */
if (pstate->base.pixel_blend_mode == DRM_MODE_BLEND_PIXEL_NONE ||
@@ -337,7 +343,7 @@ static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer 
*mixer,
} else if (pstate->base.pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) {
blend_op = DPU_BLEND_FG_ALPHA_FG_CONST |
DPU_BLEND_BG_ALPHA_FG_PIXEL;
-   if (fg_alpha != 0xff) {
+   if (fg_alpha != max_alpha) {
bg_alpha = fg_alpha;
blend_op |= DPU_BLEND_BG_MOD_ALPHA |
DPU_BLEND_BG_INV_MOD_ALPHA;
@@ -348,7 +354,7 @@ static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer 
*mixer,
/* coverage blending */
blend_op = DPU_BLEND_FG_ALPHA_FG_PIXEL |
DPU_BLEND_BG_ALPHA_FG_PIXEL;
-   if (fg_alpha != 0xff) {
+   if (fg_alpha != max_alpha) {
bg_alpha = fg_alpha;
blend_op |= DPU_BLEND_FG_MOD_ALPHA |
DPU_BLEND_FG_INV_MOD_ALPHA |
@@ -482,7 +488,8 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc 
*crtc,
 
/* blend config update */
for (lm_idx = 0; lm_idx < cstate->num_mixers; lm_idx++) {
-   _dpu_crtc_setup_blend_cfg(mixer + lm_idx, pstate, 
format);
+   _dpu_crtc_setup_blend_cfg(mixer + lm_idx, pstate, 
format,
+ ctl->mdss_ver);
 
if (bg_alpha_enable && !format->alpha_enable)
mixer[lm_idx].mixer_op_mode = 0;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
index 
3bfb61cb83672dca4236bdbbbfb1e442223576d2..f220a68e138cb9e7c88194e53e47391de7ed04f7
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
@@ -19,12 +19,20 @@
 
 /* These register are offset to mixer base + stage base */
 #define LM_BLEND0_OP 0x00
+
+/* = v12 DPU */
+#define LM_BORDER_COLOR_0_V120x1c
+#define LM_BORDER_COLOR_1_V120x20
+
+/* >= v12 DPU with offset to mixer base + stage base */
+#define LM_BLEND0_CONST_ALPHA_V120x08
 #define LM_BLEND0_FG_ALPHA   0x04
 #define LM_BLEND0_BG_ALPHA   0x08
 
@@ -83,6 +91,22 @@ static void dpu_hw_lm_setup_border_color(struct dpu_hw_mixer 
*ctx,
}
 }
 
+static void dpu_hw_lm_setup_border_color_v12(struct dpu_hw_mixer *ctx,
+struct dpu_mdss_color *color,
+u8 border_en)
+{
+   struct dpu_hw_blk_reg_map *c = &ctx->hw;
+
+   if (border_en) {
+   DPU_REG_WRITE(c, LM_BORDER_COLOR_0_V12,
+ (color->color_0 & 0x3ff) |
+ ((color->color_1 & 0x3ff) << 16));
+   DPU_REG_WRITE(c, LM_BORDER_COLOR_1_V12,
+ (color->color_2 & 0x3ff) |
+ ((color->color_3 & 0x3ff) << 16));
+   }
+}
+
 static void dpu_hw_lm_setup_misr

[PATCH v4 09/19] drm/msm/dpu: Clear CTL_FETCH_PIPE_ACTIVE before blend setup

2025-03-11 Thread Krzysztof Kozlowski
Before blend setup, all existing blend stages are cleared, so shall be
active fetch pipes.

Fixes: b3652e87c03c ("drm/msm/disp/dpu1: add support to program fetch active in 
ctl path")
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Krzysztof Kozlowski 
---

Changes in v3:
1. New patch, split from previous big DPU v12.0.
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 
2d7af6fff2708c12520a78cc6c979b9930dffc95..a4b0fe0d9899b32141928f0b6a16503a49b3c27a
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -519,6 +519,8 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
if (mixer[i].lm_ctl->ops.clear_all_blendstages)
mixer[i].lm_ctl->ops.clear_all_blendstages(
mixer[i].lm_ctl);
+   if (mixer[i].lm_ctl->ops.set_active_fetch_pipes)
+   
mixer[i].lm_ctl->ops.set_active_fetch_pipes(mixer[i].lm_ctl, NULL);
}
 
/* initialize stage cfg */

-- 
2.43.0



[PATCH v4 10/19] drm/msm/dpu: Drop useless comments

2025-03-11 Thread Krzysztof Kozlowski
Drop comments about SoC before each 'struct dpu_lm_sub_blks' for given
SoC because it's duplicating the actual name of structure.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Jessica Zhang 
Signed-off-by: Krzysztof Kozlowski 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 8 
 1 file changed, 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 
2db27c55787791309962acf796d5c49aaf018fc1..a310a5234e99ea4886e82ac2100c4099e6a1841e
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -331,8 +331,6 @@ static const struct dpu_sspp_sub_blks dpu_dma_sblk = 
_DMA_SBLK();
  * MIXER sub blocks config
  */
 
-/* MSM8998 */
-
 static const struct dpu_lm_sub_blks msm8998_lm_sblk = {
.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.maxblendstages = 7, /* excluding base layer */
@@ -342,8 +340,6 @@ static const struct dpu_lm_sub_blks msm8998_lm_sblk = {
},
 };
 
-/* SDM845 */
-
 static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.maxblendstages = 11, /* excluding base layer */
@@ -353,8 +349,6 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
},
 };
 
-/* SC7180 */
-
 static const struct dpu_lm_sub_blks sc7180_lm_sblk = {
.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.maxblendstages = 7, /* excluding base layer */
@@ -363,8 +357,6 @@ static const struct dpu_lm_sub_blks sc7180_lm_sblk = {
},
 };
 
-/* QCM2290 */
-
 static const struct dpu_lm_sub_blks qcm2290_lm_sblk = {
.maxwidth = DEFAULT_DPU_LINE_WIDTH,
.maxblendstages = 4, /* excluding base layer */

-- 
2.43.0



[PATCH v4 12/19] drm/msm/dpu: Add handling of LM_6 and LM_7 bits in pending flush mask

2025-03-11 Thread Krzysztof Kozlowski
MDSS/MDP v12 comes with new bits in flush registers (e.g.
MDP_CTL_0_FLUSH) for Layer Mixer 6 and 7.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Jessica Zhang 
Signed-off-by: Krzysztof Kozlowski 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 
2ce59ba50ffa0d14eaa07e993fadf0f218390ef1..3e5e1e09e9d00ade74371489b2b4e50e648e2d16
 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -261,6 +261,12 @@ static void dpu_hw_ctl_update_pending_flush_mixer(struct 
dpu_hw_ctl *ctx,
case LM_5:
ctx->pending_flush_mask |= BIT(20);
break;
+   case LM_6:
+   ctx->pending_flush_mask |= BIT(21);
+   break;
+   case LM_7:
+   ctx->pending_flush_mask |= BIT(27);
+   break;
default:
break;
}

-- 
2.43.0



Re: [PATCH v4 1/5] iommu/arm-smmu: Save additional information on context fault

2025-03-11 Thread Will Deacon
On Tue, Mar 04, 2025 at 11:56:47AM -0500, Connor Abbott wrote:
> This will be used by drm/msm for GPU page faults, replacing the manual
> register reading it does.
> 
> Signed-off-by: Connor Abbott 
> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c |  4 ++--
>  drivers/iommu/arm/arm-smmu/arm-smmu.c| 27 
> +---
>  drivers/iommu/arm/arm-smmu/arm-smmu.h|  5 -
>  3 files changed, 21 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c 
> b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> index 
> 548783f3f8e89fd978367afa65c473002f66e2e7..ae4fdbbce6ba80440f539557a39866a932360d4e
>  100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> @@ -400,7 +400,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
>  
>   if (list_empty(&tbu_list)) {
>   ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> -  cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? 
> IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> +  cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? 
> IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
>  
>   if (ret == -ENOSYS)
>   arm_smmu_print_context_fault_info(smmu, idx, &cfi);
> @@ -412,7 +412,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
>   phys_soft = ops->iova_to_phys(ops, cfi.iova);
>  
>   tmp = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> -  cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? 
> IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> +  cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? 
> IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
>   if (!tmp || tmp == -EBUSY) {
>   ret = IRQ_HANDLED;
>   resume = ARM_SMMU_RESUME_TERMINATE;
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c 
> b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index 
> ade4684c14c9b2724a71e2457288dbfaf7562c83..a9213e0f1579d1e3be0bfba75eea1d5de23117de
>  100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -409,9 +409,12 @@ void arm_smmu_read_context_fault_info(struct 
> arm_smmu_device *smmu, int idx,
> struct arm_smmu_context_fault_info *cfi)
>  {
>   cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
> + cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
>   cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> - cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> + cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> + cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);

We already have an implementation hook (->get_fault_info()) which the
qcom SMMU driver can override with qcom_adreno_smmu_get_fault_info().
That thing dumps these registers already so if we're moving that into
the core SMMU driver, let's get rid of the hook and move everybody over
rather than having it done in both places.

>   cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
> + cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);

I think the CONTEXTIDR register is stage-1 only, so we shouldn't dump
it for stage-2 domains.

Will


Re: [PATCH v4 2/5] iommu/arm-smmu-qcom: Don't read fault registers directly

2025-03-11 Thread Will Deacon
On Tue, Mar 04, 2025 at 11:56:48AM -0500, Connor Abbott wrote:
> In some cases drm/msm has to resume a stalled transaction directly in
> its fault handler. Experimentally this doesn't work on SMMU500 if the
> fault hasn't already been acknowledged by clearing FSR. Rather than
> trying to clear FSR in msm's fault handler and implementing a
> tricky handshake to avoid accidentally clearing FSR twice, we want to
> clear FSR before calling the fault handlers, but this means that the
> contents of registers can change underneath us in the fault handler and
> msm currently uses a private function to read the register contents for
> its own purposes in its fault handler, such as using the
> implementation-defined FSYNR1 to determine which block caused the fault.
> Fix this by making msm use the register values already read by arm-smmu
> itself before clearing FSR rather than messing around with reading
> registers directly.
> 
> Signed-off-by: Connor Abbott 
> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 +--
>  drivers/iommu/arm/arm-smmu/arm-smmu.c  | 14 +++---
>  drivers/iommu/arm/arm-smmu/arm-smmu.h  | 21 +++--
>  3 files changed, 27 insertions(+), 27 deletions(-)

[...]

> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h 
> b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> index 
> d3bc77dcd4d40f25bc70f3289616fb866649b022..411d807e0a7033833716635efb3968a0bd3ff237
>  100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> @@ -373,6 +373,16 @@ enum arm_smmu_domain_stage {
>   ARM_SMMU_DOMAIN_NESTED,
>  };
>  
> +struct arm_smmu_context_fault_info {
> + unsigned long iova;
> + u64 ttbr0;
> + u32 fsr;
> + u32 fsynr0;
> + u32 fsynr1;
> + u32 cbfrsynra;
> + u32 contextidr;
> +};
> +
>  struct arm_smmu_domain {
>   struct arm_smmu_device  *smmu;
>   struct io_pgtable_ops   *pgtbl_ops;
> @@ -380,6 +390,7 @@ struct arm_smmu_domain {
>   const struct iommu_flush_ops*flush_ops;
>   struct arm_smmu_cfg cfg;
>   enum arm_smmu_domain_stage  stage;
> + struct arm_smmu_context_fault_info cfi;

Does this mean we have to serialise all faults for a given domain? That
can't be right...

Will


Re: [PATCH v4 4/5] iommu/arm-smmu-qcom: Make set_stall work when the device is on

2025-03-11 Thread Will Deacon
On Tue, Mar 04, 2025 at 11:56:50AM -0500, Connor Abbott wrote:
> Up until now we have only called the set_stall callback during
> initialization when the device is off. But we will soon start calling it
> to temporarily disable stall-on-fault when the device is on, so handle
> that by checking if the device is on and writing SCTLR.
> 
> Signed-off-by: Connor Abbott 
> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 30 
> +++---
>  1 file changed, 27 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c 
> b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> index 
> a428e53add08d451fb2152e3ab80e0fba936e214..d34a0d917013bb3d5a24b3ce72f48e3b38474da2
>  100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> @@ -77,12 +77,36 @@ static void qcom_adreno_smmu_set_stall(const void 
> *cookie, bool enabled)
>  {
>   struct arm_smmu_domain *smmu_domain = (void *)cookie;
>   struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> - struct qcom_smmu *qsmmu = to_qcom_smmu(smmu_domain->smmu);
> + struct arm_smmu_device *smmu = smmu_domain->smmu;
> + struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
> + u32 mask = BIT(cfg->cbndx);
> + bool stall_changed = !!(qsmmu->stall_enabled & mask) != enabled;
> + unsigned long flags;
>  
>   if (enabled)
> - qsmmu->stall_enabled |= BIT(cfg->cbndx);
> + qsmmu->stall_enabled |= mask;
>   else
> - qsmmu->stall_enabled &= ~BIT(cfg->cbndx);
> + qsmmu->stall_enabled &= ~mask;
> +
> + /*
> +  * If the device is on and we changed the setting, update the register.
> +  */
> + if (stall_changed && pm_runtime_get_if_active(smmu->dev) > 0) {
> + spin_lock_irqsave(&smmu_domain->cb_lock, flags);
> +
> + u32 reg = arm_smmu_cb_read(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR);
> +
> + if (enabled)
> + reg |= ARM_SMMU_SCTLR_CFCFG;
> + else
> + reg &= ~ARM_SMMU_SCTLR_CFCFG;
> +
> + arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, reg);

Are you sure you don't need TLB invalidation for this to take effect? I
think some fields in the SCTLR can be cached in the TLB but you'll need
to check whether or not that applies to CFCFG.

Will


Re: [PATCH 05/10] dt-bindings: display/msm: Add Qualcomm SAR2130P

2025-03-11 Thread Rob Herring
On Fri, Mar 7, 2025 at 11:09 PM Dmitry Baryshkov
 wrote:
>
> On Fri, Mar 07, 2025 at 09:40:56PM -0600, Rob Herring (Arm) wrote:
> >
> > On Sat, 08 Mar 2025 03:42:23 +0200, Dmitry Baryshkov wrote:
> > > From: Dmitry Baryshkov 
> > >
> > > Describe the Mobile Display SubSystem (MDSS) device present on the
> > > Qualcomm SAR2130P platform. It looks pretty close to SM8550 on the
> > > system level. SAR2130P features two DSI hosts and single DisplayPort
> > > controller.
> > >
> > > Signed-off-by: Dmitry Baryshkov 
> > > ---
> > >  .../bindings/display/msm/qcom,sar2130p-mdss.yaml   | 445 
> > > +
> > >  1 file changed, 445 insertions(+)
> > >
> >
> > My bot found errors running 'make dt_binding_check' on your patch:
> >
> > yamllint warnings/errors:
> >
> > dtschema/dtc warnings/errors:
> > /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sar2130p-mdss.example.dtb:
> >  dsi@ae94000: compatible: 'oneOf' conditional failed, one must be fixed:
> >   ['qcom,sar2130p-dsi-ctrl', 'qcom,mdss-dsi-ctrl'] is too long
> >   'qcom,sar2130p-dsi-ctrl' is not one of ['qcom,apq8064-dsi-ctrl', 
> > 'qcom,msm8226-dsi-ctrl', 'qcom,msm8916-dsi-ctrl', 'qcom,msm8953-dsi-ctrl', 
> > 'qcom,msm8974-dsi-ctrl', 'qcom,msm8976-dsi-ctrl', 'qcom,msm8996-dsi-ctrl', 
> > 'qcom,msm8998-dsi-ctrl', 'qcom,qcm2290-dsi-ctrl', 'qcom,sc7180-dsi-ctrl', 
> > 'qcom,sc7280-dsi-ctrl', 'qcom,sdm660-dsi-ctrl', 'qcom,sdm670-dsi-ctrl', 
> > 'qcom,sdm845-dsi-ctrl', 'qcom,sm6115-dsi-ctrl', 'qcom,sm6125-dsi-ctrl', 
> > 'qcom,sm6150-dsi-ctrl', 'qcom,sm6350-dsi-ctrl', 'qcom,sm6375-dsi-ctrl', 
> > 'qcom,sm7150-dsi-ctrl', 'qcom,sm8150-dsi-ctrl', 'qcom,sm8250-dsi-ctrl', 
> > 'qcom,sm8350-dsi-ctrl', 'qcom,sm8450-dsi-ctrl', 'qcom,sm8550-dsi-ctrl', 
> > 'qcom,sm8650-dsi-ctrl']
> >   'qcom,sar2130p-dsi-ctrl' is not one of ['qcom,dsi-ctrl-6g-qcm2290', 
> > 'qcom,mdss-dsi-ctrl']
> >   from schema $id: 
> > http://devicetree.org/schemas/display/msm/dsi-controller-main.yaml#
>
> It looks like the patch 2 could not be applied and was skipped. Is the
> bot parsing the dependencies from the cover letter?

No, it's not that smart. I need to move it to using b4 though that has
its own quirks when no dependencies are given.

Rob


Re: [PATCH 1/4] drm/display: hdmi: provide central data authority for ACR params

2025-03-11 Thread Maxime Ripard
On Sun, Mar 09, 2025 at 10:13:56AM +0200, Dmitry Baryshkov wrote:
> From: Dmitry Baryshkov 
> 
> HDMI standard defines recommended N and CTS values for Audio Clock
> Regeneration. Currently each driver implements those, frequently in
> somewhat unique way. Provide a generic helper for getting those values
> to be used by the HDMI drivers.
> 
> The helper is added to drm_hdmi_helper.c rather than drm_hdmi_audio.c
> since HDMI drivers can be using this helper function even without
> switching to DRM HDMI Audio helpers.
> 
> Note: currently this only handles the values per HDMI 1.4b Section 7.2
> and HDMI 2.0 Section 9.2.1. Later the table can be expanded to
> accommodate for Deep Color TMDS char rates per HDMI 1.4 Appendix D
> and/or HDMI 2.0 / 2.1 Appendix C).
> 
> Signed-off-by: Dmitry Baryshkov 
> ---
>  drivers/gpu/drm/display/drm_hdmi_helper.c | 164 
> ++
>  include/drm/display/drm_hdmi_helper.h |   6 ++
>  2 files changed, 170 insertions(+)
> 
> diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c 
> b/drivers/gpu/drm/display/drm_hdmi_helper.c
> index 
> 74dd4d01dd9bb2c9e69ec1c60b0056bd69417e8a..89d25571bfd21c56c6835821d2272a12c816a76e
>  100644
> --- a/drivers/gpu/drm/display/drm_hdmi_helper.c
> +++ b/drivers/gpu/drm/display/drm_hdmi_helper.c
> @@ -256,3 +256,167 @@ drm_hdmi_compute_mode_clock(const struct 
> drm_display_mode *mode,
>   return DIV_ROUND_CLOSEST_ULL(clock * bpc, 8);
>  }
>  EXPORT_SYMBOL(drm_hdmi_compute_mode_clock);
> +
> +struct drm_hdmi_acr_n_cts_entry {
> + unsigned int n;
> + unsigned int cts;
> +};
> +
> +struct drm_hdmi_acr_data {
> + unsigned long tmds_clock_khz;
> + struct drm_hdmi_acr_n_cts_entry n_cts_32k,
> + n_cts_44k1,
> + n_cts_48k;
> +};
> +
> +static const struct drm_hdmi_acr_data hdmi_acr_n_cts[] = {
> + {
> + /* "Other" entry */
> + .n_cts_32k =  { .n = 4096, },
> + .n_cts_44k1 = { .n = 6272, },
> + .n_cts_48k =  { .n = 6144, },
> + }, {
> + .tmds_clock_khz = 25175,
> + .n_cts_32k =  { .n = 4576,  .cts = 28125, },
> + .n_cts_44k1 = { .n = 7007,  .cts = 31250, },
> + .n_cts_48k =  { .n = 6864,  .cts = 28125, },
> + }, {
> + .tmds_clock_khz = 25200,
> + .n_cts_32k =  { .n = 4096,  .cts = 25200, },
> + .n_cts_44k1 = { .n = 6272,  .cts = 28000, },
> + .n_cts_48k =  { .n = 6144,  .cts = 25200, },
> + }, {
> + .tmds_clock_khz = 27000,
> + .n_cts_32k =  { .n = 4096,  .cts = 27000, },
> + .n_cts_44k1 = { .n = 6272,  .cts = 3, },
> + .n_cts_48k =  { .n = 6144,  .cts = 27000, },
> + }, {
> + .tmds_clock_khz = 27027,
> + .n_cts_32k =  { .n = 4096,  .cts = 27027, },
> + .n_cts_44k1 = { .n = 6272,  .cts = 30030, },
> + .n_cts_48k =  { .n = 6144,  .cts = 27027, },
> + }, {
> + .tmds_clock_khz = 54000,
> + .n_cts_32k =  { .n = 4096,  .cts = 54000, },
> + .n_cts_44k1 = { .n = 6272,  .cts = 6, },
> + .n_cts_48k =  { .n = 6144,  .cts = 54000, },
> + }, {
> + .tmds_clock_khz = 54054,
> + .n_cts_32k =  { .n = 4096,  .cts = 54054, },
> + .n_cts_44k1 = { .n = 6272,  .cts = 60060, },
> + .n_cts_48k =  { .n = 6144,  .cts = 54054, },
> + }, {
> + .tmds_clock_khz = 74176,
> + .n_cts_32k =  { .n = 11648, .cts = 210937, }, /* and 210938 */
> + .n_cts_44k1 = { .n = 17836, .cts = 234375, },
> + .n_cts_48k =  { .n = 11648, .cts = 140625, },
> + }, {
> + .tmds_clock_khz = 74250,
> + .n_cts_32k =  { .n = 4096,  .cts = 74250, },
> + .n_cts_44k1 = { .n = 6272,  .cts = 82500, },
> + .n_cts_48k =  { .n = 6144,  .cts = 74250, },
> + }, {
> + .tmds_clock_khz = 148352,
> + .n_cts_32k =  { .n = 11648, .cts = 421875, },
> + .n_cts_44k1 = { .n = 8918,  .cts = 234375, },
> + .n_cts_48k =  { .n = 5824,  .cts = 140625, },
> + }, {
> + .tmds_clock_khz = 148500,
> + .n_cts_32k =  { .n = 4096,  .cts = 148500, },
> + .n_cts_44k1 = { .n = 6272,  .cts = 165000, },
> + .n_cts_48k =  { .n = 6144,  .cts = 148500, },
> + }, {
> + .tmds_clock_khz = 296703,
> + .n_cts_32k =  { .n = 5824,  .cts = 421875, },
> + .n_cts_44k1 = { .n = 4459,  .cts = 234375, },
> + .n_cts_48k =  { .n = 5824,  .cts = 281250, },
> + }, {
> + .tmds_clock_khz = 297000,
> + .n_cts_32k =  { .n = 3072,  .cts = 222750, },
> + .n_cts_44k1 = { .n = 4704,  .cts = 247500, },
> + .n_cts_48k =  { .n = 5120,  .cts = 247500, },
> + }, {
> + .tmds_clock

Re: [PATCH v4 2/5] iommu/arm-smmu-qcom: Don't read fault registers directly

2025-03-11 Thread Connor Abbott
On Tue, Mar 11, 2025 at 2:08 PM Will Deacon  wrote:
>
> On Tue, Mar 04, 2025 at 11:56:48AM -0500, Connor Abbott wrote:
> > In some cases drm/msm has to resume a stalled transaction directly in
> > its fault handler. Experimentally this doesn't work on SMMU500 if the
> > fault hasn't already been acknowledged by clearing FSR. Rather than
> > trying to clear FSR in msm's fault handler and implementing a
> > tricky handshake to avoid accidentally clearing FSR twice, we want to
> > clear FSR before calling the fault handlers, but this means that the
> > contents of registers can change underneath us in the fault handler and
> > msm currently uses a private function to read the register contents for
> > its own purposes in its fault handler, such as using the
> > implementation-defined FSYNR1 to determine which block caused the fault.
> > Fix this by making msm use the register values already read by arm-smmu
> > itself before clearing FSR rather than messing around with reading
> > registers directly.
> >
> > Signed-off-by: Connor Abbott 
> > ---
> >  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 +--
> >  drivers/iommu/arm/arm-smmu/arm-smmu.c  | 14 +++---
> >  drivers/iommu/arm/arm-smmu/arm-smmu.h  | 21 +++--
> >  3 files changed, 27 insertions(+), 27 deletions(-)
>
> [...]
>
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h 
> > b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > index 
> > d3bc77dcd4d40f25bc70f3289616fb866649b022..411d807e0a7033833716635efb3968a0bd3ff237
> >  100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > @@ -373,6 +373,16 @@ enum arm_smmu_domain_stage {
> >   ARM_SMMU_DOMAIN_NESTED,
> >  };
> >
> > +struct arm_smmu_context_fault_info {
> > + unsigned long iova;
> > + u64 ttbr0;
> > + u32 fsr;
> > + u32 fsynr0;
> > + u32 fsynr1;
> > + u32 cbfrsynra;
> > + u32 contextidr;
> > +};
> > +
> >  struct arm_smmu_domain {
> >   struct arm_smmu_device  *smmu;
> >   struct io_pgtable_ops   *pgtbl_ops;
> > @@ -380,6 +390,7 @@ struct arm_smmu_domain {
> >   const struct iommu_flush_ops*flush_ops;
> >   struct arm_smmu_cfg cfg;
> >   enum arm_smmu_domain_stage  stage;
> > + struct arm_smmu_context_fault_info cfi;
>
> Does this mean we have to serialise all faults for a given domain? That
> can't be right...
>
> Will

They are already serialized? There's only one of each register per
context bank, so you can only have one context fault at a time per
context bank, and AFAIK a context bank is 1:1 with a domain. Also this
struct is only written and then read inside the context bank's
interrupt handler, and you can only have one interrupt at a time, no?

Connor


Re: [PATCH v4 1/5] iommu/arm-smmu: Save additional information on context fault

2025-03-11 Thread Connor Abbott
On Tue, Mar 11, 2025 at 2:06 PM Will Deacon  wrote:
>
> On Tue, Mar 04, 2025 at 11:56:47AM -0500, Connor Abbott wrote:
> > This will be used by drm/msm for GPU page faults, replacing the manual
> > register reading it does.
> >
> > Signed-off-by: Connor Abbott 
> > ---
> >  drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c |  4 ++--
> >  drivers/iommu/arm/arm-smmu/arm-smmu.c| 27 
> > +---
> >  drivers/iommu/arm/arm-smmu/arm-smmu.h|  5 -
> >  3 files changed, 21 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c 
> > b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> > index 
> > 548783f3f8e89fd978367afa65c473002f66e2e7..ae4fdbbce6ba80440f539557a39866a932360d4e
> >  100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
> > @@ -400,7 +400,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
> >
> >   if (list_empty(&tbu_list)) {
> >   ret = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> > -  cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? 
> > IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> > +  cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR 
> > ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> >
> >   if (ret == -ENOSYS)
> >   arm_smmu_print_context_fault_info(smmu, idx, &cfi);
> > @@ -412,7 +412,7 @@ irqreturn_t qcom_smmu_context_fault(int irq, void *dev)
> >   phys_soft = ops->iova_to_phys(ops, cfi.iova);
> >
> >   tmp = report_iommu_fault(&smmu_domain->domain, NULL, cfi.iova,
> > -  cfi.fsynr & ARM_SMMU_CB_FSYNR0_WNR ? 
> > IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> > +  cfi.fsynr0 & ARM_SMMU_CB_FSYNR0_WNR ? 
> > IOMMU_FAULT_WRITE : IOMMU_FAULT_READ);
> >   if (!tmp || tmp == -EBUSY) {
> >   ret = IRQ_HANDLED;
> >   resume = ARM_SMMU_RESUME_TERMINATE;
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c 
> > b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > index 
> > ade4684c14c9b2724a71e2457288dbfaf7562c83..a9213e0f1579d1e3be0bfba75eea1d5de23117de
> >  100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > @@ -409,9 +409,12 @@ void arm_smmu_read_context_fault_info(struct 
> > arm_smmu_device *smmu, int idx,
> > struct arm_smmu_context_fault_info *cfi)
> >  {
> >   cfi->iova = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_FAR);
> > + cfi->ttbr0 = arm_smmu_cb_readq(smmu, idx, ARM_SMMU_CB_TTBR0);
> >   cfi->fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
> > - cfi->fsynr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > + cfi->fsynr0 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR0);
> > + cfi->fsynr1 = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSYNR1);
>
> We already have an implementation hook (->get_fault_info()) which the
> qcom SMMU driver can override with qcom_adreno_smmu_get_fault_info().
> That thing dumps these registers already so if we're moving that into
> the core SMMU driver, let's get rid of the hook and move everybody over
> rather than having it done in both places.

As you probably saw, the next commit moves over
qcom_adreno_smmu_get_fault_info() to use this. The current back door
used by drm/msm to access these functions is specific to adreno_smmu
and there isn't an equivalent interface to allow it to call a generic
SMMU function so it isn't possible to move it entirely to the core. At
least not without a bigger refactoring that isn't justified for this
series that is just trying to fix things.

>
> >   cfi->cbfrsynra = arm_smmu_gr1_read(smmu, ARM_SMMU_GR1_CBFRSYNRA(idx));
> > + cfi->contextidr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_CONTEXTIDR);
>
> I think the CONTEXTIDR register is stage-1 only, so we shouldn't dump
> it for stage-2 domains.
>
> Will

Does it matter if we read the register though, as long as users are
aware of this and don't use its value for anything?

Connor


Re: [PATCH v2 0/5] drm/msm/dpu: enable CDM for all supported platforms

2025-03-11 Thread Dmitry Baryshkov
From: Dmitry Baryshkov 


On Thu, 20 Feb 2025 05:59:21 +0200, Dmitry Baryshkov wrote:
> Enable CDM block on all the platforms where it is supposed to be
> present. Notably, from the platforms being supported by the DPU driver
> it is not enabled for SM6115 (DPU 6.3), QCM2290 (DPU 6.5) and SM6375
> (DPU 6.9)
> 
> 

Applied, thanks!

[1/5] drm/msm/dpu: rename CDM block definition
  https://gitlab.freedesktop.org/lumag/msm/-/commit/51bc064005c5
[2/5] drm/msm/dpu: enable CDM_0 for DPUs 5.x+
  https://gitlab.freedesktop.org/lumag/msm/-/commit/15f2825defeb
[3/5] drm/msm/dpu: enable CDM_0 for DPUs 1.x - 4.x
  https://gitlab.freedesktop.org/lumag/msm/-/commit/d5c1e00ea2de
[4/5] drm/msm/dpu: enable CDM_0 for SC8280XP platform
  https://gitlab.freedesktop.org/lumag/msm/-/commit/b5bbf4fab0a9
[5/5] drm/msm/dpu: enable CDM_0 for X Elite platform
  https://gitlab.freedesktop.org/lumag/msm/-/commit/989a24211eaf

Best regards,
-- 
Dmitry Baryshkov 


Re: [PATCH v4 4/5] iommu/arm-smmu-qcom: Make set_stall work when the device is on

2025-03-11 Thread Connor Abbott
On Tue, Mar 11, 2025 at 2:11 PM Will Deacon  wrote:
>
> On Tue, Mar 04, 2025 at 11:56:50AM -0500, Connor Abbott wrote:
> > Up until now we have only called the set_stall callback during
> > initialization when the device is off. But we will soon start calling it
> > to temporarily disable stall-on-fault when the device is on, so handle
> > that by checking if the device is on and writing SCTLR.
> >
> > Signed-off-by: Connor Abbott 
> > ---
> >  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 30 
> > +++---
> >  1 file changed, 27 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c 
> > b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > index 
> > a428e53add08d451fb2152e3ab80e0fba936e214..d34a0d917013bb3d5a24b3ce72f48e3b38474da2
> >  100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> > @@ -77,12 +77,36 @@ static void qcom_adreno_smmu_set_stall(const void 
> > *cookie, bool enabled)
> >  {
> >   struct arm_smmu_domain *smmu_domain = (void *)cookie;
> >   struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> > - struct qcom_smmu *qsmmu = to_qcom_smmu(smmu_domain->smmu);
> > + struct arm_smmu_device *smmu = smmu_domain->smmu;
> > + struct qcom_smmu *qsmmu = to_qcom_smmu(smmu);
> > + u32 mask = BIT(cfg->cbndx);
> > + bool stall_changed = !!(qsmmu->stall_enabled & mask) != enabled;
> > + unsigned long flags;
> >
> >   if (enabled)
> > - qsmmu->stall_enabled |= BIT(cfg->cbndx);
> > + qsmmu->stall_enabled |= mask;
> >   else
> > - qsmmu->stall_enabled &= ~BIT(cfg->cbndx);
> > + qsmmu->stall_enabled &= ~mask;
> > +
> > + /*
> > +  * If the device is on and we changed the setting, update the 
> > register.
> > +  */
> > + if (stall_changed && pm_runtime_get_if_active(smmu->dev) > 0) {
> > + spin_lock_irqsave(&smmu_domain->cb_lock, flags);
> > +
> > + u32 reg = arm_smmu_cb_read(smmu, cfg->cbndx, 
> > ARM_SMMU_CB_SCTLR);
> > +
> > + if (enabled)
> > + reg |= ARM_SMMU_SCTLR_CFCFG;
> > + else
> > + reg &= ~ARM_SMMU_SCTLR_CFCFG;
> > +
> > + arm_smmu_cb_write(smmu, cfg->cbndx, ARM_SMMU_CB_SCTLR, reg);
>
> Are you sure you don't need TLB invalidation for this to take effect? I
> think some fields in the SCTLR can be cached in the TLB but you'll need
> to check whether or not that applies to CFCFG.
>
> Will

I think it should be fine because CFCFG only controls behavior when
there's a context fault and there can't be TLB entries for entries
that cause a context fault: "The architecture permits the caching of
any translation table entry that has been returned from memory without
a fault and that does not, as a result of that entry, cause a
Translation Fault or an Access Flag fault."

Connor


Re: [PATCH v4 2/5] iommu/arm-smmu-qcom: Don't read fault registers directly

2025-03-11 Thread Rob Clark
On Tue, Mar 11, 2025 at 12:42 PM Connor Abbott  wrote:
>
> On Tue, Mar 11, 2025 at 2:08 PM Will Deacon  wrote:
> >
> > On Tue, Mar 04, 2025 at 11:56:48AM -0500, Connor Abbott wrote:
> > > In some cases drm/msm has to resume a stalled transaction directly in
> > > its fault handler. Experimentally this doesn't work on SMMU500 if the
> > > fault hasn't already been acknowledged by clearing FSR. Rather than
> > > trying to clear FSR in msm's fault handler and implementing a
> > > tricky handshake to avoid accidentally clearing FSR twice, we want to
> > > clear FSR before calling the fault handlers, but this means that the
> > > contents of registers can change underneath us in the fault handler and
> > > msm currently uses a private function to read the register contents for
> > > its own purposes in its fault handler, such as using the
> > > implementation-defined FSYNR1 to determine which block caused the fault.
> > > Fix this by making msm use the register values already read by arm-smmu
> > > itself before clearing FSR rather than messing around with reading
> > > registers directly.
> > >
> > > Signed-off-by: Connor Abbott 
> > > ---
> > >  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 19 +--
> > >  drivers/iommu/arm/arm-smmu/arm-smmu.c  | 14 +++---
> > >  drivers/iommu/arm/arm-smmu/arm-smmu.h  | 21 +++--
> > >  3 files changed, 27 insertions(+), 27 deletions(-)
> >
> > [...]
> >
> > > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h 
> > > b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > > index 
> > > d3bc77dcd4d40f25bc70f3289616fb866649b022..411d807e0a7033833716635efb3968a0bd3ff237
> > >  100644
> > > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> > > @@ -373,6 +373,16 @@ enum arm_smmu_domain_stage {
> > >   ARM_SMMU_DOMAIN_NESTED,
> > >  };
> > >
> > > +struct arm_smmu_context_fault_info {
> > > + unsigned long iova;
> > > + u64 ttbr0;
> > > + u32 fsr;
> > > + u32 fsynr0;
> > > + u32 fsynr1;
> > > + u32 cbfrsynra;
> > > + u32 contextidr;
> > > +};
> > > +
> > >  struct arm_smmu_domain {
> > >   struct arm_smmu_device  *smmu;
> > >   struct io_pgtable_ops   *pgtbl_ops;
> > > @@ -380,6 +390,7 @@ struct arm_smmu_domain {
> > >   const struct iommu_flush_ops*flush_ops;
> > >   struct arm_smmu_cfg cfg;
> > >   enum arm_smmu_domain_stage  stage;
> > > + struct arm_smmu_context_fault_info cfi;
> >
> > Does this mean we have to serialise all faults for a given domain? That
> > can't be right...
> >
> > Will
>
> They are already serialized? There's only one of each register per
> context bank, so you can only have one context fault at a time per
> context bank, and AFAIK a context bank is 1:1 with a domain. Also this
> struct is only written and then read inside the context bank's
> interrupt handler, and you can only have one interrupt at a time, no?
>
> Connor

And if it was a race condition with cfi getting overridden, it would
have already been an equivalent race condition currently when reading
the values from registers (ie. the register values could have changed
in the elapsed time)

So no additional serialization needed here.

BR,
-R


Re: [PATCH 1/4] drm/display: hdmi: provide central data authority for ACR params

2025-03-11 Thread Dmitry Baryshkov
On Mon, Mar 10, 2025 at 03:46:33PM +0100, Maxime Ripard wrote:
> On Sun, Mar 09, 2025 at 10:13:56AM +0200, Dmitry Baryshkov wrote:
> > From: Dmitry Baryshkov 
> > 
> > HDMI standard defines recommended N and CTS values for Audio Clock
> > Regeneration. Currently each driver implements those, frequently in
> > somewhat unique way. Provide a generic helper for getting those values
> > to be used by the HDMI drivers.
> > 
> > The helper is added to drm_hdmi_helper.c rather than drm_hdmi_audio.c
> > since HDMI drivers can be using this helper function even without
> > switching to DRM HDMI Audio helpers.
> > 
> > Note: currently this only handles the values per HDMI 1.4b Section 7.2
> > and HDMI 2.0 Section 9.2.1. Later the table can be expanded to
> > accommodate for Deep Color TMDS char rates per HDMI 1.4 Appendix D
> > and/or HDMI 2.0 / 2.1 Appendix C).
> > 
> > Signed-off-by: Dmitry Baryshkov 
> > ---
> >  drivers/gpu/drm/display/drm_hdmi_helper.c | 164 
> > ++
> >  include/drm/display/drm_hdmi_helper.h |   6 ++
> >  2 files changed, 170 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c 
> > b/drivers/gpu/drm/display/drm_hdmi_helper.c
> > index 
> > 74dd4d01dd9bb2c9e69ec1c60b0056bd69417e8a..89d25571bfd21c56c6835821d2272a12c816a76e
> >  100644
> > --- a/drivers/gpu/drm/display/drm_hdmi_helper.c
> > +++ b/drivers/gpu/drm/display/drm_hdmi_helper.c
> > @@ -256,3 +256,167 @@ drm_hdmi_compute_mode_clock(const struct 
> > drm_display_mode *mode,
> > return DIV_ROUND_CLOSEST_ULL(clock * bpc, 8);
> >  }
> >  EXPORT_SYMBOL(drm_hdmi_compute_mode_clock);
> > +
> > +struct drm_hdmi_acr_n_cts_entry {
> > +   unsigned int n;
> > +   unsigned int cts;
> > +};
> > +
> > +struct drm_hdmi_acr_data {
> > +   unsigned long tmds_clock_khz;
> > +   struct drm_hdmi_acr_n_cts_entry n_cts_32k,
> > +   n_cts_44k1,
> > +   n_cts_48k;
> > +};
> > +
> > +static const struct drm_hdmi_acr_data hdmi_acr_n_cts[] = {
> > +   {
> > +   /* "Other" entry */
> > +   .n_cts_32k =  { .n = 4096, },
> > +   .n_cts_44k1 = { .n = 6272, },
> > +   .n_cts_48k =  { .n = 6144, },
> > +   }, {
> > +   .tmds_clock_khz = 25175,
> > +   .n_cts_32k =  { .n = 4576,  .cts = 28125, },
> > +   .n_cts_44k1 = { .n = 7007,  .cts = 31250, },
> > +   .n_cts_48k =  { .n = 6864,  .cts = 28125, },
> > +   }, {
> > +   .tmds_clock_khz = 25200,
> > +   .n_cts_32k =  { .n = 4096,  .cts = 25200, },
> > +   .n_cts_44k1 = { .n = 6272,  .cts = 28000, },
> > +   .n_cts_48k =  { .n = 6144,  .cts = 25200, },
> > +   }, {
> > +   .tmds_clock_khz = 27000,
> > +   .n_cts_32k =  { .n = 4096,  .cts = 27000, },
> > +   .n_cts_44k1 = { .n = 6272,  .cts = 3, },
> > +   .n_cts_48k =  { .n = 6144,  .cts = 27000, },
> > +   }, {
> > +   .tmds_clock_khz = 27027,
> > +   .n_cts_32k =  { .n = 4096,  .cts = 27027, },
> > +   .n_cts_44k1 = { .n = 6272,  .cts = 30030, },
> > +   .n_cts_48k =  { .n = 6144,  .cts = 27027, },
> > +   }, {
> > +   .tmds_clock_khz = 54000,
> > +   .n_cts_32k =  { .n = 4096,  .cts = 54000, },
> > +   .n_cts_44k1 = { .n = 6272,  .cts = 6, },
> > +   .n_cts_48k =  { .n = 6144,  .cts = 54000, },
> > +   }, {
> > +   .tmds_clock_khz = 54054,
> > +   .n_cts_32k =  { .n = 4096,  .cts = 54054, },
> > +   .n_cts_44k1 = { .n = 6272,  .cts = 60060, },
> > +   .n_cts_48k =  { .n = 6144,  .cts = 54054, },
> > +   }, {
> > +   .tmds_clock_khz = 74176,
> > +   .n_cts_32k =  { .n = 11648, .cts = 210937, }, /* and 210938 */
> > +   .n_cts_44k1 = { .n = 17836, .cts = 234375, },
> > +   .n_cts_48k =  { .n = 11648, .cts = 140625, },
> > +   }, {
> > +   .tmds_clock_khz = 74250,
> > +   .n_cts_32k =  { .n = 4096,  .cts = 74250, },
> > +   .n_cts_44k1 = { .n = 6272,  .cts = 82500, },
> > +   .n_cts_48k =  { .n = 6144,  .cts = 74250, },
> > +   }, {
> > +   .tmds_clock_khz = 148352,
> > +   .n_cts_32k =  { .n = 11648, .cts = 421875, },
> > +   .n_cts_44k1 = { .n = 8918,  .cts = 234375, },
> > +   .n_cts_48k =  { .n = 5824,  .cts = 140625, },
> > +   }, {
> > +   .tmds_clock_khz = 148500,
> > +   .n_cts_32k =  { .n = 4096,  .cts = 148500, },
> > +   .n_cts_44k1 = { .n = 6272,  .cts = 165000, },
> > +   .n_cts_48k =  { .n = 6144,  .cts = 148500, },
> > +   }, {
> > +   .tmds_clock_khz = 296703,
> > +   .n_cts_32k =  { .n = 5824,  .cts = 421875, },
> > +   .n_cts_44k1 = { .n = 4459,  .cts = 234375, },
> > +   .n_cts_48k =  { .n = 5824,  .cts = 281250, },
> > +   }, {
> > +   .tmds_clock_khz = 297000,
> > +   .n_cts_32k =  { .n = 3072,  .cts = 222750, },
> > +  

Re: [PATCH 3/4] drm/vc4: use new helper to get ACR values

2025-03-11 Thread Maxime Ripard
On Sun, Mar 09, 2025 at 10:13:58AM +0200, Dmitry Baryshkov wrote:
> From: Dmitry Baryshkov 
> 
> Use drm_hdmi_acr_get_n_cts() helper instead of calculating N and CTS
> values in the VC4 driver.
> 
> Signed-off-by: Dmitry Baryshkov 
> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 10 +++---
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  7 +++
>  2 files changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 
> 37238a12baa58a06a5d6f40d1ab64abc7fac60d7..f24bcc2f3a2ac39aaea061b809940978341472f4
>  100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1637,6 +1637,7 @@ static void vc4_hdmi_encoder_atomic_mode_set(struct 
> drm_encoder *encoder,
> &crtc_state->adjusted_mode);
>   vc4_hdmi->output_bpc = conn_state->hdmi.output_bpc;
>   vc4_hdmi->output_format = conn_state->hdmi.output_format;
> + vc4_hdmi->tmds_char_rate = conn_state->hdmi.tmds_char_rate;
>   mutex_unlock(&vc4_hdmi->mutex);
>  }
>  
> @@ -1829,17 +1830,12 @@ static void vc4_hdmi_audio_set_mai_clock(struct 
> vc4_hdmi *vc4_hdmi,
>  
>  static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int 
> samplerate)
>  {
> - const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
> - u32 n, cts;
> - u64 tmp;
> + unsigned int n, cts;
>  
>   lockdep_assert_held(&vc4_hdmi->mutex);
>   lockdep_assert_held(&vc4_hdmi->hw_lock);
>  
> - n = 128 * samplerate / 1000;
> - tmp = (u64)(mode->clock * 1000) * n;
> - do_div(tmp, 128 * samplerate);
> - cts = tmp;
> + drm_hdmi_acr_get_n_cts(vc4_hdmi->tmds_char_rate, samplerate, &n, &cts);
>  
>   HDMI_WRITE(HDMI_CRP_CFG,
>  VC4_HDMI_CRP_CFG_EXTERNAL_CTS_EN |
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 
> e3d989ca302b72533c374dfa3fd0d5bd7fe64a82..0a775dbfe99d45521f3d0a2016555aefa81d7934
>  100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -211,6 +211,13 @@ struct vc4_hdmi {
>* KMS hooks. Protected by @mutex.
>*/
>   enum hdmi_colorspace output_format;
> +
> + /**
> +  * @tmds_char_rate: Copy of
> +  * @drm_connector_state.hdmi.tmds_char_rate for use outside of
> +  * KMS hooks. Protected by @mutex.
> +  */
> + unsigned long long tmds_char_rate;
>  };

This should be in drm_connector_hdmi if it's useful

Maxime


signature.asc
Description: PGP signature


  1   2   >