Browse Source

Merge "asoc: lpass: add pm stay awake to avoid suspend"

qctecmdr 2 years ago
parent
commit
290f69973e

+ 35 - 0
asoc/codecs/lpass-cdc/lpass-cdc-tx-macro.c

@@ -129,6 +129,7 @@ struct lpass_cdc_tx_macro_priv {
 	int tx_mclk_users;
 	bool dapm_mclk_enable;
 	struct mutex mclk_lock;
+	struct mutex wlock;
 	struct snd_soc_component *component;
 	struct hpf_work tx_hpf_work[NUM_DECIMATORS];
 	struct tx_mute_work tx_mute_dwork[NUM_DECIMATORS];
@@ -147,8 +148,32 @@ struct lpass_cdc_tx_macro_priv {
 	bool hs_slow_insert_complete;
 	int pcm_rate[NUM_DECIMATORS];
 	bool swr_dmic_enable;
+	int wlock_holders;
 };
 
+static int lpass_cdc_tx_macro_wake_enable(struct lpass_cdc_tx_macro_priv *tx_priv,
+					bool wake_enable)
+{
+	int ret = 0;
+
+	mutex_lock(&tx_priv->wlock);
+	if (wake_enable) {
+		if (tx_priv->wlock_holders++ == 0) {
+			dev_dbg(tx_priv->dev, "%s: pm wake\n", __func__);
+			pm_stay_awake(tx_priv->dev);
+		}
+	} else {
+		if (--tx_priv->wlock_holders == 0) {
+			dev_dbg(tx_priv->dev, "%s: pm release\n", __func__);
+			pm_relax(tx_priv->dev);
+		}
+		if (tx_priv->wlock_holders < 0)
+			tx_priv->wlock_holders = 0;
+	}
+	mutex_unlock(&tx_priv->wlock);
+	return ret;
+}
+
 static bool lpass_cdc_tx_macro_get_data(struct snd_soc_component *component,
 			      struct device **tx_dev,
 			      struct lpass_cdc_tx_macro_priv **tx_priv,
@@ -431,6 +456,7 @@ static void lpass_cdc_tx_macro_tx_hpf_corner_freq_callback(struct work_struct *w
 		snd_soc_component_update_bits(component, hpf_gate_reg,
 						0x02, 0x00);
 	}
+	lpass_cdc_tx_macro_wake_enable(tx_priv, 0);
 }
 
 static void lpass_cdc_tx_macro_mute_update_callback(struct work_struct *work)
@@ -454,6 +480,7 @@ static void lpass_cdc_tx_macro_mute_update_callback(struct work_struct *work)
 	snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x10, 0x00);
 	dev_dbg(tx_priv->dev, "%s: decimator %u unmute\n",
 		__func__, decimator);
+	lpass_cdc_tx_macro_wake_enable(tx_priv, 0);
 }
 
 static int lpass_cdc_tx_macro_put_dec_enum(struct snd_kcontrol *kcontrol,
@@ -941,12 +968,14 @@ static int lpass_cdc_tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
 		}
 		if (tx_unmute_delay < unmute_delay)
 			tx_unmute_delay = unmute_delay;
+		lpass_cdc_tx_macro_wake_enable(tx_priv, 1);
 		/* schedule work queue to Remove Mute */
 		queue_delayed_work(system_freezable_wq,
 				   &tx_priv->tx_mute_dwork[decimator].dwork,
 				   msecs_to_jiffies(tx_unmute_delay));
 		if (tx_priv->tx_hpf_work[decimator].hpf_cut_off_freq !=
 							CF_MIN_3DB_150HZ) {
+			lpass_cdc_tx_macro_wake_enable(tx_priv, 1);
 			queue_delayed_work(system_freezable_wq,
 				&tx_priv->tx_hpf_work[decimator].dwork,
 				msecs_to_jiffies(hpf_delay));
@@ -1011,8 +1040,10 @@ static int lpass_cdc_tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
 						0x03, 0x01);
 			}
 		}
