intel_sst: ASoC: sst_platform: Ensure that Penwell osc_clk0 in ON during voice call
authorFabien Barthes <fabienx.barthes@intel.com>
Thu, 6 Oct 2011 15:18:29 +0000 (16:18 +0100)
committermgross <mark.gross@intel.com>
Wed, 9 Nov 2011 21:16:44 +0000 (13:16 -0800)
During voice call, SST driver is in suspend mode and ensure that osc_clk0 is
turned off. This clock is input to MSIC PLL

In order to enable voice  call, the switching needs a clock source The audio
processing chip for voice call also needs this clock, so we should keep this
ON during voice call

This patch adds a function in sst driver to enable and disable the osc_clk0 and
it is done for voice and sst suspend.

Change-Id: Icc9f01c1a3780367f459cd50eb7f604a2a203027
Signed-off-by: Fabien Barthes <fabienx.barthes@intel.com>
drivers/staging/intel_sst/intel_sst.c
drivers/staging/intel_sst/intel_sst.h
drivers/staging/intel_sst/intel_sst_common.h
drivers/staging/intel_sst/intel_sst_stream.c
sound/soc/mid-x86/sst_platform.c

index 96c9617..35d6389 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/miscdevice.h>
 #include <linux/pm_runtime.h>
 #include <asm/mrst.h>
+#include <asm/intel_scu_ipc.h>
 #include "intel_sst.h"
 #include "intel_sst_ioctl.h"
 #include "intel_sst_fw_ipc.h"
@@ -468,6 +469,44 @@ void sst_save_dsp_context(void)
        return;
 }
 
