Merge tag 'drm/tegra/for-4.8-rc4' of git://anongit.freedesktop.org/tegra/linux into...
authorDave Airlie <airlied@redhat.com>
Thu, 25 Aug 2016 02:49:22 +0000 (12:49 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 25 Aug 2016 02:49:22 +0000 (12:49 +1000)
drm/tegra: Fixes for v4.8-rc4

This contains one fix for DSI runtime power management support that was
introduced in v4.8-rc1. This is slightly more elaborate than I would've
wished, but there are a few corner cases that needed fixing.

* tag 'drm/tegra/for-4.8-rc4' of git://anongit.freedesktop.org/tegra/linux:
  drm/tegra: dsi: Enhance runtime power management

drivers/gpu/drm/tegra/dsi.c
drivers/gpu/host1x/mipi.c
include/linux/host1x.h

index 3d228ad..3dea121 100644 (file)
@@ -840,6 +840,21 @@ static const struct drm_encoder_funcs tegra_dsi_encoder_funcs = {
        .destroy = tegra_output_encoder_destroy,
 };
 
+static void tegra_dsi_unprepare(struct tegra_dsi *dsi)
+{
+       int err;
+
+       if (dsi->slave)
+               tegra_dsi_unprepare(dsi->slave);
+
+       err = tegra_mipi_disable(dsi->mipi);
+       if (err < 0)
+               dev_err(dsi->dev, "failed to disable MIPI calibration: %d\n",
+                       err);
+
+       pm_runtime_put(dsi->dev);
+}
+
 static void tegra_dsi_encoder_disable(struct drm_encoder *encoder)
 {
        struct tegra_output *output = encoder_to_output(encoder);
@@ -876,7 +891,26 @@ static void tegra_dsi_encoder_disable(struct drm_encoder *encoder)
 
        tegra_dsi_disable(dsi);
 
-       pm_runtime_put(dsi->dev);
+       tegra_dsi_unprepare(dsi);
+}
+
+static void tegra_dsi_prepare(struct tegra_dsi *dsi)
+{
+       int err;
+
+       pm_runtime_get_sync(dsi->dev);
+
+       err = tegra_mipi_enable(dsi->mipi);
+       if (err < 0)
+               dev_err(dsi->dev, "failed to enable MIPI calibration: %d\n",
+                       err);
+
+       err = tegra_dsi_pad_calibrate(dsi);
+       if (err < 0)
+               dev_err(dsi->dev, "MIPI calibration failed: %d\n", err);
+
+       if (dsi->slave)
+               tegra_dsi_prepare(dsi->slave);
 }
 
 static void tegra_dsi_encoder_enable(struct drm_encoder *encoder)
@@ -887,13 +921,8 @@ static void tegra_dsi_encoder_enable(struct drm_encoder *encoder)
        struct tegra_dsi *dsi = to_dsi(output);
        struct tegra_dsi_state *state;
        u32 value;
-       int err;
-
-       pm_runtime_get_sync(dsi->dev);
 
-       err = tegra_dsi_pad_calibrate(dsi);
-       if (err < 0)
-               dev_err(dsi->dev, "MIPI calibration failed: %d\n", err);
+       tegra_dsi_prepare(dsi);
 
        state = tegra_dsi_get_state(dsi);
 
index 52a6fd2..e00809d 100644 (file)
@@ -242,20 +242,6 @@ struct tegra_mipi_device *tegra_mipi_request(struct device *device)
        dev->pads = args.args[0];
        dev->device = device;
 
-       mutex_lock(&dev->mipi->lock);
-
-       if (dev->mipi->usage_count++ == 0) {
-               err = tegra_mipi_power_up(dev->mipi);
-               if (err < 0) {
-                       dev_err(dev->mipi->dev,
-                               "failed to power up MIPI bricks: %d\n",
-                               err);
-                       return ERR_PTR(err);
-               }
-       }
-
-       mutex_unlock(&dev->mipi->lock);
-
        return dev;
 
 put:
@@ -270,29 +256,42 @@ EXPORT_SYMBOL(tegra_mipi_request);
 
 void tegra_mipi_free(struct tegra_mipi_device *device)
 {
-       int err;
+       platform_device_put(device->pdev);
+       kfree(device);
+}
+EXPORT_SYMBOL(tegra_mipi_free);
 
-       mutex_lock(&device->mipi->lock);
+int tegra_mipi_enable(struct tegra_mipi_device *dev)
+{
+       int err = 0;
 
-       if (--device->mipi->usage_count == 0) {
-               err = tegra_mipi_power_down(device->mipi);
-               if (err < 0) {
-                       /*
-                        * Not much that can be done here, so an error message
-                        * will have to do.
-                        */
-                       dev_err(device->mipi->dev,
-                               "failed to power down MIPI bricks: %d\n",
-                               err);
-               }
-       }
+       mutex_lock(&dev->mipi->lock);
 
-       mutex_unlock(&device->mipi->lock);
+       if (dev->mipi->usage_count++ == 0)
+               err = tegra_mipi_power_up(dev->mipi);
+
+       mutex_unlock(&dev->mipi->lock);
+
+       return err;
 
-       platform_device_put(device->pdev);
-       kfree(device);
 }
-EXPORT_SYMBOL(tegra_mipi_free);
+EXPORT_SYMBOL(tegra_mipi_enable);
+
+int tegra_mipi_disable(struct tegra_mipi_device *dev)
+{
+       int err = 0;
+
+       mutex_lock(&dev->mipi->lock);
+
+       if (--dev->mipi->usage_count == 0)
+               err = tegra_mipi_power_down(dev->mipi);
+
+       mutex_unlock(&dev->mipi->lock);
+
+       return err;
+
+}
+EXPORT_SYMBOL(tegra_mipi_disable);
 
 static int tegra_mipi_wait(struct tegra_mipi *mipi)
 {
index d2ba7d3..1ffbf2a 100644 (file)
@@ -304,6 +304,8 @@ struct tegra_mipi_device;
 
 struct tegra_mipi_device *tegra_mipi_request(struct device *device);
 void tegra_mipi_free(struct tegra_mipi_device *device);
+int tegra_mipi_enable(struct tegra_mipi_device *device);
+int tegra_mipi_disable(struct tegra_mipi_device *device);
 int tegra_mipi_calibrate(struct tegra_mipi_device *device);
 
 #endif