]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - sound/soc/intel/skylake/skl-sst-dsp.c
Merge remote-tracking branch 'sound-current/for-linus'
[karo-tx-linux.git] / sound / soc / intel / skylake / skl-sst-dsp.c
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 static 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_dsp_disable_core(dsp);
340 }
341 EXPORT_SYMBOL_GPL(skl_dsp_free);
342
343 bool is_skl_dsp_running(struct sst_dsp *ctx)
344 {
345         return (ctx->sst_state == SKL_DSP_RUNNING);
346 }
347 EXPORT_SYMBOL_GPL(is_skl_dsp_running);