summaryrefslogtreecommitdiff
path: root/cs40l26/cl_dsp.h
blob: eb01682e0a1d16756c6bfc88c32fb33b6b2be49e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
/* SPDX-License-Identifier: GPL-2.0
 *
 * cl_dsp.h -- DSP control for non-ALSA Cirrus Logic devices
 *
 * Copyright 2021 Cirrus Logic, Inc.
 *
 * Author: Fred Treven <fred.treven@cirrus.com>
 */

#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/regmap.h>
#include <linux/of_device.h>
#include <linux/slab.h>

#ifndef __CL_DSP_H__
#define __CL_DSP_H__

#define CL_DSP_BYTES_PER_WORD		4
#define CL_DSP_BITS_PER_BYTE		8

#define CL_DSP_BYTE_MASK		GENMASK(7, 0)
#define CL_DSP_NIBBLE_MASK		GENMASK(15, 0)

#define CL_DSP_FW_FILE_HEADER_SIZE	40
#define CL_DSP_COEFF_FILE_HEADER_SIZE	16

#define CL_DSP_MAGIC_ID_SIZE		4

#define CL_DSP_WMFW_MAGIC_ID		"WMFW"
#define CL_DSP_WMDR_MAGIC_ID		"WMDR"

#define CL_DSP_DBLK_HEADER_SIZE	8
#define CL_DSP_COEFF_DBLK_HEADER_SIZE	20

#define CL_DSP_ALIGN			0x00000003

#define CL_DSP_TARGET_CORE_ADSP1	0x01
#define CL_DSP_TARGET_CORE_ADSP2	0x02
#define CL_DSP_TARGET_CORE_HALO	0x04
#define CL_DSP_TARGET_CORE_WARP2	0x12
#define CL_DSP_TARGET_CORE_MCU		0x45

#define CL_DSP_MIN_FORMAT_VERSION	0x03
#define CL_DSP_API_REVISION		0x0300

#define CL_DSP_ALGO_NAME_LEN_SIZE	1
#define CL_DSP_ALGO_DESC_LEN_SIZE	2
#define CL_DSP_ALGO_ID_SIZE		4
#define CL_DSP_COEFF_COUNT_SIZE	4
#define CL_DSP_COEFF_OFFSET_SIZE	2
#define CL_DSP_COEFF_TYPE_SIZE		2
#define CL_DSP_COEFF_NAME_LEN_SIZE	1
#define CL_DSP_COEFF_FULLNAME_LEN_SIZE	1
#define CL_DSP_COEFF_DESC_LEN_SIZE	2
#define CL_DSP_COEFF_LEN_SIZE		4
#define CL_DSP_COEFF_FLAGS_SIZE	4
#define CL_DSP_COEFF_FLAGS_SHIFT	16
#define CL_DSP_COEFF_NAME_LEN_MAX	32
#define CL_DSP_COEFF_MIN_FORMAT_VERSION	0x01
#define CL_DSP_COEFF_API_REV_HALO	0x030000
#define CL_DSP_COEFF_API_REV_ADSP2	0x000500

#define CL_DSP_ALGO_LIST_TERM		0xBEDEAD

#define CL_DSP_REV_OFFSET_SHIFT		8

#define CL_DSP_REV_MAJOR_MASK		GENMASK(23, 16)
#define CL_DSP_REV_MAJOR_SHIFT		16
#define CL_DSP_REV_MINOR_MASK		GENMASK(15, 8)
#define CL_DSP_REV_MINOR_SHIFT		8
#define CL_DSP_REV_PATCH_MASK		GENMASK(7, 0)

#define CL_DSP_NUM_ALGOS_MAX		32

#define CL_DSP_MAX_WLEN			4096

#define CL_DSP_XM_UNPACKED_TYPE	0x0005
#define CL_DSP_YM_UNPACKED_TYPE	0x0006
#define CL_DSP_PM_PACKED_TYPE		0x0010
#define CL_DSP_XM_PACKED_TYPE		0x0011
#define CL_DSP_YM_PACKED_TYPE		0x0012
#define CL_DSP_ALGO_INFO_TYPE		0x00F2
#define CL_DSP_WMFW_INFO_TYPE		0x00FF

#define CL_DSP_MEM_REG_TYPE_MASK	GENMASK(27, 20)
#define CL_DSP_MEM_REG_TYPE_SHIFT	20

#define CL_DSP_PM_NUM_BYTES		5
#define CL_DSP_PACKED_NUM_BYTES	3
#define CL_DSP_UNPACKED_NUM_BYTES	4

