Browse Source

soc: soundwire: use pm runtime function to tear down soundwire master

Use pm_runtime_put_sync_suspend to tear down soundwire master.
It makes sure the process is synced with the autosuspend call
flow.

Change-Id: Ib4feccd905bcbf046e58bd5eaffde40ee391feda
Signed-off-by: Xiaojun Sang <[email protected]>
Xiaojun Sang 7 years ago
parent
commit
f7dd63a169
2 changed files with 26 additions and 22 deletions
  1. 23 22
      soc/swr-wcd-ctrl.c
  2. 3 0
      soc/swr-wcd-ctrl.h

+ 23 - 22
soc/swr-wcd-ctrl.c

@@ -1481,6 +1481,7 @@ static int swrm_probe(struct platform_device *pdev)
 	mutex_init(&swrm->mlock);
 	INIT_LIST_HEAD(&swrm->mport_list);
 	mutex_init(&swrm->reslock);
+	mutex_init(&swrm->force_down_lock);
 
 	ret = of_property_read_u32(swrm->dev->of_node, "qcom,swr-num-dev",
 				   &swrm->num_dev);
@@ -1557,6 +1558,9 @@ err_mstr_fail:
 	swrm->reg_irq(swrm->handle, swr_mstr_interrupt,
 			swrm, SWR_IRQ_FREE);
 err_irq_fail:
+	mutex_destroy(&swrm->mlock);
+	mutex_destroy(&swrm->reslock);
+	mutex_destroy(&swrm->force_down_lock);
 err_pdata_fail:
 	kfree(swrm);
 err_memory_fail:
@@ -1581,6 +1585,7 @@ static int swrm_remove(struct platform_device *pdev)
 	swr_unregister_master(&swrm->master);
 	mutex_destroy(&swrm->mlock);
 	mutex_destroy(&swrm->reslock);
+	mutex_destroy(&swrm->force_down_lock);
 	kfree(swrm);
 	return 0;
 }
@@ -1644,13 +1649,20 @@ static int swrm_runtime_suspend(struct device *dev)
 	int ret = 0;
 	struct swr_master *mstr = &swrm->master;
 	struct swr_device *swr_dev;
+	int current_state = 0;
 
 	dev_dbg(dev, "%s: pm_runtime: suspend state: %d\n",
 		__func__, swrm->state);
 	mutex_lock(&swrm->reslock);
-	if ((swrm->state == SWR_MSTR_RESUME) ||
-	    (swrm->state == SWR_MSTR_UP)) {
-		if (swrm_is_port_en(&swrm->master)) {
+	mutex_lock(&swrm->force_down_lock);
+	current_state = swrm->state;
+	mutex_unlock(&swrm->force_down_lock);
+	if ((current_state == SWR_MSTR_RESUME) ||
+	    (current_state == SWR_MSTR_UP) ||
+	    (current_state == SWR_MSTR_SSR)) {
+
+		if ((current_state != SWR_MSTR_SSR) &&
+			swrm_is_port_en(&swrm->master)) {
 			dev_dbg(dev, "%s ports are enabled\n", __func__);
 			ret = -EBUSY;
 			goto exit;
@@ -1679,27 +1691,16 @@ static int swrm_device_down(struct device *dev)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev);
 	int ret = 0;
-	struct swr_master *mstr = &swrm->master;
-	struct swr_device *swr_dev;
 
 	dev_dbg(dev, "%s: swrm state: %d\n", __func__, swrm->state);
-	mutex_lock(&swrm->reslock);
-	if ((swrm->state == SWR_MSTR_RESUME) ||
-	    (swrm->state == SWR_MSTR_UP)) {
-		list_for_each_entry(swr_dev, &mstr->devices, dev_list) {
-			ret = swr_device_down(swr_dev);
-			if (ret)
-				dev_err(dev,
-					"%s: failed to shutdown swr dev %d\n",
-					__func__, swr_dev->dev_num);
-		}
-		dev_dbg(dev, "%s: Shutting down SWRM\n", __func__);
-		pm_runtime_disable(dev);
-		pm_runtime_set_suspended(dev);
-		pm_runtime_enable(dev);
-		swrm_clk_request(swrm, false);
-	}
-	mutex_unlock(&swrm->reslock);
+
+	mutex_lock(&swrm->force_down_lock);
+	swrm->state = SWR_MSTR_SSR;
+	mutex_unlock(&swrm->force_down_lock);
+	/* Use pm runtime function to tear down */
+	ret = pm_runtime_put_sync_suspend(dev);
+	pm_runtime_get_noresume(dev);
+
 	return ret;
 }
 

+ 3 - 0
soc/swr-wcd-ctrl.h

@@ -34,6 +34,7 @@ enum {
 	SWR_MSTR_RESUME,
 	SWR_MSTR_UP,
 	SWR_MSTR_DOWN,
+	SWR_MSTR_SSR,
 };
 
 enum {
@@ -105,6 +106,8 @@ struct swr_mstr_ctrl {
 	struct platform_device *pdev;
 	int num_rx_chs;
 	u8 num_cfg_devs;
+	struct mutex force_down_lock;
+	int force_down_state;
 };
 
 #endif /* _SWR_WCD_CTRL_H */