driver core: bus: use to_subsys_private and to_device_private_bus
[linux/fpc-iii.git] / sound / soc / intel / skylake / skl-sst-dsp.c
blob1bfb7f63b5724d98e8acf1446364fafec01e115f
1 /*
2 * skl-sst-dsp.c - SKL SST library generic function
4 * Copyright (C) 2014-15, Intel Corporation.
5 * Author:Rafal Redzimski <rafal.f.redzimski@intel.com>
6 * Jeeja KP <jeeja.kp@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
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.
18 #include <sound/pcm.h>
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"
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
30 void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
32 mutex_lock(&ctx->mutex);
33 ctx->sst_state = state;
34 mutex_unlock(&ctx->mutex);
37 static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx)
39 int ret;
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));
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;
60 return ret;
63 static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx)
65 int ret;
67 dev_dbg(ctx->dev, "In %s\n", __func__);
69 /* update bits */
70 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
71 SKL_ADSPCS_CRST_MASK, 0);
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,
78 SKL_DSP_RESET_TO,
79 "Unset reset");
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;
87 return ret;
90 static bool is_skl_dsp_core_enable(struct sst_dsp *ctx)
92 int val;
93 bool is_enable;
95 val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPCS);
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)));
102 dev_dbg(ctx->dev, "DSP core is enabled=%d\n", is_enable);
103 return is_enable;
106 static int skl_dsp_reset_core(struct sst_dsp *ctx)
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));
113 /* set reset state */
114 return skl_dsp_core_set_reset_state(ctx);
117 static int skl_dsp_start_core(struct sst_dsp *ctx)
119 int ret;
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;
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));
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;
140 return ret;
143 static int skl_dsp_core_power_up(struct sst_dsp *ctx)
145 int ret;
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));
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");
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;
166 return ret;
169 static int skl_dsp_core_power_down(struct sst_dsp *ctx)
171 /* update bits */
172 sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
173 SKL_ADSPCS_SPA_MASK, 0);
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,
180 SKL_DSP_PD_TO,
181 "Power down");
184 static int skl_dsp_enable_core(struct sst_dsp *ctx)
186 int ret;
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;
195 return skl_dsp_start_core(ctx);
198 int skl_dsp_disable_core(struct sst_dsp *ctx)
200 int ret;
202 ret = skl_dsp_reset_core(ctx);
203 if (ret < 0) {
204 dev_err(ctx->dev, "dsp core reset failed\n");
205 return ret;
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;
215 if (is_skl_dsp_core_enable(ctx)) {
216 dev_err(ctx->dev, "DSP core disable failed\n");
217 ret = -EIO;
220 return ret;
223 int skl_dsp_boot(struct sst_dsp *ctx)
225 int ret;
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;
235 ret = skl_dsp_start_core(ctx);
236 if (ret < 0) {
237 dev_err(ctx->dev, "dsp start failed\n");
238 return ret;
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);
244 if (ret < 0) {
245 dev_err(ctx->dev, "dsp disable core failes\n");
246 return ret;
248 ret = skl_dsp_enable_core(ctx);
251 return ret;
254 irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id)
256 struct sst_dsp *ctx = dev_id;
257 u32 val;
258 irqreturn_t result = IRQ_NONE;
260 spin_lock(&ctx->spinlock);
262 val = sst_dsp_shim_read_unlocked(ctx, SKL_ADSP_REG_ADSPIS);
263 ctx->intr_status = val;
265 if (val == 0xffffffff) {
266 spin_unlock(&ctx->spinlock);
267 return IRQ_NONE;
270 if (val & SKL_ADSPIS_IPC) {
271 skl_ipc_int_disable(ctx);
272 result = IRQ_WAKE_THREAD;
275 if (val & SKL_ADSPIS_CL_DMA) {
276 skl_cldma_int_disable(ctx);
277 result = IRQ_WAKE_THREAD;
280 spin_unlock(&ctx->spinlock);
282 return result;
285 int skl_dsp_wake(struct sst_dsp *ctx)
287 return ctx->fw_ops.set_state_D0(ctx);
289 EXPORT_SYMBOL_GPL(skl_dsp_wake);
291 int skl_dsp_sleep(struct sst_dsp *ctx)
293 return ctx->fw_ops.set_state_D3(ctx);
295 EXPORT_SYMBOL_GPL(skl_dsp_sleep);
297 struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
298 struct sst_dsp_device *sst_dev, int irq)
300 int ret;
301 struct sst_dsp *sst;
303 sst = devm_kzalloc(dev, sizeof(*sst), GFP_KERNEL);
304 if (sst == NULL)
305 return NULL;
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;
315 /* Initialise SST Audio DSP */
316 if (sst->ops->init) {
317 ret = sst->ops->init(sst, NULL);
318 if (ret < 0)
319 return NULL;
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;
331 return sst;
334 void skl_dsp_free(struct sst_dsp *dsp)
336 skl_ipc_int_disable(dsp);
338 free_irq(dsp->irq, dsp);
339 skl_dsp_disable_core(dsp);
341 EXPORT_SYMBOL_GPL(skl_dsp_free);
343 bool is_skl_dsp_running(struct sst_dsp *ctx)
345 return (ctx->sst_state == SKL_DSP_RUNNING);
347 EXPORT_SYMBOL_GPL(is_skl_dsp_running);