[PATCH v5 4/4] drm/tilcdc: Add drm bridge support for attaching drm bridge drivers

2016-11-29 Thread Laurent Pinchart
Hi Jyri,

On Tuesday 29 Nov 2016 22:18:56 Jyri Sarha wrote:
> On 11/25/16 11:02, Jyri Sarha wrote:
> > -void tilcdc_remove_external_encoders(struct drm_device *dev)
> > +void tilcdc_remove_external_device(struct drm_device *dev)
> >  {
> > struct tilcdc_drm_private *priv = dev->dev_private;
> > -   int i;
> > 
> > /* Restore the original helper functions, if any. */
> > -   for (i = 0; i < priv->num_connectors; i++)
> > -   if (IS_ERR(priv->connector_funcs[i]))
> > -   drm_connector_helper_add(priv->connectors[i], NULL);
> > -   else if (priv->connector_funcs[i])
> > -   drm_connector_helper_add(priv->connectors[i],
> > -priv->connector_funcs[i]);
> > +   if (IS_ERR(priv->connector_funcs))
> > +   drm_connector_helper_add(priv->external_connector, NULL);
> > +   else if (priv->connector_funcs)
> > +   drm_connector_helper_add(priv->external_connector,
> > +priv->connector_funcs);
> 
> I still need to add:
> +
> +   if (priv->external_encoder && priv->external_encoder->bridge)
> +   drm_bridge_detach(priv->external_encoder->bridge);

"drm: bridge: Detach bridge from encoder at encoder cleanup time" :-)

> > +}
> 
> ... and reorder the tilcdc_fini() a bit. I need to put
> tilcdc_remove_external_device() before drm_mode_config_cleanup()
> for drm_bridge_detach() to be called before whole mode config is teared
> apart.
> 
> There is also a bug in tearing down drm debugfs that had to be fixed
> before I got module unload and reload to work properly. I'll send a
> patch shortly.

-- 
Regards,

Laurent Pinchart



[PATCH v5 4/4] drm/tilcdc: Add drm bridge support for attaching drm bridge drivers

2016-11-29 Thread Jyri Sarha
On 11/25/16 11:02, Jyri Sarha wrote:
> -void tilcdc_remove_external_encoders(struct drm_device *dev)
> +void tilcdc_remove_external_device(struct drm_device *dev)
>  {
>   struct tilcdc_drm_private *priv = dev->dev_private;
> - int i;
>  
>   /* Restore the original helper functions, if any. */
> - for (i = 0; i < priv->num_connectors; i++)
> - if (IS_ERR(priv->connector_funcs[i]))
> - drm_connector_helper_add(priv->connectors[i], NULL);
> - else if (priv->connector_funcs[i])
> - drm_connector_helper_add(priv->connectors[i],
> -  priv->connector_funcs[i]);
> + if (IS_ERR(priv->connector_funcs))
> + drm_connector_helper_add(priv->external_connector, NULL);
> + else if (priv->connector_funcs)
> + drm_connector_helper_add(priv->external_connector,
> +  priv->connector_funcs);


I still need to add:
+
+   if (priv->external_encoder && priv->external_encoder->bridge)
+   drm_bridge_detach(priv->external_encoder->bridge);

> +}

... and reorder the tilcdc_fini() a bit. I need to put
tilcdc_remove_external_device() before drm_mode_config_cleanup()
for drm_bridge_detach() to be called before whole mode config is teared
apart.

There is also a bug in tearing down drm debugfs that had to be fixed
before I got module unload and reload to work properly. I'll send a
patch shortly.


[PATCH v5 4/4] drm/tilcdc: Add drm bridge support for attaching drm bridge drivers

2016-11-25 Thread Jyri Sarha
Adds drm bride support for attaching drm bridge drivers to tilcdc. The
decision whether a video port leads to an external encoder or bridge
is made simply based on remote device's compatible string. The code
has been tested with BeagleBone-Black with and without BeagleBone
DVI-D Cape Rev A3 using ti-tfp410 driver.

