~hui.wang/alsa-driver/dkms-packaging.audiosdw-ppa

« back to all changes in this revision

Viewing changes to buildroot/src/oem-audiosdw-lp1836324-1ubuntu1.3/soc/sof/ops.h

  • Committer: Hui Wang
  • Date: 2019-12-13 02:41:40 UTC
  • Revision ID: hui.wang@canonical.com-20191213024140-1cprdcbl3122fn85
insert pc-oem-dkms

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
 
2
/*
 
3
 * This file is provided under a dual BSD/GPLv2 license.  When using or
 
4
 * redistributing this file, you may do so under either license.
 
5
 *
 
6
 * Copyright(c) 2018 Intel Corporation. All rights reserved.
 
7
 *
 
8
 * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
 
9
 */
 
10
 
 
11
#ifndef __SOUND_SOC_SOF_IO_H
 
12
#define __SOUND_SOC_SOF_IO_H
 
13
 
 
14
#include <linux/device.h>
 
15
#include <linux/interrupt.h>
 
16
#include <linux/kernel.h>
 
17
#include <linux/types.h>
 
18
#include <dkms/sound/pcm.h>
 
19
#include "sof-priv.h"
 
20
 
 
21
#define sof_ops(sdev) \
 
22
        ((sdev)->pdata->desc->ops)
 
23
 
 
24
/* Mandatory operations are verified during probing */
 
25
 
 
26
/* init */
 
27
static inline int snd_sof_probe(struct snd_sof_dev *sdev)
 
28
{
 
29
        return sof_ops(sdev)->probe(sdev);
 
30
}
 
31
 
 
32
static inline int snd_sof_remove(struct snd_sof_dev *sdev)
 
33
{
 
34
        if (sof_ops(sdev)->remove)
 
35
                return sof_ops(sdev)->remove(sdev);
 
36
 
 
37
        return 0;
 
38
}
 
39
 
 
40
/* control */
 
41
 
 
42
/*
 
43
 * snd_sof_dsp_run returns the core mask of the cores that are available
 
44
 * after successful fw boot
 
45
 */
 
46
static inline int snd_sof_dsp_run(struct snd_sof_dev *sdev)
 
47
{
 
48
        return sof_ops(sdev)->run(sdev);
 
49
}
 
50
 
 
51
static inline int snd_sof_dsp_stall(struct snd_sof_dev *sdev)
 
52
{
 
53
        if (sof_ops(sdev)->stall)
 
54
                return sof_ops(sdev)->stall(sdev);
 
55
 
 
56
        return 0;
 
57
}
 
58
 
 
59
static inline int snd_sof_dsp_reset(struct snd_sof_dev *sdev)
 
60
{
 
61
        if (sof_ops(sdev)->reset)
 
62
                return sof_ops(sdev)->reset(sdev);
 
63
 
 
64
        return 0;
 
65
}
 
66
 
 
67
/* dsp core power up/power down */
 
68
static inline int snd_sof_dsp_core_power_up(struct snd_sof_dev *sdev,
 
69
                                            unsigned int core_mask)
 
70
{
 
71
        if (sof_ops(sdev)->core_power_up)
 
72
                return sof_ops(sdev)->core_power_up(sdev, core_mask);
 
73
 
 
74
        return 0;
 
75
}
 
76
 
 
77
static inline int snd_sof_dsp_core_power_down(struct snd_sof_dev *sdev,
 
78
                                              unsigned int core_mask)
 
79
{
 
80
        if (sof_ops(sdev)->core_power_down)
 
81
                return sof_ops(sdev)->core_power_down(sdev, core_mask);
 
82
 
 
83
        return 0;
 
84
}
 
85
 
 
86
/* pre/post fw load */
 
87
static inline int snd_sof_dsp_pre_fw_run(struct snd_sof_dev *sdev)
 
88
{
 
89
        if (sof_ops(sdev)->pre_fw_run)
 
90
                return sof_ops(sdev)->pre_fw_run(sdev);
 
91
 
 
92
        return 0;
 
93
}
 
94
 
 
95
static inline int snd_sof_dsp_post_fw_run(struct snd_sof_dev *sdev)
 
