RE: [PATCH v2] drm: rcar-du: lvds: Get mode from state

2019-12-17 Thread Fabrizio Castro
Hi Laurent,

Thank you for your patch!

> From: linux-renesas-soc-ow...@vger.kernel.org 
>  On Behalf Of Laurent Pinchart
> Sent: 13 December 2019 18:28
> Subject: [PATCH v2] drm: rcar-du: lvds: Get mode from state
> 
> The R-Car LVDS encoder driver implements the bridge .mode_set()
> operation for the sole purpose of storing the mode in the LVDS private
> data, to be used later when enabling the encoder.
> 
> Switch to the bridge .atomic_enable() and .atomic_disable() operations
> in order to access the global atomic state, and get the mode from the
> state instead. Remove both the unneeded .mode_set() operation and the
> display_mode and mode fields storing state data from the rcar_lvds
> private structure.
> 
> As a side effect we get the CRTC from the state, replace the CRTC
> pointer retrieved through the bridge's encoder that shouldn't be used by
> atomic drivers.
> 
> Signed-off-by: Laurent Pinchart 
> ---
> Changes since v1:
> 
> - Call .atomic_enable() on the companion
> - Set companion->encoder in .attach()
> 
> The patch has been tested on the Draak board with the HDMI output in
> LVDS dual-link mode, and on the Salvator-XS board with the HDMI, VGA and
> LVDS outputs in single-link mode.
> 
> ---
>  drivers/gpu/drm/rcar-du/rcar_lvds.c | 158 +++-
>  1 file changed, 85 insertions(+), 73 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c 
> b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> index 8c6c172bbf2e..c550bfd59e71 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> @@ -65,9 +65,6 @@ struct rcar_lvds {
>   struct clk *dotclkin[2];/* External DU clocks */
>   } clocks;
> 
> - struct drm_display_mode display_mode;
> - enum rcar_lvds_mode mode;
> -
>   struct drm_bridge *companion;
>   bool dual_link;
>  };
> @@ -402,10 +399,51 @@ EXPORT_SYMBOL_GPL(rcar_lvds_clk_disable);
>   * Bridge
>   */
> 
> -static void rcar_lvds_enable(struct drm_bridge *bridge)
> +static enum rcar_lvds_mode rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds,
> + const struct drm_connector *connector)
> +{
> + const struct drm_display_info *info;
> + enum rcar_lvds_mode mode;
> +
> + /*
> +  * There is no API yet to retrieve LVDS mode from a bridge, only panels
> +  * are supported.
> +  */
> + if (!lvds->panel)
> + return RCAR_LVDS_MODE_JEIDA;
> +
> + info = >display_info;
> + if (!info->num_bus_formats || !info->bus_formats) {
> + dev_err(lvds->dev, "no LVDS bus format reported\n");

dev_warn perhaps?

Also, how about:
s/no LVDS bus format reported/no LVDS bus format reported, using JEIDA/
or something along those lines?

> + return RCAR_LVDS_MODE_JEIDA;
> + }
> +
> + switch (info->bus_formats[0]) {
> + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:

Shall we take the below into account here?
https://lwn.net/Articles/794944/

> + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
> + mode = RCAR_LVDS_MODE_JEIDA;
> + break;
> + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
> + mode = RCAR_LVDS_MODE_VESA;
> + break;
> + default:
> + dev_err(lvds->dev, "unsupported LVDS bus format 0x%04x\n",
> + info->bus_formats[0]);

dev_warn perhaps?

Also, how about:
s/unsupported LVDS bus format 0x%04x/unsupported LVDS bus format 0x%04x, using 
JEIDA/
or something along those lines?

> + return RCAR_LVDS_MODE_JEIDA;
> + }
> +
> + if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB)
> + mode |= RCAR_LVDS_MODE_MIRROR;
> +
> + return mode;
> +}
> +
> +static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
> + struct drm_atomic_state *state)
>  {
>   struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
> - const struct drm_display_mode *mode = >display_mode;
> + struct drm_connector *connector;
> + struct drm_crtc *crtc;
>   u32 lvdhcr;
>   u32 lvdcr0;
>   int ret;
> @@ -414,9 +452,14 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
>   if (ret < 0)
>   return;
> 
> + /* Retrieve the connector and CRTC through the atomic state. */
> + connector = drm_atomic_get_new_connector_for_encoder(state,
> +  bridge->encoder);
> + crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
> +
>   /* Enable the companion LVDS encoder in dual-link m

Re: [PATCH v2] drm: rcar-du: lvds: Get mode from state

2019-12-16 Thread Laurent Pinchart
Hi Fabrizio,

On Mon, Dec 16, 2019 at 05:39:55PM +, Fabrizio Castro wrote:
> > From: linux-renesas-soc-ow...@vger.kernel.org 
> >  On Behalf Of Laurent Pinchart
> > Sent: 13 December 2019 18:28
> > Subject: [PATCH v2] drm: rcar-du: lvds: Get mode from state
> > 
> > The R-Car LVDS encoder driver implements the bridge .mode_set()
> > operation for the sole purpose of storing the mode in the LVDS private
> > data, to be used later when enabling the encoder.
> > 
> > Switch to the bridge .atomic_enable() and .atomic_disable() operations
> > in order to access the global atomic state, and get the mode from the
> > state instead. Remove both the unneeded .mode_set() operation and the
> > display_mode and mode fields storing state data from the rcar_lvds
> > private structure.
> > 
> > As a side effect we get the CRTC from the state, replace the CRTC
> > pointer retrieved through the bridge's encoder that shouldn't be used by
> > atomic drivers.
> > 
> > Signed-off-by: Laurent Pinchart 
> > ---
> > Changes since v1:
> > 
> > - Call .atomic_enable() on the companion
> > - Set companion->encoder in .attach()
> > 
> > The patch has been tested on the Draak board with the HDMI output in
> > LVDS dual-link mode, and on the Salvator-XS board with the HDMI, VGA and
> > LVDS outputs in single-link mode.
> > 
> > ---
> >  drivers/gpu/drm/rcar-du/rcar_lvds.c | 158 +++-
> >  1 file changed, 85 insertions(+), 73 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c 
> > b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > index 8c6c172bbf2e..c550bfd59e71 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > @@ -65,9 +65,6 @@ struct rcar_lvds {
> > struct clk *dotclkin[2];/* External DU clocks */
> > } clocks;
> > 
> > -   struct drm_display_mode display_mode;
> > -   enum rcar_lvds_mode mode;
> > -
> > struct drm_bridge *companion;
> > bool dual_link;
> >  };
> > @@ -402,10 +399,51 @@ EXPORT_SYMBOL_GPL(rcar_lvds_clk_disable);
> >   * Bridge
> >   */
> > 
> > -static void rcar_lvds_enable(struct drm_bridge *bridge)
> > +static enum rcar_lvds_mode rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds,
> > +   const struct drm_connector *connector)
> > +{
> > +   const struct drm_display_info *info;
> > +   enum rcar_lvds_mode mode;
> > +
> > +   /*
> > +* There is no API yet to retrieve LVDS mode from a bridge, only panels
> > +* are supported.
> > +*/
> > +   if (!lvds->panel)
> > +   return RCAR_LVDS_MODE_JEIDA;
> > +
> > +   info = >display_info;
> > +   if (!info->num_bus_formats || !info->bus_formats) {
> > +   dev_err(lvds->dev, "no LVDS bus format reported\n");
> 
> dev_warn perhaps?
> 
> Also, how about:
> s/no LVDS bus format reported/no LVDS bus format reported, using JEIDA/
> or something along those lines?

Ack.

> > +   return RCAR_LVDS_MODE_JEIDA;
> > +   }
> > +
> > +   switch (info->bus_formats[0]) {
> > +   case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
> 
> Shall we take the below into account here?
> https://lwn.net/Articles/794944/

Sure, but I think it's not required when multiple cases are grouped
together with no line in-between.

> > +   case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
> > +   mode = RCAR_LVDS_MODE_JEIDA;
> > +   break;
> > +   case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
> > +   mode = RCAR_LVDS_MODE_VESA;
> > +   break;
> > +   default:
> > +   dev_err(lvds->dev, "unsupported LVDS bus format 0x%04x\n",
> > +   info->bus_formats[0]);
> 
> dev_warn perhaps?
> 
> Also, how about:
> s/unsupported LVDS bus format 0x%04x/unsupported LVDS bus format 0x%04x, 
> using JEIDA/
> or something along those lines?

Ack.

> > +   return RCAR_LVDS_MODE_JEIDA;
> > +   }
> > +
> > +   if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB)
> > +   mode |= RCAR_LVDS_MODE_MIRROR;
> > +
> > +   return mode;
> > +}
> > +
> > +static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
> > +   struct drm_atomic_state *state)
> >  {
> > struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
> > -   const struct drm_display_mode *mode = >display_mode;
> > +   struct drm_con

[PATCH v2] drm: rcar-du: lvds: Get mode from state

2019-12-13 Thread Laurent Pinchart
The R-Car LVDS encoder driver implements the bridge .mode_set()
operation for the sole purpose of storing the mode in the LVDS private
data, to be used later when enabling the encoder.

Switch to the bridge .atomic_enable() and .atomic_disable() operations
in order to access the global atomic state, and get the mode from the
state instead. Remove both the unneeded .mode_set() operation and the
display_mode and mode fields storing state data from the rcar_lvds
private structure.

As a side effect we get the CRTC from the state, replace the CRTC
pointer retrieved through the bridge's encoder that shouldn't be used by
atomic drivers.

Signed-off-by: Laurent Pinchart 
---
Changes since v1:

- Call .atomic_enable() on the companion
- Set companion->encoder in .attach()

The patch has been tested on the Draak board with the HDMI output in
LVDS dual-link mode, and on the Salvator-XS board with the HDMI, VGA and
LVDS outputs in single-link mode.

---
 drivers/gpu/drm/rcar-du/rcar_lvds.c | 158 +++-
 1 file changed, 85 insertions(+), 73 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c 
b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index 8c6c172bbf2e..c550bfd59e71 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -65,9 +65,6 @@ struct rcar_lvds {
struct clk *dotclkin[2];/* External DU clocks */
} clocks;
 
-   struct drm_display_mode display_mode;
-   enum rcar_lvds_mode mode;
-
struct drm_bridge *companion;
bool dual_link;
 };
