aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/intel/sst-haswell-ipc.h
blob: 858096041cb1bb2ca604c4823f1b7e521f240494 (plain) (blame)
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
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
/*
 * Intel SST Haswell/Broadwell IPC Support
 *
 * Copyright (C) 2013, Intel Corporation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#ifndef __SST_HASWELL_IPC_H
#define __SST_HASWELL_IPC_H

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <sound/asound.h>

#define SST_HSW_NO_CHANNELS		4
#define SST_HSW_MAX_DX_REGIONS		14
#define SST_HSW_DX_CONTEXT_SIZE        (640 * 1024)
#define SST_HSW_CHANNELS_ALL		0xffffffff

#define SST_HSW_FW_LOG_CONFIG_DWORDS	12
#define SST_HSW_GLOBAL_LOG		15

/**
 * Upfront defined maximum message size that is
 * expected by the in/out communication pipes in FW.
 */
#define SST_HSW_IPC_MAX_PAYLOAD_SIZE	400
#define SST_HSW_MAX_INFO_SIZE		64
#define SST_HSW_BUILD_HASH_LENGTH	40

struct sst_hsw;
struct sst_hsw_stream;
struct sst_hsw_log_stream;
struct sst_pdata;
struct sst_module;
struct sst_module_runtime;
extern struct sst_ops haswell_ops;

/* Stream Allocate Path ID */
enum sst_hsw_stream_path_id {
	SST_HSW_STREAM_PATH_SSP0_OUT = 0,
	SST_HSW_STREAM_PATH_SSP0_IN = 1,
	SST_HSW_STREAM_PATH_MAX_PATH_ID = 2,
};

/* Stream Allocate Stream Type */
enum sst_hsw_stream_type {
	SST_HSW_STREAM_TYPE_RENDER = 0,
	SST_HSW_STREAM_TYPE_SYSTEM = 1,
	SST_HSW_STREAM_TYPE_CAPTURE = 2,
	SST_HSW_STREAM_TYPE_LOOPBACK = 3,
	SST_HSW_STREAM_TYPE_MAX_STREAM_TYPE = 4,
};

/* Stream Allocate Stream Format */
enum sst_hsw_stream_format {
	SST_HSW_STREAM_FORMAT_PCM_FORMAT = 0,
	SST_HSW_STREAM_FORMAT_MP3_FORMAT = 1,
	SST_HSW_STREAM_FORMAT_AAC_FORMAT = 2,
	SST_HSW_STREAM_FORMAT_MAX_FORMAT_ID = 3,
};

/* Device ID */
enum sst_hsw_device_id {
	SST_HSW_DEVICE_SSP_0   = 0,
	SST_HSW_DEVICE_SSP_1   = 1,
};

/* Device Master Clock Frequency */
enum sst_hsw_device_mclk {
	SST_HSW_DEVICE_MCLK_OFF         = 0,
	SST_HSW_DEVICE_MCLK_FREQ_6_MHZ  = 1,
	SST_HSW_DEVICE_MCLK_FREQ_12_MHZ = 2,
	SST_HSW_DEVICE_MCLK_FREQ_24_MHZ = 3,
};

/* Device Clock Master */
enum sst_hsw_device_mode {
	SST_HSW_DEVICE_CLOCK_SLAVE   = 0,
	SST_HSW_DEVICE_CLOCK_MASTER  = 1,
	SST_HSW_DEVICE_TDM_CLOCK_MASTER = 2,
};

/* DX Power State */
enum sst_hsw_dx_state {
	SST_HSW_DX_STATE_D0     = 0,
	SST_HSW_DX_STATE_D1     = 1,
	SST_HSW_DX_STATE_D3     = 3,
	SST_HSW_DX_STATE_MAX	= 3,
};

/* Audio stream stage IDs */
enum sst_hsw_fx_stage_id {
	SST_HSW_STAGE_ID_WAVES = 0,
	SST_HSW_STAGE_ID_DTS   = 1,
	SST_HSW_STAGE_ID_DOLBY = 2,
	SST_HSW_STAGE_ID_BOOST = 3,
	SST_HSW_STAGE_ID_MAX_FX_ID
};

/* DX State Type */
enum sst_hsw_dx_type {
	SST_HSW_DX_TYPE_FW_IMAGE = 0,
	SST_HSW_DX_TYPE_MEMORY_DUMP = 1
};

/* Volume Curve Type*/
enum sst_hsw_volume_curve {
	SST_HSW_VOLUME_CURVE_NONE = 0,
	SST_HSW_VOLUME_CURVE_FADE = 1
};

/* Sample ordering */
enum sst_hsw_interleaving {
	SST_HSW_INTERLEAVING_PER_CHANNEL = 0,
	SST_HSW_INTERLEAVING_PER_SAMPLE  = 1,
};

/* Channel indices */
enum sst_hsw_channel_index {
	SST_HSW_CHANNEL_LEFT            = 0,
	SST_HSW_CHANNEL_CENTER          = 1,
	SST_HSW_CHANNEL_RIGHT           = 2,
	SST_HSW_CHANNEL_LEFT_SURROUND   = 3,
	SST_HSW_CHANNEL_CENTER_SURROUND = 3,
	SST_HSW_CHANNEL_RIGHT_SURROUND  = 4,
	SST_HSW_CHANNEL_LFE             = 7,
	SST_HSW_CHANNEL_INVALID         = 0xF,
};

/* List of supported channel maps. */
enum sst_hsw_channel_config {
	SST_HSW_CHANNEL_CONFIG_MONO      = 0, /* mono only. */
	SST_HSW_CHANNEL_CONFIG_STEREO    = 1, /* L & R. */
	SST_HSW_CHANNEL_CONFIG_2_POINT_1 = 2, /* L, R & LFE; PCM only. */
	SST_HSW_CHANNEL_CONFIG_3_POINT_0 = 3, /* L, C & R; MP3 & AAC only. */
	SST_HSW_CHANNEL_CONFIG_3_POINT_1 = 4, /* L, C, R & LFE; PCM only. */
	SST_HSW_CHANNEL_CONFIG_QUATRO    = 5, /* L, R, Ls & Rs; PCM only. */
	SST_HSW_CHANNEL_CONFIG_4_POINT_0 = 6, /* L, C, R & Cs; MP3 & AAC only. */
	SST_HSW_CHANNEL_CONFIG_5_POINT_0 = 7, /* L, C, R, Ls & Rs. */
	SST_HSW_CHANNEL_CONFIG_5_POINT_1 = 8, /* L, C, R, Ls, Rs & LFE. */
	SST_HSW_CHANNEL_CONFIG_DUAL_MONO = 9, /* One channel replicated in two. */
	SST_HSW_CHANNEL_CONFIG_INVALID,
};

/* List of supported bit depths. */
enum sst_hsw_bitdepth {
	SST_HSW_DEPTH_8BIT  = 8,
	SST_HSW_DEPTH_16BIT = 16,
	SST_HSW_DEPTH_24BIT = 24, /* Default. */
	SST_HSW_DEPTH_32BIT = 32,
	SST_HSW_DEPTH_INVALID = 33,
};

enum sst_hsw_module_id {
	SST_HSW_MODULE_BASE_FW = 0x0,
	SST_HSW_MODULE_MP3     = 0x1,
	SST_HSW_MODULE_AAC_5_1 = 0x2,
	SST_HSW_MODULE_AAC_2_0 = 0x3,
	SST_HSW_MODULE_SRC     = 0x4,
	SST_HSW_MODULE_WAVES   = 0x5,
	SST_HSW_MODULE_DOLBY   = 0x6,
	SST_HSW_MODULE_BOOST   = 0x7,
	SST_HSW_MODULE_LPAL    = 0x8,
	SST_HSW_MODULE_DTS     = 0x9,
	SST_HSW_MODULE_PCM_CAPTURE = 0xA,
	SST_HSW_MODULE_PCM_SYSTEM = 0xB,
	SST_HSW_MODULE_PCM_REFERENCE = 0xC,
	SST_HSW_MODULE_PCM = 0xD,
	SST_HSW_MODULE_BLUETOOTH_RENDER_MODULE = 0xE,
	SST_HSW_MODULE_BLUETOOTH_CAPTURE_MODULE = 0xF,
	SST_HSW_MAX_MODULE_ID,
};

enum sst_hsw_performance_action {
	SST_HSW_PERF_START = 0,
	SST_HSW_PERF_STOP = 1,
};

/* SST firmware module info */
struct sst_hsw_module_info {
	u8 name[SST_HSW_MAX_INFO_SIZE];
	u8 version[SST_HSW_MAX_INFO_SIZE];
} __attribute__((packed));

/* Module entry point */
struct sst_hsw_module_entry {
	enum sst_hsw_module_id module_id;
	u32 entry_point;
} __attribute__((packed));

/* Module map - alignement matches DSP */
struct sst_hsw_module_map {
	u8 module_entries_count;
	struct sst_hsw_module_entry module_entries[1];
} __attribute__((packed));

struct sst_hsw_memory_info {
	u32 offset;
	u32 size;
} __attribute__((packed));

struct sst_hsw_fx_enable {
	struct sst_hsw_module_map module_map;
	struct sst_hsw_memory_info persistent_mem;
} __attribute__((packed));

struct sst_hsw_get_fx_param {
	u32 parameter_id;
	u32 param_size;
} __attribute__((packed));

struct sst_hsw_perf_action {
	u32 action;
} __attribute__((packed));

struct sst_hsw_perf_data {
	u64 timestamp;
	u64 cycles;
	u64 datatime;
} __attribute__((packed));

/* FW version */
struct sst_hsw_ipc_fw_version {
	u8 build;
	u8 minor;
	u8 major;
	u8 type;
	u8 fw_build_hash[SST_HSW_BUILD_HASH_LENGTH];
	u32 fw_log_providers_hash;
} __attribute__((packed));

/* Stream ring info */
struct sst_hsw_ipc_stream_ring {
	u32 ring_pt_address;
	u32 num_pages;
	u32 ring_size;
	u32 ring_offset;
	u32 ring_first_pfn;
} __attribute__((packed));

/* Debug Dump Log Enable Request */
struct sst_hsw_ipc_debug_log_enable_req {
	struct sst_hsw_ipc_stream_ring ringinfo;
	u32 config[SST_HSW_FW_LOG_CONFIG_DWORDS];
} __attribute__((packed));

/* Debug Dump Log Reply */
struct sst_hsw_ipc_debug_log_reply {
	u32 log_buffer_begining;
	u32 log_buffer_size;
} __attribute__((packed));

/* Stream glitch position */
struct sst_hsw_ipc_stream_glitch_position {
	u32 glitch_type;
	u32 present_pos;
	u32 write_pos;
} __attribute__((packed));

/* Stream get position */
struct sst_hsw_ipc_stream_get_position {
	u32 position;
	u32 fw_cycle_count;
} __attribute__((packed));

/* Stream set position */
struct sst_hsw_ipc_stream_set_position {
	u32 position;
	u32 end_of_buffer;
} __attribute__((packed));

/* Stream Free Request */
struct sst_hsw_ipc_stream_free_req {
	u8 stream_id;
	u8 reserved[3];
} __attribute__((packed));

/* Set Volume Request */
struct sst_hsw_ipc_volume_req {
	u32 channel;
	u32 target_volume;
	u64 curve_duration;
	u32 curve_type;
} __attribute__((packed));

/* Device Configuration Request */
struct sst_hsw_ipc_device_config_req {
	u32 ssp_interface;
	u32 clock_frequency;
	u32 mode;
	u16 clock_divider;
	u8 channels;
	u8 reserved;
} __attribute__((packed));

/* Audio Data formats */
struct sst_hsw_audio_data_format_ipc {
	u32 frequency;
	u32 bitdepth;
	u32 map;
	u32 config;
	u32 style;
	u8 ch_num;
	u8 valid_bit;
	u8 reserved[2];
} __attribute__((packed));

/* Stream Allocate Request */
struct sst_hsw_ipc_stream_alloc_req {
	u8 path_id;
	u8 stream_type;
	u8 format_id;
	u8 reserved;
	struct sst_hsw_audio_data_format_ipc format;
	struct sst_hsw_ipc_stream_ring ringinfo;
	struct sst_hsw_module_map map;
	struct sst_hsw_memory_info persistent_mem;
	struct sst_hsw_memory_info scratch_mem;
	u32 number_of_notifications;
} __attribute__((packed));

/* Stream Allocate Reply */
struct sst_hsw_ipc_stream_alloc_reply {
	u32 stream_hw_id;
	u32 mixer_hw_id; // returns rate ????
	u32 read_position_register_address;
	u32 presentation_position_register_address;
	u32 peak_meter_register_address[SST_HSW_NO_CHANNELS];
	u32 volume_register_address[SST_HSW_NO_CHANNELS];
} __attribute__((packed));

/* Get Mixer Stream Info */
struct sst_hsw_ipc_stream_info_reply {
	u32 mixer_hw_id;
	u32 peak_meter_register_address[SST_HSW_NO_CHANNELS];
	u32 volume_register_address[SST_HSW_NO_CHANNELS];
} __attribute__((packed));

/* DX State Request */
struct sst_hsw_ipc_dx_req {
	u8 state;
	u8 reserved[3];
} __attribute__((packed));

/* DX State Reply Memory Info Item */
struct sst_hsw_ipc_dx_memory_item {
	u32 offset;
	u32 size;
	u32 source;
} __attribute__((packed));

/* DX State Reply */
struct sst_hsw_ipc_dx_reply {
	u32 entries_no;
	struct sst_hsw_ipc_dx_memory_item mem_info[SST_HSW_MAX_DX_REGIONS];
} __attribute__((packed));

struct sst_hsw_ipc_fw_version;

/* SST Init & Free */
struct sst_hsw *sst_hsw_new(struct device *dev, const u8 *fw, size_t fw_length,
	u32 fw_offset);
