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.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIwBAABCAAaBQJXvaiSExx0cmVkaW5nQG52aWRpYS5jb20ACgkQ3SOs138+s6Hv
 jg/6AnYkczQYraAb8Oy2YO3dIfz3r0TLGEEnY3AKudur867mNG0V59JcUXHQYKin
 FL7z4iIEx21RAtA9gUEc7xz9gitXP2W/GqRG6v1u0wLn+GS72TuNZCsqUVPQ6Glr
 yg0uLPoxsFyLa3rsTgif5jXxpsbSd6OV2NdkpImqt1EQLaOWYSNqLLq/YNvMsvCK
 QivRvvJEYznIyJayIN/PDekfYY3L5esMQNdDEI9jJKdJrTykQThx2eOIbsgY4MyC
 sdp/h9R23O1ZFvfGONrQHOOzDGumhDJtsRfew+q9JoBaOOgztk2LmPpRZFQsIrmV
 1rv1ahQh3boPWw3cSoQMCE8E3Eu2wD/zNrWYbKyhjChx/HTaSPyQGwk0v2WycizA
 KnNo3eQOTT/5Wb/KvhCaef4Q+yc4LbcAC8T3pkYyGVy+yhUOXr4SGOQLh4Za0Sag
 uaM20wk3TPYAiyUKZFE7RZ1WHtOp56gOIHbS5eV5ppuR2lmoCh4vK5yCojaz4gww
 DAHzldegReurS3du613KrV63lue1r3nwX1f0kKDsWd4yN0FH/74g/QC1jXKqJmmk
 ZevqKCQ1eoaPyOMQI2G0rvRL4B63s800oHO2L760e5SdbM1/Oraxzc+FobGZz9KW
 Y55SyNnn3QT5HcH6dntmisnuSbZVXVNonEJaPJWFLH/ChgI=
 =lyq1
 -----END PGP SIGNATURE-----

Merge tag 'drm/tegra/for-4.8-rc4' of git://anongit.freedesktop.org/tegra/linux into drm-fixes

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
This commit is contained in:
Dave Airlie 2016-08-25 12:49:22 +10:00
commit 30bffd1b44
3 changed files with 70 additions and 40 deletions

View 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);

View 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,30 +256,43 @@ EXPORT_SYMBOL(tegra_mipi_request);
void tegra_mipi_free(struct tegra_mipi_device *device)
{
int err;
mutex_lock(&device->mipi->lock);
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_unlock(&device->mipi->lock);
platform_device_put(device->pdev);
kfree(device);
}
EXPORT_SYMBOL(tegra_mipi_free);
int tegra_mipi_enable(struct tegra_mipi_device *dev)
{
int err = 0;
mutex_lock(&dev->mipi->lock);
if (dev->mipi->usage_count++ == 0)
err = tegra_mipi_power_up(dev->mipi);
mutex_unlock(&dev->mipi->lock);
return err;
}
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)
{
unsigned long timeout = jiffies + msecs_to_jiffies(250);

View 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