+		lpass_cdc_tx_macro_wake_enable(tx_priv, 0);
 		cancel_delayed_work_sync(
 				&tx_priv->tx_mute_dwork[decimator].dwork);
+		lpass_cdc_tx_macro_wake_enable(tx_priv, 0);
 
 		if (snd_soc_component_read(component, adc_mux_reg)
 						& SWR_MIC)
@@ -2039,6 +2070,7 @@ static int lpass_cdc_tx_macro_probe(struct platform_device *pdev)
 	}
 	tx_priv->tx_io_base = tx_io_base;
 	tx_priv->swr_dmic_enable = false;
+	tx_priv->wlock_holders = 0;
 	ret = of_property_read_u32(pdev->dev.of_node, dmic_sample_rate,
 				   &sample_rate);
 	if (ret) {
@@ -2053,6 +2085,7 @@ static int lpass_cdc_tx_macro_probe(struct platform_device *pdev)
 	}
 
 	mutex_init(&tx_priv->mclk_lock);
+	mutex_init(&tx_priv->wlock);
 	lpass_cdc_tx_macro_init_ops(&ops, tx_io_base);
 	ops.clk_id_req = TX_CORE_CLK;
 	ops.default_clk_id = TX_CORE_CLK;
@@ -2071,6 +2104,7 @@ static int lpass_cdc_tx_macro_probe(struct platform_device *pdev)
 	return 0;
 err_reg_macro:
 	mutex_destroy(&tx_priv->mclk_lock);
+	mutex_destroy(&tx_priv->wlock);
 	return ret;
 }
 
@@ -2086,6 +2120,7 @@ static int lpass_cdc_tx_macro_remove(struct platform_device *pdev)
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 	mutex_destroy(&tx_priv->mclk_lock);
+	mutex_destroy(&tx_priv->wlock);
 	lpass_cdc_unregister_macro(&pdev->dev, TX_MACRO);
 	return 0;
 }

+ 38 - 1
asoc/codecs/lpass-cdc/lpass-cdc-va-macro.c

@@ -138,6 +138,7 @@ struct lpass_cdc_va_macro_priv {
 	struct clk *lpass_audio_hw_vote;
 	struct mutex mclk_lock;
 	struct mutex swr_clk_lock;
+	struct mutex wlock;
 	struct snd_soc_component *component;
 	struct hpf_work va_hpf_work[LPASS_CDC_VA_MACRO_NUM_DECIMATORS];
 	struct va_mute_work va_mute_dwork[LPASS_CDC_VA_MACRO_NUM_DECIMATORS];
@@ -179,8 +180,33 @@ struct lpass_cdc_va_macro_priv {
 	bool pre_dev_up;
 	bool swr_dmic_enable;
 	bool use_lpi_mixer_control;
+	int wlock_holders;
 };
 
+
+static int lpass_cdc_va_macro_wake_enable(struct lpass_cdc_va_macro_priv *va_priv,
+				bool wake_enable)
+{
+	int ret = 0;
+
+	mutex_lock(&va_priv->wlock);
+	if (wake_enable) {
+		if (va_priv->wlock_holders++ == 0) {
+			dev_dbg(va_priv->dev, "%s: pm wake\n", __func__);
+			pm_stay_awake(va_priv->dev);
+		}
+	} else {
+		 if (--va_priv->wlock_holders == 0) {
+			dev_dbg(va_priv->dev, "%s: pm release\n", __func__);
+			pm_relax(va_priv->dev);
+		}
+		if (va_priv->wlock_holders < 0)
+			va_priv->wlock_holders = 0;
+	}
+	mutex_unlock(&va_priv->wlock);
+	return ret;
+}
+
 static bool lpass_cdc_va_macro_get_data(struct snd_soc_component *component,
 			      struct device **va_dev,
 			      struct lpass_cdc_va_macro_priv **va_priv,
@@ -949,6 +975,7 @@ static void lpass_cdc_va_macro_tx_hpf_corner_freq_callback(
 		snd_soc_component_update_bits(component, hpf_gate_reg,
 					      0x02, 0x00);
 	}
+	lpass_cdc_va_macro_wake_enable(va_priv, 0);
 }
 
 static void lpass_cdc_va_macro_mute_update_callback(struct work_struct *work)
@@ -971,6 +998,7 @@ static void lpass_cdc_va_macro_mute_update_callback(struct work_struct *work)
 	snd_soc_component_update_bits(component, tx_vol_ctl_reg, 0x10, 0x00);
 	dev_dbg(va_priv->dev, "%s: decimator %u unmute\n",
 		__func__, decimator);
+	lpass_cdc_va_macro_wake_enable(va_priv, 0);
 }
 
 static int lpass_cdc_va_macro_put_dec_enum(struct snd_kcontrol *kcontrol,
@@ -1297,14 +1325,17 @@ static int lpass_cdc_va_macro_enable_dec(struct snd_soc_dapm_widget *w,
 		 */
 		usleep_range(6000, 6010);
 		/* schedule work queue to Remove Mute */
+		lpass_cdc_va_macro_wake_enable(va_priv, 1);
 		queue_delayed_work(system_freezable_wq,
 				   &va_priv->va_mute_dwork[decimator].dwork,
 				   msecs_to_jiffies(va_tx_unmute_delay));
 		if (va_priv->va_hpf_work[decimator].hpf_cut_off_freq !=
-							CF_MIN_3DB_150HZ)
+							CF_MIN_3DB_150HZ) {
+		lpass_cdc_va_macro_wake_enable(va_priv, 1);
 			queue_delayed_work(system_freezable_wq,
 					&va_priv->va_hpf_work[decimator].dwork,
 					msecs_to_jiffies(hpf_delay));
+		}
 		/* apply gain after decimator is enabled */
 		snd_soc_component_write(component, tx_gain_ctl_reg,
 			snd_soc_component_read(component, tx_gain_ctl_reg));
@@ -1339,8 +1370,10 @@ static int lpass_cdc_va_macro_enable_dec(struct snd_soc_dapm_widget *w,
 						0x03, 0x01);
 			}
 		}
