|
@@ -1458,66 +1458,6 @@ static const struct mipi_dsi_host_ops exynos_dsi_ops = {
|
|
|
.transfer = exynos_dsi_host_transfer,
|
|
|
};
|
|
|
|
|
|
-static int exynos_dsi_poweron(struct exynos_dsi *dsi)
|
|
|
-{
|
|
|
- struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
|
|
- int ret, i;
|
|
|
-
|
|
|
- ret = regulator_bulk_enable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
|
|
|
- if (ret < 0) {
|
|
|
- dev_err(dsi->dev, "cannot enable regulators %d\n", ret);
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
- for (i = 0; i < driver_data->num_clks; i++) {
|
|
|
- ret = clk_prepare_enable(dsi->clks[i]);
|
|
|
- if (ret < 0)
|
|
|
- goto err_clk;
|
|
|
- }
|
|
|
-
|
|
|
- ret = phy_power_on(dsi->phy);
|
|
|
- if (ret < 0) {
|
|
|
- dev_err(dsi->dev, "cannot enable phy %d\n", ret);
|
|
|
- goto err_clk;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-
|
|
|
-err_clk:
|
|
|
- while (--i > -1)
|
|
|
- clk_disable_unprepare(dsi->clks[i]);
|
|
|
- regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-static void exynos_dsi_poweroff(struct exynos_dsi *dsi)
|
|
|
-{
|
|
|
- struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
|
|
- int ret, i;
|
|
|
-
|
|
|
- usleep_range(10000, 20000);
|
|
|
-
|
|
|
- if (dsi->state & DSIM_STATE_INITIALIZED) {
|
|
|
- dsi->state &= ~DSIM_STATE_INITIALIZED;
|
|
|
-
|
|
|
- exynos_dsi_disable_clock(dsi);
|
|
|
-
|
|
|
- exynos_dsi_disable_irq(dsi);
|
|
|
- }
|
|
|
-
|
|
|
- dsi->state &= ~DSIM_STATE_CMD_LPM;
|
|
|
-
|
|
|
- phy_power_off(dsi->phy);
|
|
|
-
|
|
|
- for (i = driver_data->num_clks - 1; i > -1; i--)
|
|
|
- clk_disable_unprepare(dsi->clks[i]);
|
|
|
-
|
|
|
- ret = regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
|
|
|
- if (ret < 0)
|
|
|
- dev_err(dsi->dev, "cannot disable regulators %d\n", ret);
|
|
|
-}
|
|
|
-
|
|
|
static void exynos_dsi_enable(struct drm_encoder *encoder)
|
|
|
{
|
|
|
struct exynos_dsi *dsi = encoder_to_dsi(encoder);
|
|
@@ -1526,16 +1466,14 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
|
|
|
if (dsi->state & DSIM_STATE_ENABLED)
|
|
|
return;
|
|
|
|
|
|
- ret = exynos_dsi_poweron(dsi);
|
|
|
- if (ret < 0)
|
|
|
- return;
|
|
|
+ pm_runtime_get_sync(dsi->dev);
|
|
|
|
|
|
dsi->state |= DSIM_STATE_ENABLED;
|
|
|
|
|
|
ret = drm_panel_prepare(dsi->panel);
|
|
|
if (ret < 0) {
|
|
|
dsi->state &= ~DSIM_STATE_ENABLED;
|
|
|
- exynos_dsi_poweroff(dsi);
|
|
|
+ pm_runtime_put_sync(dsi->dev);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -1547,7 +1485,7 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
|
|
|
dsi->state &= ~DSIM_STATE_ENABLED;
|
|
|
exynos_dsi_set_display_enable(dsi, false);
|
|
|
drm_panel_unprepare(dsi->panel);
|
|
|
- exynos_dsi_poweroff(dsi);
|
|
|
+ pm_runtime_put_sync(dsi->dev);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -1569,7 +1507,7 @@ static void exynos_dsi_disable(struct drm_encoder *encoder)
|
|
|
|
|
|
dsi->state &= ~DSIM_STATE_ENABLED;
|
|
|
|
|
|
- exynos_dsi_poweroff(dsi);
|
|
|
+ pm_runtime_put_sync(dsi->dev);
|
|
|
}
|
|
|
|
|
|
static enum drm_connector_status
|
|
@@ -1954,22 +1892,99 @@ static int exynos_dsi_probe(struct platform_device *pdev)
|
|
|
|
|
|
platform_set_drvdata(pdev, &dsi->encoder);
|
|
|
|
|
|
+ pm_runtime_enable(dev);
|
|
|
+
|
|
|
return component_add(dev, &exynos_dsi_component_ops);
|
|
|
}
|
|
|
|
|
|
static int exynos_dsi_remove(struct platform_device *pdev)
|
|
|
{
|
|
|
+ pm_runtime_disable(&pdev->dev);
|
|
|
+
|
|
|
component_del(&pdev->dev, &exynos_dsi_component_ops);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_PM
|
|
|
+static int exynos_dsi_suspend(struct device *dev)
|
|
|
+{
|
|
|
+ struct drm_encoder *encoder = dev_get_drvdata(dev);
|
|
|
+ struct exynos_dsi *dsi = encoder_to_dsi(encoder);
|
|
|
+ struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
|
|
+ int ret, i;
|
|
|
+
|
|
|
+ usleep_range(10000, 20000);
|
|
|
+
|
|
|
+ if (dsi->state & DSIM_STATE_INITIALIZED) {
|
|
|
+ dsi->state &= ~DSIM_STATE_INITIALIZED;
|
|
|
+
|
|
|
+ exynos_dsi_disable_clock(dsi);
|
|
|
+
|
|
|
+ exynos_dsi_disable_irq(dsi);
|
|
|
+ }
|
|
|
+
|
|
|
+ dsi->state &= ~DSIM_STATE_CMD_LPM;
|
|
|
+
|
|
|
+ phy_power_off(dsi->phy);
|
|
|
+
|
|
|
+ for (i = driver_data->num_clks - 1; i > -1; i--)
|
|
|
+ clk_disable_unprepare(dsi->clks[i]);
|
|
|
+
|
|
|
+ ret = regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
|
|
|
+ if (ret < 0)
|
|
|
+ dev_err(dsi->dev, "cannot disable regulators %d\n", ret);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int exynos_dsi_resume(struct device *dev)
|
|
|
+{
|
|
|
+ struct drm_encoder *encoder = dev_get_drvdata(dev);
|
|
|
+ struct exynos_dsi *dsi = encoder_to_dsi(encoder);
|
|
|
+ struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
|
|
|
+ int ret, i;
|
|
|
+
|
|
|
+ ret = regulator_bulk_enable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
|
|
|
+ if (ret < 0) {
|
|
|
+ dev_err(dsi->dev, "cannot enable regulators %d\n", ret);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < driver_data->num_clks; i++) {
|
|
|
+ ret = clk_prepare_enable(dsi->clks[i]);
|
|
|
+ if (ret < 0)
|
|
|
+ goto err_clk;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = phy_power_on(dsi->phy);
|
|
|
+ if (ret < 0) {
|
|
|
+ dev_err(dsi->dev, "cannot enable phy %d\n", ret);
|
|
|
+ goto err_clk;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+err_clk:
|
|
|
+ while (--i > -1)
|
|
|
+ clk_disable_unprepare(dsi->clks[i]);
|
|
|
+ regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+static const struct dev_pm_ops exynos_dsi_pm_ops = {
|
|
|
+ SET_RUNTIME_PM_OPS(exynos_dsi_suspend, exynos_dsi_resume, NULL)
|
|
|
+};
|
|
|
+
|
|
|
struct platform_driver dsi_driver = {
|
|
|
.probe = exynos_dsi_probe,
|
|
|
.remove = exynos_dsi_remove,
|
|
|
.driver = {
|
|
|
.name = "exynos-dsi",
|
|
|
.owner = THIS_MODULE,
|
|
|
+ .pm = &exynos_dsi_pm_ops,
|
|
|
.of_match_table = exynos_dsi_of_match,
|
|
|
},
|
|
|
};
|