Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  *  sst-atom-controls.h - Intel MID Platform driver header file
0004  *
0005  *  Copyright (C) 2013-14 Intel Corp
0006  *  Author: Ramesh Babu <ramesh.babu.koul@intel.com>
0007  *      Omair M Abdullah <omair.m.abdullah@intel.com>
0008  *      Samreen Nilofer <samreen.nilofer@intel.com>
0009  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0010  *
0011  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0012  */
0013 
0014 #ifndef __SST_ATOM_CONTROLS_H__
0015 #define __SST_ATOM_CONTROLS_H__
0016 
0017 #include <sound/soc.h>
0018 #include <sound/tlv.h>
0019 
0020 enum {
0021     MERR_DPCM_AUDIO = 0,
0022     MERR_DPCM_DEEP_BUFFER,
0023     MERR_DPCM_COMPR,
0024 };
0025 
0026 /* define a bit for each mixer input */
0027 #define SST_MIX_IP(x)       (x)
0028 
0029 #define SST_IP_MODEM        SST_MIX_IP(0)
0030 #define SST_IP_BT       SST_MIX_IP(1)
0031 #define SST_IP_CODEC0       SST_MIX_IP(2)
0032 #define SST_IP_CODEC1       SST_MIX_IP(3)
0033 #define SST_IP_LOOP0        SST_MIX_IP(4)
0034 #define SST_IP_LOOP1        SST_MIX_IP(5)
0035 #define SST_IP_LOOP2        SST_MIX_IP(6)
0036 #define SST_IP_PROBE        SST_MIX_IP(7)
0037 #define SST_IP_VOIP     SST_MIX_IP(12)
0038 #define SST_IP_PCM0     SST_MIX_IP(13)
0039 #define SST_IP_PCM1     SST_MIX_IP(14)
0040 #define SST_IP_MEDIA0       SST_MIX_IP(17)
0041 #define SST_IP_MEDIA1       SST_MIX_IP(18)
0042 #define SST_IP_MEDIA2       SST_MIX_IP(19)
0043 #define SST_IP_MEDIA3       SST_MIX_IP(20)
0044 
0045 #define SST_IP_LAST     SST_IP_MEDIA3
0046 
0047 #define SST_SWM_INPUT_COUNT (SST_IP_LAST + 1)
0048 #define SST_CMD_SWM_MAX_INPUTS  6
0049 
0050 #define SST_PATH_ID_SHIFT   8
0051 #define SST_DEFAULT_LOCATION_ID 0xFFFF
0052 #define SST_DEFAULT_CELL_NBR    0xFF
0053 #define SST_DEFAULT_MODULE_ID   0xFFFF
0054 
0055 /*
0056  * Audio DSP Path Ids. Specified by the audio DSP FW
0057  */
0058 enum sst_path_index {
0059     SST_PATH_INDEX_MODEM_OUT                = (0x00 << SST_PATH_ID_SHIFT),
0060     SST_PATH_INDEX_CODEC_OUT0               = (0x02 << SST_PATH_ID_SHIFT),
0061     SST_PATH_INDEX_CODEC_OUT1               = (0x03 << SST_PATH_ID_SHIFT),
0062 
0063     SST_PATH_INDEX_SPROT_LOOP_OUT           = (0x04 << SST_PATH_ID_SHIFT),
0064     SST_PATH_INDEX_MEDIA_LOOP1_OUT          = (0x05 << SST_PATH_ID_SHIFT),
0065     SST_PATH_INDEX_MEDIA_LOOP2_OUT          = (0x06 << SST_PATH_ID_SHIFT),
0066 
0067     SST_PATH_INDEX_VOIP_OUT                 = (0x0C << SST_PATH_ID_SHIFT),
0068     SST_PATH_INDEX_PCM0_OUT                 = (0x0D << SST_PATH_ID_SHIFT),
0069     SST_PATH_INDEX_PCM1_OUT                 = (0x0E << SST_PATH_ID_SHIFT),
0070     SST_PATH_INDEX_PCM2_OUT                 = (0x0F << SST_PATH_ID_SHIFT),
0071 
0072     SST_PATH_INDEX_MEDIA0_OUT               = (0x12 << SST_PATH_ID_SHIFT),
0073     SST_PATH_INDEX_MEDIA1_OUT               = (0x13 << SST_PATH_ID_SHIFT),
0074 
0075 
0076     /* Start of input paths */
0077     SST_PATH_INDEX_MODEM_IN                 = (0x80 << SST_PATH_ID_SHIFT),
0078     SST_PATH_INDEX_CODEC_IN0                = (0x82 << SST_PATH_ID_SHIFT),
0079     SST_PATH_INDEX_CODEC_IN1                = (0x83 << SST_PATH_ID_SHIFT),
0080 
0081     SST_PATH_INDEX_SPROT_LOOP_IN            = (0x84 << SST_PATH_ID_SHIFT),
0082     SST_PATH_INDEX_MEDIA_LOOP1_IN           = (0x85 << SST_PATH_ID_SHIFT),
0083     SST_PATH_INDEX_MEDIA_LOOP2_IN           = (0x86 << SST_PATH_ID_SHIFT),
0084 
0085     SST_PATH_INDEX_VOIP_IN                  = (0x8C << SST_PATH_ID_SHIFT),
0086 
0087     SST_PATH_INDEX_PCM0_IN                  = (0x8D << SST_PATH_ID_SHIFT),
0088     SST_PATH_INDEX_PCM1_IN                  = (0x8E << SST_PATH_ID_SHIFT),
0089 
0090     SST_PATH_INDEX_MEDIA0_IN                = (0x8F << SST_PATH_ID_SHIFT),
0091     SST_PATH_INDEX_MEDIA1_IN                = (0x90 << SST_PATH_ID_SHIFT),
0092     SST_PATH_INDEX_MEDIA2_IN                = (0x91 << SST_PATH_ID_SHIFT),
0093 
0094     SST_PATH_INDEX_MEDIA3_IN        = (0x9C << SST_PATH_ID_SHIFT),
0095 
0096     SST_PATH_INDEX_RESERVED                 = (0xFF << SST_PATH_ID_SHIFT),
0097 };
0098 
0099 /*
0100  * path IDs
0101  */
0102 enum sst_swm_inputs {
0103     SST_SWM_IN_MODEM    = (SST_PATH_INDEX_MODEM_IN    | SST_DEFAULT_CELL_NBR),
0104     SST_SWM_IN_CODEC0   = (SST_PATH_INDEX_CODEC_IN0   | SST_DEFAULT_CELL_NBR),
0105     SST_SWM_IN_CODEC1   = (SST_PATH_INDEX_CODEC_IN1   | SST_DEFAULT_CELL_NBR),
0106     SST_SWM_IN_SPROT_LOOP   = (SST_PATH_INDEX_SPROT_LOOP_IN   | SST_DEFAULT_CELL_NBR),
0107     SST_SWM_IN_MEDIA_LOOP1  = (SST_PATH_INDEX_MEDIA_LOOP1_IN  | SST_DEFAULT_CELL_NBR),
0108     SST_SWM_IN_MEDIA_LOOP2  = (SST_PATH_INDEX_MEDIA_LOOP2_IN  | SST_DEFAULT_CELL_NBR),
0109     SST_SWM_IN_VOIP     = (SST_PATH_INDEX_VOIP_IN     | SST_DEFAULT_CELL_NBR),
0110     SST_SWM_IN_PCM0     = (SST_PATH_INDEX_PCM0_IN     | SST_DEFAULT_CELL_NBR),
0111     SST_SWM_IN_PCM1     = (SST_PATH_INDEX_PCM1_IN     | SST_DEFAULT_CELL_NBR),
0112     SST_SWM_IN_MEDIA0   = (SST_PATH_INDEX_MEDIA0_IN   | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
0113     SST_SWM_IN_MEDIA1   = (SST_PATH_INDEX_MEDIA1_IN   | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
0114     SST_SWM_IN_MEDIA2   = (SST_PATH_INDEX_MEDIA2_IN   | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
0115     SST_SWM_IN_MEDIA3   = (SST_PATH_INDEX_MEDIA3_IN   | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
0116     SST_SWM_IN_END      = (SST_PATH_INDEX_RESERVED    | SST_DEFAULT_CELL_NBR)
0117 };
0118 
0119 /*
0120  * path IDs
0121  */
0122 enum sst_swm_outputs {
0123     SST_SWM_OUT_MODEM   = (SST_PATH_INDEX_MODEM_OUT   | SST_DEFAULT_CELL_NBR),
0124     SST_SWM_OUT_CODEC0  = (SST_PATH_INDEX_CODEC_OUT0      | SST_DEFAULT_CELL_NBR),
0125     SST_SWM_OUT_CODEC1  = (SST_PATH_INDEX_CODEC_OUT1      | SST_DEFAULT_CELL_NBR),
0126     SST_SWM_OUT_SPROT_LOOP  = (SST_PATH_INDEX_SPROT_LOOP_OUT  | SST_DEFAULT_CELL_NBR),
0127     SST_SWM_OUT_MEDIA_LOOP1 = (SST_PATH_INDEX_MEDIA_LOOP1_OUT | SST_DEFAULT_CELL_NBR),
0128     SST_SWM_OUT_MEDIA_LOOP2 = (SST_PATH_INDEX_MEDIA_LOOP2_OUT | SST_DEFAULT_CELL_NBR),
0129     SST_SWM_OUT_VOIP    = (SST_PATH_INDEX_VOIP_OUT    | SST_DEFAULT_CELL_NBR),
0130     SST_SWM_OUT_PCM0    = (SST_PATH_INDEX_PCM0_OUT    | SST_DEFAULT_CELL_NBR),
0131     SST_SWM_OUT_PCM1    = (SST_PATH_INDEX_PCM1_OUT    | SST_DEFAULT_CELL_NBR),
0132     SST_SWM_OUT_PCM2    = (SST_PATH_INDEX_PCM2_OUT    | SST_DEFAULT_CELL_NBR),
0133     SST_SWM_OUT_MEDIA0  = (SST_PATH_INDEX_MEDIA0_OUT      | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
0134     SST_SWM_OUT_MEDIA1  = (SST_PATH_INDEX_MEDIA1_OUT      | SST_DEFAULT_CELL_NBR), /* Part of Media Mixer */
0135     SST_SWM_OUT_END     = (SST_PATH_INDEX_RESERVED    | SST_DEFAULT_CELL_NBR),
0136 };
0137 
0138 enum sst_ipc_msg {
0139     SST_IPC_IA_CMD = 1,
0140     SST_IPC_IA_SET_PARAMS,
0141     SST_IPC_IA_GET_PARAMS,
0142 };
0143 
0144 enum sst_cmd_type {
0145     SST_CMD_BYTES_SET = 1,
0146     SST_CMD_BYTES_GET = 2,
0147 };
0148 
0149 enum sst_task {
0150     SST_TASK_SBA = 1,
0151     SST_TASK_MMX = 3,
0152 };
0153 
0154 enum sst_type {
0155     SST_TYPE_CMD = 1,
0156     SST_TYPE_PARAMS,
0157 };
0158 
0159 enum sst_flag {
0160     SST_FLAG_BLOCKED = 1,
0161     SST_FLAG_NONBLOCK,
0162 };
0163 
0164 /*
0165  * Enumeration for indexing the gain cells in VB_SET_GAIN DSP command
0166  */
0167 enum sst_gain_index {
0168     /* GAIN IDs for SB task start here */
0169     SST_GAIN_INDEX_CODEC_OUT0,
0170     SST_GAIN_INDEX_CODEC_OUT1,
0171     SST_GAIN_INDEX_CODEC_IN0,
0172     SST_GAIN_INDEX_CODEC_IN1,
0173 
0174     SST_GAIN_INDEX_SPROT_LOOP_OUT,
0175     SST_GAIN_INDEX_MEDIA_LOOP1_OUT,
0176     SST_GAIN_INDEX_MEDIA_LOOP2_OUT,
0177 
0178     SST_GAIN_INDEX_PCM0_IN_LEFT,
0179     SST_GAIN_INDEX_PCM0_IN_RIGHT,
0180 
0181     SST_GAIN_INDEX_PCM1_OUT_LEFT,
0182     SST_GAIN_INDEX_PCM1_OUT_RIGHT,
0183     SST_GAIN_INDEX_PCM1_IN_LEFT,
0184     SST_GAIN_INDEX_PCM1_IN_RIGHT,
0185     SST_GAIN_INDEX_PCM2_OUT_LEFT,
0186 
0187     SST_GAIN_INDEX_PCM2_OUT_RIGHT,
0188     SST_GAIN_INDEX_VOIP_OUT,
0189     SST_GAIN_INDEX_VOIP_IN,
0190 
0191     /* Gain IDs for MMX task start here */
0192     SST_GAIN_INDEX_MEDIA0_IN_LEFT,
0193     SST_GAIN_INDEX_MEDIA0_IN_RIGHT,
0194     SST_GAIN_INDEX_MEDIA1_IN_LEFT,
0195     SST_GAIN_INDEX_MEDIA1_IN_RIGHT,
0196 
0197     SST_GAIN_INDEX_MEDIA2_IN_LEFT,
0198     SST_GAIN_INDEX_MEDIA2_IN_RIGHT,
0199 
0200     SST_GAIN_INDEX_GAIN_END
0201 };
0202 
0203 /*
0204  * Audio DSP module IDs specified by FW spec
0205  * TODO: Update with all modules
0206  */
0207 enum sst_module_id {
0208     SST_MODULE_ID_PCM         = 0x0001,
0209     SST_MODULE_ID_MP3         = 0x0002,
0210     SST_MODULE_ID_MP24        = 0x0003,
0211     SST_MODULE_ID_AAC         = 0x0004,
0212     SST_MODULE_ID_AACP        = 0x0005,
0213     SST_MODULE_ID_EAACP       = 0x0006,
0214     SST_MODULE_ID_WMA9        = 0x0007,
0215     SST_MODULE_ID_WMA10       = 0x0008,
0216     SST_MODULE_ID_WMA10P          = 0x0009,
0217     SST_MODULE_ID_RA          = 0x000A,
0218     SST_MODULE_ID_DDAC3       = 0x000B,
0219     SST_MODULE_ID_TRUE_HD         = 0x000C,
0220     SST_MODULE_ID_HD_PLUS         = 0x000D,
0221 
0222     SST_MODULE_ID_SRC         = 0x0064,
0223     SST_MODULE_ID_DOWNMIX         = 0x0066,
0224     SST_MODULE_ID_GAIN_CELL       = 0x0067,
0225     SST_MODULE_ID_SPROT       = 0x006D,
0226     SST_MODULE_ID_BASS_BOOST      = 0x006E,
0227     SST_MODULE_ID_STEREO_WDNG     = 0x006F,
0228     SST_MODULE_ID_AV_REMOVAL      = 0x0070,
0229     SST_MODULE_ID_MIC_EQ          = 0x0071,
0230     SST_MODULE_ID_SPL         = 0x0072,
0231     SST_MODULE_ID_ALGO_VTSV           = 0x0073,
0232     SST_MODULE_ID_NR          = 0x0076,
0233     SST_MODULE_ID_BWX         = 0x0077,
0234     SST_MODULE_ID_DRP         = 0x0078,
0235     SST_MODULE_ID_MDRP        = 0x0079,
0236 
0237     SST_MODULE_ID_ANA         = 0x007A,
0238     SST_MODULE_ID_AEC         = 0x007B,
0239     SST_MODULE_ID_NR_SNS          = 0x007C,
0240     SST_MODULE_ID_SER         = 0x007D,
0241     SST_MODULE_ID_AGC         = 0x007E,
0242 
0243     SST_MODULE_ID_CNI         = 0x007F,
0244     SST_MODULE_ID_CONTEXT_ALGO_AWARE  = 0x0080,
0245     SST_MODULE_ID_FIR_24          = 0x0081,
0246     SST_MODULE_ID_IIR_24          = 0x0082,
0247 
0248     SST_MODULE_ID_ASRC        = 0x0083,
0249     SST_MODULE_ID_TONE_GEN        = 0x0084,
0250     SST_MODULE_ID_BMF         = 0x0086,
0251     SST_MODULE_ID_EDL         = 0x0087,
0252     SST_MODULE_ID_GLC         = 0x0088,
0253 
0254     SST_MODULE_ID_FIR_16          = 0x0089,
0255     SST_MODULE_ID_IIR_16          = 0x008A,
0256     SST_MODULE_ID_DNR         = 0x008B,
0257 
0258     SST_MODULE_ID_VIRTUALIZER     = 0x008C,
0259     SST_MODULE_ID_VISUALIZATION   = 0x008D,
0260     SST_MODULE_ID_LOUDNESS_OPTIMIZER  = 0x008E,
0261     SST_MODULE_ID_REVERBERATION   = 0x008F,
0262 
0263     SST_MODULE_ID_CNI_TX          = 0x0090,
0264     SST_MODULE_ID_REF_LINE        = 0x0091,
0265     SST_MODULE_ID_VOLUME          = 0x0092,
0266     SST_MODULE_ID_FILT_DCR        = 0x0094,
0267     SST_MODULE_ID_SLV         = 0x009A,
0268     SST_MODULE_ID_NLF         = 0x009B,
0269     SST_MODULE_ID_TNR         = 0x009C,
0270     SST_MODULE_ID_WNR         = 0x009D,
0271 
0272     SST_MODULE_ID_LOG         = 0xFF00,
0273 
0274     SST_MODULE_ID_TASK        = 0xFFFF,
0275 };
0276 
0277 enum sst_cmd {
0278     SBA_IDLE        = 14,
0279     SBA_VB_SET_SPEECH_PATH  = 26,
0280     MMX_SET_GAIN        = 33,
0281     SBA_VB_SET_GAIN     = 33,
0282     FBA_VB_RX_CNI       = 35,
0283     MMX_SET_GAIN_TIMECONST  = 36,
0284     SBA_VB_SET_TIMECONST    = 36,
0285     SBA_VB_START        = 85,
0286     SBA_SET_SWM     = 114,
0287     SBA_SET_MDRP            = 116,
0288     SBA_HW_SET_SSP      = 117,
0289     SBA_SET_MEDIA_LOOP_MAP  = 118,
0290     SBA_SET_MEDIA_PATH  = 119,
0291     MMX_SET_MEDIA_PATH  = 119,
0292     SBA_VB_LPRO             = 126,
0293     SBA_VB_SET_FIR          = 128,
0294     SBA_VB_SET_IIR          = 129,
0295     SBA_SET_SSP_SLOT_MAP    = 130,
0296 };
0297 
0298 enum sst_dsp_switch {
0299     SST_SWITCH_OFF = 0,
0300     SST_SWITCH_ON = 3,
0301 };
0302 
0303 enum sst_path_switch {
0304     SST_PATH_OFF = 0,
0305     SST_PATH_ON = 1,
0306 };
0307 
0308 enum sst_swm_state {
0309     SST_SWM_OFF = 0,
0310     SST_SWM_ON = 3,
0311 };
0312 
0313 #define SST_FILL_LOCATION_IDS(dst, cell_idx, pipe_id)       do {    \
0314         dst.location_id.p.cell_nbr_idx = (cell_idx);        \
0315         dst.location_id.p.path_id = (pipe_id);          \
0316     } while (0)
0317 #define SST_FILL_LOCATION_ID(dst, loc_id)               (\
0318     dst.location_id.f = (loc_id))
0319 #define SST_FILL_MODULE_ID(dst, mod_id)                 (\
0320     dst.module_id = (mod_id))
0321 
0322 #define SST_FILL_DESTINATION1(dst, id)              do {    \
0323         SST_FILL_LOCATION_ID(dst, (id) & 0xFFFF);       \
0324         SST_FILL_MODULE_ID(dst, ((id) & 0xFFFF0000) >> 16); \
0325     } while (0)
0326 #define SST_FILL_DESTINATION2(dst, loc_id, mod_id)      do {    \
0327         SST_FILL_LOCATION_ID(dst, loc_id);          \
0328         SST_FILL_MODULE_ID(dst, mod_id);            \
0329     } while (0)
0330 #define SST_FILL_DESTINATION3(dst, cell_idx, path_id, mod_id)   do {    \
0331         SST_FILL_LOCATION_IDS(dst, cell_idx, path_id);      \
0332         SST_FILL_MODULE_ID(dst, mod_id);            \
0333     } while (0)
0334 
0335 #define SST_FILL_DESTINATION(level, dst, ...)               \
0336     SST_FILL_DESTINATION##level(dst, __VA_ARGS__)
0337 #define SST_FILL_DEFAULT_DESTINATION(dst)               \
0338     SST_FILL_DESTINATION(2, dst, SST_DEFAULT_LOCATION_ID, SST_DEFAULT_MODULE_ID)
0339 
0340 struct sst_destination_id {
0341     union sst_location_id {
0342         struct {
0343             u8 cell_nbr_idx;    /* module index */
0344             u8 path_id;     /* pipe_id */
0345         } __packed  p;      /* part */
0346         u16     f;      /* full */
0347     } __packed location_id;
0348     u16    module_id;
0349 } __packed;
0350 struct sst_dsp_header {
0351     struct sst_destination_id dst;
0352     u16 command_id;
0353     u16 length;
0354 } __packed;
0355 
0356 /*
0357  *
0358  * Common Commands
0359  *
0360  */
0361 struct sst_cmd_generic {
0362     struct sst_dsp_header header;
0363 } __packed;
0364 
0365 struct swm_input_ids {
0366     struct sst_destination_id input_id;
0367 } __packed;
0368 
0369 struct sst_cmd_set_swm {
0370     struct sst_dsp_header header;
0371     struct sst_destination_id output_id;
0372     u16    switch_state;
0373     u16    nb_inputs;
0374     struct swm_input_ids input[SST_CMD_SWM_MAX_INPUTS];
0375 } __packed;
0376 
0377 struct sst_cmd_set_media_path {
0378     struct sst_dsp_header header;
0379     u16    switch_state;
0380 } __packed;
0381 
0382 struct pcm_cfg {
0383         u8 s_length:2;
0384         u8 rate:3;
0385         u8 format:3;
0386 } __packed;
0387 
0388 struct sst_cmd_set_speech_path {
0389     struct sst_dsp_header header;
0390     u16    switch_state;
0391     struct {
0392         u16 rsvd:8;
0393         struct pcm_cfg cfg;
0394     } config;
0395 } __packed;
0396 
0397 struct gain_cell {
0398     struct sst_destination_id dest;
0399     s16 cell_gain_left;
0400     s16 cell_gain_right;
0401     u16 gain_time_constant;
0402 } __packed;
0403 
0404 #define NUM_GAIN_CELLS 1
0405 struct sst_cmd_set_gain_dual {
0406     struct sst_dsp_header header;
0407     u16    gain_cell_num;
0408     struct gain_cell cell_gains[NUM_GAIN_CELLS];
0409 } __packed;
0410 struct sst_cmd_set_params {
0411     struct sst_destination_id dst;
0412     u16 command_id;
0413     char params[];
0414 } __packed;
0415 
0416 
0417 struct sst_cmd_sba_vb_start {
0418     struct sst_dsp_header header;
0419 } __packed;
0420 
0421 union sba_media_loop_params {
0422     struct {
0423         u16 rsvd:8;
0424         struct pcm_cfg cfg;
0425     } part;
0426     u16 full;
0427 } __packed;
0428 
0429 struct sst_cmd_sba_set_media_loop_map {
0430     struct  sst_dsp_header header;
0431     u16 switch_state;
0432     union   sba_media_loop_params param;
0433     u16 map;
0434 } __packed;
0435 
0436 struct sst_cmd_tone_stop {
0437     struct  sst_dsp_header header;
0438     u16 switch_state;
0439 } __packed;
0440 
0441 enum sst_ssp_mode {
0442     SSP_MODE_PROVIDER = 0,
0443     SSP_MODE_CONSUMER = 1,
0444 };
0445 
0446 enum sst_ssp_pcm_mode {
0447     SSP_PCM_MODE_NORMAL = 0,
0448     SSP_PCM_MODE_NETWORK = 1,
0449 };
0450 
0451 enum sst_ssp_duplex {
0452     SSP_DUPLEX = 0,
0453     SSP_RX = 1,
0454     SSP_TX = 2,
0455 };
0456 
0457 enum sst_ssp_fs_frequency {
0458     SSP_FS_8_KHZ = 0,
0459     SSP_FS_16_KHZ = 1,
0460     SSP_FS_44_1_KHZ = 2,
0461     SSP_FS_48_KHZ = 3,
0462 };
0463 
0464 enum sst_ssp_fs_polarity {
0465     SSP_FS_ACTIVE_LOW = 0,
0466     SSP_FS_ACTIVE_HIGH = 1,
0467 };
0468 
0469 enum sst_ssp_protocol {
0470     SSP_MODE_PCM = 0,
0471     SSP_MODE_I2S = 1,
0472 };
0473 
0474 enum sst_ssp_port_id {
0475     SSP_MODEM = 0,
0476     SSP_BT = 1,
0477     SSP_FM = 2,
0478     SSP_CODEC = 3,
0479 };
0480 
0481 struct sst_cmd_sba_hw_set_ssp {
0482     struct sst_dsp_header header;
0483     u16 selection;          /* 0:SSP0(def), 1:SSP1, 2:SSP2 */
0484 
0485     u16 switch_state;
0486 
0487     u16 nb_bits_per_slots:6;        /* 0-32 bits, 24 (def) */
0488     u16 nb_slots:4;         /* 0-8: slots per frame  */
0489     u16 mode:3;         /* 0:Master, 1: Slave  */
0490     u16 duplex:3;
0491 
0492     u16 active_tx_slot_map:8;       /* Bit map, 0:off, 1:on */
0493     u16 reserved1:8;
0494 
0495     u16 active_rx_slot_map:8;       /* Bit map 0: Off, 1:On */
0496     u16 reserved2:8;
0497 
0498     u16 frame_sync_frequency;
0499 
0500     u16 frame_sync_polarity:8;
0501     u16 data_polarity:8;
0502 
0503     u16 frame_sync_width;           /* 1 to N clocks */
0504     u16 ssp_protocol:8;
0505     u16 start_delay:8;      /* Start delay in terms of clock ticks */
0506 } __packed;
0507 
0508 #define SST_MAX_TDM_SLOTS 8
0509 
0510 struct sst_param_sba_ssp_slot_map {
0511     struct sst_dsp_header header;
0512 
0513     u16 param_id;
0514     u16 param_len;
0515     u16 ssp_index;
0516 
0517     u8 rx_slot_map[SST_MAX_TDM_SLOTS];
0518     u8 tx_slot_map[SST_MAX_TDM_SLOTS];
0519 } __packed;
0520 
0521 enum {
0522     SST_PROBE_EXTRACTOR = 0,
0523     SST_PROBE_INJECTOR = 1,
0524 };
0525 
0526 /**** widget defines *****/
0527 
0528 #define SST_MODULE_GAIN 1
0529 #define SST_MODULE_ALGO 2
0530 
0531 #define SST_FMT_MONO 0
0532 #define SST_FMT_STEREO 3
0533 
0534 /* physical SSP numbers */
0535 enum {
0536     SST_SSP0 = 0,
0537     SST_SSP1,
0538     SST_SSP2,
0539     SST_SSP_LAST = SST_SSP2,
0540 };
0541 
0542 #define SST_NUM_SSPS        (SST_SSP_LAST + 1)  /* physical SSPs */
0543 #define SST_MAX_SSP_MUX     2           /* single SSP muxed between pipes */
0544 #define SST_MAX_SSP_DOMAINS 2           /* domains present in each pipe */
0545 
0546 struct sst_module {
0547     struct snd_kcontrol *kctl;
0548     struct list_head node;
0549 };
0550 
0551 struct sst_ssp_config {
0552     u8 ssp_id;
0553     u8 bits_per_slot;
0554     u8 slots;
0555     u8 ssp_mode;
0556     u8 pcm_mode;
0557     u8 duplex;
0558     u8 ssp_protocol;
0559     u8 fs_frequency;
0560     u8 active_slot_map;
0561     u8 start_delay;
0562     u16 fs_width;
0563     u8 frame_sync_polarity;
0564     u8 data_polarity;
0565 };
0566 
0567 struct sst_ssp_cfg {
0568     const u8 ssp_number;
0569     const int *mux_shift;
0570     const int (*domain_shift)[SST_MAX_SSP_MUX];
0571     const struct sst_ssp_config (*ssp_config)[SST_MAX_SSP_MUX][SST_MAX_SSP_DOMAINS];
0572 };
0573 
0574 struct sst_ids {
0575     u16 location_id;
0576     u16 module_id;
0577     u8  task_id;
0578     u8  format;
0579     u8  reg;
0580     const char *parent_wname;
0581     struct snd_soc_dapm_widget *parent_w;
0582     struct list_head algo_list;
0583     struct list_head gain_list;
0584     const struct sst_pcm_format *pcm_fmt;
0585 };
0586 
0587 
0588 #define SST_AIF_IN(wname, wevent)                           \
0589 {   .id = snd_soc_dapm_aif_in, .name = wname, .sname = NULL,            \
0590     .reg = SND_SOC_NOPM, .shift = 0,                    \
0591     .on_val = 1, .off_val = 0,                          \
0592     .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
0593     .priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }        \
0594 }
0595 
0596 #define SST_AIF_OUT(wname, wevent)                          \
0597 {   .id = snd_soc_dapm_aif_out, .name = wname, .sname = NULL,           \
0598     .reg = SND_SOC_NOPM, .shift = 0,                        \
0599     .on_val = 1, .off_val = 0,                          \
0600     .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
0601     .priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }        \
0602 }
0603 
0604 #define SST_INPUT(wname, wevent)                            \
0605 {   .id = snd_soc_dapm_input, .name = wname, .sname = NULL,             \
0606     .reg = SND_SOC_NOPM, .shift = 0,                        \
0607     .on_val = 1, .off_val = 0,                          \
0608     .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
0609     .priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }        \
0610 }
0611 
0612 #define SST_OUTPUT(wname, wevent)                           \
0613 {   .id = snd_soc_dapm_output, .name = wname, .sname = NULL,            \
0614     .reg = SND_SOC_NOPM, .shift = 0,                        \
0615     .on_val = 1, .off_val = 0,                          \
0616     .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
0617     .priv = (void *)&(struct sst_ids) { .task_id = 0, .location_id = 0 }        \
0618 }
0619 
0620 #define SST_DAPM_OUTPUT(wname, wloc_id, wtask_id, wformat, wevent)                      \
0621 {   .id = snd_soc_dapm_output, .name = wname, .sname = NULL,                        \
0622     .reg = SND_SOC_NOPM, .shift = 0,                        \
0623     .on_val = 1, .off_val = 0,                          \
0624     .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD,   \
0625     .priv = (void *)&(struct sst_ids) { .location_id = wloc_id, .task_id = wtask_id,\
0626                         .pcm_fmt = wformat, }           \
0627 }
0628 
0629 #define SST_PATH(wname, wtask, wloc_id, wevent, wflags)                 \
0630 {   .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,     \
0631     .kcontrol_news = NULL, .num_kcontrols = 0,              \
0632     .on_val = 1, .off_val = 0,                          \
0633     .event = wevent, .event_flags = wflags,                     \
0634     .priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id, } \
0635 }
0636 
0637 #define SST_LINKED_PATH(wname, wtask, wloc_id, linked_wname, wevent, wflags)        \
0638 {   .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,     \
0639     .kcontrol_news = NULL, .num_kcontrols = 0,              \
0640     .on_val = 1, .off_val = 0,                          \
0641     .event = wevent, .event_flags = wflags,                     \
0642     .priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id,   \
0643                     .parent_wname = linked_wname}           \
0644 }
0645 
0646 #define SST_PATH_MEDIA_LOOP(wname, wtask, wloc_id, wformat, wevent, wflags)             \
0647 {   .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,         \
0648     .kcontrol_news = NULL, .num_kcontrols = 0,                         \
0649     .event = wevent, .event_flags = wflags,                                         \
0650     .priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id,   \
0651                         .format = wformat,}             \
0652 }
0653 
0654 /* output is triggered before input */
0655 #define SST_PATH_INPUT(name, task_id, loc_id, event)                    \
0656     SST_PATH(name, task_id, loc_id, event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
0657 
0658 #define SST_PATH_LINKED_INPUT(name, task_id, loc_id, linked_wname, event)       \
0659     SST_LINKED_PATH(name, task_id, loc_id, linked_wname, event,         \
0660                     SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
0661 
0662 #define SST_PATH_OUTPUT(name, task_id, loc_id, event)                   \
0663     SST_PATH(name, task_id, loc_id, event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)
0664 
0665 #define SST_PATH_LINKED_OUTPUT(name, task_id, loc_id, linked_wname, event)      \
0666     SST_LINKED_PATH(name, task_id, loc_id, linked_wname, event,         \
0667                     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)
0668 
0669 #define SST_PATH_MEDIA_LOOP_OUTPUT(name, task_id, loc_id, format, event)        \
0670     SST_PATH_MEDIA_LOOP(name, task_id, loc_id, format, event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)
0671 
0672 
0673 #define SST_SWM_MIXER(wname, wreg, wtask, wloc_id, wcontrols, wevent)           \
0674 {   .id = snd_soc_dapm_mixer, .name = wname, .reg = SND_SOC_NOPM, .shift = 0,   \
0675     .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols),\
0676     .event = wevent, .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD |  \
0677                     SND_SOC_DAPM_POST_REG,              \
0678     .priv = (void *)&(struct sst_ids) { .task_id = wtask, .location_id = wloc_id,   \
0679                         .reg = wreg }               \
0680 }
0681 
0682 enum sst_gain_kcontrol_type {
0683     SST_GAIN_TLV,
0684     SST_GAIN_MUTE,
0685     SST_GAIN_RAMP_DURATION,
0686 };
0687 
0688 struct sst_gain_mixer_control {
0689     bool stereo;
0690     enum sst_gain_kcontrol_type type;
0691     struct sst_gain_value *gain_val;
0692     int max;
0693     int min;
0694     u16 instance_id;
0695     u16 module_id;
0696     u16 pipe_id;
0697     u16 task_id;
0698     char pname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
0699     struct snd_soc_dapm_widget *w;
0700 };
0701 
0702 struct sst_gain_value {
0703     u16 ramp_duration;
0704     s16 l_gain;
0705     s16 r_gain;
0706     bool mute;
0707 };
0708 #define SST_GAIN_VOLUME_DEFAULT     (-1440)
0709 #define SST_GAIN_RAMP_DURATION_DEFAULT  5 /* timeconstant */
0710 #define SST_GAIN_MUTE_DEFAULT       true
0711 
0712 #define SST_GAIN_KCONTROL_TLV(xname, xhandler_get, xhandler_put, \
0713                   xmod, xpipe, xinstance, xtask, tlv_array, xgain_val, \
0714                   xmin, xmax, xpname) \
0715     .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
0716     .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
0717           SNDRV_CTL_ELEM_ACCESS_READWRITE, \
0718     .tlv.p = (tlv_array), \
0719     .info = sst_gain_ctl_info,\
0720     .get = xhandler_get, .put = xhandler_put, \
0721     .private_value = (unsigned long)&(struct sst_gain_mixer_control) \
0722     { .stereo = true, .max = xmax, .min = xmin, .type = SST_GAIN_TLV, \
0723       .module_id = xmod, .pipe_id = xpipe, .task_id = xtask,\
0724       .instance_id = xinstance, .gain_val = xgain_val, .pname = xpname}
0725 
0726 #define SST_GAIN_KCONTROL_INT(xname, xhandler_get, xhandler_put, \
0727                   xmod, xpipe, xinstance, xtask, xtype, xgain_val, \
0728                   xmin, xmax, xpname) \
0729     .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
0730     .info = sst_gain_ctl_info, \
0731     .get = xhandler_get, .put = xhandler_put, \
0732     .private_value = (unsigned long)&(struct sst_gain_mixer_control) \
0733     { .stereo = false, .max = xmax, .min = xmin, .type = xtype, \
0734       .module_id = xmod, .pipe_id = xpipe, .task_id = xtask,\
0735       .instance_id = xinstance, .gain_val = xgain_val, .pname =  xpname}
0736 
0737 #define SST_GAIN_KCONTROL_BOOL(xname, xhandler_get, xhandler_put,\
0738                    xmod, xpipe, xinstance, xtask, xgain_val, xpname) \
0739     .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
0740     .info = snd_soc_info_bool_ext, \
0741     .get = xhandler_get, .put = xhandler_put, \
0742     .private_value = (unsigned long)&(struct sst_gain_mixer_control) \
0743     { .stereo = false, .type = SST_GAIN_MUTE, \
0744       .module_id = xmod, .pipe_id = xpipe, .task_id = xtask,\
0745       .instance_id = xinstance, .gain_val = xgain_val, .pname = xpname}
0746 #define SST_CONTROL_NAME(xpname, xmname, xinstance, xtype) \
0747     xpname " " xmname " " #xinstance " " xtype
0748 
0749 #define SST_COMBO_CONTROL_NAME(xpname, xmname, xinstance, xtype, xsubmodule) \
0750     xpname " " xmname " " #xinstance " " xtype " " xsubmodule
0751 
0752 /*
0753  * 3 Controls for each Gain module
0754  * e.g. - pcm0_in Gain 0 Volume
0755  *  - pcm0_in Gain 0 Ramp Delay
0756  *  - pcm0_in Gain 0 Switch
0757  */
0758 #define SST_GAIN_KCONTROLS(xpname, xmname, xmin_gain, xmax_gain, xmin_tc, xmax_tc, \
0759                xhandler_get, xhandler_put, \
0760                xmod, xpipe, xinstance, xtask, tlv_array, xgain_val) \
0761     { SST_GAIN_KCONTROL_INT(SST_CONTROL_NAME(xpname, xmname, xinstance, "Ramp Delay"), \
0762         xhandler_get, xhandler_put, xmod, xpipe, xinstance, xtask, SST_GAIN_RAMP_DURATION, \
0763         xgain_val, xmin_tc, xmax_tc, xpname) }, \
0764     { SST_GAIN_KCONTROL_BOOL(SST_CONTROL_NAME(xpname, xmname, xinstance, "Switch"), \
0765         xhandler_get, xhandler_put, xmod, xpipe, xinstance, xtask, \
0766         xgain_val, xpname) } ,\
0767     { SST_GAIN_KCONTROL_TLV(SST_CONTROL_NAME(xpname, xmname, xinstance, "Volume"), \
0768         xhandler_get, xhandler_put, xmod, xpipe, xinstance, xtask, tlv_array, \
0769         xgain_val, xmin_gain, xmax_gain, xpname) }
0770 
0771 #define SST_GAIN_TC_MIN     5
0772 #define SST_GAIN_TC_MAX     5000
0773 #define SST_GAIN_MIN_VALUE  -1440 /* in 0.1 DB units */
0774 #define SST_GAIN_MAX_VALUE  360
0775 
0776 enum sst_algo_kcontrol_type {
0777     SST_ALGO_PARAMS,
0778     SST_ALGO_BYPASS,
0779 };
0780 
0781 struct sst_algo_control {
0782     enum sst_algo_kcontrol_type type;
0783     int max;
0784     u16 module_id;
0785     u16 pipe_id;
0786     u16 task_id;
0787     u16 cmd_id;
0788     bool bypass;
0789     unsigned char *params;
0790     struct snd_soc_dapm_widget *w;
0791 };
0792 
0793 /* size of the control = size of params + size of length field */
0794 #define SST_ALGO_CTL_VALUE(xcount, xtype, xpipe, xmod, xtask, xcmd)         \
0795     (struct sst_algo_control){                          \
0796         .max = xcount + sizeof(u16), .type = xtype, .module_id = xmod,          \
0797         .pipe_id = xpipe, .task_id = xtask, .cmd_id = xcmd,         \
0798     }
0799 
0800 #define SST_ALGO_KCONTROL(xname, xcount, xmod, xpipe,                   \
0801               xtask, xcmd, xtype, xinfo, xget, xput)            \
0802 {   .iface = SNDRV_CTL_ELEM_IFACE_MIXER,                        \
0803     .name =  xname,                                 \
0804     .info = xinfo, .get = xget, .put = xput,                    \
0805     .private_value = (unsigned long)&                       \
0806             SST_ALGO_CTL_VALUE(xcount, xtype, xpipe,            \
0807                        xmod, xtask, xcmd),              \
0808 }
0809 
0810 #define SST_ALGO_KCONTROL_BYTES(xpname, xmname, xcount, xmod,               \
0811                 xpipe, xinstance, xtask, xcmd)              \
0812     SST_ALGO_KCONTROL(SST_CONTROL_NAME(xpname, xmname, xinstance, "params"),    \
0813               xcount, xmod, xpipe, xtask, xcmd, SST_ALGO_PARAMS,        \
0814               sst_algo_bytes_ctl_info,                  \
0815               sst_algo_control_get, sst_algo_control_set)
0816 
0817 #define SST_ALGO_KCONTROL_BOOL(xpname, xmname, xmod, xpipe, xinstance, xtask)       \
0818     SST_ALGO_KCONTROL(SST_CONTROL_NAME(xpname, xmname, xinstance, "bypass"),    \
0819               0, xmod, xpipe, xtask, 0, SST_ALGO_BYPASS,            \
0820               snd_soc_info_bool_ext,                    \
0821               sst_algo_control_get, sst_algo_control_set)
0822 
0823 #define SST_ALGO_BYPASS_PARAMS(xpname, xmname, xcount, xmod, xpipe,         \
0824                 xinstance, xtask, xcmd)                 \
0825     SST_ALGO_KCONTROL_BOOL(xpname, xmname, xmod, xpipe, xinstance, xtask),      \
0826     SST_ALGO_KCONTROL_BYTES(xpname, xmname, xcount, xmod, xpipe, xinstance, xtask, xcmd)
0827 
0828 #define SST_COMBO_ALGO_KCONTROL_BYTES(xpname, xmname, xsubmod, xcount, xmod,        \
0829                       xpipe, xinstance, xtask, xcmd)            \
0830     SST_ALGO_KCONTROL(SST_COMBO_CONTROL_NAME(xpname, xmname, xinstance, "params",   \
0831                          xsubmod),              \
0832               xcount, xmod, xpipe, xtask, xcmd, SST_ALGO_PARAMS,        \
0833               sst_algo_bytes_ctl_info,                  \
0834               sst_algo_control_get, sst_algo_control_set)
0835 
0836 
0837 struct sst_enum {
0838     bool tx;
0839     unsigned short reg;
0840     unsigned int max;
0841     const char * const *texts;
0842     struct snd_soc_dapm_widget *w;
0843 };
0844 
0845 /* only 4 slots/channels supported atm */
0846 #define SST_SSP_SLOT_ENUM(s_ch_no, is_tx, xtexts) \
0847     (struct sst_enum){ .reg = s_ch_no, .tx = is_tx, .max = 4+1, .texts = xtexts, }
0848 
0849 #define SST_SLOT_CTL_NAME(xpname, xmname, s_ch_name) \
0850     xpname " " xmname " " s_ch_name
0851 
0852 #define SST_SSP_SLOT_CTL(xpname, xmname, s_ch_name, s_ch_no, is_tx, xtexts, xget, xput) \
0853 {   .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
0854     .name = SST_SLOT_CTL_NAME(xpname, xmname, s_ch_name), \
0855     .info = sst_slot_enum_info, \
0856     .get = xget, .put = xput, \
0857     .private_value = (unsigned long)&SST_SSP_SLOT_ENUM(s_ch_no, is_tx, xtexts), \
0858 }
0859 
0860 #define SST_MUX_CTL_NAME(xpname, xinstance) \
0861     xpname " " #xinstance
0862 
0863 #define SST_SSP_MUX_ENUM(xreg, xshift, xtexts) \
0864     (struct soc_enum) SOC_ENUM_DOUBLE(xreg, xshift, xshift, ARRAY_SIZE(xtexts), xtexts)
0865 
0866 #define SST_SSP_MUX_CTL(xpname, xinstance, xreg, xshift, xtexts) \
0867     SOC_DAPM_ENUM(SST_MUX_CTL_NAME(xpname, xinstance), \
0868               SST_SSP_MUX_ENUM(xreg, xshift, xtexts))
0869 
0870 int sst_fill_ssp_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
0871                 unsigned int rx_mask, int slots, int slot_width);
0872 int sst_fill_ssp_config(struct snd_soc_dai *dai, unsigned int fmt);
0873 void sst_fill_ssp_defaults(struct snd_soc_dai *dai);
0874 
0875 #endif