#define CL_DSP_WMDR_DBLK_OFFSET_SIZE	2
#define CL_DSP_WMDR_DBLK_TYPE_SIZE	2
#define CL_DSP_WMDR_ALGO_ID_SIZE	4
#define CL_DSP_WMDR_ALGO_REV_SIZE	4
#define CL_DSP_WMDR_SAMPLE_RATE_SIZE	4
#define CL_DSP_WMDR_DBLK_LEN_SIZE	4
#define CL_DSP_WMDR_NAME_LEN		32
#define CL_DSP_WMDR_DATE_LEN		16
#define CL_DSP_WMDR_HEADER_LEN_SIZE	4

#define CL_DSP_WMDR_DATE_PREFIX	"Date: "
#define CL_DSP_WMDR_DATE_PREFIX_LEN	6

#define CL_DSP_WMDR_FILE_NAME_MISSING	"N/A"
#define CL_DSP_WMDR_FILE_DATE_MISSING	"N/A"

#define CL_DSP_WMDR_NAME_TYPE		0xFE00
#define CL_DSP_WMDR_INFO_TYPE		0xFF00

//HALO core specific registers
#define CL_DSP_HALO_XMEM_PACKED_BASE		0x02000000
#define CL_DSP_HALO_XROM_PACKED_BASE		0x02006000
#define CL_DSP_HALO_XMEM_UNPACKED32_BASE	0x02400000
#define CL_DSP_HALO_XMEM_UNPACKED24_BASE	0x02800000
#define CL_DSP_HALO_XROM_UNPACKED24_BASE	0x02808000
#define CL_DSP_HALO_YMEM_PACKED_BASE		0x02C00000
#define CL_DSP_HALO_YMEM_UNPACKED32_BASE	0x03000000
#define CL_DSP_HALO_YMEM_UNPACKED24_BASE	0x03400000
#define CL_DSP_HALO_PMEM_BASE			0x03800000
#define CL_DSP_HALO_PROM_BASE			0x03C60000

#define CL_DSP_HALO_XM_FW_ID_REG		0x0280000C
#define CL_DSP_HALO_NUM_ALGOS_REG		0x02800024

#define CL_DSP_HALO_ALGO_REV_OFFSET		4
#define CL_DSP_HALO_ALGO_XM_BASE_OFFSET	8
#define CL_DSP_HALO_ALGO_XM_SIZE_OFFSET	12
#define CL_DSP_HALO_ALGO_YM_BASE_OFFSET	16
#define CL_DSP_HALO_ALGO_YM_SIZE_OFFSET	20
#define CL_DSP_ALGO_ENTRY_SIZE			24

/* open wavetable */
#define CL_DSP_OWT_HEADER_MAX_LEN		254
#define CL_DSP_OWT_HEADER_ENTRY_SIZE		12

/* macros */
#define CL_DSP_WORD_ALIGN(n)	(CL_DSP_BYTES_PER_WORD +\
				(((n) / CL_DSP_BYTES_PER_WORD) *\
				CL_DSP_BYTES_PER_WORD))

#define CL_DSP_GET_MAJOR(n)	(((n) & CL_DSP_REV_MAJOR_MASK) >>\
				CL_DSP_REV_MAJOR_SHIFT)

#define CL_DSP_GET_MINOR(n)	(((n) & CL_DSP_REV_MINOR_MASK) >>\
				CL_DSP_REV_MINOR_SHIFT)

#define CL_DSP_GET_PATCH(n)	((n) & CL_DSP_REV_PATCH_MASK)

enum cl_dsp_wt_type {
	WT_TYPE_V4_PCM			= 0,
	WT_TYPE_V4_PWLE			= 1,
	WT_TYPE_V4_PCM_F0_REDC		= 2,
	WT_TYPE_V4_PCM_F0_REDC_VAR	= 3,
	WT_TYPE_V4_COMPOSITE		= 4,
	WT_TYPE_V5_PCM_PCM_F0_REDC_Q	= 5,
	WT_TYPE_V5_PWLE_LONG		= 6,
	WT_TYPE_V5_PWLE_LINEAR		= 7,
	WT_TYPE_V6_PCM_F0_REDC		= 8,
	WT_TYPE_V6_PCM_F0_REDC_VAR	= 9,
	WT_TYPE_V6_COMPOSITE		= 10,
	WT_TYPE_V6_PCM_F0_REDC_Q	= 11,
	WT_TYPE_V6_PWLE			= 12,

	WT_TYPE_TERMINATOR		= 0xFF,
};

union cl_dsp_wmdr_header {
	struct {
		char magic[CL_DSP_BYTES_PER_WORD];
		u32 header_len;
		u32 fw_revision : 24;
		u8 file_format_version;
		u32 api_revision : 24;
		u8 target_core;
	} __attribute__((__packed__));
	u8 data[CL_DSP_COEFF_FILE_HEADER_SIZE];
};