+int intel_sst_set_pll(unsigned int enable, enum intel_sst_pll_mode mode)
+{
+       u32 *ipc_wbuf, ret = 0;
+       u8 cbuf[16] = { '\0' };
+
+       pr_debug("set_pll, for %x\n", enable);
+       ipc_wbuf = (u32 *)&cbuf;
+       cbuf[0] = 0; /* OSC_CLK_OUT0 */
+       mutex_lock(&sst_drv_ctx->sst_lock);
+       if (enable == true) {
+               cbuf[1] = 1; /* enable the clock, preserve clk ratio */
+               if (sst_drv_ctx->pll_mode) {
+                       /* clock is on, so just update and return */
+                       sst_drv_ctx->pll_mode |= mode;
+                       goto out;
+               }
+               sst_drv_ctx->pll_mode |= mode;
+               pr_debug("set_pll, enabling pll %x\n", sst_drv_ctx->pll_mode);
+       } else {
+               /* for turning off only, we check device state and turn off only
+                * when device is supspended
+                */
+               sst_drv_ctx->pll_mode &= ~mode;
+               pr_debug("set_pll, disabling pll %x\n", sst_drv_ctx->pll_mode);
+               if (!sst_drv_ctx->pll_mode)
+                       goto out;
+               cbuf[1] = 0; /* Disable the clock */
+       }
+       /* send ipc command to configure the PNW clock to MSIC PLLIN */
+       ret = intel_scu_ipc_command(0xE6, 0, ipc_wbuf, 2, NULL, 0);
+       if (ret)
+               pr_err("ipc clk disable command failed: %d\n", ret);
+out:
+       mutex_unlock(&sst_drv_ctx->sst_lock);
+       return ret;
+}
+EXPORT_SYMBOL(intel_sst_set_pll);
+
 /*
  * The runtime_suspend/resume is pretty much similar to the legacy
  * suspend/resume with the noted exception below: The PCI core takes care of
@@ -476,11 +515,7 @@ void sst_save_dsp_context(void)
  */
 static int intel_sst_runtime_suspend(struct device *dev)
 {
-       struct pci_dev *pci_dev = to_pci_dev(dev);
        union config_status_reg csr;
-       u32 *ipc_wbuf;
-       u8 cbuf[16] = { '\0' };
-       int ret = 0;
 
        pr_debug("sst: runtime_suspend called\n");
 
@@ -495,28 +530,17 @@ static int intel_sst_runtime_suspend(struct device *dev)
        sst_drv_ctx->csr_value = csr.full;
        csr.full = csr.full | 0x2;
 
-       ipc_wbuf = (u32 *)&cbuf;
-       cbuf[0] = 0; /* OSC_CLK_OUT0 */
-       cbuf[1] = 0; /* Disable the clock */
-
        /* Move the SST state to Suspended */
        mutex_lock(&sst_drv_ctx->sst_lock);
        sst_drv_ctx->sst_state = SST_SUSPENDED;
        sst_shim_write(sst_drv_ctx->shim, SST_CSR, csr.full);
-       /* send ipc command to disable the PNW clock to MSIC PLLIN */
-       ret = intel_scu_ipc_command(0xE6, 0, ipc_wbuf, 2, NULL, 0);
-       if (ret != 0)
-               pr_err("ipc clk disable command failed\n");
        mutex_unlock(&sst_drv_ctx->sst_lock);
+       intel_sst_set_pll(false, SST_PLL_AUDIO);
        return 0;
 }
 
 static int intel_sst_runtime_resume(struct device *dev)
 {
-       struct pci_dev *pci_dev = to_pci_dev(dev);
-       int ret = 0;
-       u32 *ipc_wbuf;
-       u8 cbuf[16] = { '\0' };
        u32 csr;
 
        pr_debug("sst: runtime_resume called\n");
@@ -534,13 +558,7 @@ static int intel_sst_runtime_resume(struct device *dev)
         */
        csr |= (sst_drv_ctx->csr_value | 0x30000);
 
-       ipc_wbuf = (u32 *)&cbuf;
-       cbuf[0] = 0; /* OSC_CLK_OUT0 */
-       cbuf[1] = 1; /* enable the clock, preserve clk ratio */
-       ret = intel_scu_ipc_command(0xE6, 0, ipc_wbuf, 2, NULL, 0);
-       if (ret != 0)
-               pr_err("ipc clk enable command failed\n");
-
+       intel_sst_set_pll(true, SST_PLL_AUDIO);
        mutex_lock(&sst_drv_ctx->sst_lock);
        sst_drv_ctx->sst_state = SST_UN_INIT;
        mutex_unlock(&sst_drv_ctx->sst_lock);
index fbfaeea..a938e69 100644 (file)
@@ -139,6 +139,12 @@ enum sc_reg_access_type {
        PMIC_READ_MODIFY,
 };
 
+enum intel_sst_pll_mode {
+       SST_PLL_VOICE = 0x1,
+       SST_PLL_AUDIO = 0x2,
+};
+
 int register_sst_card(struct intel_sst_card_ops *card);
 void unregister_sst_card(struct intel_sst_card_ops *card);
+int intel_sst_set_pll(unsigned int enable, enum intel_sst_pll_mode mode);
 #endif /* __INTEL_SST_H__ */
index 293060e..5a070b6 100644 (file)
@@ -423,6 +423,7 @@ struct intel_sst_drv {
        unsigned int            *fw_cntx;
        unsigned int            fw_cntx_size;
        unsigned int            csr_value;
+       unsigned int            pll_mode;
 
        unsigned int            fw_downloaded;
 };
index 6d926d2..68caaf9 100644 (file)
@@ -474,7 +474,8 @@ int sst_drop_stream(int str_id)
                }
        } else {
                retval = -EBADRQC;
-               pr_err("SST ERR: BADQRC for stream\n");
+               pr_debug("SST ERR:BADQRC for stream, state %x\n",
+                        str_info->status);
        }
        return retval;
 }
index 7aba8d4..e4fa2d4 100644 (file)
@@ -259,8 +259,12 @@ static int sst_platform_open(struct snd_pcm_substream *substream)
                        return -EBUSY;
                }
                sst_cpu_ctx->active_voice_cnt++;
-               return snd_pcm_hw_constraint_integer(runtime,
-                        SNDRV_PCM_HW_PARAM_PERIODS);
+               ret_val = intel_sst_set_pll(true, SST_PLL_VOICE);
+               if (!ret_val)
+                       return snd_pcm_hw_constraint_integer(runtime,
+                               SNDRV_PCM_HW_PARAM_PERIODS);
+               else
+                       return ret_val;
        }
 
        if (sst_cpu_ctx->active_voice_cnt > 0) {
@@ -316,6 +320,7 @@ static int sst_platform_close(struct snd_pcm_substream *substream)
 
        if (!strcmp(dai_link->cpu_dai_name, SST_VOICE_DAI)) {
                sst_cpu_ctx->active_voice_cnt--;
+               intel_sst_set_pll(false, SST_PLL_VOICE);
                goto func_exit;
        }
        sst_cpu_ctx->active_nonvoice_cnt--;