+		lpass_cdc_va_macro_wake_enable(va_priv, 0);
 		cancel_delayed_work_sync(
 				&va_priv->va_mute_dwork[decimator].dwork);
+		lpass_cdc_va_macro_wake_enable(va_priv, 0);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		/* Disable TX CLK */
@@ -2519,6 +2552,7 @@ static int lpass_cdc_va_macro_probe(struct platform_device *pdev)
 	}
 	va_priv->default_clk_id = default_clk_id;
 	va_priv->current_clk_id = TX_CORE_CLK;
+	va_priv->wlock_holders = 0;
 
 	va_priv->use_lpi_mixer_control = false;
 	if (of_find_property(pdev->dev.of_node, "use-lpi-control", NULL)) {
@@ -2544,6 +2578,7 @@ static int lpass_cdc_va_macro_probe(struct platform_device *pdev)
 	va_priv->pre_dev_up = true;
 
 	mutex_init(&va_priv->mclk_lock);
+	mutex_init(&va_priv->wlock);
 	dev_set_drvdata(&pdev->dev, va_priv);
 	lpass_cdc_va_macro_init_ops(&ops, va_io_base);
 	ops.clk_id_req = va_priv->default_clk_id;
@@ -2564,6 +2599,7 @@ static int lpass_cdc_va_macro_probe(struct platform_device *pdev)
 
 reg_macro_fail:
 	mutex_destroy(&va_priv->mclk_lock);
+	mutex_destroy(&va_priv->wlock);
 	if (is_used_va_swr_gpio)
 		mutex_destroy(&va_priv->swr_clk_lock);
 	return ret;
@@ -2591,6 +2627,7 @@ static int lpass_cdc_va_macro_remove(struct platform_device *pdev)
 	pm_runtime_set_suspended(&pdev->dev);
 	lpass_cdc_unregister_macro(&pdev->dev, VA_MACRO);
 	mutex_destroy(&va_priv->mclk_lock);
+	mutex_destroy(&va_priv->wlock);
 	if (va_priv->is_used_va_swr_gpio)
 		mutex_destroy(&va_priv->swr_clk_lock);
 	return 0;