Signed-off-by: Jyri Sarha 
---
 drivers/gpu/drm/tilcdc/tilcdc_drv.c  |  11 +-
 drivers/gpu/drm/tilcdc/tilcdc_drv.h  |   5 +-
 drivers/gpu/drm/tilcdc/tilcdc_external.c | 260 +++
 drivers/gpu/drm/tilcdc/tilcdc_external.h |   5 +-
 4 files changed, 207 insertions(+), 74 deletions(-)

diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c 
b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index 3d2cea0..7f4d3bc 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -209,7 +209,7 @@ static void tilcdc_fini(struct drm_device *dev)

drm_irq_uninstall(dev);
drm_mode_config_cleanup(dev);
-   tilcdc_remove_external_encoders(dev);
+   tilcdc_remove_external_device(dev);

 #ifdef CONFIG_CPU_FREQ
if (priv->freq_transition.notifier_call)
@@ -381,12 +381,17 @@ static int tilcdc_init(struct drm_driver *ddrv, struct 
device *dev)
if (ret < 0)
goto init_failed;

-   ret = tilcdc_add_external_encoders(ddev);
+   ret = tilcdc_add_component_encoder(ddev);
if (ret < 0)
goto init_failed;
+   } else {
+   ret = tilcdc_attach_external_device(ddev);
+   if (ret)
+   goto init_failed;
}

-   if ((priv->num_encoders == 0) || (priv->num_connectors == 0)) {
+   if (!priv->external_connector &&
+   ((priv->num_encoders == 0) || (priv->num_connectors == 0))) {
dev_err(dev, "no encoders/connectors found\n");
ret = -ENXIO;
goto init_failed;
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h 
b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
index d31fe5d..411f8a8 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
@@ -88,7 +88,10 @@ struct tilcdc_drm_private {

unsigned int num_connectors;
struct drm_connector *connectors[8];
-   const struct drm_connector_helper_funcs *connector_funcs[8];
+
+   struct drm_encoder *external_encoder;
+   struct drm_connector *external_connector;
+   const struct drm_connector_helper_funcs *connector_funcs;

bool is_registered;
bool is_componentized;
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c 
b/drivers/gpu/drm/tilcdc/tilcdc_external.c
index 06a4c58..c67d7cd 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
@@ -28,44 +28,50 @@
.raster_order   = 0,
 };

+static const struct tilcdc_panel_info panel_info_default = {
+   .ac_bias= 255,
+   .ac_bias_intrpt = 0,
+   .dma_burst_sz   = 16,
+   .bpp= 16,
+   .fdd= 0x80,
+   .tft_alt_mode   = 0,
+   .sync_edge  = 0,
+   .sync_ctrl  = 1,
+   .raster_order   = 0,
+};
+
 static int tilcdc_external_mode_valid(struct drm_connector *connector,
  struct drm_display_mode *mode)
 {
struct tilcdc_drm_private *priv = connector->dev->dev_private;
-   int ret, i;
+   int ret;

ret = tilcdc_crtc_mode_valid(priv->crtc, mode);
if (ret != MODE_OK)
return ret;

-   for (i = 0; i < priv->num_connectors &&
-priv->connectors[i] != connector; i++)
-   ;
-
-   BUG_ON(priv->connectors[i] != connector);
-   BUG_ON(!priv->connector_funcs[i]);
+   BUG_ON(priv->external_connector != connector);
+   BUG_ON(!priv->connector_funcs);

/* If the connector has its own mode_valid call it. */
-   if (!IS_ERR(priv->connector_funcs[i]) &&
-   priv->connector_funcs[i]->mode_valid)
-   return priv->connector_funcs[i]->mode_valid(connector, mode);
+   if (!IS_ERR(priv->connector_funcs) &&
+   priv->connector_funcs->mode_valid)
+   return priv->connector_funcs->mode_valid(connector, mode);

return MODE_OK;
 }

-static int tilcdc_add_external_encoder(struct drm_device *dev,
-  struct drm_connector *connector)
+static int tilcdc_add_external_connector(struct drm_device *dev,
+struct drm_connector *connector)
 {
struct tilcdc_drm_private *priv = dev->dev_private;
struct drm_connector_helper_funcs *connector_funcs;

-   priv->connectors[priv->num_connectors] = connector;
-   priv->encoders[priv->num_encoders++] =