~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/intel/skylake/skl-sst-dsp.c

Version: ~ [ linux-5.9 ] ~ [ linux-5.8.14 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.70 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.150 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.200 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.238 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.238 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * skl-sst-dsp.c - SKL SST library generic function
  3  *
  4  * Copyright (C) 2014-15, Intel Corporation.
  5  * Author:Rafal Redzimski <rafal.f.redzimski@intel.com>
  6  *      Jeeja KP <jeeja.kp@intel.com>
  7  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8  *
  9  * This program is free software; you can redistribute it and/or modify
 10  * it under the terms of the GNU General Public License as version 2, as
 11  * published by the Free Software Foundation.
 12  *
 13  * This program is distributed in the hope that it will be useful, but
 14  * WITHOUT ANY WARRANTY; without even the implied warranty of
 15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16  * General Public License for more details.
 17  */
 18 #include <sound/pcm.h>
 19 
 20 #include "../common/sst-dsp.h"
 21 #include "../common/sst-ipc.h"
 22 #include "../common/sst-dsp-priv.h"
 23 #include "skl-sst-ipc.h"
 24 
 25 /* various timeout values */
 26 #define SKL_DSP_PU_TO           50
 27 #define SKL_DSP_PD_TO           50
 28 #define SKL_DSP_RESET_TO        50
 29 
 30 void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
 31 {
 32         mutex_lock(&ctx->mutex);
 33         ctx->sst_state = state;
 34         mutex_unlock(&ctx->mutex);
 35 }
 36 
 37 static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx)
 38 {
 39         int ret;
 40 
 41         /* update bits */
 42         sst_dsp_shim_update_bits_unlocked(ctx,
 43                         SKL_ADSP_REG_ADSPCS, SKL_ADSPCS_CRST_MASK,
 44                         SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK));
 45 
 46         /* poll with timeout to check if operation successful */
 47         ret = sst_dsp_register_poll(ctx,
 48                         SKL_ADSP_REG_ADSPCS,
 49                         SKL_ADSPCS_CRST_MASK,
 50                         SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK),
 51                         SKL_DSP_RESET_TO,
 52                         "Set reset");
 53         if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
 54                                 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) !=
 55                                 SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) {
 56                 dev_err(ctx->dev, "Set reset state failed\n");
 57                 ret = -EIO;
 58         }
 59 
 60         return ret;
 61 }
 62 
 63 static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx)
 64 {
 65         int ret;
 66 
 67         dev_dbg(ctx->dev, "In %s\n", __func__);
 68 
 69         /* update bits */
 70         sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
 71                                         SKL_ADSPCS_CRST_MASK, 0);
 72 
 73         /* poll with timeout to check if operation successful */
 74         ret = sst_dsp_register_poll(ctx,
 75                         SKL_ADSP_REG_ADSPCS,
 76                         SKL_ADSPCS_CRST_MASK,
 77                         0,
 78                         SKL_DSP_RESET_TO,
 79                         "Unset reset");
 80 
 81         if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
 82                                  SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) != 0) {
 83                 dev_err(ctx->dev, "Unset reset state failed\n");
 84                 ret = -EIO;
 85         }
 86 
 87         return ret;
 88 }
 89 
 90 static bool is_skl_dsp_core_enable(struct sst_dsp *ctx)
 91 {
 92         int val;
 93         bool is_enable;
 94 
 95         val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
 96 
 97         is_enable = ((val & SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) &&
 98                         (val & SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK)) &&
 99                         !(val & SKL_ADSPCS_CRST(SKL_DSP_CORES_MASK)) &&
100                         !(val & SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK)));
101 
102         dev_dbg(ctx->dev, "DSP core is enabled=%d\n", is_enable);
103         return is_enable;
104 }
105 
106 static int skl_dsp_reset_core(struct sst_dsp *ctx)
107 {
108         /* stall core */
109         sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
110                          sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
111                                 SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK));
112 
113         /* set reset state */
114         return skl_dsp_core_set_reset_state(ctx);
115 }
116 
117 static int skl_dsp_start_core(struct sst_dsp *ctx)
118 {
119         int ret;
120 
121         /* unset reset state */
122         ret = skl_dsp_core_unset_reset_state(ctx);
123         if (ret < 0) {
124                 dev_dbg(ctx->dev, "dsp unset reset fails\n");
125                 return ret;
126         }
127 
128         /* run core */
129         dev_dbg(ctx->dev, "run core...\n");
130         sst_dsp_shim_write_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
131                          sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
132                                 ~SKL_ADSPCS_CSTALL(SKL_DSP_CORES_MASK));
133 
134         if (!is_skl_dsp_core_enable(ctx)) {
135                 skl_dsp_reset_core(ctx);
136                 dev_err(ctx->dev, "DSP core enable failed\n");
137                 ret = -EIO;
138         }
139 
140         return ret;
141 }
142 
143 static int skl_dsp_core_power_up(struct sst_dsp *ctx)
144 {
145         int ret;
146 
147         /* update bits */
148         sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
149                         SKL_ADSPCS_SPA_MASK, SKL_ADSPCS_SPA(SKL_DSP_CORES_MASK));
150 
151         /* poll with timeout to check if operation successful */
152         ret = sst_dsp_register_poll(ctx,
153                         SKL_ADSP_REG_ADSPCS,
154                         SKL_ADSPCS_CPA_MASK,
155                         SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK),
156                         SKL_DSP_PU_TO,
157                         "Power up");
158 
159         if ((sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS) &
160                         SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) !=
161                         SKL_ADSPCS_CPA(SKL_DSP_CORES_MASK)) {
162                 dev_err(ctx->dev, "DSP core power up failed\n");
163                 ret = -EIO;
164         }
165 
166         return ret;
167 }
168 
169 static int skl_dsp_core_power_down(struct sst_dsp *ctx)
170 {
171         /* update bits */
172         sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
173                                         SKL_ADSPCS_SPA_MASK, 0);
174 
175         /* poll with timeout to check if operation successful */
176         return sst_dsp_register_poll(ctx,
177                         SKL_ADSP_REG_ADSPCS,
178                         SKL_ADSPCS_CPA_MASK,
179                         0,
180                         SKL_DSP_PD_TO,
181                         "Power down");
182 }
183 
184 int skl_dsp_enable_core(struct sst_dsp *ctx)
185 {
186         int ret;
187 
188         /* power up */
189         ret = skl_dsp_core_power_up(ctx);
190         if (ret < 0) {
191                 dev_dbg(ctx->dev, "dsp core power up failed\n");
192                 return ret;
193         }
194 
195         return skl_dsp_start_core(ctx);
196 }
197 
198 int skl_dsp_disable_core(struct sst_dsp *ctx)
199 {
200         int ret;
201 
202         ret = skl_dsp_reset_core(ctx);
203         if (ret < 0) {
204                 dev_err(ctx->dev, "dsp core reset failed\n");
205                 return ret;
206         }
207 
208         /* power down core*/
209         ret = skl_dsp_core_power_down(ctx);
210         if (ret < 0) {
211                 dev_err(ctx->dev, "dsp core power down failed\n");
212                 return ret;
213         }
214 
215         if (is_skl_dsp_core_enable(ctx)) {
216                 dev_err(ctx->dev, "DSP core disable failed\n");
217                 ret = -EIO;
218         }
219 
220         return ret;
221 }
222 
223 int skl_dsp_boot(struct sst_dsp *ctx)
224 {
225         int ret;
226 
227         if (is_skl_dsp_core_enable(ctx)) {
228                 dev_dbg(ctx->dev, "dsp core is already enabled, so reset the dap core\n");
229                 ret = skl_dsp_reset_core(ctx);
230                 if (ret < 0) {
231                         dev_err(ctx->dev, "dsp reset failed\n");
232                         return ret;
233                 }
234 
235                 ret = skl_dsp_start_core(ctx);
236                 if (ret < 0) {
237                         dev_err(ctx->dev, "dsp start failed\n");
238                         return ret;
239                 }
240         } else {
241                 dev_dbg(ctx->dev, "disable and enable to make sure DSP is invalid state\n");
242                 ret = skl_dsp_disable_core(ctx);
243 
244                 if (ret < 0) {
245                         dev_err(ctx->dev, "dsp disable core failes\n");
246                         return ret;
247                 }
248                 ret = skl_dsp_enable_core(ctx);
249         }
250 
251         return ret;
252 }
253 
254 irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id)
255 {
256         struct sst_dsp *ctx = dev_id;
257         u32 val;
258         irqreturn_t result = IRQ_NONE;
259 
260         spin_lock(&ctx->spinlock);
261 
262         val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS);
263         ctx->intr_status = val;
264 
265         if (val == 0xffffffff) {
266                 spin_unlock(&ctx->spinlock);
267                 return IRQ_NONE;
268         }
269 
270         if (val & SKL_ADSPIS_IPC) {
271                 skl_ipc_int_disable(ctx);
272                 result = IRQ_WAKE_THREAD;
273         }
274 
275         if (val & SKL_ADSPIS_CL_DMA) {
276                 skl_cldma_int_disable(ctx);
277                 result = IRQ_WAKE_THREAD;
278         }
279 
280         spin_unlock(&ctx->spinlock);
281 
282         return result;
283 }
284 
285 int skl_dsp_wake(struct sst_dsp *ctx)
286 {
287         return ctx->fw_ops.set_state_D0(ctx);
288 }
289 EXPORT_SYMBOL_GPL(skl_dsp_wake);
290 
291 int skl_dsp_sleep(struct sst_dsp *ctx)
292 {
293         return ctx->fw_ops.set_state_D3(ctx);
294 }
295 EXPORT_SYMBOL_GPL(skl_dsp_sleep);
296 
297 struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
298                 struct sst_dsp_device *sst_dev, int irq)
299 {
300         int ret;
301         struct sst_dsp *sst;
302 
303         sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL);
304         if (sst == NULL)
305                 return NULL;
306 
307         spin_lock_init(&sst->spinlock);
308         mutex_init(&sst->mutex);
309         sst->dev = dev;
310         sst->sst_dev = sst_dev;
311         sst->irq = irq;
312         sst->ops = sst_dev->ops;
313         sst->thread_context = sst_dev->thread_context;
314 
315         /* Initialise SST Audio DSP */
316         if (sst->ops->init) {
317                 ret = sst->ops->init(sst, NULL);
318                 if (ret < 0)
319                         return NULL;
320         }
321 
322         /* Register the ISR */
323         ret = request_threaded_irq(sst->irq, sst->ops->irq_handler,
324                 sst_dev->thread, IRQF_SHARED, "AudioDSP", sst);
325         if (ret) {
326                 dev_err(sst->dev, "unable to grab threaded IRQ %d, disabling device\n",
327                                sst->irq);
328                 return NULL;
329         }
330 
331         return sst;
332 }
333 
334 void skl_dsp_free(struct sst_dsp *dsp)
335 {
336         skl_ipc_int_disable(dsp);
337 
338         free_irq(dsp->irq, dsp);
339         skl_ipc_op_int_disable(dsp);
340         skl_ipc_int_disable(dsp);
341 
342         skl_dsp_disable_core(dsp);
343 }
344 EXPORT_SYMBOL_GPL(skl_dsp_free);
345 
346 bool is_skl_dsp_running(struct sst_dsp *ctx)
347 {
348         return (ctx->sst_state == SKL_DSP_RUNNING);
349 }
350 EXPORT_SYMBOL_GPL(is_skl_dsp_running);
351 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp