sst-haswell-ipc.h 15.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * 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>
23
#include <sound/asound.h>
24

25
#define SST_HSW_NO_CHANNELS		4
26
#define SST_HSW_MAX_DX_REGIONS		14
27
#define SST_HSW_DX_CONTEXT_SIZE        (640 * 1024)
28
#define SST_HSW_CHANNELS_ALL		0xffffffff
29 30 31 32 33 34 35 36 37 38 39

#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
40
#define SST_HSW_IPC_MAX_SHORT_PARAMETER_SIZE	500
41 42 43 44 45 46

struct sst_hsw;
struct sst_hsw_stream;
struct sst_hsw_log_stream;
struct sst_pdata;
struct sst_module;
47
struct sst_module_runtime;
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
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,
92
	SST_HSW_DEVICE_TDM_CLOCK_MASTER = 2,
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
};

/* 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,
};

191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
struct sst_hsw_transfer_info {
	uint32_t destination;       /* destination address */
	uint32_t reverse:1;         /* if 1 data flows from destination */
	uint32_t size:31;           /* transfer size in bytes.*/
	uint16_t first_page_offset; /* offset to data in the first page. */
	uint8_t  packed_pages;   /* page addresses. Each occupies 20 bits */
} __attribute__((packed));

struct sst_hsw_transfer_list {
	uint32_t transfers_count;
	struct sst_hsw_transfer_info transfers;
} __attribute__((packed));

struct sst_hsw_transfer_parameter {
	uint32_t parameter_id;
	uint32_t data_size;
	union {
		uint8_t data[1];
		struct sst_hsw_transfer_list transfer_list;
	};
} __attribute__((packed));

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
/* 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));

241 242 243 244 245 246
struct sst_hsw_ipc_module_config {
	struct sst_hsw_module_map map;
	struct sst_hsw_memory_info persistent_mem;
	struct sst_hsw_memory_info scratch_mem;
} __attribute__((packed));

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
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;
332 333
	u8 channels;
	u8 reserved;
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
} __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,
453
	struct sst_hsw_stream *stream, struct sst_module_runtime *runtime);
454 455 456 457
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);
458 459 460 461 462 463 464 465
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);
466 467 468 469 470 471 472 473 474 475 476 477 478 479
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);
480 481 482
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,
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
	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);
498

499 500
/* fw module function */
void sst_hsw_init_module_state(struct sst_hsw *hsw);
501
bool sst_hsw_is_module_loaded(struct sst_hsw *hsw, u32 module_id);
502
bool sst_hsw_is_module_active(struct sst_hsw *hsw, u32 module_id);
503 504 505
void sst_hsw_set_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id);
void sst_hsw_set_module_disabled_rtd3(struct sst_hsw *hsw, u32 module_id);
bool sst_hsw_is_module_enabled_rtd3(struct sst_hsw *hsw, u32 module_id);
506 507 508

int sst_hsw_module_load(struct sst_hsw *hsw,
	u32 module_id, u32 instance_id, char *name);
509 510 511 512
int sst_hsw_module_enable(struct sst_hsw *hsw,
	u32 module_id, u32 instance_id);
int sst_hsw_module_disable(struct sst_hsw *hsw,
	u32 module_id, u32 instance_id);
513 514 515
int sst_hsw_module_set_param(struct sst_hsw *hsw,
	u32 module_id, u32 instance_id, u32 parameter_id,
	u32 param_size, char *param);
516

517 518 519 520
/* 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);
521

522 523 524 525 526 527
/* 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);

528
#endif