union cl_dsp_wmfw_header {
	struct {
		char magic[CL_DSP_BYTES_PER_WORD];
		u32 header_len;
		u16 api_revision;
		u8 target_core;
		u8 file_format_version;
		u32 xm_size;
		u32 ym_size;
		u32 pm_size;
		u32 zm_size;
		u32 timestamp[2];
		u32 checksum;
	} __attribute__((__packed__));
	u8 data[CL_DSP_FW_FILE_HEADER_SIZE];
};

union cl_dsp_data_block_header {
	struct {
		u32 start_offset : 24;
		u8 block_type;
		u32 data_len;
	} __attribute__((__packed__));
	u8 data[CL_DSP_DBLK_HEADER_SIZE];
};

union cl_dsp_coeff_data_block_header {
	struct {
		u16 start_offset;
		u16 block_type;
		u32 algo_id;
		u32 algo_rev;
		u32 sample_rate;
		u32 data_len;
	} __attribute__((__packed__));
	u8 data[CL_DSP_COEFF_DBLK_HEADER_SIZE];
};

struct cl_dsp_data_block {
	union cl_dsp_data_block_header header;
	u8 *payload;
};

struct cl_dsp_coeff_data_block {
	union cl_dsp_coeff_data_block_header header;
	u8 *payload;
};

struct cl_dsp_coeff_desc {
	u32 parent_id;
	char *parent_name;
	u16 block_offset;
	u16 block_type;
	unsigned char name[CL_DSP_COEFF_NAME_LEN_MAX];
	unsigned int reg;
	unsigned int flags;
	unsigned int length;
	struct list_head list;
};

struct cl_dsp_memchunk {
	u8 *data;
	u8 *max;
	u32 bytes;
	u32 cache;
	int cachebits;
};

struct cl_dsp_owt_header {
	enum cl_dsp_wt_type type;
	u16 flags;
	u32 offset;
	u32 size;
	void *data;
};

struct cl_dsp_owt_desc {
	struct cl_dsp_owt_header waves[CL_DSP_OWT_HEADER_MAX_LEN];
	int nwaves;
	u32 bytes;
	u8 *raw_data;
};

struct cl_dsp_wt_desc {
	unsigned int id;
	char wt_name_xm[CL_DSP_WMDR_NAME_LEN];
	char wt_name_ym[CL_DSP_WMDR_NAME_LEN];
	unsigned int wt_limit_xm;
	unsigned int wt_limit_ym;
	char wt_file[CL_DSP_WMDR_NAME_LEN];
	char wt_date[CL_DSP_WMDR_DATE_LEN];
	struct cl_dsp_owt_desc owt;
	bool is_xm;
};

struct cl_dsp_algo_info {
	unsigned int id;
	unsigned int rev;
	unsigned int xm_base;
	unsigned int xm_size;
	unsigned int ym_base;
	unsigned int ym_size;
};

struct cl_dsp {
	struct device *dev;
	struct regmap *regmap;
	struct list_head coeff_desc_head;
	unsigned int num_algos;
	struct cl_dsp_algo_info algo_info[CL_DSP_NUM_ALGOS_MAX + 1];
	const struct cl_dsp_fw_desc *fw_desc;
	const struct cl_dsp_mem_reg_desc *mem_reg_desc;
	const struct cl_dsp_algo_params *algo_params;
	struct cl_dsp_wt_desc *wt_desc;
};

struct cl_dsp *cl_dsp_create(struct device *dev, struct regmap *regmap);
int cl_dsp_destroy(struct cl_dsp *dsp);
int cl_dsp_wavetable_create(struct cl_dsp *dsp, unsigned int id,
		const char *wt_name_xm, const char *wt_name_ym,
		const char *wt_file);
int cl_dsp_firmware_parse(struct cl_dsp *dsp, const struct firmware *fw,
		bool write_fw);
int cl_dsp_coeff_file_parse(struct cl_dsp *dsp, const struct firmware *fw);
int cl_dsp_get_reg(struct cl_dsp *dsp, const char *coeff_name,
		const unsigned int block_type, const unsigned int algo_id,
		unsigned int *reg);
struct cl_dsp_memchunk cl_dsp_memchunk_create(void *data, int size);
int cl_dsp_memchunk_write(struct cl_dsp_memchunk *ch, int nbits, u32 val);
int cl_dsp_memchunk_read(struct cl_dsp_memchunk *ch, int nbits);
int cl_dsp_memchunk_flush(struct cl_dsp_memchunk *ch);
int cl_dsp_raw_write(struct cl_dsp *dsp, unsigned int reg,
		const void *val, size_t val_len, size_t limit);
int cl_dsp_fw_id_get(struct cl_dsp *dsp, unsigned int *id);
int cl_dsp_fw_rev_get(struct cl_dsp *dsp, unsigned int *rev);

#endif /* __CL_DSP_H */