Title: [6633] trunk/sound/soc/codecs/ad1938.c: add codec suspend/resume entry and clean power management codes
Revision
6633
Author
bhsong
Date
2009-06-10 05:13:36 -0500 (Wed, 10 Jun 2009)

Log Message

add codec suspend/resume entry and clean power management codes

Modified Paths


Diff

Modified: trunk/sound/soc/codecs/ad1938.c (6632 => 6633)


--- trunk/sound/soc/codecs/ad1938.c	2009-06-10 09:08:02 UTC (rev 6632)
+++ trunk/sound/soc/codecs/ad1938.c	2009-06-10 10:13:36 UTC (rev 6633)
@@ -27,12 +27,6 @@
 
 struct snd_soc_device *ad1938_socdev;
 
-/* struct to flag whether adc and dac need power to work */
-struct ad1938_pwr_sta {
-	int adc_pwr;
-	int dac_pwr;
-};
-
 /* dac de-emphasis enum control */
 static const char *ad1938_deemp[] = {"flat", "48kHz", "44.1kHz", "32kHz"};
 
@@ -103,25 +97,66 @@
 	return 0;
 }
 
+/* dac/adc/pll poweron/off functions */
+static int ad1938_dac_powerctrl(struct snd_soc_codec *codec, int cmd)
+{
+	int reg;
+
+	reg = codec->read(codec, AD1938_DAC_CTRL0);
+	if (cmd)
+		reg &= ~DAC_POWERDOWN;
+	else
+		reg |= DAC_POWERDOWN;
+
+	codec->write(codec, AD1938_DAC_CTRL0, reg);
+
+	return 0;
+
+}
+
+static int ad1938_adc_powerctrl(struct snd_soc_codec *codec, int cmd)
+{
+	int reg;
+
+	reg = codec->read(codec, AD1938_ADC_CTRL0);
+	if (cmd)
+		reg &= ~ADC_POWERDOWN;
+	else
+		reg |= ADC_POWERDOWN;
+
+	codec->write(codec, AD1938_ADC_CTRL0, reg);
+
+	return 0;
+}
+
+static int ad1938_pll_powerctrl(struct snd_soc_codec *codec, int cmd)
+{
+	int reg;
+
+	reg = codec->read(codec, AD1938_PLL_CLK_CTRL0);
+	if (cmd)
+		reg &= ~PLL_POWERDOWN;
+	else
+		reg |= PLL_POWERDOWN;
+
+	codec->write(codec, AD1938_PLL_CLK_CTRL0, reg);
+
+	return 0;
+
+}
+
 /* dai_ops.set_pll entry */
 static int ad1938_set_pll(struct snd_soc_dai *codec_dai,
 		int pll_id, unsigned int freq_in, unsigned int freq_out)
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
-	struct ad1938_pwr_sta *pwr_sta = codec->private_data;
-	int pll_reg;
 
-	if (freq_out) {
-		pll_reg = codec->read(codec, AD1938_PLL_CLK_CTRL0);
-		pll_reg &= ~PLL_POWERDOWN;
-		codec->write(codec, AD1938_PLL_CLK_CTRL0, pll_reg);
-	} else {
+	if (freq_out)
+		ad1938_pll_powerctrl(codec, 1);
+	else {
 		/* playing while recording, framework will poweroff-poweron pll redundantly */
-		if ((pwr_sta->dac_pwr == 0) && (pwr_sta->adc_pwr == 0)) {
-			pll_reg = codec->read(codec, AD1938_PLL_CLK_CTRL0);
-			pll_reg |= PLL_POWERDOWN;
-			codec->write(codec, AD1938_PLL_CLK_CTRL0, pll_reg);
-		}
+		if ((!codec_dai->capture.active) && (!codec_dai->playback.active))
+			ad1938_pll_powerctrl(codec, 0);
 	}
 
 	return 0;
@@ -133,68 +168,42 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
 	struct snd_soc_codec *codec = socdev->codec;
-	struct ad1938_pwr_sta *pwr_sta = codec->private_data;
-	int pwr_reg;
+	struct snd_soc_dai *codec_dai = codec->dai;
 
 	/* set active */
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		/* If not poweron adc, dac can't work */
-		pwr_reg = codec->read(codec, AD1938_ADC_CTRL0);
-		if (pwr_reg & ADC_POWERDOWN)
-			codec->write(codec, AD1938_ADC_CTRL0, pwr_reg & ~ADC_POWERDOWN);
-
-		/* poweron dac */
-		pwr_reg = codec->read(codec, AD1938_DAC_CTRL0);
-		pwr_reg &= ~DAC_POWERDOWN;
-		codec->write(codec, AD1938_DAC_CTRL0, pwr_reg);
-
-		pwr_sta->dac_pwr = 1;
+		if (!codec_dai->capture.active)
+			ad1938_adc_powerctrl(codec, 1);
+		ad1938_dac_powerctrl(codec, 1);
 	} else {
 		/* poweron adc */
-		pwr_reg = codec->read(codec, AD1938_ADC_CTRL0);
-		pwr_reg &= ~ADC_POWERDOWN;
-		codec->write(codec, AD1938_ADC_CTRL0, pwr_reg);
-
-		pwr_sta->adc_pwr = 1;
+		ad1938_adc_powerctrl(codec, 1);
 	}
 
 	return 0;
 }
 