@@ -402,10 +399,51 @@ EXPORT_SYMBOL_GPL(rcar_lvds_clk_disable);
  * Bridge
  */
 
-static void rcar_lvds_enable(struct drm_bridge *bridge)
+static enum rcar_lvds_mode rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds,
+   const struct drm_connector *connector)
+{
+   const struct drm_display_info *info;
+   enum rcar_lvds_mode mode;
+
+   /*
+* There is no API yet to retrieve LVDS mode from a bridge, only panels
+* are supported.
+*/
+   if (!lvds->panel)
+   return RCAR_LVDS_MODE_JEIDA;
+
+   info = >display_info;
+   if (!info->num_bus_formats || !info->bus_formats) {
+   dev_err(lvds->dev, "no LVDS bus format reported\n");
+   return RCAR_LVDS_MODE_JEIDA;
+   }
+
+   switch (info->bus_formats[0]) {
+   case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
+   case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
+   mode = RCAR_LVDS_MODE_JEIDA;
+   break;
+   case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
+   mode = RCAR_LVDS_MODE_VESA;
+   break;
+   default:
+   dev_err(lvds->dev, "unsupported LVDS bus format 0x%04x\n",
+   info->bus_formats[0]);
+   return RCAR_LVDS_MODE_JEIDA;
+   }
+
+   if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB)
+   mode |= RCAR_LVDS_MODE_MIRROR;
+
+   return mode;
+}
+
+static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
+   struct drm_atomic_state *state)
 {
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
-   const struct drm_display_mode *mode = >display_mode;
+   struct drm_connector *connector;
+   struct drm_crtc *crtc;
u32 lvdhcr;
u32 lvdcr0;
int ret;
@@ -414,9 +452,14 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
if (ret < 0)
return;
 
+   /* Retrieve the connector and CRTC through the atomic state. */
+   connector = drm_atomic_get_new_connector_for_encoder(state,
+bridge->encoder);
+   crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
+
/* Enable the companion LVDS encoder in dual-link mode. */
if (lvds->dual_link && lvds->companion)
-   lvds->companion->funcs->enable(lvds->companion);
+   lvds->companion->funcs->atomic_enable(lvds->companion, state);
 
/*
 * Hardcode the channels and control signals routing for now.
@@ -452,18 +495,20 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
 * PLL clock configuration on all instances but the companion in
 * dual-link mode.
 */
-   if (!lvds->dual_link || lvds->companion)
+   if (!lvds->dual_link || lvds->companion) {
+   const struct drm_crtc_state *crtc_state =
+   drm_atomic_get_new_crtc_state(state, crtc);
+   const struct drm_display_mode *mode =
+   _state->adjusted_mode;
+
lvds->info->pll_setup(lvds, mode->clock * 1000);
+   }
 
/* Set the LVDS mode and select the input. */
-   lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT;
+   lvdcr0 = rcar_lvds_get_lvds_mode(lvds, connector) << LVDCR0_LVMD_SHIFT;
 
if (lvds->bridge.encoder) {
-   /*