1 /*
2  *  sst-atom-controls.h - Intel MID Platform driver header file
3  *
4  *  Copyright (C) 2013-14 Intel Corp
5  *  Author: Ramesh Babu <ramesh.babu.koul@intel.com>
6  *  	Omair M Abdullah <omair.m.abdullah@intel.com>
7  *  	Samreen Nilofer <samreen.nilofer@intel.com>
8  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; version 2 of the License.
13  *
14  *  This program is distributed in the hope that it will be useful, but
15  *  WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  General Public License for more details.
18  *
19  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20  *
21  */
22 
23 #ifndef __SST_ATOM_CONTROLS_H__
24 #define __SST_ATOM_CONTROLS_H__
25 
26 #include <sound/soc.h>
27 #include <sound/tlv.h>
28 
29 enum {
30 	MERR_DPCM_AUDIO = 0,
31 	MERR_DPCM_COMPR,
32 };
33 
34 /* define a bit for each mixer input */
35 #define SST_MIX_IP(x)		(x)
36 
37 #define SST_IP_CODEC0		SST_MIX_IP(2)
38 #define SST_IP_CODEC1		SST_MIX_IP(3)
39 #define SST_IP_LOOP0		SST_MIX_IP(4)
40 #define SST_IP_LOOP1		SST_MIX_IP(5)
41 #define SST_IP_LOOP2		SST_MIX_IP(6)
42 #define SST_IP_PROBE		SST_MIX_IP(7)
43 #define SST_IP_VOIP		SST_MIX_IP(12)
44 #define SST_IP_PCM0		SST_MIX_IP(13)
45 #define SST_IP_PCM1		SST_MIX_IP(14)
46 #define SST_IP_MEDIA0		SST_MIX_IP(17)
47 #define SST_IP_MEDIA1		SST_MIX_IP(18)
48 #define SST_IP_MEDIA2		SST_MIX_IP(19)
49 #define SST_IP_MEDIA3		SST_MIX_IP(20)
50 
51 #define SST_IP_LAST		SST_IP_MEDIA3
52 
53 #define SST_SWM_INPUT_COUNT	(SST_IP_LAST + 1)
54 #define SST_CMD_SWM_MAX_INPUTS	6
55 
56 #define SST_PATH_ID_SHIFT	8
57 #define SST_DEFAULT_LOCATION_ID	0xFFFF
58 #define SST_DEFAULT_CELL_NBR	0xFF
59 #define SST_DEFAULT_MODULE_ID	0xFFFF
60 
61 /*
62  * Audio DSP Path Ids. Specified by the audio DSP FW
63  */
64 enum sst_path_index {
65 	SST_PATH_INDEX_CODEC_OUT0               = (0x02 << SST_PATH_ID_SHIFT),
66 	SST_PATH_INDEX_CODEC_OUT1               = (0x03 << SST_PATH_ID_SHIFT),
67 
68 	SST_PATH_INDEX_SPROT_LOOP_OUT           = (0x04 << SST_PATH_ID_SHIFT),
69 	SST_PATH_INDEX_MEDIA_LOOP1_OUT          = (0x05 << SST_PATH_ID_SHIFT),
70 	SST_PATH_INDEX_MEDIA_LOOP2_OUT          = (0x06 << SST_PATH_ID_SHIFT),
71 
72 	SST_PATH_INDEX_VOIP_OUT                 = (0x0C << SST_PATH_ID_SHIFT),
73 	SST_PATH_INDEX_PCM0_OUT                 = (0x0D << SST_PATH_ID_SHIFT),
74 	SST_PATH_INDEX_PCM1_OUT                 = (0x0E << SST_PATH_ID_SHIFT),
75 	SST_PATH_INDEX_PCM2_OUT                 = (0x0F << SST_PATH_ID_SHIFT),
76 
77 	SST_PATH_INDEX_MEDIA0_OUT               = (0x12 << SST_PATH_ID_SHIFT),
78 	SST_PATH_INDEX_MEDIA1_OUT               = (0x13 << SST_PATH_ID_SHIFT),
79 
80 
81 	/* Start of input paths */
82 	SST_PATH_INDEX_CODEC_IN0                = (0x82 << SST_PATH_ID_SHIFT),
83 	SST_PATH_INDEX_CODEC_IN1                = (0x83 << SST_PATH_ID_SHIFT),
84 
85 	SST_PATH_INDEX_SPROT_LOOP_IN            = (0x84 << SST_PATH_ID_SHIFT),
86 	SST_PATH_INDEX_MEDIA_LOOP1_IN           = (0x85 << SST_PATH_ID_SHIFT),
87 	SST_PATH_INDEX_MEDIA_LOOP2_IN           = (0x86 << SST_PATH_ID_SHIFT),
88 
89 	SST_PATH_INDEX_VOIP_IN                  = (0x8C << SST_PATH_ID_SHIFT),
90 
91 	SST_PATH_INDEX_PCM0_IN                  = (0x8D << SST_PATH_ID_SHIFT),
92 	SST_PATH_INDEX_PCM1_IN                  = (0x8E << SST_PATH_ID_SHIFT),
93 
94 	SST_PATH_INDEX_MEDIA0_IN                = (0x8F << SST_PATH_ID_SHIFT),
95 	SST_PATH_INDEX_MEDIA1_IN                = (0x90 << SST_PATH_ID_SHIFT),
96 	SST_PATH_INDEX_MEDIA2_IN                = (0x91 << SST_PATH_ID_SHIFT),
97 
98 	SST_PATH_INDEX_MEDIA3_IN		= (0x9C << SST_PATH_ID_SHIFT),
99 
100 	SST_PATH_INDEX_RESERVED                 = (0xFF << SST_PATH_ID_SHIFT),
101 };
102 
103 /*
104  * path IDs
105  */
106 enum sst_swm_inputs {
107 	SST_SWM_IN_CODEC0	= (SST_PATH_INDEX_CODEC_IN0	  | SST_DEFAULT_CELL_NBR),
108 	SST_SWM_IN_CODEC1	= (SST_PATH_INDEX_CODEC_IN1	  | SST_DEFAULT_CELL_NBR),
109 	SST_SWM_IN_SPROT_LOOP	= (SST_PATH_INDEX_SPROT_LOOP_IN	  | SST_DEFAULT_CELL_NBR),
110 	SST_SWM_IN_MEDIA_LOOP1	= (SST_PATH_INDEX_MEDIA_LOOP1_IN  | SST_DEFAULT_CELL_NBR),
111 	SST_SWM_IN_MEDIA_LOOP2	= (SST_PATH_INDEX_MEDIA_LOOP2_IN  | SST_DEFAULT_CELL_NBR),
112 	SST_SWM_IN_VOIP		= (SST_PATH_INDEX_VOIP_IN	  | SST_DEFAULT_CELL_NBR),
113 	SST_SWM_IN_PCM0		= (SST_PATH_INDEX_PCM0_IN	  | SST_DEFAULT_CELL_NBR),
114 	SST_SWM_IN_PCM1		= (SST_PATH_INDEX_PCM1_IN	  | SST_DEFAULT_CELL_NBR),
115 	SST_SWM_IN_MEDIA0	= (SST_PATH_INDEX_MEDIA0_IN	  | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
116 	SST_SWM_IN_MEDIA1	= (SST_PATH_INDEX_MEDIA1_IN	  | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
117 	SST_SWM_IN_MEDIA2	= (SST_PATH_INDEX_MEDIA2_IN	  | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
118 	SST_SWM_IN_MEDIA3	= (SST_PATH_INDEX_MEDIA3_IN	  | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
119 	SST_SWM_IN_END		= (SST_PATH_INDEX_RESERVED	  | SST_DEFAULT_CELL_NBR)
120 };
121 
122 /*
123  * path IDs
124  */
125 enum sst_swm_outputs {
126 	SST_SWM_OUT_CODEC0	= (SST_PATH_INDEX_CODEC_OUT0	  | SST_DEFAULT_CELL_NBR),
127 	SST_SWM_OUT_CODEC1	= (SST_PATH_INDEX_CODEC_OUT1	  | SST_DEFAULT_CELL_NBR),
128 	SST_SWM_OUT_SPROT_LOOP	= (SST_PATH_INDEX_SPROT_LOOP_OUT  | SST_DEFAULT_CELL_NBR),
129 	SST_SWM_OUT_MEDIA_LOOP1	= (SST_PATH_INDEX_MEDIA_LOOP1_OUT | SST_DEFAULT_CELL_NBR),
130 	SST_SWM_OUT_MEDIA_LOOP2	= (SST_PATH_INDEX_MEDIA_LOOP2_OUT | SST_DEFAULT_CELL_NBR),
131 	SST_SWM_OUT_VOIP	= (SST_PATH_INDEX_VOIP_OUT	  | SST_DEFAULT_CELL_NBR),
132 	SST_SWM_OUT_PCM0	= (SST_PATH_INDEX_PCM0_OUT	  | SST_DEFAULT_CELL_NBR),
133 	SST_SWM_OUT_PCM1	= (SST_PATH_INDEX_PCM1_OUT	  | SST_DEFAULT_CELL_NBR),
134 	SST_SWM_OUT_PCM2	= (SST_PATH_INDEX_PCM2_OUT	  | SST_DEFAULT_CELL_NBR),
135 	SST_SWM_OUT_MEDIA0	= (SST_PATH_INDEX_MEDIA0_OUT	  | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
136 	SST_SWM_OUT_MEDIA1	= (SST_PATH_INDEX_MEDIA1_OUT	  | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
137 	SST_SWM_OUT_END		= (SST_PATH_INDEX_RESERVED	  | SST_DEFAULT_CELL_NBR),
138 };
139 
140 enum sst_ipc_msg {
141 	SST_IPC_IA_CMD = 1,
142 	SST_IPC_IA_SET_PARAMS,
143 	SST_IPC_IA_GET_PARAMS,
144 };
145 
146 enum sst_cmd_type {
147 	SST_CMD_BYTES_SET = 1,
148 	SST_CMD_BYTES_GET = 2,
149 };
150 
151 enum sst_task {
152 	SST_TASK_SBA = 1,
153 	SST_TASK_MMX = 3,
154 };
155 
156 enum sst_type {
157 	SST_TYPE_CMD = 1,
158 	SST_TYPE_PARAMS,
159 };
160 
161 enum sst_flag {
162 	SST_FLAG_BLOCKED = 1,
163 	SST_FLAG_NONBLOCK,
164 };
165 
166 /*
167  * Enumeration for indexing the gain cells in VB_SET_GAIN DSP command
168  */
169 enum sst_gain_index {
170 	/* GAIN IDs for SB task start here */
171 	SST_GAIN_INDEX_CODEC_OUT0,
172 	SST_GAIN_INDEX_CODEC_OUT1,
173 	SST_GAIN_INDEX_CODEC_IN0,
174 	SST_GAIN_INDEX_CODEC_IN1,
175 
176 	SST_GAIN_INDEX_SPROT_LOOP_OUT,
177 	SST_GAIN_INDEX_MEDIA_LOOP1_OUT,
178 	SST_GAIN_INDEX_MEDIA_LOOP2_OUT,
179 
180 	SST_GAIN_INDEX_PCM0_IN_LEFT,
181 	SST_GAIN_INDEX_PCM0_IN_RIGHT,
182 
183 	SST_GAIN_INDEX_PCM1_OUT_LEFT,
184 	SST_GAIN_INDEX_PCM1_OUT_RIGHT,
185 	SST_GAIN_INDEX_PCM1_IN_LEFT,
186 	SST_GAIN_INDEX_PCM1_IN_RIGHT,
187 	SST_GAIN_INDEX_PCM2_OUT_LEFT,
188 
189 	SST_GAIN_INDEX_PCM2_OUT_RIGHT,
190 	SST_GAIN_INDEX_VOIP_OUT,
191 	SST_GAIN_INDEX_VOIP_IN,
192 
193 	/* Gain IDs for MMX task start here */
194 	SST_GAIN_INDEX_MEDIA0_IN_LEFT,
195 	SST_GAIN_INDEX_MEDIA0_IN_RIGHT,
196 	SST_GAIN_INDEX_MEDIA1_IN_LEFT,
197 	SST_GAIN_INDEX_MEDIA1_IN_RIGHT,
198 
199 	SST_GAIN_INDEX_MEDIA2_IN_LEFT,
200 	SST_GAIN_INDEX_MEDIA2_IN_RIGHT,
201 
202 	SST_GAIN_INDEX_GAIN_END
203 };
204 
205 /*
206  * Audio DSP module IDs specified by FW spec
207  * TODO: Update with all modules
208  */
209 enum sst_module_id {
210 	SST_MODULE_ID_PCM		  = 0x0001,
211 	SST_MODULE_ID_MP3		  = 0x0002,
212 	SST_MODULE_ID_MP24		  = 0x0003,
213 	SST_MODULE_ID_AAC		  = 0x0004,
214 	SST_MODULE_ID_AACP		  = 0x0005,
215 	SST_MODULE_ID_EAACP		  = 0x0006,
216 	SST_MODULE_ID_WMA9		  = 0x0007,
217 	SST_MODULE_ID_WMA10		  = 0x0008,
218 	SST_MODULE_ID_WMA10P		  = 0x0009,
219 	SST_MODULE_ID_RA		  = 0x000A,
220 	SST_MODULE_ID_DDAC3		  = 0x000B,
221 	SST_MODULE_ID_TRUE_HD		  = 0x000C,
222 	SST_MODULE_ID_HD_PLUS		  = 0x000D,
223 
224 	SST_MODULE_ID_SRC		  = 0x0064,
225 	SST_MODULE_ID_DOWNMIX		  = 0x0066,
226 	SST_MODULE_ID_GAIN_CELL		  = 0x0067,
227 	SST_MODULE_ID_SPROT		  = 0x006D,
228 	SST_MODULE_ID_BASS_BOOST	  = 0x006E,
229 	SST_MODULE_ID_STEREO_WDNG	  = 0x006F,
230 	SST_MODULE_ID_AV_REMOVAL	  = 0x0070,
231 	SST_MODULE_ID_MIC_EQ		  = 0x0071,
232 	SST_MODULE_ID_SPL		  = 0x0072,
233 	SST_MODULE_ID_ALGO_VTSV           = 0x0073,
234 	SST_MODULE_ID_NR		  = 0x0076,
235 	SST_MODULE_ID_BWX		  = 0x0077,
236 	SST_MODULE_ID_DRP		  = 0x0078,
237 	SST_MODULE_ID_MDRP		  = 0x0079,
238 
239 	SST_MODULE_ID_ANA		  = 0x007A,
240 	SST_MODULE_ID_AEC		  = 0x007B,
241 	SST_MODULE_ID_NR_SNS		  = 0x007C,
242 	SST_MODULE_ID_SER		  = 0x007D,
243 	SST_MODULE_ID_AGC		  = 0x007E,
244 
245 	SST_MODULE_ID_CNI		  = 0x007F,
246 	SST_MODULE_ID_CONTEXT_ALGO_AWARE  = 0x0080,
247 	SST_MODULE_ID_FIR_24		  = 0x0081,
248 	SST_MODULE_ID_IIR_24		  = 0x0082,
249 
250 	SST_MODULE_ID_ASRC		  = 0x0083,
251 	SST_MODULE_ID_TONE_GEN		  = 0x0084,
252 	SST_MODULE_ID_BMF		  = 0x0086,
253 	SST_MODULE_ID_EDL		  = 0x0087,
254 	SST_MODULE_ID_GLC		  = 0x0088,
255 
256 	SST_MODULE_ID_FIR_16		  = 0x0089,
257 	SST_MODULE_ID_IIR_16		  = 0x008A,
258 	SST_MODULE_ID_DNR		  = 0x008B,
259 
260 	SST_MODULE_ID_VIRTUALIZER	  = 0x008C,
261 	SST_MODULE_ID_VISUALIZATION	  = 0x008D,
262 	SST_MODULE_ID_LOUDNESS_OPTIMIZER  = 0x008E,
263 	SST_MODULE_ID_REVERBERATION	  = 0x008F,
264 
265 	SST_MODULE_ID_CNI_TX		  = 0x0090,
266 	SST_MODULE_ID_REF_LINE		  = 0x0091,
267 	SST_MODULE_ID_VOLUME		  = 0x0092,
268 	SST_MODULE_ID_FILT_DCR		  = 0x0094,
269 	SST_MODULE_ID_SLV		  = 0x009A,
270 	SST_MODULE_ID_NLF		  = 0x009B,
271 	SST_MODULE_ID_TNR		  = 0x009C,
272 	SST_MODULE_ID_WNR		  = 0x009D,
273 
274 	SST_MODULE_ID_LOG		  = 0xFF00,
275 
276 	SST_MODULE_ID_TASK		  = 0xFFFF,
277 };
278 
279 enum sst_cmd {
280 	SBA_IDLE		= 14,
281 	SBA_VB_SET_SPEECH_PATH	= 26,
282 	MMX_SET_GAIN		= 33,
283 	SBA_VB_SET_GAIN		= 33,
284 	FBA_VB_RX_CNI		= 35,
285 	MMX_SET_GAIN_TIMECONST	= 36,
286 	SBA_VB_SET_TIMECONST	= 36,
287 	SBA_VB_START		= 85,
288 	SBA_SET_SWM		= 114,
289 	SBA_SET_MDRP            = 116,
290 	SBA_HW_SET_SSP		= 117,
291 	SBA_SET_MEDIA_LOOP_MAP	= 118,
292 	SBA_SET_MEDIA_PATH	= 119,
293 	MMX_SET_MEDIA_PATH	= 119,
294 	SBA_VB_LPRO             = 126,
295 	SBA_VB_SET_FIR          = 128,
296 	SBA_VB_SET_IIR          = 129,
297 	SBA_SET_SSP_SLOT_MAP	= 130,
298 };
299 
300 enum sst_dsp_switch {
301 	SST_SWITCH_OFF = 0,
302 	SST_SWITCH_ON = 3,
303 };
304 
305 enum sst_path_switch {
306 	SST_PATH_OFF = 0,
307 	SST_PATH_ON = 1,
308 };
309 
310 enum sst_swm_state {
311 	SST_SWM_OFF = 0,
312 	SST_SWM_ON = 3,
313 };
314 
315 #define SST_FILL_LOCATION_IDS(dst, cell_idx, pipe_id)		do {	\
316 		dst.location_id.p.cell_nbr_idx = (cell_idx);		\
317 		dst.location_id.p.path_id = (pipe_id);			\
318 	} while (0)
319 #define SST_FILL_LOCATION_ID(dst, loc_id)				(\
320 	dst.location_id.f = (loc_id))
321 #define SST_FILL_MODULE_ID(dst, mod_id)					(\
322 	dst.module_id = (mod_id))
323 
324 #define SST_FILL_DESTINATION1(dst, id)				do {	\
325 		SST_FILL_LOCATION_ID(dst, (id) & 0xFFFF);		\
326 		SST_FILL_MODULE_ID(dst, ((id) & 0xFFFF0000) >> 16);	\
327 	} while (0)
328 #define SST_FILL_DESTINATION2(dst, loc_id, mod_id)		do {	\
329 		SST_FILL_LOCATION_ID(dst, loc_id);			\
330 		SST_FILL_MODULE_ID(dst, mod_id);			\
331 	} while (0)
332 #define SST_FILL_DESTINATION3(dst, cell_idx, path_id, mod_id)	do {	\
333 		SST_FILL_LOCATION_IDS(dst, cell_idx, path_id);		\
334 		SST_FILL_MODULE_ID(dst, mod_id);			\
335 	} while (0)
336 
337 #define SST_FILL_DESTINATION(level, dst, ...)				\
338 	SST_FILL_DESTINATION##level(dst, __VA_ARGS__)
339 #define SST_FILL_DEFAULT_DESTINATION(dst)				\
340 	SST_FILL_DESTINATION(2, dst, SST_DEFAULT_LOCATION_ID, SST_DEFAULT_MODULE_ID)
341 
342 struct sst_destination_id {
343 	union sst_location_id {
344 		struct {
345 			u8 cell_nbr_idx;	/* module index */
346 			u8 path_id;		/* pipe_id */
347 		} __packed	p;		/* part */
348 		u16		f;		/* full */
349 	} __packed location_id;
350 	u16	   module_id;
351 } __packed;
352 struct sst_dsp_header {
353 	struct sst_destination_id dst;
354 	u16 command_id;
355 	u16 length;
356 } __packed;
357 
358 /*
359  *
360  * Common Commands
361  *
362  */
363 struct sst_cmd_generic {
364 	struct sst_dsp_header header;
365 } __packed;
366 
367 struct swm_input_ids {
368 	struct sst_destination_id input_id;
369 } __packed;
370 
371 struct sst_cmd_set_swm {
372 	struct sst_dsp_header header;
373 	struct sst_destination_id output_id;
374 	u16    switch_state;
375 	u16    nb_inputs;
376 	struct swm_input_ids input[SST_CMD_SWM_MAX_INPUTS];
377 } __packed;
378 
379 struct sst_cmd_set_media_path {
380 	struct sst_dsp_header header;
381 	u16    switch_state;
382 } __packed;
383 
384 struct pcm_cfg {
385 		u8 s_length:2;
386 		u8 rate:3;
387 		u8 format:3;
388 } __packed;
389 
390 struct sst_cmd_set_speech_path {
391 	struct sst_dsp_header header;
392 	u16    switch_state;
393 	struct {
394 		u16 rsvd:8;
395 		struct pcm_cfg cfg;
396 	} config;
397 } __packed;
398 
399 struct gain_cell {
400 	struct sst_destination_id dest;
401 	s16 cell_gain_left;
402 	s16 cell_gain_right;
403 	u16 gain_time_constant;
404 } __packed;
405 
406 #define NUM_GAIN_CELLS 1
407 struct sst_cmd_set_gain_dual {
408 	struct sst_dsp_header header;
409 	u16    gain_cell_num;
410 	struct gain_cell cell_gains[NUM_GAIN_CELLS];
411 } __packed;
412 struct sst_cmd_set_params {
413 	struct sst_destination_id dst;
414 	u16 command_id;
415 	char params[0];
416 } __packed;
417 
418 
419 struct sst_cmd_sba_vb_start {
420 	struct sst_dsp_header header;
421 } __packed;
422 
423 union sba_media_loop_params {
424 	struct {
425 		u16 rsvd:8;
426 		struct pcm_cfg cfg;
427 	} part;
428 	u16 full;
429 } __packed;
430 
431 struct sst_cmd_sba_set_media_loop_map {
432 	struct	sst_dsp_header header;
433 	u16	switch_state;
434 	union	sba_media_loop_params param;
435 	u16	map;
436 } __packed;
437 
438 struct sst_cmd_tone_stop {
439 	struct	sst_dsp_header header;
440 	u16	switch_state;
441 } __packed;
442 
443 enum sst_ssp_mode {
444 	SSP_MODE_MASTER = 0,
445 	SSP_MODE_SLAVE = 1,
446 };
447 
448 enum sst_ssp_pcm_mode {
449 	SSP_PCM_MODE_NORMAL = 0,
450 	SSP_PCM_MODE_NETWORK = 1,
451 };
452 
453 enum sst_ssp_duplex {
454 	SSP_DUPLEX = 0,
455 	SSP_RX = 1,
456 	SSP_TX = 2,
457 };
458 
459 enum sst_ssp_fs_frequency {
460 	SSP_FS_8_KHZ = 0,
461 	SSP_FS_16_KHZ = 1,
462 	SSP_FS_44_1_KHZ = 2,
463 	SSP_FS_48_KHZ = 3,
464 };
465 
466 enum sst_ssp_fs_polarity {
467 	SSP_FS_ACTIVE_LOW = 0,
468 	SSP_FS_ACTIVE_HIGH = 1,
469 };
470 
471 enum sst_ssp_protocol {
472 	SSP_MODE_PCM = 0,
473 	SSP_MODE_I2S = 1,
474 };
475 
476 enum sst_ssp_port_id {
477 	SSP_MODEM = 0,
478 	SSP_BT = 1,
479 	SSP_FM = 2,
480 	SSP_CODEC = 3,
481 };
482 
483 struct sst_cmd_sba_hw_set_ssp {
484 	struct sst_dsp_header header;
485 	u16 selection;			/* 0:SSP0(def), 1:SSP1, 2:SSP2 */
486 
487 	u16 switch_state;
488 
489 	u16 nb_bits_per_slots:6;        /* 0-32 bits, 24 (def) */
490 	u16 nb_slots:4;			/* 0-8: slots per frame  */
491 	u16 mode:3;			/* 0:Master, 1: Slave  */
492 	u16 duplex:3;
493 
494 	u16 active_tx_slot_map:8;       /* Bit map, 0:off, 1:on */
495 	u16 reserved1:8;
496 
497 	u16 active_rx_slot_map:8;       /* Bit map 0: Off, 1:On */
498 	u16 reserved2:8;
499 
500 	u16 frame_sync_frequency;
501 
502 	u16 frame_sync_polarity:8;
503 	u16 data_polarity:8;
504 
505 	u16 frame_sync_width;           /* 1 to N clocks */
506 	u16 ssp_protocol:8;
507 	u16 start_delay:8;		/* Start delay in terms of clock ticks */
508 } __packed;
509 
510 #define SST_MAX_TDM_SLOTS 8
511 
512 struct sst_param_sba_ssp_slot_map {
513 	struct sst_dsp_header header;
514 
515 	u16 param_id;
516 	u16 param_len;
517 	u16 ssp_index;
518 
519 	u8 rx_slot_map[SST_MAX_TDM_SLOTS];
520 	u8 tx_slot_map[SST_MAX_TDM_SLOTS];
521 } __packed;
522 
523 enum {
524 	SST_PROBE_EXTRACTOR = 0,
525 	SST_PROBE_INJECTOR = 1,
526 };
527 
528 /**** widget defines *****/
529 
530 #define SST_MODULE_GAIN 1
531 #define SST_MODULE_ALGO 2
532 
533 #define SST_FMT_MONO 0
534 #define SST_FMT_STEREO 3
535 
536 /* physical SSP numbers */
537 enum {
538 	SST_SSP0 = 0,
539 	SST_SSP1,
540 	SST_SSP2,
541 	SST_SSP_LAST = SST_SSP2,
542 };
543 
544 #define SST_NUM_SSPS		(SST_SSP_LAST + 1)	/* physical SSPs */
545 #define SST_MAX_SSP_MUX		2			/* single SSP muxed between pipes */
546 #define SST_MAX_SSP_DOMAINS	2			/* domains present in each pipe */
547 
548 struct sst_module {
549 	struct snd_kcontrol *kctl;
550 	struct list_head node;
551 };
552 
553 struct sst_ssp_config {
554 	u8 ssp_id;
555 	u8 bits_per_slot;
556 	u8 slots;
557 	u8 ssp_mode;
558 	u8 pcm_mode;
559 	u8 duplex;
560 	u8 ssp_protocol;
561 	u8 fs_frequency;
562 	u8 active_slot_map;
563 	u8 start_delay;
564 	u16 fs_width;
565 	u8 frame_sync_polarity;
566 	u8 data_polarity;
567 };
568 
569 struct sst_ssp_cfg {
570 	const u8 ssp_number;
571 	const int *mux_shift;
572 	const int (*domain_shift)[SST_MAX_SSP_MUX];
573 	const struct sst_ssp_config (*ssp_config)[SST_MAX_SSP_MUX][SST_MAX_SSP_DOMAINS];
574 };
575 
576 struct sst_ids {
577 	u16 location_id;
578 	u16 module_id;
579 	u8  task_id;
580 	u8  format;
581 	u8  reg;
582 	const char *parent_wname;
583 	struct snd_soc_dapm_widget *parent_w;
584 	struct list_head algo_list;
585 	struct list_head gain_list;
586 	const struct sst_pcm_format *pcm_fmt;
587 };
588 
589 
590 #define SST_AIF_IN(wname, wevent)							\
591 {	.id = snd_soc_dapm_aif_in, .name = wname, .sname = NULL,			\
592 	.reg = SND_SOC_NOPM, .shift = 0,					\
593 	.on_val = 1, .off_val = 0,							\
594 	.event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,	\
595 	.priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }		\
596 }
597 
598 #define SST_AIF_OUT(wname, wevent)							\
599 {	.id = snd_soc_dapm_aif_out, .name = wname, .sname = NULL,			\
600 	.reg = SND_SOC_NOPM, .shift = 0,						\
601 	.on_val = 1, .off_val = 0,							\
602 	.event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,	\
603 	.priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }		\
604 }
605 
606 #define SST_INPUT(wname, wevent)							\
607 {	.id = snd_soc_dapm_input, .name = wname, .sname = NULL,				\
608 	.reg = SND_SOC_NOPM, .shift = 0,						\
609 	.on_val = 1, .off_val = 0,							\
610 	.event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,	\
611 	.priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }		\
612 }
613 
614 #define SST_OUTPUT(wname, wevent)							\
615 {	.id = snd_soc_dapm_output, .name = wname, .sname = NULL,			\
616 	.reg = SND_SOC_NOPM, .shift = 0,						\
617 	.on_val = 1, .off_val = 0,							\
618 	.event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,	\
619 	.priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }		\
620 }
621 
622 #define SST_DAPM_OUTPUT(wname, wloc_id, wtask_id, wformat, wevent)                      \
623 {	.id = snd_soc_dapm_output, .name = wname, .sname = NULL,                        \
624 	.reg = SND_SOC_NOPM, .shift = 0,						\
625 	.on_val = 1, .off_val = 0,							\
626 	.event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
627 	.priv = (void *)&(struct sst_ids) { .location_id = wloc_id, .task_id = wtask_id,\
628 						.pcm_fmt = wformat, }			\
629 }
630 
631 #define SST_PATH(wname, wtask, wloc_id, wevent, wflags)					\
632 {	.id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,		\
633 	.kcontrol_news = NULL, .num_kcontrols = 0,				\
634 	.on_val = 1, .off_val = 0,							\
635 	.event = wevent, .event_flags = wflags,						\
636 	.priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id, }	\
637 }
638 
639 #define SST_LINKED_PATH(wname, wtask, wloc_id, linked_wname, wevent, wflags)		\
640 {	.id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,		\
641 	.kcontrol_news = NULL, .num_kcontrols = 0,				\
642 	.on_val = 1, .off_val = 0,							\
643 	.event = wevent, .event_flags = wflags,						\
644 	.priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id,	\
645 					.parent_wname = linked_wname}			\
646 }
647 
648 #define SST_PATH_MEDIA_LOOP(wname, wtask, wloc_id, wformat, wevent, wflags)             \
649 {	.id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,         \
650 	.kcontrol_news = NULL, .num_kcontrols = 0,                         \
651 	.event = wevent, .event_flags = wflags,                                         \
652 	.priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id,	\
653 					    .format = wformat,}				\
654 }
655 
656 /* output is triggered before input */
657 #define SST_PATH_INPUT(name, task_id, loc_id, event)					\
658 	SST_PATH(name, task_id, loc_id, event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
659 
660 #define SST_PATH_LINKED_INPUT(name, task_id, loc_id, linked_wname, event)		\
661 	SST_LINKED_PATH(name, task_id, loc_id, linked_wname, event,			\
662 					SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
663 
664 #define SST_PATH_OUTPUT(name, task_id, loc_id, event)					\
665 	SST_PATH(name, task_id, loc_id, event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)
666 
667 #define SST_PATH_LINKED_OUTPUT(name, task_id, loc_id, linked_wname, event)		\
668 	SST_LINKED_PATH(name, task_id, loc_id, linked_wname, event,			\
669 					SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)
670 
671 #define SST_PATH_MEDIA_LOOP_OUTPUT(name, task_id, loc_id, format, event)		\
672 	SST_PATH_MEDIA_LOOP(name, task_id, loc_id, format, event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)
673 
674 
675 #define SST_SWM_MIXER(wname, wreg, wtask, wloc_id, wcontrols, wevent)			\
676 {	.id = snd_soc_dapm_mixer, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,	\
677 	.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols),\
678 	.event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD |	\
679 					SND_SOC_DAPM_POST_REG,				\
680 	.priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id,	\
681 					    .reg = wreg }				\
682 }
683 
684 enum sst_gain_kcontrol_type {
685 	SST_GAIN_TLV,
686 	SST_GAIN_MUTE,
687 	SST_GAIN_RAMP_DURATION,
688 };
689 
690 struct sst_gain_mixer_control {
691 	bool stereo;
692 	enum sst_gain_kcontrol_type type;
693 	struct sst_gain_value *gain_val;
694 	int max;
695 	int min;
696 	u16 instance_id;
697 	u16 module_id;
698 	u16 pipe_id;
699 	u16 task_id;
700 	char pname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
701 	struct snd_soc_dapm_widget *w;
702 };
703 
704 struct sst_gain_value {
705 	u16 ramp_duration;
706 	s16 l_gain;
707 	s16 r_gain;
708 	bool mute;
709 };
710 #define SST_GAIN_VOLUME_DEFAULT		(-1440)
711 #define SST_GAIN_RAMP_DURATION_DEFAULT	5 /* timeconstant */
712 #define SST_GAIN_MUTE_DEFAULT		true
713 
714 #define SST_GAIN_KCONTROL_TLV(xname, xhandler_get, xhandler_put, \
715 			      xmod, xpipe, xinstance, xtask, tlv_array, xgain_val, \
716 			      xmin, xmax, xpname) \
717 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
718 	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
719 		  SNDRV_CTL_ELEM_ACCESS_READWRITE, \
720 	.tlv.p = (tlv_array), \
721 	.info = sst_gain_ctl_info,\
722 	.get = xhandler_get, .put = xhandler_put, \
723 	.private_value = (unsigned long)&(struct sst_gain_mixer_control) \
724 	{ .stereo = true, .max = xmax, .min = xmin, .type = SST_GAIN_TLV, \
725 	  .module_id = xmod, .pipe_id = xpipe, .task_id = xtask,\
726 	  .instance_id = xinstance, .gain_val = xgain_val, .pname = xpname}
727 
728 #define SST_GAIN_KCONTROL_INT(xname, xhandler_get, xhandler_put, \
729 			      xmod, xpipe, xinstance, xtask, xtype, xgain_val, \
730 			      xmin, xmax, xpname) \
731 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
732 	.info = sst_gain_ctl_info, \
733 	.get = xhandler_get, .put = xhandler_put, \
734 	.private_value = (unsigned long)&(struct sst_gain_mixer_control) \
735 	{ .stereo = false, .max = xmax, .min = xmin, .type = xtype, \
736 	  .module_id = xmod, .pipe_id = xpipe, .task_id = xtask,\
737 	  .instance_id = xinstance, .gain_val = xgain_val, .pname =  xpname}
738 
739 #define SST_GAIN_KCONTROL_BOOL(xname, xhandler_get, xhandler_put,\
740 			       xmod, xpipe, xinstance, xtask, xgain_val, xpname) \
741 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
742 	.info = snd_soc_info_bool_ext, \
743 	.get = xhandler_get, .put = xhandler_put, \
744 	.private_value = (unsigned long)&(struct sst_gain_mixer_control) \
745 	{ .stereo = false, .type = SST_GAIN_MUTE, \
746 	  .module_id = xmod, .pipe_id = xpipe, .task_id = xtask,\
747 	  .instance_id = xinstance, .gain_val = xgain_val, .pname = xpname}
748 #define SST_CONTROL_NAME(xpname, xmname, xinstance, xtype) \
749 	xpname " " xmname " " #xinstance " " xtype
750 
751 #define SST_COMBO_CONTROL_NAME(xpname, xmname, xinstance, xtype, xsubmodule) \
752 	xpname " " xmname " " #xinstance " " xtype " " xsubmodule
753 
754 /*
755  * 3 Controls for each Gain module
756  * e.g.	- pcm0_in Gain 0 Volume
757  *	- pcm0_in Gain 0 Ramp Delay
758  *	- pcm0_in Gain 0 Switch
759  */
760 #define SST_GAIN_KCONTROLS(xpname, xmname, xmin_gain, xmax_gain, xmin_tc, xmax_tc, \
761 			   xhandler_get, xhandler_put, \
762 			   xmod, xpipe, xinstance, xtask, tlv_array, xgain_val) \
763 	{ SST_GAIN_KCONTROL_INT(SST_CONTROL_NAME(xpname, xmname, xinstance, "Ramp Delay"), \
764 		xhandler_get, xhandler_put, xmod, xpipe, xinstance, xtask, SST_GAIN_RAMP_DURATION, \
765 		xgain_val, xmin_tc, xmax_tc, xpname) }, \
766 	{ SST_GAIN_KCONTROL_BOOL(SST_CONTROL_NAME(xpname, xmname, xinstance, "Switch"), \
767 		xhandler_get, xhandler_put, xmod, xpipe, xinstance, xtask, \
768 		xgain_val, xpname) } ,\
769 	{ SST_GAIN_KCONTROL_TLV(SST_CONTROL_NAME(xpname, xmname, xinstance, "Volume"), \
770 		xhandler_get, xhandler_put, xmod, xpipe, xinstance, xtask, tlv_array, \
771 		xgain_val, xmin_gain, xmax_gain, xpname) }
772 
773 #define SST_GAIN_TC_MIN		5
774 #define SST_GAIN_TC_MAX		5000
775 #define SST_GAIN_MIN_VALUE	-1440 /* in 0.1 DB units */
776 #define SST_GAIN_MAX_VALUE	360
777 
778 enum sst_algo_kcontrol_type {
779 	SST_ALGO_PARAMS,
780 	SST_ALGO_BYPASS,
781 };
782 
783 struct sst_algo_control {
784 	enum sst_algo_kcontrol_type type;
785 	int max;
786 	u16 module_id;
787 	u16 pipe_id;
788 	u16 task_id;
789 	u16 cmd_id;
790 	bool bypass;
791 	unsigned char *params;
792 	struct snd_soc_dapm_widget *w;
793 };
794 
795 /* size of the control = size of params + size of length field */
796 #define SST_ALGO_CTL_VALUE(xcount, xtype, xpipe, xmod, xtask, xcmd)			\
797 	(struct sst_algo_control){							\
798 		.max = xcount + sizeof(u16), .type = xtype, .module_id = xmod,			\
799 		.pipe_id = xpipe, .task_id = xtask, .cmd_id = xcmd,			\
800 	}
801 
802 #define SST_ALGO_KCONTROL(xname, xcount, xmod, xpipe,					\
803 			  xtask, xcmd, xtype, xinfo, xget, xput)			\
804 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,						\
805 	.name =  xname,									\
806 	.info = xinfo, .get = xget, .put = xput,					\
807 	.private_value = (unsigned long)&						\
808 			SST_ALGO_CTL_VALUE(xcount, xtype, xpipe,			\
809 					   xmod, xtask, xcmd),				\
810 }
811 
812 #define SST_ALGO_KCONTROL_BYTES(xpname, xmname, xcount, xmod,				\
813 				xpipe, xinstance, xtask, xcmd)				\
814 	SST_ALGO_KCONTROL(SST_CONTROL_NAME(xpname, xmname, xinstance, "params"),	\
815 			  xcount, xmod, xpipe, xtask, xcmd, SST_ALGO_PARAMS,		\
816 			  sst_algo_bytes_ctl_info,					\
817 			  sst_algo_control_get, sst_algo_control_set)
818 
819 #define SST_ALGO_KCONTROL_BOOL(xpname, xmname, xmod, xpipe, xinstance, xtask)		\
820 	SST_ALGO_KCONTROL(SST_CONTROL_NAME(xpname, xmname, xinstance, "bypass"),	\
821 			  0, xmod, xpipe, xtask, 0, SST_ALGO_BYPASS,			\
822 			  snd_soc_info_bool_ext,					\
823 			  sst_algo_control_get, sst_algo_control_set)
824 
825 #define SST_ALGO_BYPASS_PARAMS(xpname, xmname, xcount, xmod, xpipe,			\
826 				xinstance, xtask, xcmd)					\
827 	SST_ALGO_KCONTROL_BOOL(xpname, xmname, xmod, xpipe, xinstance, xtask),		\
828 	SST_ALGO_KCONTROL_BYTES(xpname, xmname, xcount, xmod, xpipe, xinstance, xtask, xcmd)
829 
830 #define SST_COMBO_ALGO_KCONTROL_BYTES(xpname, xmname, xsubmod, xcount, xmod,		\
831 				      xpipe, xinstance, xtask, xcmd)			\
832 	SST_ALGO_KCONTROL(SST_COMBO_CONTROL_NAME(xpname, xmname, xinstance, "params",	\
833 						 xsubmod),				\
834 			  xcount, xmod, xpipe, xtask, xcmd, SST_ALGO_PARAMS,		\
835 			  sst_algo_bytes_ctl_info,					\
836 			  sst_algo_control_get, sst_algo_control_set)
837 
838 
839 struct sst_enum {
840 	bool tx;
841 	unsigned short reg;
842 	unsigned int max;
843 	const char * const *texts;
844 	struct snd_soc_dapm_widget *w;
845 };
846 
847 /* only 4 slots/channels supported atm */
848 #define SST_SSP_SLOT_ENUM(s_ch_no, is_tx, xtexts) \
849 	(struct sst_enum){ .reg = s_ch_no, .tx = is_tx, .max = 4+1, .texts = xtexts, }
850 
851 #define SST_SLOT_CTL_NAME(xpname, xmname, s_ch_name) \
852 	xpname " " xmname " " s_ch_name
853 
854 #define SST_SSP_SLOT_CTL(xpname, xmname, s_ch_name, s_ch_no, is_tx, xtexts, xget, xput) \
855 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
856 	.name = SST_SLOT_CTL_NAME(xpname, xmname, s_ch_name), \
857 	.info = sst_slot_enum_info, \
858 	.get = xget, .put = xput, \
859 	.private_value = (unsigned long)&SST_SSP_SLOT_ENUM(s_ch_no, is_tx, xtexts), \
860 }
861 
862 #define SST_MUX_CTL_NAME(xpname, xinstance) \
863 	xpname " " #xinstance
864 
865 #define SST_SSP_MUX_ENUM(xreg, xshift, xtexts) \
866 	(struct soc_enum) SOC_ENUM_DOUBLE(xreg, xshift, xshift, ARRAY_SIZE(xtexts), xtexts)
867 
868 #define SST_SSP_MUX_CTL(xpname, xinstance, xreg, xshift, xtexts) \
869 	SOC_DAPM_ENUM(SST_MUX_CTL_NAME(xpname, xinstance), \
870 			  SST_SSP_MUX_ENUM(xreg, xshift, xtexts))
871 
872 int sst_fill_ssp_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
873 				unsigned int rx_mask, int slots, int slot_width);
874 int sst_fill_ssp_config(struct snd_soc_dai *dai, unsigned int fmt);
875 void sst_fill_ssp_defaults(struct snd_soc_dai *dai);
876 
877 #endif
878