96
{
 
97
        if (sof_ops(sdev)->post_fw_run)
 
98
                return sof_ops(sdev)->post_fw_run(sdev);
 
99
 
 
100
        return 0;
 
101
}
 
102
 
 
103
/* misc */
 
104
 
 
105
/**
 
106
 * snd_sof_dsp_get_bar_index - Maps a section type with a BAR index
 
107
 *
 
108
 * @sdev: sof device
 
109
 * @type: section type as described by snd_sof_fw_blk_type
 
110
 *
 
111
 * Returns the corresponding BAR index (a positive integer) or -EINVAL
 
112
 * in case there is no mapping
 
113
 */
 
114
static inline int snd_sof_dsp_get_bar_index(struct snd_sof_dev *sdev, u32 type)
 
115
{
 
116
        if (sof_ops(sdev)->get_bar_index)
 
117
                return sof_ops(sdev)->get_bar_index(sdev, type);
 
118
 
 
119
        return sdev->mmio_bar;
 
120
}
 
121
 
 
122
static inline int snd_sof_dsp_get_mailbox_offset(struct snd_sof_dev *sdev)
 
123
{
 
124
        if (sof_ops(sdev)->get_mailbox_offset)
 
125
                return sof_ops(sdev)->get_mailbox_offset(sdev);
 
126
 
 
127
        dev_err(sdev->dev, "error: %s not defined\n", __func__);
 
128
        return -ENOTSUPP;
 
129
}
 
130
 
 
131
static inline int snd_sof_dsp_get_window_offset(struct snd_sof_dev *sdev,
 
132
                                                u32 id)
 
133
{
 
134
        if (sof_ops(sdev)->get_window_offset)
 
135
                return sof_ops(sdev)->get_window_offset(sdev, id);
 
136
 
 
137
        dev_err(sdev->dev, "error: %s not defined\n", __func__);
 
138
        return -ENOTSUPP;
 
139
}
 
140
/* power management */
 
141
static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev)
 
142
{
 
143
        if (sof_ops(sdev)->resume)
 
144
                return sof_ops(sdev)->resume(sdev);
 
145
 
 
146
        return 0;
 
147
}
 
148
 
 
149
static inline int snd_sof_dsp_suspend(struct snd_sof_dev *sdev)
 
150
{
 
151
        if (sof_ops(sdev)->suspend)
 
152
                return sof_ops(sdev)->suspend(sdev);
 
153
 
 
154
        return 0;
 
155
}
 
156
 
 
157
static inline int snd_sof_dsp_runtime_resume(struct snd_sof_dev *sdev)
 
158
{
 
159
        if (sof_ops(sdev)->runtime_resume)
 
160
                return sof_ops(sdev)->runtime_resume(sdev);
 
161
 
 
162
        return 0;
 
163
}
 
164
 
 
165
static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev)
 
166
{
 
167
        if (sof_ops(sdev)->runtime_suspend)
 
168
                return sof_ops(sdev)->runtime_suspend(sdev);
 
169
 
 
170
        return 0;
 
171
}
 
172
 
 
173
static inline int snd_sof_dsp_runtime_idle(struct snd_sof_dev *sdev)
 
174
{
 
175
        if (sof_ops(sdev)->runtime_idle)
 
176
                return sof_ops(sdev)->runtime_idle(sdev);
 
177
 
 
178
        return 0;
 
179
}
 
180
 
 
181
static inline int snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev *sdev)
 
182
{
 
183
        if (sof_ops(sdev)->set_hw_params_upon_resume)
 
184
                return sof_ops(sdev)->set_hw_params_upon_resume(sdev);
 
185
        return 0;
 
186
}
 
187
 
 
188
static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq)
 
189
{
 
190
        if (sof_ops(sdev)->set_clk)
 
191
                return sof_ops(sdev)->set_clk(sdev, freq);
 
192
 
 
193
        return 0;
 
194
}
 
195
 
 
196
static inline int snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev,
 
197
                                              enum sof_d0_substate substate)
 
198
{
 
199
        if (sof_ops(sdev)->set_power_state)
 
200
                return sof_ops(sdev)->set_power_state(sdev, substate);
 
201
 
 
202
        /* D0 substate is not supported */
 
203
        return -ENOTSUPP;
 
204
}
 
205
 
 
206
/* debug */
 
207
static inline void snd_sof_dsp_dbg_dump(struct snd_sof_dev *sdev, u32 flags)
 
208
{
 
209
        if (sof_ops(sdev)->dbg_dump)
 
210
                return sof_ops(sdev)->dbg_dump(sdev, flags);
 
211
}
 
212
 
 
213
static inline void snd_sof_ipc_dump(struct snd_sof_dev *sdev)
 
214
{
 
215
        if (sof_ops(sdev)->ipc_dump)
 
216
                return sof_ops(sdev)->ipc_dump(sdev);
 
217
}
 
218
 
 
219
/* register IO */
 
220
static inline void snd_sof_dsp_write(struct snd_sof_dev *sdev, u32 bar,
 
221
                                     u32 offset, u32 value)
 
222
{
 
223
        if (sof_ops(sdev)->write) {
 
224
                sof_ops(sdev)->write(sdev, sdev->bar[bar] + offset, value);
 
225
                return;
 
226
        }
 
227
 
 
228
        dev_err_ratelimited(sdev->dev, "error: %s not defined\n", __func__);
 
229
}
 
230
 
 
231
static inline void snd_sof_dsp_write64(struct snd_sof_dev *sdev, u32 bar,
 
232
                                       u32 offset, u64 value)
 
233
{
 
234
        if (sof_ops(sdev)->write64) {
 
235
                sof_ops(sdev)->write64(sdev, sdev->bar[bar] + offset, value);
 
236
                return;
 
237
        }
 
238
 
 
239
        dev_err_ratelimited(sdev->dev, "error: %s not defined\n", __func__);
 
240
}
 
241
 
 
242
static inline u32 snd_sof_dsp_read(struct snd_sof_dev *sdev, u32 bar,
 
243
                                   u32 offset)
 
244
{
 
245
        if (sof_ops(sdev)->read)
 
246
                return sof_ops(sdev)->read(sdev, sdev->bar[bar] + offset);
 
247
 
 
248
        dev_err(sdev->dev, "error: %s not defined\n", __func__);
 
249
        return -ENOTSUPP;
 
250
}
 
251
 
 
252
static inline u64 snd_sof_dsp_read64(struct snd_sof_dev *sdev, u32 bar,
 
253
                                     u32 offset)
 
254
{
 
255
        if (sof_ops(sdev)->read64)
 
256
                return sof_ops(sdev)->read64(sdev, sdev->bar[bar] + offset);
 
257
 
 
258
        dev_err(sdev->dev, "error: %s not defined\n", __func__);
 
259
        return -ENOTSUPP;
 
260
}
 
261
 
 
262
/* block IO */
 
263
static inline void snd_sof_dsp_block_read(struct snd_sof_dev *sdev, u32 bar,
 
264
                                          u32 offset, void *dest, size_t bytes)
 
265
{
 
266
        sof_ops(sdev)->block_read(sdev, bar, offset, dest, bytes);
 
267
}
 
268
 
 
269
static inline void snd_sof_dsp_block_write(struct snd_sof_dev *sdev, u32 bar,
 
270
                                           u32 offset, void *src, size_t bytes)
 
271
{
 
272
        sof_ops(sdev)->block_write(sdev, bar, offset, src, bytes);
 
273
}
 
274
 
 
275
/* ipc */
 
276
static inline int snd_sof_dsp_send_msg(struct snd_sof_dev *sdev,
 
277
                                       struct snd_sof_ipc_msg *msg)
 
278
{
 
279
        return sof_ops(sdev)->send_msg(sdev, msg);
 
280
}
 
281
 
 
282
/* host DMA trace */
 
283
static inline int snd_sof_dma_trace_init(struct snd_sof_dev *sdev,
 
284
                                         u32 *stream_tag)
 
285
{
 
286
        if (sof_ops(sdev)->trace_init)
 
287
                return sof_ops(sdev)->trace_init(sdev, stream_tag);
 
288
 
 
289
        return 0;
 
290
}
 
291
 
 
292
static inline int snd_sof_dma_trace_release(struct snd_sof_dev *sdev)
 
