aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarkko Nikula <jarkko.nikula@linux.intel.com>2014-02-19 03:30:38 -0500
committerMark Brown <broonie@linaro.org>2014-02-19 07:20:42 -0500
commite5161d7987f14338ad0a3cf376b9bb6838416183 (patch)
tree072cc4c6481b44ff91ec919ea5bc5f183167bd4d
parent0c49a8c9f9fafdf4345259b9b50513905afcf860 (diff)
ASoC: Intel: sst-acpi: Request firmware before SST platform driver probing
We originally thought to request SST audio DSP firmware during the SST platform driver initialization. However plain request_firmware doesn't work in driver probe paths if userspace is not ready to handle it. For instance when drivers are built-in. Implementing asynchronous firmware request in SST platform driver initialization complicates code needlessly since it anyway will fail if firmware is missing. This is more simple to handle by requesting firmware asynchronously in sst_acpi_probe() and register SST platform only after firmware is loaded. Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--sound/soc/intel/sst-acpi.c56
-rw-r--r--sound/soc/intel/sst-dsp.h2
2 files changed, 40 insertions, 18 deletions
diff --git a/sound/soc/intel/sst-acpi.c b/sound/soc/intel/sst-acpi.c
index aba73ca8a923..64154a77d904 100644
--- a/sound/soc/intel/sst-acpi.c
+++ b/sound/soc/intel/sst-acpi.c
@@ -16,6 +16,7 @@
16 16
17#include <linux/acpi.h> 17#include <linux/acpi.h>
18#include <linux/device.h> 18#include <linux/device.h>
19#include <linux/firmware.h>
19#include <linux/module.h> 20#include <linux/module.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
21 22
@@ -56,6 +57,32 @@ struct sst_acpi_priv {
56 struct sst_acpi_desc *desc; 57 struct sst_acpi_desc *desc;
57}; 58};
58 59
60static void sst_acpi_fw_cb(const struct firmware *fw, void *context)
61{
62 struct platform_device *pdev = context;
63 struct device *dev = &pdev->dev;
64 struct sst_acpi_priv *sst_acpi = platform_get_drvdata(pdev);
65 struct sst_pdata *sst_pdata = &sst_acpi->sst_pdata;
66 struct sst_acpi_desc *desc = sst_acpi->desc;
67
68 sst_pdata->fw = fw;
69 if (!fw) {
70 dev_err(dev, "Cannot load firmware %s\n", desc->fw_filename);
71 return;
72 }
73
74 /* register PCM and DAI driver */
75 sst_acpi->pdev_pcm =
76 platform_device_register_data(dev, desc->drv_name, -1,
77 sst_pdata, sizeof(*sst_pdata));
78 if (IS_ERR(sst_acpi->pdev_pcm)) {
79 dev_err(dev, "Cannot register device %s. Error %d\n",
80 desc->drv_name, (int)PTR_ERR(sst_acpi->pdev_pcm));
81 }
82
83 return;
84}
85
59static int sst_acpi_probe(struct platform_device *pdev) 86static int sst_acpi_probe(struct platform_device *pdev)
60{ 87{
61 const struct acpi_device_id *id; 88 const struct acpi_device_id *id;
@@ -79,7 +106,6 @@ static int sst_acpi_probe(struct platform_device *pdev)
79 desc = mach->res_desc; 106 desc = mach->res_desc;
80 sst_pdata = &sst_acpi->sst_pdata; 107 sst_pdata = &sst_acpi->sst_pdata;
81 sst_pdata->id = desc->sst_id; 108 sst_pdata->id = desc->sst_id;
82 sst_pdata->fw_filename = desc->fw_filename;
83 sst_acpi->desc = desc; 109 sst_acpi->desc = desc;
84 110
85 if (desc->resindex_dma_base >= 0) { 111 if (desc->resindex_dma_base >= 0) {
@@ -118,37 +144,33 @@ static int sst_acpi_probe(struct platform_device *pdev)
118 } 144 }
119 } 145 }
120 146
121 /* register PCM and DAI driver */
122 sst_acpi->pdev_pcm =
123 platform_device_register_data(dev, desc->drv_name, -1,
124 sst_pdata, sizeof(*sst_pdata));
125 if (IS_ERR(sst_acpi->pdev_pcm))
126 return PTR_ERR(sst_acpi->pdev_pcm);
127
128 /* register machine driver */
129 platform_set_drvdata(pdev, sst_acpi); 147 platform_set_drvdata(pdev, sst_acpi);
130 148
149 /* register machine driver */
131 sst_acpi->pdev_mach = 150 sst_acpi->pdev_mach =
132 platform_device_register_data(dev, mach->drv_name, -1, 151 platform_device_register_data(dev, mach->drv_name, -1,
133 sst_pdata, sizeof(*sst_pdata)); 152 sst_pdata, sizeof(*sst_pdata));
134 if (IS_ERR(sst_acpi->pdev_mach)) { 153 if (IS_ERR(sst_acpi->pdev_mach))
135 ret = PTR_ERR(sst_acpi->pdev_mach); 154 return PTR_ERR(sst_acpi->pdev_mach);
136 goto sst_err;
137 }
138 155
139 return ret; 156 /* continue SST probing after firmware is loaded */
157 ret = request_firmware_nowait(THIS_MODULE, true, desc->fw_filename,
158 dev, GFP_KERNEL, pdev, sst_acpi_fw_cb);
159 if (ret)
160 platform_device_unregister(sst_acpi->pdev_mach);
140 161
141sst_err:
142 platform_device_unregister(sst_acpi->pdev_pcm);
143 return ret; 162 return ret;
144} 163}
145 164
146static int sst_acpi_remove(struct platform_device *pdev) 165static int sst_acpi_remove(struct platform_device *pdev)
147{ 166{
148 struct sst_acpi_priv *sst_acpi = platform_get_drvdata(pdev); 167 struct sst_acpi_priv *sst_acpi = platform_get_drvdata(pdev);
168 struct sst_pdata *sst_pdata = &sst_acpi->sst_pdata;
149 169
150 platform_device_unregister(sst_acpi->pdev_mach); 170 platform_device_unregister(sst_acpi->pdev_mach);
151 platform_device_unregister(sst_acpi->pdev_pcm); 171 if (!IS_ERR_OR_NULL(sst_acpi->pdev_pcm))
172 platform_device_unregister(sst_acpi->pdev_pcm);
173 release_firmware(sst_pdata->fw);
152 174
153 return 0; 175 return 0;
154} 176}
diff --git a/sound/soc/intel/sst-dsp.h b/sound/soc/intel/sst-dsp.h
index d134359fecac..3730fd324455 100644
--- a/sound/soc/intel/sst-dsp.h
+++ b/sound/soc/intel/sst-dsp.h
@@ -152,7 +152,7 @@ struct sst_pdata {
152 int irq; 152 int irq;
153 153
154 /* Firmware */ 154 /* Firmware */
155 const char *fw_filename; 155 const struct firmware *fw;
156 156
157 /* DMA */ 157 /* DMA */
158 u32 dma_base; 158 u32 dma_base;