@@ -51,9 +51,9 @@ static const struct of_device_id mtk_mdp_comp_driver_dt_match[] = {
};
MODULE_DEVICE_TABLE(of, mtk_mdp_comp_driver_dt_match);
-int mtk_mdp_comp_clock_on(struct mtk_mdp_comp *comp)
+int mtk_mdp_comp_power_on(struct mtk_mdp_comp *comp)
{
- int i, err, status;
+ int status, err;
if (comp->larb_dev) {
err = mtk_smi_larb_get(comp->larb_dev);
@@ -63,12 +63,54 @@ int mtk_mdp_comp_clock_on(struct mtk_mdp_comp *comp)
err = pm_runtime_get_sync(comp->dev);
if (err < 0) {
- dev_err(comp->dev,
- "failed to runtime get, err %d.\n",
- err);
+ dev_err(comp->dev, "failed to runtime get, err %d.\n", err);
return err;
}
+ err = mtk_mdp_comp_clock_on(comp);
+ if (err) {
+ dev_err(comp->dev, "failed to turn on clock. err=%d", err);
+ status = err;
+ goto err_mtk_mdp_comp_clock_on;
+ }
+
+ return 0;
+
+err_mtk_mdp_comp_clock_on:
+ err = pm_runtime_put_sync(comp->dev);
+ if (err)
+ dev_err(comp->dev, "failed to runtime put in cleanup. err=%d", err);
+
+ return status;
+}
+
+int mtk_mdp_comp_power_off(struct mtk_mdp_comp *comp)
+{
+ int status, err;
+
+ mtk_mdp_comp_clock_off(comp);
+
+ err = pm_runtime_put_sync(comp->dev);
+ if (err < 0) {
+ dev_err(comp->dev, "failed to runtime put, err %d.\n", err);
+ status = err;
+ goto err_pm_runtime_put_sync;
+ }
+
+ return 0;
+
+err_pm_runtime_put_sync:
+ err = mtk_mdp_comp_clock_on(comp);
+ if (err)
+ dev_err(comp->dev, "failed to turn on clock in cleanup. err=%d", err);
+
+ return status;
+}
+
+int mtk_mdp_comp_clock_on(struct mtk_mdp_comp *comp)
+{
+ int i, err, status;
+
for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
if (IS_ERR(comp->clk[i]))
continue;
@@ -94,7 +136,8 @@ int mtk_mdp_comp_clock_on(struct mtk_mdp_comp *comp)
return status;
}
-int mtk_mdp_comp_clock_off(struct mtk_mdp_comp *comp)
+
+void mtk_mdp_comp_clock_off(struct mtk_mdp_comp *comp)
{
int i;
@@ -106,8 +149,6 @@ int mtk_mdp_comp_clock_off(struct mtk_mdp_comp *comp)
if (comp->larb_dev)
mtk_smi_larb_put(comp->larb_dev);
-
- return pm_runtime_put_sync(comp->dev);
}
static int mtk_mdp_comp_bind(struct device *dev, struct device *master, void *data)
@@ -23,8 +23,11 @@ struct mtk_mdp_comp {
int mtk_mdp_comp_init(struct mtk_mdp_comp *comp, struct device *dev);
+int mtk_mdp_comp_power_on(struct mtk_mdp_comp *comp);
+int mtk_mdp_comp_power_off(struct mtk_mdp_comp *comp);
+
int mtk_mdp_comp_clock_on(struct mtk_mdp_comp *comp);
-int mtk_mdp_comp_clock_off(struct mtk_mdp_comp *comp);
+void mtk_mdp_comp_clock_off(struct mtk_mdp_comp *comp);
extern struct platform_driver mtk_mdp_component_driver;
@@ -57,29 +57,64 @@ static int mtk_mdp_clock_on(struct mtk_mdp_dev *mdp)
struct device *dev = &mdp->pdev->dev;
int err;
+ /*
+ * The master / rdma0 component will have pm_runtime_get_sync called
+ * on it through mtk_mdp_m2m_start_streaming, making it unnecessary to
+ * have mtk_mdp_comp_power_on called on it.
+ */
+ err = mtk_mdp_comp_clock_on(&mdp->comp_self);
+ if (err)
+ return err;
+
list_for_each_entry(comp_node, &mdp->comp_list, node) {
- err = mtk_mdp_comp_clock_on(comp_node);
+ err = mtk_mdp_comp_power_on(comp_node);
if (err) {
status = err;
- goto err_mtk_mdp_comp_clock_on;
+ goto err_mtk_mdp_comp_power_on;
}
}
return 0;
-err_mtk_mdp_comp_clock_on:
- list_for_each_entry_continue_reverse(comp_node, &mdp->comp_list, node)
- mtk_mdp_comp_clock_off(comp_node);
-
+err_mtk_mdp_comp_power_on:
+ list_for_each_entry_continue_reverse(comp_node, &mdp->comp_list, node) {
+ err = mtk_mdp_comp_power_off(comp_node);
+ if (err)
+ dev_err(&mdp->pdev->dev, "failed to power off after error. err=%d", err);
+ }
return status;
}
-static void mtk_mdp_clock_off(struct mtk_mdp_dev *mdp)
+static int mtk_mdp_clock_off(struct mtk_mdp_dev *mdp)
{
struct mtk_mdp_comp *comp_node;
+ int status, err;
+
+ list_for_each_entry(comp_node, &mdp->comp_list, node) {
+ err = mtk_mdp_comp_power_off(comp_node);
+ if (err) {
+ status = err;
+ goto err_mtk_mdp_comp_power_off;
+ }
+ }
- list_for_each_entry(comp_node, &mdp->comp_list, node)
- mtk_mdp_comp_clock_off(comp_node);
+ /*
+ * The master / rdma0 component will have pm_runtime_put called
+ * on it through mtk_mdp_m2m_stop_streaming, making it unnecessary to
+ * have mtk_mdp_comp_power_off called on it.
+ */
+ mtk_mdp_comp_clock_off(&mdp->comp_self);
+
+ return 0;
+
+err_mtk_mdp_comp_power_off:
+ list_for_each_entry_continue_reverse(comp_node, &mdp->comp_list, node) {
+ err = mtk_mdp_comp_power_on(comp_node);
+ if (err)
+ dev_err(&mdp->pdev->dev, "failed to power on after error. err=%d", err);
+ }
+
+ return status;
}
static void mtk_mdp_wdt_worker(struct work_struct *work)
@@ -118,8 +153,6 @@ static int mtk_mdp_master_bind(struct device *dev)
int status;
struct mtk_mdp_dev *mdp = dev_get_drvdata(dev);
- mtk_mdp_register_component(mdp, &mdp->comp_self);
-
status = component_bind_all(dev, mdp);
if (status) {
dev_err(dev, "Failed to bind all components: %d\n", status);
@@ -140,8 +173,6 @@ static int mtk_mdp_master_bind(struct device *dev)
component_unbind_all(dev, mdp);
err_component_bind_all:
- mtk_mdp_unregister_component(mdp, &mdp->comp_self);
-
return status;
}
@@ -152,7 +183,6 @@ static void mtk_mdp_master_unbind(struct device *dev)
pm_runtime_disable(dev);
mtk_mdp_unregister_m2m_device(mdp);
component_unbind_all(dev, mdp);
- mtk_mdp_unregister_component(mdp, &mdp->comp_self);
}
static const struct component_master_ops mtk_mdp_com_ops = {
@@ -337,9 +367,7 @@ static int __maybe_unused mtk_mdp_pm_suspend(struct device *dev)
{
struct mtk_mdp_dev *mdp = dev_get_drvdata(dev);
- mtk_mdp_clock_off(mdp);
-
- return 0;
+ return mtk_mdp_clock_off(mdp);
}
static int __maybe_unused mtk_mdp_pm_resume(struct device *dev)