293
{
 
294
        if (sof_ops(sdev)->trace_release)
 
295
                return sof_ops(sdev)->trace_release(sdev);
 
296
 
 
297
        return 0;
 
298
}
 
299
 
 
300
static inline int snd_sof_dma_trace_trigger(struct snd_sof_dev *sdev, int cmd)
 
301
{
 
302
        if (sof_ops(sdev)->trace_trigger)
 
303
                return sof_ops(sdev)->trace_trigger(sdev, cmd);
 
304
 
 
305
        return 0;
 
306
}
 
307
 
 
308
/* host PCM ops */
 
309
static inline int
 
310
snd_sof_pcm_platform_open(struct snd_sof_dev *sdev,
 
311
                          struct snd_pcm_substream *substream)
 
312
{
 
313
        if (sof_ops(sdev) && sof_ops(sdev)->pcm_open)
 
314
                return sof_ops(sdev)->pcm_open(sdev, substream);
 
315
 
 
316
        return 0;
 
317
}
 
318
 
 
319
/* disconnect pcm substream to a host stream */
 
320
static inline int
 
321
snd_sof_pcm_platform_close(struct snd_sof_dev *sdev,
 
322
                           struct snd_pcm_substream *substream)
 
323
{
 
324
        if (sof_ops(sdev) && sof_ops(sdev)->pcm_close)
 
325
                return sof_ops(sdev)->pcm_close(sdev, substream);
 
326
 
 
327
        return 0;
 
328
}
 
329
 
 
330
/* host stream hw params */
 
331
static inline int
 
332
snd_sof_pcm_platform_hw_params(struct snd_sof_dev *sdev,
 
333
                               struct snd_pcm_substream *substream,
 
334
                               struct snd_pcm_hw_params *params,
 
335
                               struct sof_ipc_stream_params *ipc_params)
 
336
{
 
337
        if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_params)
 
338
                return sof_ops(sdev)->pcm_hw_params(sdev, substream,
 
339
                                                    params, ipc_params);
 
340
 
 
341
        return 0;
 
342
}
 
343
 
 
344
/* host stream hw free */
 
345
static inline int
 
346
snd_sof_pcm_platform_hw_free(struct snd_sof_dev *sdev,
 
347
                             struct snd_pcm_substream *substream)
 
348
{
 
349
        if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_free)
 
350
                return sof_ops(sdev)->pcm_hw_free(sdev, substream);
 
351
 
 
352
        return 0;
 
353
}
 
354
 
 
355
/* host stream trigger */
 
356
static inline int
 
357
snd_sof_pcm_platform_trigger(struct snd_sof_dev *sdev,
 
358
                             struct snd_pcm_substream *substream, int cmd)
 
359
{
 
360
        if (sof_ops(sdev) && sof_ops(sdev)->pcm_trigger)
 
361
                return sof_ops(sdev)->pcm_trigger(sdev, substream, cmd);
 
362
 
 
363
        return 0;
 
364
}
 
365
 
 
366
/* host DSP message data */
 
367
static inline void snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
 
368
                                        struct snd_pcm_substream *substream,
 
369
                                        void *p, size_t sz)
 
370
{
 
371
        sof_ops(sdev)->ipc_msg_data(sdev, substream, p, sz);
 
372
}
 
373
 
 
374
/* host configure DSP HW parameters */
 
375
static inline int
 
376
snd_sof_ipc_pcm_params(struct snd_sof_dev *sdev,
 
377
                       struct snd_pcm_substream *substream,
 
378
                       const struct sof_ipc_pcm_params_reply *reply)
 
379
{
 
380
        return sof_ops(sdev)->ipc_pcm_params(sdev, substream, reply);
 
381
}
 
382
 
 
383
/* host stream pointer */
 
384
static inline snd_pcm_uframes_t
 
385
snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev,
 
386
                             struct snd_pcm_substream *substream)
 
387
{
 
388
        if (sof_ops(sdev) && sof_ops(sdev)->pcm_pointer)
 
389
                return sof_ops(sdev)->pcm_pointer(sdev, substream);
 
390
 
 
391
        return 0;
 
392
}
 
393
 
 
394
static inline const struct snd_sof_dsp_ops
 
