2 * sst-atom-controls.c - Intel MID Platform driver DPCM ALSA controls for Mrfld
4 * Copyright (C) 2013-14 Intel Corp
5 * Author: Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
6 * Vinod Koul <vinod.koul@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * In the dpcm driver modelling when a particular FE/BE/Mixer/Pipe is active
19 * we forward the settings and parameters, rest we keep the values in
20 * driver and forward when DAPM enables them
21 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25 #include <linux/slab.h>
26 #include <sound/soc.h>
27 #include <sound/tlv.h>
28 #include "sst-mfld-platform.h"
29 #include "sst-atom-controls.h"
31 static int sst_fill_byte_control(struct sst_data
*drv
,
33 u8 task_id
, u8 pipe_id
,
34 u16 len
, void *cmd_data
)
36 struct snd_sst_bytes_v2
*byte_data
= drv
->byte_stream
;
38 byte_data
->type
= SST_CMD_BYTES_SET
;
39 byte_data
->ipc_msg
= ipc_msg
;
40 byte_data
->block
= block
;
41 byte_data
->task_id
= task_id
;
42 byte_data
->pipe_id
= pipe_id
;
44 if (len
> SST_MAX_BIN_BYTES
- sizeof(*byte_data
)) {
45 dev_err(&drv
->pdev
->dev
, "command length too big (%u)", len
);
49 memcpy(byte_data
->bytes
, cmd_data
, len
);
50 print_hex_dump_bytes("writing to lpe: ", DUMP_PREFIX_OFFSET
,
51 byte_data
, len
+ sizeof(*byte_data
));
55 static int sst_fill_and_send_cmd_unlocked(struct sst_data
*drv
,
56 u8 ipc_msg
, u8 block
, u8 task_id
, u8 pipe_id
,
57 void *cmd_data
, u16 len
)
61 ret
= sst_fill_byte_control(drv
, ipc_msg
,
62 block
, task_id
, pipe_id
, len
, cmd_data
);
65 return sst
->ops
->send_byte_stream(sst
->dev
, drv
->byte_stream
);
69 * sst_fill_and_send_cmd - generate the IPC message and send it to the FW
70 * @ipc_msg: type of IPC (CMD, SET_PARAMS, GET_PARAMS)
71 * @cmd_data: the IPC payload
73 static int sst_fill_and_send_cmd(struct sst_data
*drv
,
74 u8 ipc_msg
, u8 block
, u8 task_id
, u8 pipe_id
,
75 void *cmd_data
, u16 len
)
79 mutex_lock(&drv
->lock
);
80 ret
= sst_fill_and_send_cmd_unlocked(drv
, ipc_msg
, block
,
81 task_id
, pipe_id
, cmd_data
, len
);
82 mutex_unlock(&drv
->lock
);
88 * tx map value is a bitfield where each bit represents a FW channel
90 * 3 2 1 0 # 0 = codec0, 1 = codec1
91 * RLRLRLRL # 3, 4 = reserved
93 * e.g. slot 0 rx map = 00001100b -> data from slot 0 goes into codec_in1 L,R
95 static u8 sst_ssp_tx_map
[SST_MAX_TDM_SLOTS
] = {
96 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, /* default rx map */
100 * rx map value is a bitfield where each bit represents a slot
102 * 76543210 # 0 = slot 0, 1 = slot 1
104 * e.g. codec1_0 tx map = 00000101b -> data from codec_out1_0 goes into slot 0, 2
106 static u8 sst_ssp_rx_map
[SST_MAX_TDM_SLOTS
] = {
107 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, /* default tx map */
111 * NOTE: this is invoked with lock held
113 static int sst_send_slot_map(struct sst_data
*drv
)
115 struct sst_param_sba_ssp_slot_map cmd
;
117 SST_FILL_DEFAULT_DESTINATION(cmd
.header
.dst
);
118 cmd
.header
.command_id
= SBA_SET_SSP_SLOT_MAP
;
119 cmd
.header
.length
= sizeof(struct sst_param_sba_ssp_slot_map
)
120 - sizeof(struct sst_dsp_header
);
122 cmd
.param_id
= SBA_SET_SSP_SLOT_MAP
;
123 cmd
.param_len
= sizeof(cmd
.rx_slot_map
) + sizeof(cmd
.tx_slot_map
)
124 + sizeof(cmd
.ssp_index
);
125 cmd
.ssp_index
= SSP_CODEC
;
127 memcpy(cmd
.rx_slot_map
, &sst_ssp_tx_map
[0], sizeof(cmd
.rx_slot_map
));
128 memcpy(cmd
.tx_slot_map
, &sst_ssp_rx_map
[0], sizeof(cmd
.tx_slot_map
));
130 return sst_fill_and_send_cmd_unlocked(drv
, SST_IPC_IA_SET_PARAMS
,
131 SST_FLAG_BLOCKED
, SST_TASK_SBA
, 0, &cmd
,
132 sizeof(cmd
.header
) + cmd
.header
.length
);
135 static int sst_slot_enum_info(struct snd_kcontrol
*kcontrol
,
136 struct snd_ctl_elem_info
*uinfo
)
138 struct sst_enum
*e
= (struct sst_enum
*)kcontrol
->private_value
;
140 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_ENUMERATED
;
142 uinfo
->value
.enumerated
.items
= e
->max
;
144 if (uinfo
->value
.enumerated
.item
> e
->max
- 1)
145 uinfo
->value
.enumerated
.item
= e
->max
- 1;
146 strcpy(uinfo
->value
.enumerated
.name
,
147 e
->texts
[uinfo
->value
.enumerated
.item
]);
153 * sst_slot_get - get the status of the interleaver/deinterleaver control
155 * Searches the map where the control status is stored, and gets the
156 * channel/slot which is currently set for this enumerated control. Since it is
157 * an enumerated control, there is only one possible value.
159 static int sst_slot_get(struct snd_kcontrol
*kcontrol
,
160 struct snd_ctl_elem_value
*ucontrol
)
162 struct sst_enum
*e
= (void *)kcontrol
->private_value
;
163 struct snd_soc_component
*c
= snd_kcontrol_chip(kcontrol
);
164 struct sst_data
*drv
= snd_soc_component_get_drvdata(c
);
165 unsigned int ctl_no
= e
->reg
;
166 unsigned int is_tx
= e
->tx
;
167 unsigned int val
, mux
;
168 u8
*map
= is_tx
? sst_ssp_rx_map
: sst_ssp_tx_map
;
170 mutex_lock(&drv
->lock
);
172 /* search which slot/channel has this bit set - there should be only one */
173 for (mux
= e
->max
; mux
> 0; mux
--)
174 if (map
[mux
- 1] & val
)
177 ucontrol
->value
.enumerated
.item
[0] = mux
;
178 mutex_unlock(&drv
->lock
);
180 dev_dbg(c
->dev
, "%s - %s map = %#x\n",
181 is_tx
? "tx channel" : "rx slot",
182 e
->texts
[mux
], mux
? map
[mux
- 1] : -1);
186 /* sst_check_and_send_slot_map - helper for checking power state and sending
189 * called with lock held
191 static int sst_check_and_send_slot_map(struct sst_data
*drv
, struct snd_kcontrol
*kcontrol
)
193 struct sst_enum
*e
= (void *)kcontrol
->private_value
;
196 if (e
->w
&& e
->w
->power
)
197 ret
= sst_send_slot_map(drv
);
199 dev_err(&drv
->pdev
->dev
, "Slot control: %s doesn't have DAPM widget!!!\n",
205 * sst_slot_put - set the status of interleaver/deinterleaver control
207 * (de)interleaver controls are defined in opposite sense to be user-friendly
209 * Instead of the enum value being the value written to the register, it is the
210 * register address; and the kcontrol number (register num) is the value written
211 * to the register. This is so that there can be only one value for each
212 * slot/channel since there is only one control for each slot/channel.
214 * This means that whenever an enum is set, we need to clear the bit
215 * for that kcontrol_no for all the interleaver OR deinterleaver registers
217 static int sst_slot_put(struct snd_kcontrol
*kcontrol
,
218 struct snd_ctl_elem_value
*ucontrol
)
220 struct snd_soc_component
*c
= snd_soc_kcontrol_component(kcontrol
);
221 struct sst_data
*drv
= snd_soc_component_get_drvdata(c
);
222 struct sst_enum
*e
= (void *)kcontrol
->private_value
;
224 unsigned int ctl_no
= e
->reg
;
225 unsigned int is_tx
= e
->tx
;
226 unsigned int slot_channel_no
;
227 unsigned int val
, mux
;
230 map
= is_tx
? sst_ssp_rx_map
: sst_ssp_tx_map
;
233 mux
= ucontrol
->value
.enumerated
.item
[0];
234 if (mux
> e
->max
- 1)
237 mutex_lock(&drv
->lock
);
238 /* first clear all registers of this bit */
239 for (i
= 0; i
< e
->max
; i
++)
243 /* kctl set to 'none' and we reset the bits so send IPC */
244 ret
= sst_check_and_send_slot_map(drv
, kcontrol
);
246 mutex_unlock(&drv
->lock
);
250 /* offset by one to take "None" into account */
251 slot_channel_no
= mux
- 1;
252 map
[slot_channel_no
] |= val
;
254 dev_dbg(c
->dev
, "%s %s map = %#x\n",
255 is_tx
? "tx channel" : "rx slot",
256 e
->texts
[mux
], map
[slot_channel_no
]);
258 ret
= sst_check_and_send_slot_map(drv
, kcontrol
);
260 mutex_unlock(&drv
->lock
);
264 static int sst_send_algo_cmd(struct sst_data
*drv
,
265 struct sst_algo_control
*bc
)
268 struct sst_cmd_set_params
*cmd
;
270 /*bc->max includes sizeof algos + length field*/
271 len
= sizeof(cmd
->dst
) + sizeof(cmd
->command_id
) + bc
->max
;
273 cmd
= kzalloc(len
, GFP_KERNEL
);
277 SST_FILL_DESTINATION(2, cmd
->dst
, bc
->pipe_id
, bc
->module_id
);
278 cmd
->command_id
= bc
->cmd_id
;
279 memcpy(cmd
->params
, bc
->params
, bc
->max
);
281 ret
= sst_fill_and_send_cmd_unlocked(drv
, SST_IPC_IA_SET_PARAMS
,
282 SST_FLAG_BLOCKED
, bc
->task_id
, 0, cmd
, len
);
288 * sst_find_and_send_pipe_algo - send all the algo parameters for a pipe
290 * The algos which are in each pipeline are sent to the firmware one by one
292 * Called with lock held
294 static int sst_find_and_send_pipe_algo(struct sst_data
*drv
,
295 const char *pipe
, struct sst_ids
*ids
)
298 struct sst_algo_control
*bc
;
299 struct sst_module
*algo
= NULL
;
301 dev_dbg(&drv
->pdev
->dev
, "Enter: widget=%s\n", pipe
);
303 list_for_each_entry(algo
, &ids
->algo_list
, node
) {
304 bc
= (void *)algo
->kctl
->private_value
;
306 dev_dbg(&drv
->pdev
->dev
, "Found algo control name=%s pipe=%s\n",
307 algo
->kctl
->id
.name
, pipe
);
308 ret
= sst_send_algo_cmd(drv
, bc
);
315 static int sst_algo_bytes_ctl_info(struct snd_kcontrol
*kcontrol
,
316 struct snd_ctl_elem_info
*uinfo
)
318 struct sst_algo_control
*bc
= (void *)kcontrol
->private_value
;
320 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BYTES
;
321 uinfo
->count
= bc
->max
;
326 static int sst_algo_control_get(struct snd_kcontrol
*kcontrol
,
327 struct snd_ctl_elem_value
*ucontrol
)
329 struct sst_algo_control
*bc
= (void *)kcontrol
->private_value
;
330 struct snd_soc_component
*component
= snd_kcontrol_chip(kcontrol
);
333 case SST_ALGO_PARAMS
:
334 memcpy(ucontrol
->value
.bytes
.data
, bc
->params
, bc
->max
);
337 dev_err(component
->dev
, "Invalid Input- algo type:%d\n",
345 static int sst_algo_control_set(struct snd_kcontrol
*kcontrol
,
346 struct snd_ctl_elem_value
*ucontrol
)
349 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
350 struct sst_data
*drv
= snd_soc_component_get_drvdata(cmpnt
);
351 struct sst_algo_control
*bc
= (void *)kcontrol
->private_value
;
353 dev_dbg(cmpnt
->dev
, "control_name=%s\n", kcontrol
->id
.name
);
354 mutex_lock(&drv
->lock
);
356 case SST_ALGO_PARAMS
:
357 memcpy(bc
->params
, ucontrol
->value
.bytes
.data
, bc
->max
);
360 mutex_unlock(&drv
->lock
);
361 dev_err(cmpnt
->dev
, "Invalid Input- algo type:%d\n",
365 /*if pipe is enabled, need to send the algo params from here*/
366 if (bc
->w
&& bc
->w
->power
)
367 ret
= sst_send_algo_cmd(drv
, bc
);
368 mutex_unlock(&drv
->lock
);
373 static int sst_gain_ctl_info(struct snd_kcontrol
*kcontrol
,
374 struct snd_ctl_elem_info
*uinfo
)
376 struct sst_gain_mixer_control
*mc
= (void *)kcontrol
->private_value
;
378 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
379 uinfo
->count
= mc
->stereo
? 2 : 1;
380 uinfo
->value
.integer
.min
= mc
->min
;
381 uinfo
->value
.integer
.max
= mc
->max
;
387 * sst_send_gain_cmd - send the gain algorithm IPC to the FW
388 * @gv: the stored value of gain (also contains rampduration)
389 * @mute: flag that indicates whether this was called from the
390 * digital_mute callback or directly. If called from the
391 * digital_mute callback, module will be muted/unmuted based on this
392 * flag. The flag is always 0 if called directly.
394 * Called with sst_data.lock held
396 * The user-set gain value is sent only if the user-controllable 'mute' control
397 * is OFF (indicated by gv->mute). Otherwise, the mute value (MIN value) is
400 static int sst_send_gain_cmd(struct sst_data
*drv
, struct sst_gain_value
*gv
,
401 u16 task_id
, u16 loc_id
, u16 module_id
, int mute
)
403 struct sst_cmd_set_gain_dual cmd
;
405 dev_dbg(&drv
->pdev
->dev
, "Enter\n");
407 cmd
.header
.command_id
= MMX_SET_GAIN
;
408 SST_FILL_DEFAULT_DESTINATION(cmd
.header
.dst
);
409 cmd
.gain_cell_num
= 1;
411 if (mute
|| gv
->mute
) {
412 cmd
.cell_gains
[0].cell_gain_left
= SST_GAIN_MIN_VALUE
;
413 cmd
.cell_gains
[0].cell_gain_right
= SST_GAIN_MIN_VALUE
;
415 cmd
.cell_gains
[0].cell_gain_left
= gv
->l_gain
;
416 cmd
.cell_gains
[0].cell_gain_right
= gv
->r_gain
;
419 SST_FILL_DESTINATION(2, cmd
.cell_gains
[0].dest
,
421 cmd
.cell_gains
[0].gain_time_constant
= gv
->ramp_duration
;
423 cmd
.header
.length
= sizeof(struct sst_cmd_set_gain_dual
)
424 - sizeof(struct sst_dsp_header
);
426 /* we are with lock held, so call the unlocked api to send */
427 return sst_fill_and_send_cmd_unlocked(drv
, SST_IPC_IA_SET_PARAMS
,
428 SST_FLAG_BLOCKED
, task_id
, 0, &cmd
,
429 sizeof(cmd
.header
) + cmd
.header
.length
);
432 static int sst_gain_get(struct snd_kcontrol
*kcontrol
,
433 struct snd_ctl_elem_value
*ucontrol
)
435 struct snd_soc_component
*component
= snd_kcontrol_chip(kcontrol
);
436 struct sst_gain_mixer_control
*mc
= (void *)kcontrol
->private_value
;
437 struct sst_gain_value
*gv
= mc
->gain_val
;
441 ucontrol
->value
.integer
.value
[0] = gv
->l_gain
;
442 ucontrol
->value
.integer
.value
[1] = gv
->r_gain
;
446 ucontrol
->value
.integer
.value
[0] = gv
->mute
? 0 : 1;
449 case SST_GAIN_RAMP_DURATION
:
450 ucontrol
->value
.integer
.value
[0] = gv
->ramp_duration
;
454 dev_err(component
->dev
, "Invalid Input- gain type:%d\n",
462 static int sst_gain_put(struct snd_kcontrol
*kcontrol
,
463 struct snd_ctl_elem_value
*ucontrol
)
466 struct snd_soc_component
*cmpnt
= snd_soc_kcontrol_component(kcontrol
);
467 struct sst_data
*drv
= snd_soc_component_get_drvdata(cmpnt
);
468 struct sst_gain_mixer_control
*mc
= (void *)kcontrol
->private_value
;
469 struct sst_gain_value
*gv
= mc
->gain_val
;
471 mutex_lock(&drv
->lock
);
475 gv
->l_gain
= ucontrol
->value
.integer
.value
[0];
476 gv
->r_gain
= ucontrol
->value
.integer
.value
[1];
477 dev_dbg(cmpnt
->dev
, "%s: Volume %d, %d\n",
478 mc
->pname
, gv
->l_gain
, gv
->r_gain
);
482 gv
->mute
= !ucontrol
->value
.integer
.value
[0];
483 dev_dbg(cmpnt
->dev
, "%s: Mute %d\n", mc
->pname
, gv
->mute
);
486 case SST_GAIN_RAMP_DURATION
:
487 gv
->ramp_duration
= ucontrol
->value
.integer
.value
[0];
488 dev_dbg(cmpnt
->dev
, "%s: Ramp Delay%d\n",
489 mc
->pname
, gv
->ramp_duration
);
493 mutex_unlock(&drv
->lock
);
494 dev_err(cmpnt
->dev
, "Invalid Input- gain type:%d\n",
499 if (mc
->w
&& mc
->w
->power
)
500 ret
= sst_send_gain_cmd(drv
, gv
, mc
->task_id
,
501 mc
->pipe_id
| mc
->instance_id
, mc
->module_id
, 0);
502 mutex_unlock(&drv
->lock
);
507 static int sst_set_pipe_gain(struct sst_ids
*ids
,
508 struct sst_data
*drv
, int mute
);
510 static int sst_send_pipe_module_params(struct snd_soc_dapm_widget
*w
,
511 struct snd_kcontrol
*kcontrol
)
513 struct snd_soc_component
*c
= snd_soc_dapm_to_component(w
->dapm
);
514 struct sst_data
*drv
= snd_soc_component_get_drvdata(c
);
515 struct sst_ids
*ids
= w
->priv
;
517 mutex_lock(&drv
->lock
);
518 sst_find_and_send_pipe_algo(drv
, w
->name
, ids
);
519 sst_set_pipe_gain(ids
, drv
, 0);
520 mutex_unlock(&drv
->lock
);
525 static int sst_generic_modules_event(struct snd_soc_dapm_widget
*w
,
526 struct snd_kcontrol
*k
, int event
)
528 if (SND_SOC_DAPM_EVENT_ON(event
))
529 return sst_send_pipe_module_params(w
, k
);
533 static const DECLARE_TLV_DB_SCALE(sst_gain_tlv_common
, SST_GAIN_MIN_VALUE
* 10, 10, 0);
535 /* Look up table to convert MIXER SW bit regs to SWM inputs */
536 static const uint swm_mixer_input_ids
[SST_SWM_INPUT_COUNT
] = {
537 [SST_IP_CODEC0
] = SST_SWM_IN_CODEC0
,
538 [SST_IP_CODEC1
] = SST_SWM_IN_CODEC1
,
539 [SST_IP_LOOP0
] = SST_SWM_IN_SPROT_LOOP
,
540 [SST_IP_LOOP1
] = SST_SWM_IN_MEDIA_LOOP1
,
541 [SST_IP_LOOP2
] = SST_SWM_IN_MEDIA_LOOP2
,
542 [SST_IP_PCM0
] = SST_SWM_IN_PCM0
,
543 [SST_IP_PCM1
] = SST_SWM_IN_PCM1
,
544 [SST_IP_MEDIA0
] = SST_SWM_IN_MEDIA0
,
545 [SST_IP_MEDIA1
] = SST_SWM_IN_MEDIA1
,
546 [SST_IP_MEDIA2
] = SST_SWM_IN_MEDIA2
,
547 [SST_IP_MEDIA3
] = SST_SWM_IN_MEDIA3
,
551 * fill_swm_input - fill in the SWM input ids given the register
553 * The register value is a bit-field inicated which mixer inputs are ON. Use the
554 * lookup table to get the input-id and fill it in the structure.
556 static int fill_swm_input(struct snd_soc_component
*cmpnt
,
557 struct swm_input_ids
*swm_input
, unsigned int reg
)
559 uint i
, is_set
, nb_inputs
= 0;
562 dev_dbg(cmpnt
->dev
, "reg: %#x\n", reg
);
563 for (i
= 0; i
< SST_SWM_INPUT_COUNT
; i
++) {
564 is_set
= reg
& BIT(i
);
568 input_loc_id
= swm_mixer_input_ids
[i
];
569 SST_FILL_DESTINATION(2, swm_input
->input_id
,
570 input_loc_id
, SST_DEFAULT_MODULE_ID
);
573 dev_dbg(cmpnt
->dev
, "input id: %#x, nb_inputs: %d\n",
574 input_loc_id
, nb_inputs
);
576 if (nb_inputs
== SST_CMD_SWM_MAX_INPUTS
) {
577 dev_warn(cmpnt
->dev
, "SET_SWM cmd max inputs reached");
586 * called with lock held
588 static int sst_set_pipe_gain(struct sst_ids
*ids
,
589 struct sst_data
*drv
, int mute
)
592 struct sst_gain_mixer_control
*mc
;
593 struct sst_gain_value
*gv
;
594 struct sst_module
*gain
= NULL
;
596 list_for_each_entry(gain
, &ids
->gain_list
, node
) {
597 struct snd_kcontrol
*kctl
= gain
->kctl
;
599 dev_dbg(&drv
->pdev
->dev
, "control name=%s\n", kctl
->id
.name
);
600 mc
= (void *)kctl
->private_value
;
603 ret
= sst_send_gain_cmd(drv
, gv
, mc
->task_id
,
604 mc
->pipe_id
| mc
->instance_id
, mc
->module_id
, mute
);
611 static int sst_swm_mixer_event(struct snd_soc_dapm_widget
*w
,
612 struct snd_kcontrol
*k
, int event
)
614 struct sst_cmd_set_swm cmd
;
615 struct snd_soc_component
*cmpnt
= snd_soc_dapm_to_component(w
->dapm
);
616 struct sst_data
*drv
= snd_soc_component_get_drvdata(cmpnt
);
617 struct sst_ids
*ids
= w
->priv
;
618 bool set_mixer
= false;
619 struct soc_mixer_control
*mc
;
623 dev_dbg(cmpnt
->dev
, "widget = %s\n", w
->name
);
625 * Identify which mixer input is on and send the bitmap of the
626 * inputs as an IPC to the DSP.
628 for (i
= 0; i
< w
->num_kcontrols
; i
++) {
629 if (dapm_kcontrol_get_value(w
->kcontrols
[i
])) {
630 mc
= (struct soc_mixer_control
*)(w
->kcontrols
[i
])->private_value
;
631 val
|= 1 << mc
->shift
;
634 dev_dbg(cmpnt
->dev
, "val = %#x\n", val
);
637 case SND_SOC_DAPM_PRE_PMU
:
638 case SND_SOC_DAPM_POST_PMD
:
641 case SND_SOC_DAPM_POST_REG
:
649 if (set_mixer
== false)
652 if (SND_SOC_DAPM_EVENT_ON(event
) ||
653 event
== SND_SOC_DAPM_POST_REG
)
654 cmd
.switch_state
= SST_SWM_ON
;
656 cmd
.switch_state
= SST_SWM_OFF
;
658 SST_FILL_DEFAULT_DESTINATION(cmd
.header
.dst
);
659 /* MMX_SET_SWM == SBA_SET_SWM */
660 cmd
.header
.command_id
= SBA_SET_SWM
;
662 SST_FILL_DESTINATION(2, cmd
.output_id
,
663 ids
->location_id
, SST_DEFAULT_MODULE_ID
);
664 cmd
.nb_inputs
= fill_swm_input(cmpnt
, &cmd
.input
[0], val
);
665 cmd
.header
.length
= offsetof(struct sst_cmd_set_swm
, input
)
666 - sizeof(struct sst_dsp_header
)
667 + (cmd
.nb_inputs
* sizeof(cmd
.input
[0]));
669 return sst_fill_and_send_cmd(drv
, SST_IPC_IA_CMD
, SST_FLAG_BLOCKED
,
670 ids
->task_id
, 0, &cmd
,
671 sizeof(cmd
.header
) + cmd
.header
.length
);
674 /* SBA mixers - 16 inputs */
675 #define SST_SBA_DECLARE_MIX_CONTROLS(kctl_name) \
676 static const struct snd_kcontrol_new kctl_name[] = { \
677 SOC_DAPM_SINGLE("codec_in0 Switch", SND_SOC_NOPM, SST_IP_CODEC0, 1, 0), \
678 SOC_DAPM_SINGLE("codec_in1 Switch", SND_SOC_NOPM, SST_IP_CODEC1, 1, 0), \
679 SOC_DAPM_SINGLE("sprot_loop_in Switch", SND_SOC_NOPM, SST_IP_LOOP0, 1, 0), \
680 SOC_DAPM_SINGLE("media_loop1_in Switch", SND_SOC_NOPM, SST_IP_LOOP1, 1, 0), \
681 SOC_DAPM_SINGLE("media_loop2_in Switch", SND_SOC_NOPM, SST_IP_LOOP2, 1, 0), \
682 SOC_DAPM_SINGLE("pcm0_in Switch", SND_SOC_NOPM, SST_IP_PCM0, 1, 0), \
683 SOC_DAPM_SINGLE("pcm1_in Switch", SND_SOC_NOPM, SST_IP_PCM1, 1, 0), \
686 #define SST_SBA_MIXER_GRAPH_MAP(mix_name) \
687 { mix_name, "codec_in0 Switch", "codec_in0" }, \
688 { mix_name, "codec_in1 Switch", "codec_in1" }, \
689 { mix_name, "sprot_loop_in Switch", "sprot_loop_in" }, \
690 { mix_name, "media_loop1_in Switch", "media_loop1_in" }, \
691 { mix_name, "media_loop2_in Switch", "media_loop2_in" }, \
692 { mix_name, "pcm0_in Switch", "pcm0_in" }, \
693 { mix_name, "pcm1_in Switch", "pcm1_in" }
695 #define SST_MMX_DECLARE_MIX_CONTROLS(kctl_name) \
696 static const struct snd_kcontrol_new kctl_name[] = { \
697 SOC_DAPM_SINGLE("media0_in Switch", SND_SOC_NOPM, SST_IP_MEDIA0, 1, 0), \
698 SOC_DAPM_SINGLE("media1_in Switch", SND_SOC_NOPM, SST_IP_MEDIA1, 1, 0), \
699 SOC_DAPM_SINGLE("media2_in Switch", SND_SOC_NOPM, SST_IP_MEDIA2, 1, 0), \
700 SOC_DAPM_SINGLE("media3_in Switch", SND_SOC_NOPM, SST_IP_MEDIA3, 1, 0), \
703 SST_MMX_DECLARE_MIX_CONTROLS(sst_mix_media0_controls
);
704 SST_MMX_DECLARE_MIX_CONTROLS(sst_mix_media1_controls
);
707 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm0_controls
);
708 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm1_controls
);
709 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm2_controls
);
710 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_sprot_l0_controls
);
711 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l1_controls
);
712 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l2_controls
);
713 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_voip_controls
);
714 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec0_controls
);
715 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec1_controls
);
718 * sst_handle_vb_timer - Start/Stop the DSP scheduler
720 * The DSP expects first cmd to be SBA_VB_START, so at first startup send
722 * DSP expects last cmd to be SBA_VB_IDLE, so at last shutdown send that.
724 * Do refcount internally so that we send command only at first start
725 * and last end. Since SST driver does its own ref count, invoke sst's
728 int sst_handle_vb_timer(struct snd_soc_dai
*dai
, bool enable
)
731 struct sst_cmd_generic cmd
;
732 struct sst_data
*drv
= snd_soc_dai_get_drvdata(dai
);
733 static int timer_usage
;
736 cmd
.header
.command_id
= SBA_VB_START
;
738 cmd
.header
.command_id
= SBA_IDLE
;
739 dev_dbg(dai
->dev
, "enable=%u, usage=%d\n", enable
, timer_usage
);
741 SST_FILL_DEFAULT_DESTINATION(cmd
.header
.dst
);
742 cmd
.header
.length
= 0;
745 ret
= sst
->ops
->power(sst
->dev
, true);
750 mutex_lock(&drv
->lock
);
757 * Send the command only if this call is the first enable or last
760 if ((enable
&& (timer_usage
== 1)) ||
761 (!enable
&& (timer_usage
== 0))) {
762 ret
= sst_fill_and_send_cmd_unlocked(drv
, SST_IPC_IA_CMD
,
763 SST_FLAG_BLOCKED
, SST_TASK_SBA
, 0, &cmd
,
764 sizeof(cmd
.header
) + cmd
.header
.length
);
770 mutex_unlock(&drv
->lock
);
773 sst
->ops
->power(sst
->dev
, false);
777 int sst_fill_ssp_slot(struct snd_soc_dai
*dai
, unsigned int tx_mask
,
778 unsigned int rx_mask
, int slots
, int slot_width
)
780 struct sst_data
*ctx
= snd_soc_dai_get_drvdata(dai
);
782 ctx
->ssp_cmd
.nb_slots
= slots
;
783 ctx
->ssp_cmd
.active_tx_slot_map
= tx_mask
;
784 ctx
->ssp_cmd
.active_rx_slot_map
= rx_mask
;
785 ctx
->ssp_cmd
.nb_bits_per_slots
= slot_width
;
790 static int sst_get_frame_sync_polarity(struct snd_soc_dai
*dai
,
795 format
= fmt
& SND_SOC_DAIFMT_INV_MASK
;
796 dev_dbg(dai
->dev
, "Enter:%s, format=%x\n", __func__
, format
);
799 case SND_SOC_DAIFMT_NB_NF
:
800 return SSP_FS_ACTIVE_LOW
;
801 case SND_SOC_DAIFMT_NB_IF
:
802 return SSP_FS_ACTIVE_HIGH
;
803 case SND_SOC_DAIFMT_IB_IF
:
804 return SSP_FS_ACTIVE_LOW
;
805 case SND_SOC_DAIFMT_IB_NF
:
806 return SSP_FS_ACTIVE_HIGH
;
808 dev_err(dai
->dev
, "Invalid frame sync polarity %d\n", format
);
814 static int sst_get_ssp_mode(struct snd_soc_dai
*dai
, unsigned int fmt
)
818 format
= (fmt
& SND_SOC_DAIFMT_MASTER_MASK
);
819 dev_dbg(dai
->dev
, "Enter:%s, format=%x\n", __func__
, format
);
822 case SND_SOC_DAIFMT_CBS_CFS
:
823 return SSP_MODE_MASTER
;
824 case SND_SOC_DAIFMT_CBM_CFM
:
825 return SSP_MODE_SLAVE
;
827 dev_err(dai
->dev
, "Invalid ssp protocol: %d\n", format
);
834 int sst_fill_ssp_config(struct snd_soc_dai
*dai
, unsigned int fmt
)
838 struct sst_data
*ctx
= snd_soc_dai_get_drvdata(dai
);
840 mode
= fmt
& SND_SOC_DAIFMT_FORMAT_MASK
;
843 case SND_SOC_DAIFMT_DSP_B
:
844 ctx
->ssp_cmd
.ssp_protocol
= SSP_MODE_PCM
;
845 ctx
->ssp_cmd
.mode
= sst_get_ssp_mode(dai
, fmt
) | (SSP_PCM_MODE_NETWORK
<< 1);
846 ctx
->ssp_cmd
.start_delay
= 0;
847 ctx
->ssp_cmd
.data_polarity
= 1;
848 ctx
->ssp_cmd
.frame_sync_width
= 1;
851 case SND_SOC_DAIFMT_DSP_A
:
852 ctx
->ssp_cmd
.ssp_protocol
= SSP_MODE_PCM
;
853 ctx
->ssp_cmd
.mode
= sst_get_ssp_mode(dai
, fmt
) | (SSP_PCM_MODE_NETWORK
<< 1);
854 ctx
->ssp_cmd
.start_delay
= 1;
855 ctx
->ssp_cmd
.data_polarity
= 1;
856 ctx
->ssp_cmd
.frame_sync_width
= 1;
859 case SND_SOC_DAIFMT_I2S
:
860 ctx
->ssp_cmd
.ssp_protocol
= SSP_MODE_I2S
;
861 ctx
->ssp_cmd
.mode
= sst_get_ssp_mode(dai
, fmt
) | (SSP_PCM_MODE_NORMAL
<< 1);
862 ctx
->ssp_cmd
.start_delay
= 1;
863 ctx
->ssp_cmd
.data_polarity
= 0;
864 ctx
->ssp_cmd
.frame_sync_width
= ctx
->ssp_cmd
.nb_bits_per_slots
;
867 case SND_SOC_DAIFMT_LEFT_J
:
868 ctx
->ssp_cmd
.ssp_protocol
= SSP_MODE_I2S
;
869 ctx
->ssp_cmd
.mode
= sst_get_ssp_mode(dai
, fmt
) | (SSP_PCM_MODE_NORMAL
<< 1);
870 ctx
->ssp_cmd
.start_delay
= 0;
871 ctx
->ssp_cmd
.data_polarity
= 0;
872 ctx
->ssp_cmd
.frame_sync_width
= ctx
->ssp_cmd
.nb_bits_per_slots
;
876 dev_dbg(dai
->dev
, "using default ssp configs\n");
879 fs_polarity
= sst_get_frame_sync_polarity(dai
, fmt
);
883 ctx
->ssp_cmd
.frame_sync_polarity
= fs_polarity
;
889 * sst_ssp_config - contains SSP configuration for media UC
890 * this can be overwritten by set_dai_xxx APIs
892 static const struct sst_ssp_config sst_ssp_configs
= {
896 .ssp_mode
= SSP_MODE_MASTER
,
897 .pcm_mode
= SSP_PCM_MODE_NETWORK
,
898 .duplex
= SSP_DUPLEX
,
899 .ssp_protocol
= SSP_MODE_PCM
,
901 .fs_frequency
= SSP_FS_48_KHZ
,
902 .active_slot_map
= 0xF,
904 .frame_sync_polarity
= SSP_FS_ACTIVE_HIGH
,
908 void sst_fill_ssp_defaults(struct snd_soc_dai
*dai
)
910 const struct sst_ssp_config
*config
;
911 struct sst_data
*ctx
= snd_soc_dai_get_drvdata(dai
);
913 config
= &sst_ssp_configs
;
915 ctx
->ssp_cmd
.selection
= config
->ssp_id
;
916 ctx
->ssp_cmd
.nb_bits_per_slots
= config
->bits_per_slot
;
917 ctx
->ssp_cmd
.nb_slots
= config
->slots
;
918 ctx
->ssp_cmd
.mode
= config
->ssp_mode
| (config
->pcm_mode
<< 1);
919 ctx
->ssp_cmd
.duplex
= config
->duplex
;
920 ctx
->ssp_cmd
.active_tx_slot_map
= config
->active_slot_map
;
921 ctx
->ssp_cmd
.active_rx_slot_map
= config
->active_slot_map
;
922 ctx
->ssp_cmd
.frame_sync_frequency
= config
->fs_frequency
;
923 ctx
->ssp_cmd
.frame_sync_polarity
= config
->frame_sync_polarity
;
924 ctx
->ssp_cmd
.data_polarity
= config
->data_polarity
;
925 ctx
->ssp_cmd
.frame_sync_width
= config
->fs_width
;
926 ctx
->ssp_cmd
.ssp_protocol
= config
->ssp_protocol
;
927 ctx
->ssp_cmd
.start_delay
= config
->start_delay
;
928 ctx
->ssp_cmd
.reserved1
= ctx
->ssp_cmd
.reserved2
= 0xFF;
931 int send_ssp_cmd(struct snd_soc_dai
*dai
, const char *id
, bool enable
)
933 struct sst_data
*drv
= snd_soc_dai_get_drvdata(dai
);
934 const struct sst_ssp_config
*config
;
936 dev_info(dai
->dev
, "Enter: enable=%d port_name=%s\n", enable
, id
);
938 SST_FILL_DEFAULT_DESTINATION(drv
->ssp_cmd
.header
.dst
);
939 drv
->ssp_cmd
.header
.command_id
= SBA_HW_SET_SSP
;
940 drv
->ssp_cmd
.header
.length
= sizeof(struct sst_cmd_sba_hw_set_ssp
)
941 - sizeof(struct sst_dsp_header
);
943 config
= &sst_ssp_configs
;
944 dev_dbg(dai
->dev
, "ssp_id: %u\n", config
->ssp_id
);
947 drv
->ssp_cmd
.switch_state
= SST_SWITCH_ON
;
949 drv
->ssp_cmd
.switch_state
= SST_SWITCH_OFF
;
951 return sst_fill_and_send_cmd(drv
, SST_IPC_IA_CMD
, SST_FLAG_BLOCKED
,
952 SST_TASK_SBA
, 0, &drv
->ssp_cmd
,
953 sizeof(drv
->ssp_cmd
.header
) + drv
->ssp_cmd
.header
.length
);
956 static int sst_set_be_modules(struct snd_soc_dapm_widget
*w
,
957 struct snd_kcontrol
*k
, int event
)
960 struct snd_soc_component
*c
= snd_soc_dapm_to_component(w
->dapm
);
961 struct sst_data
*drv
= snd_soc_component_get_drvdata(c
);
963 dev_dbg(c
->dev
, "Enter: widget=%s\n", w
->name
);
965 if (SND_SOC_DAPM_EVENT_ON(event
)) {
966 ret
= sst_send_slot_map(drv
);
969 ret
= sst_send_pipe_module_params(w
, k
);
974 static int sst_set_media_path(struct snd_soc_dapm_widget
*w
,
975 struct snd_kcontrol
*k
, int event
)
978 struct sst_cmd_set_media_path cmd
;
979 struct snd_soc_component
*c
= snd_soc_dapm_to_component(w
->dapm
);
980 struct sst_data
*drv
= snd_soc_component_get_drvdata(c
);
981 struct sst_ids
*ids
= w
->priv
;
983 dev_dbg(c
->dev
, "widget=%s\n", w
->name
);
984 dev_dbg(c
->dev
, "task=%u, location=%#x\n",
985 ids
->task_id
, ids
->location_id
);
987 if (SND_SOC_DAPM_EVENT_ON(event
))
988 cmd
.switch_state
= SST_PATH_ON
;
990 cmd
.switch_state
= SST_PATH_OFF
;
992 SST_FILL_DESTINATION(2, cmd
.header
.dst
,
993 ids
->location_id
, SST_DEFAULT_MODULE_ID
);
995 /* MMX_SET_MEDIA_PATH == SBA_SET_MEDIA_PATH */
996 cmd
.header
.command_id
= MMX_SET_MEDIA_PATH
;
997 cmd
.header
.length
= sizeof(struct sst_cmd_set_media_path
)
998 - sizeof(struct sst_dsp_header
);
1000 ret
= sst_fill_and_send_cmd(drv
, SST_IPC_IA_CMD
, SST_FLAG_BLOCKED
,
1001 ids
->task_id
, 0, &cmd
,
1002 sizeof(cmd
.header
) + cmd
.header
.length
);
1006 if (SND_SOC_DAPM_EVENT_ON(event
))
1007 ret
= sst_send_pipe_module_params(w
, k
);
1011 static int sst_set_media_loop(struct snd_soc_dapm_widget
*w
,
1012 struct snd_kcontrol
*k
, int event
)
1015 struct sst_cmd_sba_set_media_loop_map cmd
;
1016 struct snd_soc_component
*c
= snd_soc_dapm_to_component(w
->dapm
);
1017 struct sst_data
*drv
= snd_soc_component_get_drvdata(c
);
1018 struct sst_ids
*ids
= w
->priv
;
1020 dev_dbg(c
->dev
, "Enter:widget=%s\n", w
->name
);
1021 if (SND_SOC_DAPM_EVENT_ON(event
))
1022 cmd
.switch_state
= SST_SWITCH_ON
;
1024 cmd
.switch_state
= SST_SWITCH_OFF
;
1026 SST_FILL_DESTINATION(2, cmd
.header
.dst
,
1027 ids
->location_id
, SST_DEFAULT_MODULE_ID
);
1029 cmd
.header
.command_id
= SBA_SET_MEDIA_LOOP_MAP
;
1030 cmd
.header
.length
= sizeof(struct sst_cmd_sba_set_media_loop_map
)
1031 - sizeof(struct sst_dsp_header
);
1032 cmd
.param
.part
.cfg
.rate
= 2; /* 48khz */
1034 cmd
.param
.part
.cfg
.format
= ids
->format
; /* stereo/Mono */
1035 cmd
.param
.part
.cfg
.s_length
= 1; /* 24bit left justified */
1036 cmd
.map
= 0; /* Algo sequence: Gain - DRP - FIR - IIR */
1038 ret
= sst_fill_and_send_cmd(drv
, SST_IPC_IA_CMD
, SST_FLAG_BLOCKED
,
1039 SST_TASK_SBA
, 0, &cmd
,
1040 sizeof(cmd
.header
) + cmd
.header
.length
);
1044 if (SND_SOC_DAPM_EVENT_ON(event
))
1045 ret
= sst_send_pipe_module_params(w
, k
);
1049 static const struct snd_soc_dapm_widget sst_dapm_widgets
[] = {
1050 SST_AIF_IN("codec_in0", sst_set_be_modules
),
1051 SST_AIF_IN("codec_in1", sst_set_be_modules
),
1052 SST_AIF_OUT("codec_out0", sst_set_be_modules
),
1053 SST_AIF_OUT("codec_out1", sst_set_be_modules
),
1056 /* MediaX IN paths are set via ALLOC, so no SET_MEDIA_PATH command */
1057 SST_PATH_INPUT("media0_in", SST_TASK_MMX
, SST_SWM_IN_MEDIA0
, sst_generic_modules_event
),
1058 SST_PATH_INPUT("media1_in", SST_TASK_MMX
, SST_SWM_IN_MEDIA1
, NULL
),
1059 SST_PATH_INPUT("media2_in", SST_TASK_MMX
, SST_SWM_IN_MEDIA2
, sst_set_media_path
),
1060 SST_PATH_INPUT("media3_in", SST_TASK_MMX
, SST_SWM_IN_MEDIA3
, NULL
),
1061 SST_PATH_OUTPUT("media0_out", SST_TASK_MMX
, SST_SWM_OUT_MEDIA0
, sst_set_media_path
),
1062 SST_PATH_OUTPUT("media1_out", SST_TASK_MMX
, SST_SWM_OUT_MEDIA1
, sst_set_media_path
),
1065 SST_PATH_INPUT("pcm0_in", SST_TASK_SBA
, SST_SWM_IN_PCM0
, sst_set_media_path
),
1066 SST_PATH_INPUT("pcm1_in", SST_TASK_SBA
, SST_SWM_IN_PCM1
, sst_set_media_path
),
1067 SST_PATH_OUTPUT("pcm0_out", SST_TASK_SBA
, SST_SWM_OUT_PCM0
, sst_set_media_path
),
1068 SST_PATH_OUTPUT("pcm1_out", SST_TASK_SBA
, SST_SWM_OUT_PCM1
, sst_set_media_path
),
1069 SST_PATH_OUTPUT("pcm2_out", SST_TASK_SBA
, SST_SWM_OUT_PCM2
, sst_set_media_path
),
1072 SST_PATH_INPUT("sprot_loop_in", SST_TASK_SBA
, SST_SWM_IN_SPROT_LOOP
, NULL
),
1073 SST_PATH_INPUT("media_loop1_in", SST_TASK_SBA
, SST_SWM_IN_MEDIA_LOOP1
, NULL
),
1074 SST_PATH_INPUT("media_loop2_in", SST_TASK_SBA
, SST_SWM_IN_MEDIA_LOOP2
, NULL
),
1075 SST_PATH_MEDIA_LOOP_OUTPUT("sprot_loop_out", SST_TASK_SBA
, SST_SWM_OUT_SPROT_LOOP
, SST_FMT_MONO
, sst_set_media_loop
),
1076 SST_PATH_MEDIA_LOOP_OUTPUT("media_loop1_out", SST_TASK_SBA
, SST_SWM_OUT_MEDIA_LOOP1
, SST_FMT_MONO
, sst_set_media_loop
),
1077 SST_PATH_MEDIA_LOOP_OUTPUT("media_loop2_out", SST_TASK_SBA
, SST_SWM_OUT_MEDIA_LOOP2
, SST_FMT_STEREO
, sst_set_media_loop
),
1080 SST_SWM_MIXER("media0_out mix 0", SND_SOC_NOPM
, SST_TASK_MMX
, SST_SWM_OUT_MEDIA0
,
1081 sst_mix_media0_controls
, sst_swm_mixer_event
),
1082 SST_SWM_MIXER("media1_out mix 0", SND_SOC_NOPM
, SST_TASK_MMX
, SST_SWM_OUT_MEDIA1
,
1083 sst_mix_media1_controls
, sst_swm_mixer_event
),
1085 /* SBA PCM mixers */
1086 SST_SWM_MIXER("pcm0_out mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_PCM0
,
1087 sst_mix_pcm0_controls
, sst_swm_mixer_event
),
1088 SST_SWM_MIXER("pcm1_out mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_PCM1
,
1089 sst_mix_pcm1_controls
, sst_swm_mixer_event
),
1090 SST_SWM_MIXER("pcm2_out mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_PCM2
,
1091 sst_mix_pcm2_controls
, sst_swm_mixer_event
),
1093 /* SBA Loop mixers */
1094 SST_SWM_MIXER("sprot_loop_out mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_SPROT_LOOP
,
1095 sst_mix_sprot_l0_controls
, sst_swm_mixer_event
),
1096 SST_SWM_MIXER("media_loop1_out mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_MEDIA_LOOP1
,
1097 sst_mix_media_l1_controls
, sst_swm_mixer_event
),
1098 SST_SWM_MIXER("media_loop2_out mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_MEDIA_LOOP2
,
1099 sst_mix_media_l2_controls
, sst_swm_mixer_event
),
1101 /* SBA Backend mixers */
1102 SST_SWM_MIXER("codec_out0 mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_CODEC0
,
1103 sst_mix_codec0_controls
, sst_swm_mixer_event
),
1104 SST_SWM_MIXER("codec_out1 mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_CODEC1
,
1105 sst_mix_codec1_controls
, sst_swm_mixer_event
),
1108 static const struct snd_soc_dapm_route intercon
[] = {
1109 {"media0_in", NULL
, "Compress Playback"},
1110 {"media1_in", NULL
, "Headset Playback"},
1111 {"media2_in", NULL
, "pcm0_out"},
1112 {"media3_in", NULL
, "Deepbuffer Playback"},
1114 {"media0_out mix 0", "media0_in Switch", "media0_in"},
1115 {"media0_out mix 0", "media1_in Switch", "media1_in"},
1116 {"media0_out mix 0", "media2_in Switch", "media2_in"},
1117 {"media0_out mix 0", "media3_in Switch", "media3_in"},
1118 {"media1_out mix 0", "media0_in Switch", "media0_in"},
1119 {"media1_out mix 0", "media1_in Switch", "media1_in"},
1120 {"media1_out mix 0", "media2_in Switch", "media2_in"},
1121 {"media1_out mix 0", "media3_in Switch", "media3_in"},
1123 {"media0_out", NULL
, "media0_out mix 0"},
1124 {"media1_out", NULL
, "media1_out mix 0"},
1125 {"pcm0_in", NULL
, "media0_out"},
1126 {"pcm1_in", NULL
, "media1_out"},
1128 {"Headset Capture", NULL
, "pcm1_out"},
1129 {"Headset Capture", NULL
, "pcm2_out"},
1130 {"pcm0_out", NULL
, "pcm0_out mix 0"},
1131 SST_SBA_MIXER_GRAPH_MAP("pcm0_out mix 0"),
1132 {"pcm1_out", NULL
, "pcm1_out mix 0"},
1133 SST_SBA_MIXER_GRAPH_MAP("pcm1_out mix 0"),
1134 {"pcm2_out", NULL
, "pcm2_out mix 0"},
1135 SST_SBA_MIXER_GRAPH_MAP("pcm2_out mix 0"),
1137 {"media_loop1_in", NULL
, "media_loop1_out"},
1138 {"media_loop1_out", NULL
, "media_loop1_out mix 0"},
1139 SST_SBA_MIXER_GRAPH_MAP("media_loop1_out mix 0"),
1140 {"media_loop2_in", NULL
, "media_loop2_out"},
1141 {"media_loop2_out", NULL
, "media_loop2_out mix 0"},
1142 SST_SBA_MIXER_GRAPH_MAP("media_loop2_out mix 0"),
1143 {"sprot_loop_in", NULL
, "sprot_loop_out"},
1144 {"sprot_loop_out", NULL
, "sprot_loop_out mix 0"},
1145 SST_SBA_MIXER_GRAPH_MAP("sprot_loop_out mix 0"),
1147 {"codec_out0", NULL
, "codec_out0 mix 0"},
1148 SST_SBA_MIXER_GRAPH_MAP("codec_out0 mix 0"),
1149 {"codec_out1", NULL
, "codec_out1 mix 0"},
1150 SST_SBA_MIXER_GRAPH_MAP("codec_out1 mix 0"),
1153 static const char * const slot_names
[] = {
1155 "slot 0", "slot 1", "slot 2", "slot 3",
1156 "slot 4", "slot 5", "slot 6", "slot 7", /* not supported by FW */
1159 static const char * const channel_names
[] = {
1161 "codec_out0_0", "codec_out0_1", "codec_out1_0", "codec_out1_1",
1162 "codec_out2_0", "codec_out2_1", "codec_out3_0", "codec_out3_1", /* not supported by FW */
1165 #define SST_INTERLEAVER(xpname, slot_name, slotno) \
1166 SST_SSP_SLOT_CTL(xpname, "tx interleaver", slot_name, slotno, true, \
1167 channel_names, sst_slot_get, sst_slot_put)
1169 #define SST_DEINTERLEAVER(xpname, channel_name, channel_no) \
1170 SST_SSP_SLOT_CTL(xpname, "rx deinterleaver", channel_name, channel_no, false, \
1171 slot_names, sst_slot_get, sst_slot_put)
1173 static const struct snd_kcontrol_new sst_slot_controls
[] = {
1174 SST_INTERLEAVER("codec_out", "slot 0", 0),
1175 SST_INTERLEAVER("codec_out", "slot 1", 1),
1176 SST_INTERLEAVER("codec_out", "slot 2", 2),
1177 SST_INTERLEAVER("codec_out", "slot 3", 3),
1178 SST_DEINTERLEAVER("codec_in", "codec_in0_0", 0),
1179 SST_DEINTERLEAVER("codec_in", "codec_in0_1", 1),
1180 SST_DEINTERLEAVER("codec_in", "codec_in1_0", 2),
1181 SST_DEINTERLEAVER("codec_in", "codec_in1_1", 3),
1184 /* Gain helper with min/max set */
1185 #define SST_GAIN(name, path_id, task_id, instance, gain_var) \
1186 SST_GAIN_KCONTROLS(name, "Gain", SST_GAIN_MIN_VALUE, SST_GAIN_MAX_VALUE, \
1187 SST_GAIN_TC_MIN, SST_GAIN_TC_MAX, \
1188 sst_gain_get, sst_gain_put, \
1189 SST_MODULE_ID_GAIN_CELL, path_id, instance, task_id, \
1190 sst_gain_tlv_common, gain_var)
1192 #define SST_VOLUME(name, path_id, task_id, instance, gain_var) \
1193 SST_GAIN_KCONTROLS(name, "Volume", SST_GAIN_MIN_VALUE, SST_GAIN_MAX_VALUE, \
1194 SST_GAIN_TC_MIN, SST_GAIN_TC_MAX, \
1195 sst_gain_get, sst_gain_put, \
1196 SST_MODULE_ID_VOLUME, path_id, instance, task_id, \
1197 sst_gain_tlv_common, gain_var)
1199 static struct sst_gain_value sst_gains
[];
1201 static const struct snd_kcontrol_new sst_gain_controls
[] = {
1202 SST_GAIN("media0_in", SST_PATH_INDEX_MEDIA0_IN
, SST_TASK_MMX
, 0, &sst_gains
[0]),
1203 SST_GAIN("media1_in", SST_PATH_INDEX_MEDIA1_IN
, SST_TASK_MMX
, 0, &sst_gains
[1]),
1204 SST_GAIN("media2_in", SST_PATH_INDEX_MEDIA2_IN
, SST_TASK_MMX
, 0, &sst_gains
[2]),
1205 SST_GAIN("media3_in", SST_PATH_INDEX_MEDIA3_IN
, SST_TASK_MMX
, 0, &sst_gains
[3]),
1207 SST_GAIN("pcm0_in", SST_PATH_INDEX_PCM0_IN
, SST_TASK_SBA
, 0, &sst_gains
[4]),
1208 SST_GAIN("pcm1_in", SST_PATH_INDEX_PCM1_IN
, SST_TASK_SBA
, 0, &sst_gains
[5]),
1209 SST_GAIN("pcm1_out", SST_PATH_INDEX_PCM1_OUT
, SST_TASK_SBA
, 0, &sst_gains
[6]),
1210 SST_GAIN("pcm2_out", SST_PATH_INDEX_PCM2_OUT
, SST_TASK_SBA
, 0, &sst_gains
[7]),
1212 SST_GAIN("codec_in0", SST_PATH_INDEX_CODEC_IN0
, SST_TASK_SBA
, 0, &sst_gains
[8]),
1213 SST_GAIN("codec_in1", SST_PATH_INDEX_CODEC_IN1
, SST_TASK_SBA
, 0, &sst_gains
[9]),
1214 SST_GAIN("codec_out0", SST_PATH_INDEX_CODEC_OUT0
, SST_TASK_SBA
, 0, &sst_gains
[10]),
1215 SST_GAIN("codec_out1", SST_PATH_INDEX_CODEC_OUT1
, SST_TASK_SBA
, 0, &sst_gains
[11]),
1216 SST_GAIN("media_loop1_out", SST_PATH_INDEX_MEDIA_LOOP1_OUT
, SST_TASK_SBA
, 0, &sst_gains
[12]),
1217 SST_GAIN("media_loop2_out", SST_PATH_INDEX_MEDIA_LOOP2_OUT
, SST_TASK_SBA
, 0, &sst_gains
[13]),
1218 SST_GAIN("sprot_loop_out", SST_PATH_INDEX_SPROT_LOOP_OUT
, SST_TASK_SBA
, 0, &sst_gains
[14]),
1219 SST_VOLUME("media0_in", SST_PATH_INDEX_MEDIA0_IN
, SST_TASK_MMX
, 0, &sst_gains
[15]),
1222 #define SST_GAIN_NUM_CONTROLS 3
1223 /* the SST_GAIN macro above will create three alsa controls for each
1224 * instance invoked, gain, mute and ramp duration, which use the same gain
1225 * cell sst_gain to keep track of data
1226 * To calculate number of gain cell instances we need to device by 3 in
1227 * below caulcation for gain cell memory.
1228 * This gets rid of static number and issues while adding new controls
1230 static struct sst_gain_value sst_gains
[ARRAY_SIZE(sst_gain_controls
)/SST_GAIN_NUM_CONTROLS
];
1232 static const struct snd_kcontrol_new sst_algo_controls
[] = {
1233 SST_ALGO_KCONTROL_BYTES("media_loop1_out", "fir", 272, SST_MODULE_ID_FIR_24
,
1234 SST_PATH_INDEX_MEDIA_LOOP1_OUT
, 0, SST_TASK_SBA
, SBA_VB_SET_FIR
),
1235 SST_ALGO_KCONTROL_BYTES("media_loop1_out", "iir", 300, SST_MODULE_ID_IIR_24
,
1236 SST_PATH_INDEX_MEDIA_LOOP1_OUT
, 0, SST_TASK_SBA
, SBA_VB_SET_IIR
),
1237 SST_ALGO_KCONTROL_BYTES("media_loop1_out", "mdrp", 286, SST_MODULE_ID_MDRP
,
1238 SST_PATH_INDEX_MEDIA_LOOP1_OUT
, 0, SST_TASK_SBA
, SBA_SET_MDRP
),
1239 SST_ALGO_KCONTROL_BYTES("media_loop2_out", "fir", 272, SST_MODULE_ID_FIR_24
,
1240 SST_PATH_INDEX_MEDIA_LOOP2_OUT
, 0, SST_TASK_SBA
, SBA_VB_SET_FIR
),
1241 SST_ALGO_KCONTROL_BYTES("media_loop2_out", "iir", 300, SST_MODULE_ID_IIR_24
,
1242 SST_PATH_INDEX_MEDIA_LOOP2_OUT
, 0, SST_TASK_SBA
, SBA_VB_SET_IIR
),
1243 SST_ALGO_KCONTROL_BYTES("media_loop2_out", "mdrp", 286, SST_MODULE_ID_MDRP
,
1244 SST_PATH_INDEX_MEDIA_LOOP2_OUT
, 0, SST_TASK_SBA
, SBA_SET_MDRP
),
1245 SST_ALGO_KCONTROL_BYTES("sprot_loop_out", "lpro", 192, SST_MODULE_ID_SPROT
,
1246 SST_PATH_INDEX_SPROT_LOOP_OUT
, 0, SST_TASK_SBA
, SBA_VB_LPRO
),
1247 SST_ALGO_KCONTROL_BYTES("codec_in0", "dcr", 52, SST_MODULE_ID_FILT_DCR
,
1248 SST_PATH_INDEX_CODEC_IN0
, 0, SST_TASK_SBA
, SBA_VB_SET_IIR
),
1249 SST_ALGO_KCONTROL_BYTES("codec_in1", "dcr", 52, SST_MODULE_ID_FILT_DCR
,
1250 SST_PATH_INDEX_CODEC_IN1
, 0, SST_TASK_SBA
, SBA_VB_SET_IIR
),
1254 static int sst_algo_control_init(struct device
*dev
)
1257 struct sst_algo_control
*bc
;
1258 /*allocate space to cache the algo parameters in the driver*/
1259 for (i
= 0; i
< ARRAY_SIZE(sst_algo_controls
); i
++) {
1260 bc
= (struct sst_algo_control
*)sst_algo_controls
[i
].private_value
;
1261 bc
->params
= devm_kzalloc(dev
, bc
->max
, GFP_KERNEL
);
1262 if (bc
->params
== NULL
)
1268 static bool is_sst_dapm_widget(struct snd_soc_dapm_widget
*w
)
1271 case snd_soc_dapm_pga
:
1272 case snd_soc_dapm_aif_in
:
1273 case snd_soc_dapm_aif_out
:
1274 case snd_soc_dapm_input
:
1275 case snd_soc_dapm_output
:
1276 case snd_soc_dapm_mixer
:
1284 * sst_send_pipe_gains - send gains for the front-end DAIs
1286 * The gains in the pipes connected to the front-ends are muted/unmuted
1287 * automatically via the digital_mute() DAPM callback. This function sends the
1288 * gains for the front-end pipes.
1290 int sst_send_pipe_gains(struct snd_soc_dai
*dai
, int stream
, int mute
)
1292 struct sst_data
*drv
= snd_soc_dai_get_drvdata(dai
);
1293 struct snd_soc_dapm_widget
*w
;
1294 struct snd_soc_dapm_path
*p
= NULL
;
1296 dev_dbg(dai
->dev
, "enter, dai-name=%s dir=%d\n", dai
->name
, stream
);
1298 if (stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
1299 dev_dbg(dai
->dev
, "Stream name=%s\n",
1300 dai
->playback_widget
->name
);
1301 w
= dai
->playback_widget
;
1302 snd_soc_dapm_widget_for_each_sink_path(w
, p
) {
1303 if (p
->connected
&& !p
->connected(w
, p
->sink
))
1306 if (p
->connect
&& p
->sink
->power
&&
1307 is_sst_dapm_widget(p
->sink
)) {
1308 struct sst_ids
*ids
= p
->sink
->priv
;
1310 dev_dbg(dai
->dev
, "send gains for widget=%s\n",
1312 mutex_lock(&drv
->lock
);
1313 sst_set_pipe_gain(ids
, drv
, mute
);
1314 mutex_unlock(&drv
->lock
);
1318 dev_dbg(dai
->dev
, "Stream name=%s\n",
1319 dai
->capture_widget
->name
);
1320 w
= dai
->capture_widget
;
1321 snd_soc_dapm_widget_for_each_source_path(w
, p
) {
1322 if (p
->connected
&& !p
->connected(w
, p
->sink
))
1325 if (p
->connect
&& p
->source
->power
&&
1326 is_sst_dapm_widget(p
->source
)) {
1327 struct sst_ids
*ids
= p
->source
->priv
;
1329 dev_dbg(dai
->dev
, "send gain for widget=%s\n",
1331 mutex_lock(&drv
->lock
);
1332 sst_set_pipe_gain(ids
, drv
, mute
);
1333 mutex_unlock(&drv
->lock
);
1341 * sst_fill_module_list - populate the list of modules/gains for a pipe
1344 * Fills the widget pointer in the kcontrol private data, and also fills the
1345 * kcontrol pointer in the widget private data.
1347 * Widget pointer is used to send the algo/gain in the .put() handler if the
1348 * widget is powerd on.
1350 * Kcontrol pointer is used to send the algo/gain in the widget power ON/OFF
1351 * event handler. Each widget (pipe) has multiple algos stored in the algo_list.
1353 static int sst_fill_module_list(struct snd_kcontrol
*kctl
,
1354 struct snd_soc_dapm_widget
*w
, int type
)
1356 struct sst_module
*module
= NULL
;
1357 struct snd_soc_component
*c
= snd_soc_dapm_to_component(w
->dapm
);
1358 struct sst_ids
*ids
= w
->priv
;
1361 module
= devm_kzalloc(c
->dev
, sizeof(*module
), GFP_KERNEL
);
1365 if (type
== SST_MODULE_GAIN
) {
1366 struct sst_gain_mixer_control
*mc
= (void *)kctl
->private_value
;
1369 module
->kctl
= kctl
;
1370 list_add_tail(&module
->node
, &ids
->gain_list
);
1371 } else if (type
== SST_MODULE_ALGO
) {
1372 struct sst_algo_control
*bc
= (void *)kctl
->private_value
;
1375 module
->kctl
= kctl
;
1376 list_add_tail(&module
->node
, &ids
->algo_list
);
1378 dev_err(c
->dev
, "invoked for unknown type %d module %s",
1379 type
, kctl
->id
.name
);
1387 * sst_fill_widget_module_info - fill list of gains/algos for the pipe
1388 * @widget: pipe modelled as a DAPM widget
1390 * Fill the list of gains/algos for the widget by looking at all the card
1391 * controls and comparing the name of the widget with the first part of control
1392 * name. First part of control name contains the pipe name (widget name).
1394 static int sst_fill_widget_module_info(struct snd_soc_dapm_widget
*w
,
1395 struct snd_soc_platform
*platform
)
1397 struct snd_kcontrol
*kctl
;
1399 struct snd_card
*card
= platform
->component
.card
->snd_card
;
1402 down_read(&card
->controls_rwsem
);
1404 list_for_each_entry(kctl
, &card
->controls
, list
) {
1405 idx
= strchr(kctl
->id
.name
, ' ');
1408 index
= idx
- (char*)kctl
->id
.name
;
1409 if (strncmp(kctl
->id
.name
, w
->name
, index
))
1412 if (strstr(kctl
->id
.name
, "Volume"))
1413 ret
= sst_fill_module_list(kctl
, w
, SST_MODULE_GAIN
);
1415 else if (strstr(kctl
->id
.name
, "params"))
1416 ret
= sst_fill_module_list(kctl
, w
, SST_MODULE_ALGO
);
1418 else if (strstr(kctl
->id
.name
, "Switch") &&
1419 strstr(kctl
->id
.name
, "Gain")) {
1420 struct sst_gain_mixer_control
*mc
=
1421 (void *)kctl
->private_value
;
1425 } else if (strstr(kctl
->id
.name
, "interleaver")) {
1426 struct sst_enum
*e
= (void *)kctl
->private_value
;
1430 } else if (strstr(kctl
->id
.name
, "deinterleaver")) {
1431 struct sst_enum
*e
= (void *)kctl
->private_value
;
1437 up_read(&card
->controls_rwsem
);
1442 up_read(&card
->controls_rwsem
);
1447 * sst_fill_linked_widgets - fill the parent pointer for the linked widget
1449 static void sst_fill_linked_widgets(struct snd_soc_platform
*platform
,
1450 struct sst_ids
*ids
)
1452 struct snd_soc_dapm_widget
*w
;
1453 unsigned int len
= strlen(ids
->parent_wname
);
1455 list_for_each_entry(w
, &platform
->component
.card
->widgets
, list
) {
1456 if (!strncmp(ids
->parent_wname
, w
->name
, len
)) {
1464 * sst_map_modules_to_pipe - fill algo/gains list for all pipes
1466 static int sst_map_modules_to_pipe(struct snd_soc_platform
*platform
)
1468 struct snd_soc_dapm_widget
*w
;
1471 list_for_each_entry(w
, &platform
->component
.card
->widgets
, list
) {
1472 if (is_sst_dapm_widget(w
) && (w
->priv
)) {
1473 struct sst_ids
*ids
= w
->priv
;
1475 dev_dbg(platform
->dev
, "widget type=%d name=%s\n",
1477 INIT_LIST_HEAD(&ids
->algo_list
);
1478 INIT_LIST_HEAD(&ids
->gain_list
);
1479 ret
= sst_fill_widget_module_info(w
, platform
);
1484 /* fill linked widgets */
1485 if (ids
->parent_wname
!= NULL
)
1486 sst_fill_linked_widgets(platform
, ids
);
1492 int sst_dsp_init_v2_dpcm(struct snd_soc_platform
*platform
)
1495 struct snd_soc_dapm_context
*dapm
=
1496 snd_soc_component_get_dapm(&platform
->component
);
1497 struct sst_data
*drv
= snd_soc_platform_get_drvdata(platform
);
1498 unsigned int gains
= ARRAY_SIZE(sst_gain_controls
)/3;
1500 drv
->byte_stream
= devm_kzalloc(platform
->dev
,
1501 SST_MAX_BIN_BYTES
, GFP_KERNEL
);
1502 if (!drv
->byte_stream
)
1505 snd_soc_dapm_new_controls(dapm
, sst_dapm_widgets
,
1506 ARRAY_SIZE(sst_dapm_widgets
));
1507 snd_soc_dapm_add_routes(dapm
, intercon
,
1508 ARRAY_SIZE(intercon
));
1509 snd_soc_dapm_new_widgets(dapm
->card
);
1511 for (i
= 0; i
< gains
; i
++) {
1512 sst_gains
[i
].mute
= SST_GAIN_MUTE_DEFAULT
;
1513 sst_gains
[i
].l_gain
= SST_GAIN_VOLUME_DEFAULT
;
1514 sst_gains
[i
].r_gain
= SST_GAIN_VOLUME_DEFAULT
;
1515 sst_gains
[i
].ramp_duration
= SST_GAIN_RAMP_DURATION_DEFAULT
;
1518 ret
= snd_soc_add_platform_controls(platform
, sst_gain_controls
,
1519 ARRAY_SIZE(sst_gain_controls
));
1523 /* Initialize algo control params */
1524 ret
= sst_algo_control_init(platform
->dev
);
1527 ret
= snd_soc_add_platform_controls(platform
, sst_algo_controls
,
1528 ARRAY_SIZE(sst_algo_controls
));
1532 ret
= snd_soc_add_platform_controls(platform
, sst_slot_controls
,
1533 ARRAY_SIZE(sst_slot_controls
));
1537 ret
= sst_map_modules_to_pipe(platform
);