From d92627ab7e10187aefbbcc39895a4ea57ec4d4de Mon Sep 17 00:00:00 2001 From: Jeeja Date: Thu, 6 Oct 2011 16:18:35 +0100 Subject: [PATCH] ASoC: sn95031: intel_sst: Fixes delay in powering up PLL and firmware download Powering up of Audio rail and firmware download together was consuming 80ms which didn't meet the latency requirement for openning a pcm device. This patch fixes the delay during firmware download by caching the firmware instead of using request_firmware() when firmware download is required and also reduces the delay from 10ms to 1ms to power up PLL. Change-Id: I4585bb9fc4b9ede9f99c001d8538bf4246c1b22f Signed-off-by: Jeeja --- drivers/staging/intel_sst/intel_sst.c | 9 +++++++ drivers/staging/intel_sst/intel_sst_common.h | 1 + .../staging/intel_sst/intel_sst_drv_interface.c | 28 ++++++++++++++-------- sound/soc/codecs/sn95031.c | 8 +++---- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/drivers/staging/intel_sst/intel_sst.c b/drivers/staging/intel_sst/intel_sst.c index 987f1d5..21ec1a4 100644 --- a/drivers/staging/intel_sst/intel_sst.c +++ b/drivers/staging/intel_sst/intel_sst.c @@ -205,6 +205,7 @@ static int __devinit intel_sst_probe(struct pci_dev *pci, sst_drv_ctx->cp_streams = 0; sst_drv_ctx->unique_id = 0; sst_drv_ctx->pmic_port_instance = SST_DEFAULT_PMIC_PORT; + sst_drv_ctx->fw = NULL; INIT_LIST_HEAD(&sst_drv_ctx->ipc_dispatch_list); INIT_WORK(&sst_drv_ctx->ipc_post_msg.wq, sst_post_message); @@ -428,6 +429,10 @@ static void __devexit intel_sst_remove(struct pci_dev *pci) destroy_workqueue(sst_drv_ctx->post_msg_wq); destroy_workqueue(sst_drv_ctx->mad_wq); kfree(pci_get_drvdata(pci)); + if (sst_drv_ctx->fw) { + release_firmware(sst_drv_ctx->fw); + sst_drv_ctx->fw = NULL; + } sst_drv_ctx = NULL; pci_release_regions(pci); pci_disable_device(pci); @@ -641,6 +646,10 @@ static void __exit intel_sst_exit(void) pci_unregister_driver(&driver); pr_debug("driver unloaded\n"); + if (sst_drv_ctx->fw) { + release_firmware(sst_drv_ctx->fw); + sst_drv_ctx->fw = NULL; + } sst_drv_ctx = NULL; return; } diff --git a/drivers/staging/intel_sst/intel_sst_common.h b/drivers/staging/intel_sst/intel_sst_common.h index 686308c..6d98011 100644 --- a/drivers/staging/intel_sst/intel_sst_common.h +++ b/drivers/staging/intel_sst/intel_sst_common.h @@ -425,6 +425,7 @@ struct intel_sst_drv { unsigned int fw_cntx_size; unsigned int csr_value; unsigned int pll_mode; + const struct firmware *fw; unsigned int fw_downloaded; }; diff --git a/drivers/staging/intel_sst/intel_sst_drv_interface.c b/drivers/staging/intel_sst/intel_sst_drv_interface.c index 4bcebed..a7831e3 100644 --- a/drivers/staging/intel_sst/intel_sst_drv_interface.c +++ b/drivers/staging/intel_sst/intel_sst_drv_interface.c @@ -89,7 +89,7 @@ void sst_restore_fw_context(void) int sst_download_fw(void) { int retval; - const struct firmware *fw_sst; + char name[20]; if (sst_drv_ctx->sst_state != SST_UN_INIT) @@ -106,25 +106,33 @@ int sst_download_fw(void) sst_drv_ctx->pci_id, ".bin"); pr_debug("Downloading %s FW now...\n", name); - retval = request_firmware(&fw_sst, name, &sst_drv_ctx->pci->dev); - if (retval) { - pr_err("request fw failed %d\n", retval); - return retval; + if (!sst_drv_ctx->fw) { + retval = request_firmware(&sst_drv_ctx->fw, name, + &sst_drv_ctx->pci->dev); + pr_err("sst: requuest firmware %d\n", retval); + if (retval) { + pr_err("sst: request fw failed %d\n", retval); + return retval; + } } sst_drv_ctx->alloc_block[0].sst_id = FW_DWNL_ID; sst_drv_ctx->alloc_block[0].ops_block.condition = false; - retval = sst_load_fw(fw_sst, NULL); - if (retval) + retval = sst_load_fw(sst_drv_ctx->fw, NULL); + if (retval) { + release_firmware(sst_drv_ctx->fw); + sst_drv_ctx->fw = NULL; goto end_restore; + } retval = sst_wait_timeout(sst_drv_ctx, &sst_drv_ctx->alloc_block[0]); - if (retval) + if (retval) { pr_err("fw download failed %d\n" , retval); - else + release_firmware(sst_drv_ctx->fw); + sst_drv_ctx->fw = NULL; + } else sst_drv_ctx->fw_downloaded = 1; end_restore: - release_firmware(fw_sst); sst_drv_ctx->alloc_block[0].sst_id = BLOCK_UNINIT; if (retval) return retval; diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 7359030..34c812b 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c @@ -125,17 +125,15 @@ static void sn95031_configure_pll(struct snd_soc_codec *codec, int operation) if (operation) { pr_debug("enabling PLL\n"); - snd_soc_write(codec, SN95031_AUDPLLCTRL, 0); /* PLL takes few msec to stabilize Refer sec2.3 MFLD Audio Interface Doc-rev0.7 */ - msleep(10); snd_soc_write(codec, SN95031_AUDPLLCTRL, (sn95031_ctx->clk_src)<<2); - msleep(10); + udelay(1000); snd_soc_update_bits(codec, SN95031_AUDPLLCTRL, BIT(1), BIT(1)); - msleep(10); + udelay(1000); snd_soc_update_bits(codec, SN95031_AUDPLLCTRL, BIT(5), BIT(5)); - msleep(10); + udelay(1000); sn95031_ctx->pll_state = PLL_ENABLED; } else { pr_debug("disabling PLL\n"); -- 2.7.4