395
*sof_get_ops(const struct sof_dev_desc *d,
 
396
             const struct sof_ops_table mach_ops[], int asize)
 
397
{
 
398
        int i;
 
399
 
 
400
        for (i = 0; i < asize; i++) {
 
401
                if (d == mach_ops[i].desc)
 
402
                        return mach_ops[i].ops;
 
403
        }
 
404
 
 
405
        /* not found */
 
406
        return NULL;
 
407
}
 
408
 
 
409
/**
 
410
 * snd_sof_dsp_register_poll_timeout - Periodically poll an address
 
411
 * until a condition is met or a timeout occurs
 
412
 * @op: accessor function (takes @addr as its only argument)
 
413
 * @addr: Address to poll
 
414
 * @val: Variable to read the value into
 
415
 * @cond: Break condition (usually involving @val)
 
416
 * @sleep_us: Maximum time to sleep between reads in us (0
 
417
 *            tight-loops).  Should be less than ~20ms since usleep_range
 
418
 *            is used (see Documentation/timers/timers-howto.rst).
 
419
 * @timeout_us: Timeout in us, 0 means never timeout
 
420
 *
 
421
 * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
 
422
 * case, the last read value at @addr is stored in @val. Must not
 
423
 * be called from atomic context if sleep_us or timeout_us are used.
 
424
 *
 
425
 * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
 
426
 */
 
427
#define snd_sof_dsp_read_poll_timeout(sdev, bar, offset, val, cond, sleep_us, timeout_us) \
 
428
({ \
 
429
        u64 __timeout_us = (timeout_us); \
 
430
        unsigned long __sleep_us = (sleep_us); \
 
431
        ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
 
432
        might_sleep_if((__sleep_us) != 0); \
 
433
        for (;;) {                                                      \
 
434
                (val) = snd_sof_dsp_read(sdev, bar, offset);            \
 
435
                if (cond) { \
 
436
                        dev_dbg(sdev->dev, \
 
437
                                "FW Poll Status: reg=%#x successful\n", (val)); \
 
438
                        break; \
 
439
                } \
 
440
                if (__timeout_us && \
 
441
                    ktime_compare(ktime_get(), __timeout) > 0) { \
 
442
                        (val) = snd_sof_dsp_read(sdev, bar, offset); \
 
443
                        dev_dbg(sdev->dev, \
 
444
                                "FW Poll Status: reg=%#x timedout\n", (val)); \
 
445
                        break; \
 
446
                } \
 
447
                if (__sleep_us) \
 
448
                        usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
 
449
        } \
 
450
        (cond) ? 0 : -ETIMEDOUT; \
 
451
})
 
452
 
 
453
/* This is for registers bits with attribute RWC */
 
454
bool snd_sof_pci_update_bits(struct snd_sof_dev *sdev, u32 offset,
 
455
                             u32 mask, u32 value);
 
456
 
 
457
bool snd_sof_dsp_update_bits_unlocked(struct snd_sof_dev *sdev, u32 bar,
 
458
                                      u32 offset, u32 mask, u32 value);
 
459
 
 
460
bool snd_sof_dsp_update_bits64_unlocked(struct snd_sof_dev *sdev, u32 bar,
 
461
                                        u32 offset, u64 mask, u64 value);
 
462
 
 
463
bool snd_sof_dsp_update_bits(struct snd_sof_dev *sdev, u32 bar, u32 offset,
 
464
                             u32 mask, u32 value);
 
465
 
 
466
bool snd_sof_dsp_update_bits64(struct snd_sof_dev *sdev, u32 bar,
 
467
                               u32 offset, u64 mask, u64 value);
 
468
 
 
469
void snd_sof_dsp_update_bits_forced(struct snd_sof_dev *sdev, u32 bar,
 
470
                                    u32 offset, u32 mask, u32 value);
 
471
 
 
472
int snd_sof_dsp_register_poll(struct snd_sof_dev *sdev, u32 bar, u32 offset,
 
473
                              u32 mask, u32 target, u32 timeout_ms,
 
474
                              u32 interval_us);
 
475
 
 
476
void snd_sof_dsp_panic(struct snd_sof_dev *sdev, u32 offset);
 
477
#endif