-
 /* ops.shutdown entry */
 static void ad1938_pcm_shutdown(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_device *socdev = rtd->socdev;
 	struct snd_soc_codec *codec = socdev->codec;
-	struct ad1938_pwr_sta *pwr_sta = codec->private_data;
-	int pwr_reg;
+	struct snd_soc_dai *codec_dai = codec->dai;
 
 	/* deactivate */
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		/* poweroff dac */
-		pwr_reg = codec->read(codec, AD1938_DAC_CTRL0);
-		pwr_reg |= DAC_POWERDOWN;
-		codec->write(codec, AD1938_DAC_CTRL0, pwr_reg);
+		ad1938_dac_powerctrl(codec, 0);
 
-		pwr_sta->dac_pwr = 0;
-
 		/* after poweroff dac, if adc is not opened, poweroff it too */
-		if (pwr_sta->adc_pwr == 0) {
-			pwr_reg = codec->read(codec, AD1938_ADC_CTRL0);
-			pwr_reg |= ADC_POWERDOWN;
-			codec->write(codec, AD1938_ADC_CTRL0, pwr_reg);
-		}
+		if (!codec_dai->capture.active)
+			ad1938_adc_powerctrl(codec, 0);
 	} else {
 		/* if dac is still working, can't shutdown adc */
-		if (pwr_sta->dac_pwr == 0) {
-			pwr_reg = codec->read(codec, AD1938_ADC_CTRL0);
-			pwr_reg |= ADC_POWERDOWN;
-			codec->write(codec, AD1938_ADC_CTRL0, pwr_reg);
-		}
-
-		pwr_sta->adc_pwr = 0;
+		if (!codec_dai->playback.active)
+			ad1938_adc_powerctrl(codec, 0);
 	}
 }
 
@@ -325,7 +334,7 @@
 	int ret = 0;
 
 	/* codec alloc and init */
-	codec = kzalloc(sizeof(struct snd_soc_codec) + sizeof(struct ad1938_pwr_sta), GFP_KERNEL);
+	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
 	if (codec == NULL)
 		return -ENOMEM;
 	mutex_init(&codec->mutex);
@@ -335,7 +344,6 @@
 	codec->num_dai = 1;
 	codec->write = ad1938_reg_write;
 	codec->read = ad1938_reg_read;
-	codec->private_data = codec + 1;
 	socdev->codec = codec;
 	INIT_LIST_HEAD(&codec->dapm_widgets);
 	INIT_LIST_HEAD(&codec->dapm_paths);
@@ -403,9 +411,47 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int ad1938_soc_suspend(struct platform_device *pdev,
+		pm_message_t state)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+
+	/* poweroff dac/adc/pll */
+	ad1938_dac_powerctrl(codec, 0);
+	ad1938_adc_powerctrl(codec, 0);
+	ad1938_pll_powerctrl(codec, 0);
+
+	return 0;
+}
+
+static int ad1938_soc_resume(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+	struct snd_soc_dai *codec_dai = codec->dai;
+
+	/* playing while recording, framework will poweroff-poweron pll redundantly */
+	if (codec_dai->capture.active || codec_dai->playback.active) {
+		ad1938_pll_powerctrl(codec, 1);
+		ad1938_adc_powerctrl(codec, 1);
+	}
+	if (codec_dai->playback.active)
+		ad1938_adc_powerctrl(codec, 1);
+
+	return 0;
+}
+#else
+#define ad1938_soc_suspend NULL
+#define ad1938_soc_resume NULL
+#endif
+
 struct snd_soc_codec_device soc_codec_dev_ad1938 = {
 	.probe = 	ad1938_soc_probe,
 	.remove = 	ad1938_soc_remove,
+	.suspend =      ad1938_soc_suspend,
+	.resume =       ad1938_soc_resume,
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_ad1938);
 
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to