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