void sst_hsw_free(struct sst_hsw *hsw);
int sst_hsw_fw_get_version(struct sst_hsw *hsw,
	struct sst_hsw_ipc_fw_version *version);
u32 create_channel_map(enum sst_hsw_channel_config config);

/* Stream Mixer Controls - */
int sst_hsw_stream_set_volume(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 volume);
int sst_hsw_stream_get_volume(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream, u32 stage_id, u32 channel, u32 *volume);

/* Global Mixer Controls - */
int sst_hsw_mixer_set_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel,
	u32 volume);
int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel,
	u32 *volume);

/* Stream API */
struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id,
	u32 (*get_write_position)(struct sst_hsw_stream *stream, void *data),
	void *data);

int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream);

/* Stream Configuration */
int sst_hsw_stream_format(struct sst_hsw *hsw, struct sst_hsw_stream *stream,
	enum sst_hsw_stream_path_id path_id,
	enum sst_hsw_stream_type stream_type,
	enum sst_hsw_stream_format format_id);

int sst_hsw_stream_buffer(struct sst_hsw *hsw, struct sst_hsw_stream *stream,
	u32 ring_pt_address, u32 num_pages,
	u32 ring_size, u32 ring_offset, u32 ring_first_pfn);

int sst_hsw_stream_commit(struct sst_hsw *hsw, struct sst_hsw_stream *stream);

int sst_hsw_stream_set_valid(struct sst_hsw *hsw, struct sst_hsw_stream *stream,
	u32 bits);
int sst_hsw_stream_set_rate(struct sst_hsw *hsw, struct sst_hsw_stream *stream,
	int rate);
int sst_hsw_stream_set_bits(struct sst_hsw *hsw, struct sst_hsw_stream *stream,
	enum sst_hsw_bitdepth bits);
int sst_hsw_stream_set_channels(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream, int channels);
int sst_hsw_stream_set_map_config(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream, u32 map,
	enum sst_hsw_channel_config config);
int sst_hsw_stream_set_style(struct sst_hsw *hsw, struct sst_hsw_stream *stream,
	enum sst_hsw_interleaving style);
int sst_hsw_stream_set_module_info(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream, struct sst_module_runtime *runtime);
int sst_hsw_stream_set_pmemory_info(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream, u32 offset, u32 size);
int sst_hsw_stream_set_smemory_info(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream, u32 offset, u32 size);
snd_pcm_uframes_t sst_hsw_stream_get_old_position(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream);
void sst_hsw_stream_set_old_position(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream, snd_pcm_uframes_t val);
bool sst_hsw_stream_get_silence_start(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream);
void sst_hsw_stream_set_silence_start(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream, bool val);
int sst_hsw_mixer_get_info(struct sst_hsw *hsw);

/* Stream ALSA trigger operations */
int sst_hsw_stream_pause(struct sst_hsw *hsw, struct sst_hsw_stream *stream,
	int wait);
int sst_hsw_stream_resume(struct sst_hsw *hsw, struct sst_hsw_stream *stream,
	int wait);
int sst_hsw_stream_reset(struct sst_hsw *hsw, struct sst_hsw_stream *stream);

/* Stream pointer positions */
int sst_hsw_stream_get_read_pos(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream, u32 *position);
int sst_hsw_stream_get_write_pos(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream, u32 *position);
u32 sst_hsw_get_dsp_position(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream);
u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw,
	struct sst_hsw_stream *stream);

/* HW port config */
int sst_hsw_device_set_config(struct sst_hsw *hsw,
	enum sst_hsw_device_id dev, enum sst_hsw_device_mclk mclk,
	enum sst_hsw_device_mode mode, u32 clock_divider);

/* DX Config */
int sst_hsw_dx_set_state(struct sst_hsw *hsw,
	enum sst_hsw_dx_state state, struct sst_hsw_ipc_dx_reply *dx);

/* init */
int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata);
void sst_hsw_dsp_free(struct device *dev, struct sst_pdata *pdata);
struct sst_dsp *sst_hsw_get_dsp(struct sst_hsw *hsw);

/* runtime module management */
struct sst_module_runtime *sst_hsw_runtime_module_create(struct sst_hsw *hsw,
	int mod_id, int offset);
void sst_hsw_runtime_module_free(struct sst_module_runtime *runtime);

/* PM */
int sst_hsw_dsp_runtime_resume(struct sst_hsw *hsw);
int sst_hsw_dsp_runtime_suspend(struct sst_hsw *hsw);
int sst_hsw_dsp_load(struct sst_hsw *hsw);
int sst_hsw_dsp_runtime_sleep(struct sst_hsw *hsw);

#endif