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_MODEM
] = SST_SWM_IN_MODEM
,
538 [SST_IP_CODEC0
] = SST_SWM_IN_CODEC0
,
539 [SST_IP_CODEC1
] = SST_SWM_IN_CODEC1
,
540 [SST_IP_LOOP0
] = SST_SWM_IN_SPROT_LOOP
,
541 [SST_IP_LOOP1
] = SST_SWM_IN_MEDIA_LOOP1
,
542 [SST_IP_LOOP2
] = SST_SWM_IN_MEDIA_LOOP2
,
543 [SST_IP_PCM0
] = SST_SWM_IN_PCM0
,
544 [SST_IP_PCM1
] = SST_SWM_IN_PCM1
,
545 [SST_IP_MEDIA0
] = SST_SWM_IN_MEDIA0
,
546 [SST_IP_MEDIA1
] = SST_SWM_IN_MEDIA1
,
547 [SST_IP_MEDIA2
] = SST_SWM_IN_MEDIA2
,
548 [SST_IP_MEDIA3
] = SST_SWM_IN_MEDIA3
,
552 * fill_swm_input - fill in the SWM input ids given the register
554 * The register value is a bit-field inicated which mixer inputs are ON. Use the
555 * lookup table to get the input-id and fill it in the structure.
557 static int fill_swm_input(struct snd_soc_component
*cmpnt
,
558 struct swm_input_ids
*swm_input
, unsigned int reg
)
560 uint i
, is_set
, nb_inputs
= 0;
563 dev_dbg(cmpnt
->dev
, "reg: %#x\n", reg
);
564 for (i
= 0; i
< SST_SWM_INPUT_COUNT
; i
++) {
565 is_set
= reg
& BIT(i
);
569 input_loc_id
= swm_mixer_input_ids
[i
];
570 SST_FILL_DESTINATION(2, swm_input
->input_id
,
571 input_loc_id
, SST_DEFAULT_MODULE_ID
);
574 dev_dbg(cmpnt
->dev
, "input id: %#x, nb_inputs: %d\n",
575 input_loc_id
, nb_inputs
);
577 if (nb_inputs
== SST_CMD_SWM_MAX_INPUTS
) {
578 dev_warn(cmpnt
->dev
, "SET_SWM cmd max inputs reached");
587 * called with lock held
589 static int sst_set_pipe_gain(struct sst_ids
*ids
,
590 struct sst_data
*drv
, int mute
)
593 struct sst_gain_mixer_control
*mc
;
594 struct sst_gain_value
*gv
;
595 struct sst_module
*gain
= NULL
;
597 list_for_each_entry(gain
, &ids
->gain_list
, node
) {
598 struct snd_kcontrol
*kctl
= gain
->kctl
;
600 dev_dbg(&drv
->pdev
->dev
, "control name=%s\n", kctl
->id
.name
);
601 mc
= (void *)kctl
->private_value
;
604 ret
= sst_send_gain_cmd(drv
, gv
, mc
->task_id
,
605 mc
->pipe_id
| mc
->instance_id
, mc
->module_id
, mute
);
612 static int sst_swm_mixer_event(struct snd_soc_dapm_widget
*w
,
613 struct snd_kcontrol
*k
, int event
)
615 struct sst_cmd_set_swm cmd
;
616 struct snd_soc_component
*cmpnt
= snd_soc_dapm_to_component(w
->dapm
);
617 struct sst_data
*drv
= snd_soc_component_get_drvdata(cmpnt
);
618 struct sst_ids
*ids
= w
->priv
;
619 bool set_mixer
= false;
620 struct soc_mixer_control
*mc
;
624 dev_dbg(cmpnt
->dev
, "widget = %s\n", w
->name
);
626 * Identify which mixer input is on and send the bitmap of the
627 * inputs as an IPC to the DSP.
629 for (i
= 0; i
< w
->num_kcontrols
; i
++) {
630 if (dapm_kcontrol_get_value(w
->kcontrols
[i
])) {
631 mc
= (struct soc_mixer_control
*)(w
->kcontrols
[i
])->private_value
;
632 val
|= 1 << mc
->shift
;
635 dev_dbg(cmpnt
->dev
, "val = %#x\n", val
);
638 case SND_SOC_DAPM_PRE_PMU
:
639 case SND_SOC_DAPM_POST_PMD
:
642 case SND_SOC_DAPM_POST_REG
:
650 if (set_mixer
== false)
653 if (SND_SOC_DAPM_EVENT_ON(event
) ||
654 event
== SND_SOC_DAPM_POST_REG
)
655 cmd
.switch_state
= SST_SWM_ON
;
657 cmd
.switch_state
= SST_SWM_OFF
;
659 SST_FILL_DEFAULT_DESTINATION(cmd
.header
.dst
);
660 /* MMX_SET_SWM == SBA_SET_SWM */
661 cmd
.header
.command_id
= SBA_SET_SWM
;
663 SST_FILL_DESTINATION(2, cmd
.output_id
,
664 ids
->location_id
, SST_DEFAULT_MODULE_ID
);
665 cmd
.nb_inputs
= fill_swm_input(cmpnt
, &cmd
.input
[0], val
);
666 cmd
.header
.length
= offsetof(struct sst_cmd_set_swm
, input
)
667 - sizeof(struct sst_dsp_header
)
668 + (cmd
.nb_inputs
* sizeof(cmd
.input
[0]));
670 return sst_fill_and_send_cmd(drv
, SST_IPC_IA_CMD
, SST_FLAG_BLOCKED
,
671 ids
->task_id
, 0, &cmd
,
672 sizeof(cmd
.header
) + cmd
.header
.length
);
675 /* SBA mixers - 16 inputs */
676 #define SST_SBA_DECLARE_MIX_CONTROLS(kctl_name) \
677 static const struct snd_kcontrol_new kctl_name[] = { \
678 SOC_DAPM_SINGLE("modem_in Switch", SND_SOC_NOPM, SST_IP_MODEM, 1, 0), \
679 SOC_DAPM_SINGLE("codec_in0 Switch", SND_SOC_NOPM, SST_IP_CODEC0, 1, 0), \
680 SOC_DAPM_SINGLE("codec_in1 Switch", SND_SOC_NOPM, SST_IP_CODEC1, 1, 0), \
681 SOC_DAPM_SINGLE("sprot_loop_in Switch", SND_SOC_NOPM, SST_IP_LOOP0, 1, 0), \
682 SOC_DAPM_SINGLE("media_loop1_in Switch", SND_SOC_NOPM, SST_IP_LOOP1, 1, 0), \
683 SOC_DAPM_SINGLE("media_loop2_in Switch", SND_SOC_NOPM, SST_IP_LOOP2, 1, 0), \
684 SOC_DAPM_SINGLE("pcm0_in Switch", SND_SOC_NOPM, SST_IP_PCM0, 1, 0), \
685 SOC_DAPM_SINGLE("pcm1_in Switch", SND_SOC_NOPM, SST_IP_PCM1, 1, 0), \
688 #define SST_SBA_MIXER_GRAPH_MAP(mix_name) \
689 { mix_name, "modem_in Switch", "modem_in" }, \
690 { mix_name, "codec_in0 Switch", "codec_in0" }, \
691 { mix_name, "codec_in1 Switch", "codec_in1" }, \
692 { mix_name, "sprot_loop_in Switch", "sprot_loop_in" }, \
693 { mix_name, "media_loop1_in Switch", "media_loop1_in" }, \
694 { mix_name, "media_loop2_in Switch", "media_loop2_in" }, \
695 { mix_name, "pcm0_in Switch", "pcm0_in" }, \
696 { mix_name, "pcm1_in Switch", "pcm1_in" }
698 #define SST_MMX_DECLARE_MIX_CONTROLS(kctl_name) \
699 static const struct snd_kcontrol_new kctl_name[] = { \
700 SOC_DAPM_SINGLE("media0_in Switch", SND_SOC_NOPM, SST_IP_MEDIA0, 1, 0), \
701 SOC_DAPM_SINGLE("media1_in Switch", SND_SOC_NOPM, SST_IP_MEDIA1, 1, 0), \
702 SOC_DAPM_SINGLE("media2_in Switch", SND_SOC_NOPM, SST_IP_MEDIA2, 1, 0), \
703 SOC_DAPM_SINGLE("media3_in Switch", SND_SOC_NOPM, SST_IP_MEDIA3, 1, 0), \
706 SST_MMX_DECLARE_MIX_CONTROLS(sst_mix_media0_controls
);
707 SST_MMX_DECLARE_MIX_CONTROLS(sst_mix_media1_controls
);
710 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm0_controls
);
711 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm1_controls
);
712 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm2_controls
);
713 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_sprot_l0_controls
);
714 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l1_controls
);
715 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l2_controls
);
716 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_voip_controls
);
717 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec0_controls
);
718 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec1_controls
);
719 SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_modem_controls
);
722 * sst_handle_vb_timer - Start/Stop the DSP scheduler
724 * The DSP expects first cmd to be SBA_VB_START, so at first startup send
726 * DSP expects last cmd to be SBA_VB_IDLE, so at last shutdown send that.
728 * Do refcount internally so that we send command only at first start
729 * and last end. Since SST driver does its own ref count, invoke sst's
732 int sst_handle_vb_timer(struct snd_soc_dai
*dai
, bool enable
)
735 struct sst_cmd_generic cmd
;
736 struct sst_data
*drv
= snd_soc_dai_get_drvdata(dai
);
737 static int timer_usage
;
740 cmd
.header
.command_id
= SBA_VB_START
;
742 cmd
.header
.command_id
= SBA_IDLE
;
743 dev_dbg(dai
->dev
, "enable=%u, usage=%d\n", enable
, timer_usage
);
745 SST_FILL_DEFAULT_DESTINATION(cmd
.header
.dst
);
746 cmd
.header
.length
= 0;
749 ret
= sst
->ops
->power(sst
->dev
, true);
754 mutex_lock(&drv
->lock
);
761 * Send the command only if this call is the first enable or last
764 if ((enable
&& (timer_usage
== 1)) ||
765 (!enable
&& (timer_usage
== 0))) {
766 ret
= sst_fill_and_send_cmd_unlocked(drv
, SST_IPC_IA_CMD
,
767 SST_FLAG_BLOCKED
, SST_TASK_SBA
, 0, &cmd
,
768 sizeof(cmd
.header
) + cmd
.header
.length
);
774 mutex_unlock(&drv
->lock
);
777 sst
->ops
->power(sst
->dev
, false);
781 int sst_fill_ssp_slot(struct snd_soc_dai
*dai
, unsigned int tx_mask
,
782 unsigned int rx_mask
, int slots
, int slot_width
)
784 struct sst_data
*ctx
= snd_soc_dai_get_drvdata(dai
);
786 ctx
->ssp_cmd
.nb_slots
= slots
;
787 ctx
->ssp_cmd
.active_tx_slot_map
= tx_mask
;
788 ctx
->ssp_cmd
.active_rx_slot_map
= rx_mask
;
789 ctx
->ssp_cmd
.nb_bits_per_slots
= slot_width
;
794 static int sst_get_frame_sync_polarity(struct snd_soc_dai
*dai
,
799 format
= fmt
& SND_SOC_DAIFMT_INV_MASK
;
800 dev_dbg(dai
->dev
, "Enter:%s, format=%x\n", __func__
, format
);
803 case SND_SOC_DAIFMT_NB_NF
:
804 return SSP_FS_ACTIVE_LOW
;
805 case SND_SOC_DAIFMT_NB_IF
:
806 return SSP_FS_ACTIVE_HIGH
;
807 case SND_SOC_DAIFMT_IB_IF
:
808 return SSP_FS_ACTIVE_LOW
;
809 case SND_SOC_DAIFMT_IB_NF
:
810 return SSP_FS_ACTIVE_HIGH
;
812 dev_err(dai
->dev
, "Invalid frame sync polarity %d\n", format
);
818 static int sst_get_ssp_mode(struct snd_soc_dai
*dai
, unsigned int fmt
)
822 format
= (fmt
& SND_SOC_DAIFMT_MASTER_MASK
);
823 dev_dbg(dai
->dev
, "Enter:%s, format=%x\n", __func__
, format
);
826 case SND_SOC_DAIFMT_CBS_CFS
:
827 return SSP_MODE_MASTER
;
828 case SND_SOC_DAIFMT_CBM_CFM
:
829 return SSP_MODE_SLAVE
;
831 dev_err(dai
->dev
, "Invalid ssp protocol: %d\n", format
);
838 int sst_fill_ssp_config(struct snd_soc_dai
*dai
, unsigned int fmt
)
842 struct sst_data
*ctx
= snd_soc_dai_get_drvdata(dai
);
844 mode
= fmt
& SND_SOC_DAIFMT_FORMAT_MASK
;
847 case SND_SOC_DAIFMT_DSP_B
:
848 ctx
->ssp_cmd
.ssp_protocol
= SSP_MODE_PCM
;
849 ctx
->ssp_cmd
.mode
= sst_get_ssp_mode(dai
, fmt
) | (SSP_PCM_MODE_NETWORK
<< 1);
850 ctx
->ssp_cmd
.start_delay
= 0;
851 ctx
->ssp_cmd
.data_polarity
= 1;
852 ctx
->ssp_cmd
.frame_sync_width
= 1;
855 case SND_SOC_DAIFMT_DSP_A
:
856 ctx
->ssp_cmd
.ssp_protocol
= SSP_MODE_PCM
;
857 ctx
->ssp_cmd
.mode
= sst_get_ssp_mode(dai
, fmt
) | (SSP_PCM_MODE_NETWORK
<< 1);
858 ctx
->ssp_cmd
.start_delay
= 1;
859 ctx
->ssp_cmd
.data_polarity
= 1;
860 ctx
->ssp_cmd
.frame_sync_width
= 1;
863 case SND_SOC_DAIFMT_I2S
:
864 ctx
->ssp_cmd
.ssp_protocol
= SSP_MODE_I2S
;
865 ctx
->ssp_cmd
.mode
= sst_get_ssp_mode(dai
, fmt
) | (SSP_PCM_MODE_NORMAL
<< 1);
866 ctx
->ssp_cmd
.start_delay
= 1;
867 ctx
->ssp_cmd
.data_polarity
= 0;
868 ctx
->ssp_cmd
.frame_sync_width
= ctx
->ssp_cmd
.nb_bits_per_slots
;
871 case SND_SOC_DAIFMT_LEFT_J
:
872 ctx
->ssp_cmd
.ssp_protocol
= SSP_MODE_I2S
;
873 ctx
->ssp_cmd
.mode
= sst_get_ssp_mode(dai
, fmt
) | (SSP_PCM_MODE_NORMAL
<< 1);
874 ctx
->ssp_cmd
.start_delay
= 0;
875 ctx
->ssp_cmd
.data_polarity
= 0;
876 ctx
->ssp_cmd
.frame_sync_width
= ctx
->ssp_cmd
.nb_bits_per_slots
;
880 dev_dbg(dai
->dev
, "using default ssp configs\n");
883 fs_polarity
= sst_get_frame_sync_polarity(dai
, fmt
);
887 ctx
->ssp_cmd
.frame_sync_polarity
= fs_polarity
;
893 * sst_ssp_config - contains SSP configuration for media UC
894 * this can be overwritten by set_dai_xxx APIs
896 static const struct sst_ssp_config sst_ssp_configs
= {
900 .ssp_mode
= SSP_MODE_MASTER
,
901 .pcm_mode
= SSP_PCM_MODE_NETWORK
,
902 .duplex
= SSP_DUPLEX
,
903 .ssp_protocol
= SSP_MODE_PCM
,
905 .fs_frequency
= SSP_FS_48_KHZ
,
906 .active_slot_map
= 0xF,
908 .frame_sync_polarity
= SSP_FS_ACTIVE_HIGH
,
912 void sst_fill_ssp_defaults(struct snd_soc_dai
*dai
)
914 const struct sst_ssp_config
*config
;
915 struct sst_data
*ctx
= snd_soc_dai_get_drvdata(dai
);
917 config
= &sst_ssp_configs
;
919 ctx
->ssp_cmd
.selection
= config
->ssp_id
;
920 ctx
->ssp_cmd
.nb_bits_per_slots
= config
->bits_per_slot
;
921 ctx
->ssp_cmd
.nb_slots
= config
->slots
;
922 ctx
->ssp_cmd
.mode
= config
->ssp_mode
| (config
->pcm_mode
<< 1);
923 ctx
->ssp_cmd
.duplex
= config
->duplex
;
924 ctx
->ssp_cmd
.active_tx_slot_map
= config
->active_slot_map
;
925 ctx
->ssp_cmd
.active_rx_slot_map
= config
->active_slot_map
;
926 ctx
->ssp_cmd
.frame_sync_frequency
= config
->fs_frequency
;
927 ctx
->ssp_cmd
.frame_sync_polarity
= config
->frame_sync_polarity
;
928 ctx
->ssp_cmd
.data_polarity
= config
->data_polarity
;
929 ctx
->ssp_cmd
.frame_sync_width
= config
->fs_width
;
930 ctx
->ssp_cmd
.ssp_protocol
= config
->ssp_protocol
;
931 ctx
->ssp_cmd
.start_delay
= config
->start_delay
;
932 ctx
->ssp_cmd
.reserved1
= ctx
->ssp_cmd
.reserved2
= 0xFF;
935 int send_ssp_cmd(struct snd_soc_dai
*dai
, const char *id
, bool enable
)
937 struct sst_data
*drv
= snd_soc_dai_get_drvdata(dai
);
940 dev_info(dai
->dev
, "Enter: enable=%d port_name=%s\n", enable
, id
);
942 if (strcmp(id
, "ssp0-port") == 0)
944 else if (strcmp(id
, "ssp2-port") == 0)
947 dev_dbg(dai
->dev
, "port %s is not supported\n", id
);
951 SST_FILL_DEFAULT_DESTINATION(drv
->ssp_cmd
.header
.dst
);
952 drv
->ssp_cmd
.header
.command_id
= SBA_HW_SET_SSP
;
953 drv
->ssp_cmd
.header
.length
= sizeof(struct sst_cmd_sba_hw_set_ssp
)
954 - sizeof(struct sst_dsp_header
);
956 drv
->ssp_cmd
.selection
= ssp_id
;
957 dev_dbg(dai
->dev
, "ssp_id: %u\n", ssp_id
);
960 drv
->ssp_cmd
.switch_state
= SST_SWITCH_ON
;
962 drv
->ssp_cmd
.switch_state
= SST_SWITCH_OFF
;
964 return sst_fill_and_send_cmd(drv
, SST_IPC_IA_CMD
, SST_FLAG_BLOCKED
,
965 SST_TASK_SBA
, 0, &drv
->ssp_cmd
,
966 sizeof(drv
->ssp_cmd
.header
) + drv
->ssp_cmd
.header
.length
);
969 static int sst_set_be_modules(struct snd_soc_dapm_widget
*w
,
970 struct snd_kcontrol
*k
, int event
)
973 struct snd_soc_component
*c
= snd_soc_dapm_to_component(w
->dapm
);
974 struct sst_data
*drv
= snd_soc_component_get_drvdata(c
);
976 dev_dbg(c
->dev
, "Enter: widget=%s\n", w
->name
);
978 if (SND_SOC_DAPM_EVENT_ON(event
)) {
979 ret
= sst_send_slot_map(drv
);
982 ret
= sst_send_pipe_module_params(w
, k
);
987 static int sst_set_media_path(struct snd_soc_dapm_widget
*w
,
988 struct snd_kcontrol
*k
, int event
)
991 struct sst_cmd_set_media_path cmd
;
992 struct snd_soc_component
*c
= snd_soc_dapm_to_component(w
->dapm
);
993 struct sst_data
*drv
= snd_soc_component_get_drvdata(c
);
994 struct sst_ids
*ids
= w
->priv
;
996 dev_dbg(c
->dev
, "widget=%s\n", w
->name
);
997 dev_dbg(c
->dev
, "task=%u, location=%#x\n",
998 ids
->task_id
, ids
->location_id
);
1000 if (SND_SOC_DAPM_EVENT_ON(event
))
1001 cmd
.switch_state
= SST_PATH_ON
;
1003 cmd
.switch_state
= SST_PATH_OFF
;
1005 SST_FILL_DESTINATION(2, cmd
.header
.dst
,
1006 ids
->location_id
, SST_DEFAULT_MODULE_ID
);
1008 /* MMX_SET_MEDIA_PATH == SBA_SET_MEDIA_PATH */
1009 cmd
.header
.command_id
= MMX_SET_MEDIA_PATH
;
1010 cmd
.header
.length
= sizeof(struct sst_cmd_set_media_path
)
1011 - sizeof(struct sst_dsp_header
);
1013 ret
= sst_fill_and_send_cmd(drv
, SST_IPC_IA_CMD
, SST_FLAG_BLOCKED
,
1014 ids
->task_id
, 0, &cmd
,
1015 sizeof(cmd
.header
) + cmd
.header
.length
);
1019 if (SND_SOC_DAPM_EVENT_ON(event
))
1020 ret
= sst_send_pipe_module_params(w
, k
);
1024 static int sst_set_media_loop(struct snd_soc_dapm_widget
*w
,
1025 struct snd_kcontrol
*k
, int event
)
1028 struct sst_cmd_sba_set_media_loop_map cmd
;
1029 struct snd_soc_component
*c
= snd_soc_dapm_to_component(w
->dapm
);
1030 struct sst_data
*drv
= snd_soc_component_get_drvdata(c
);
1031 struct sst_ids
*ids
= w
->priv
;
1033 dev_dbg(c
->dev
, "Enter:widget=%s\n", w
->name
);
1034 if (SND_SOC_DAPM_EVENT_ON(event
))
1035 cmd
.switch_state
= SST_SWITCH_ON
;
1037 cmd
.switch_state
= SST_SWITCH_OFF
;
1039 SST_FILL_DESTINATION(2, cmd
.header
.dst
,
1040 ids
->location_id
, SST_DEFAULT_MODULE_ID
);
1042 cmd
.header
.command_id
= SBA_SET_MEDIA_LOOP_MAP
;
1043 cmd
.header
.length
= sizeof(struct sst_cmd_sba_set_media_loop_map
)
1044 - sizeof(struct sst_dsp_header
);
1045 cmd
.param
.part
.cfg
.rate
= 2; /* 48khz */
1047 cmd
.param
.part
.cfg
.format
= ids
->format
; /* stereo/Mono */
1048 cmd
.param
.part
.cfg
.s_length
= 1; /* 24bit left justified */
1049 cmd
.map
= 0; /* Algo sequence: Gain - DRP - FIR - IIR */
1051 ret
= sst_fill_and_send_cmd(drv
, SST_IPC_IA_CMD
, SST_FLAG_BLOCKED
,
1052 SST_TASK_SBA
, 0, &cmd
,
1053 sizeof(cmd
.header
) + cmd
.header
.length
);
1057 if (SND_SOC_DAPM_EVENT_ON(event
))
1058 ret
= sst_send_pipe_module_params(w
, k
);
1062 static const struct snd_soc_dapm_widget sst_dapm_widgets
[] = {
1063 SST_AIF_IN("modem_in", sst_set_be_modules
),
1064 SST_AIF_IN("codec_in0", sst_set_be_modules
),
1065 SST_AIF_IN("codec_in1", sst_set_be_modules
),
1066 SST_AIF_OUT("modem_out", sst_set_be_modules
),
1067 SST_AIF_OUT("codec_out0", sst_set_be_modules
),
1068 SST_AIF_OUT("codec_out1", sst_set_be_modules
),
1071 /* MediaX IN paths are set via ALLOC, so no SET_MEDIA_PATH command */
1072 SST_PATH_INPUT("media0_in", SST_TASK_MMX
, SST_SWM_IN_MEDIA0
, sst_generic_modules_event
),
1073 SST_PATH_INPUT("media1_in", SST_TASK_MMX
, SST_SWM_IN_MEDIA1
, NULL
),
1074 SST_PATH_INPUT("media2_in", SST_TASK_MMX
, SST_SWM_IN_MEDIA2
, sst_set_media_path
),
1075 SST_PATH_INPUT("media3_in", SST_TASK_MMX
, SST_SWM_IN_MEDIA3
, NULL
),
1076 SST_PATH_OUTPUT("media0_out", SST_TASK_MMX
, SST_SWM_OUT_MEDIA0
, sst_set_media_path
),
1077 SST_PATH_OUTPUT("media1_out", SST_TASK_MMX
, SST_SWM_OUT_MEDIA1
, sst_set_media_path
),
1080 SST_PATH_INPUT("pcm0_in", SST_TASK_SBA
, SST_SWM_IN_PCM0
, sst_set_media_path
),
1081 SST_PATH_INPUT("pcm1_in", SST_TASK_SBA
, SST_SWM_IN_PCM1
, sst_set_media_path
),
1082 SST_PATH_OUTPUT("pcm0_out", SST_TASK_SBA
, SST_SWM_OUT_PCM0
, sst_set_media_path
),
1083 SST_PATH_OUTPUT("pcm1_out", SST_TASK_SBA
, SST_SWM_OUT_PCM1
, sst_set_media_path
),
1084 SST_PATH_OUTPUT("pcm2_out", SST_TASK_SBA
, SST_SWM_OUT_PCM2
, sst_set_media_path
),
1087 SST_PATH_INPUT("sprot_loop_in", SST_TASK_SBA
, SST_SWM_IN_SPROT_LOOP
, NULL
),
1088 SST_PATH_INPUT("media_loop1_in", SST_TASK_SBA
, SST_SWM_IN_MEDIA_LOOP1
, NULL
),
1089 SST_PATH_INPUT("media_loop2_in", SST_TASK_SBA
, SST_SWM_IN_MEDIA_LOOP2
, NULL
),
1090 SST_PATH_MEDIA_LOOP_OUTPUT("sprot_loop_out", SST_TASK_SBA
, SST_SWM_OUT_SPROT_LOOP
, SST_FMT_MONO
, sst_set_media_loop
),
1091 SST_PATH_MEDIA_LOOP_OUTPUT("media_loop1_out", SST_TASK_SBA
, SST_SWM_OUT_MEDIA_LOOP1
, SST_FMT_MONO
, sst_set_media_loop
),
1092 SST_PATH_MEDIA_LOOP_OUTPUT("media_loop2_out", SST_TASK_SBA
, SST_SWM_OUT_MEDIA_LOOP2
, SST_FMT_STEREO
, sst_set_media_loop
),
1095 SST_SWM_MIXER("media0_out mix 0", SND_SOC_NOPM
, SST_TASK_MMX
, SST_SWM_OUT_MEDIA0
,
1096 sst_mix_media0_controls
, sst_swm_mixer_event
),
1097 SST_SWM_MIXER("media1_out mix 0", SND_SOC_NOPM
, SST_TASK_MMX
, SST_SWM_OUT_MEDIA1
,
1098 sst_mix_media1_controls
, sst_swm_mixer_event
),
1100 /* SBA PCM mixers */
1101 SST_SWM_MIXER("pcm0_out mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_PCM0
,
1102 sst_mix_pcm0_controls
, sst_swm_mixer_event
),
1103 SST_SWM_MIXER("pcm1_out mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_PCM1
,
1104 sst_mix_pcm1_controls
, sst_swm_mixer_event
),
1105 SST_SWM_MIXER("pcm2_out mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_PCM2
,
1106 sst_mix_pcm2_controls
, sst_swm_mixer_event
),
1108 /* SBA Loop mixers */
1109 SST_SWM_MIXER("sprot_loop_out mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_SPROT_LOOP
,
1110 sst_mix_sprot_l0_controls
, sst_swm_mixer_event
),
1111 SST_SWM_MIXER("media_loop1_out mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_MEDIA_LOOP1
,
1112 sst_mix_media_l1_controls
, sst_swm_mixer_event
),
1113 SST_SWM_MIXER("media_loop2_out mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_MEDIA_LOOP2
,
1114 sst_mix_media_l2_controls
, sst_swm_mixer_event
),
1116 /* SBA Backend mixers */
1117 SST_SWM_MIXER("codec_out0 mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_CODEC0
,
1118 sst_mix_codec0_controls
, sst_swm_mixer_event
),
1119 SST_SWM_MIXER("codec_out1 mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_CODEC1
,
1120 sst_mix_codec1_controls
, sst_swm_mixer_event
),
1121 SST_SWM_MIXER("modem_out mix 0", SND_SOC_NOPM
, SST_TASK_SBA
, SST_SWM_OUT_MODEM
,
1122 sst_mix_modem_controls
, sst_swm_mixer_event
),
1126 static const struct snd_soc_dapm_route intercon
[] = {
1127 {"media0_in", NULL
, "Compress Playback"},
1128 {"media1_in", NULL
, "Headset Playback"},
1129 {"media2_in", NULL
, "pcm0_out"},
1130 {"media3_in", NULL
, "Deepbuffer Playback"},
1132 {"media0_out mix 0", "media0_in Switch", "media0_in"},
1133 {"media0_out mix 0", "media1_in Switch", "media1_in"},
1134 {"media0_out mix 0", "media2_in Switch", "media2_in"},
1135 {"media0_out mix 0", "media3_in Switch", "media3_in"},
1136 {"media1_out mix 0", "media0_in Switch", "media0_in"},
1137 {"media1_out mix 0", "media1_in Switch", "media1_in"},
1138 {"media1_out mix 0", "media2_in Switch", "media2_in"},
1139 {"media1_out mix 0", "media3_in Switch", "media3_in"},
1141 {"media0_out", NULL
, "media0_out mix 0"},
1142 {"media1_out", NULL
, "media1_out mix 0"},
1143 {"pcm0_in", NULL
, "media0_out"},
1144 {"pcm1_in", NULL
, "media1_out"},
1146 {"Headset Capture", NULL
, "pcm1_out"},
1147 {"Headset Capture", NULL
, "pcm2_out"},
1148 {"pcm0_out", NULL
, "pcm0_out mix 0"},
1149 SST_SBA_MIXER_GRAPH_MAP("pcm0_out mix 0"),
1150 {"pcm1_out", NULL
, "pcm1_out mix 0"},
1151 SST_SBA_MIXER_GRAPH_MAP("pcm1_out mix 0"),
1152 {"pcm2_out", NULL
, "pcm2_out mix 0"},
1153 SST_SBA_MIXER_GRAPH_MAP("pcm2_out mix 0"),
1155 {"media_loop1_in", NULL
, "media_loop1_out"},
1156 {"media_loop1_out", NULL
, "media_loop1_out mix 0"},
1157 SST_SBA_MIXER_GRAPH_MAP("media_loop1_out mix 0"),
1158 {"media_loop2_in", NULL
, "media_loop2_out"},
1159 {"media_loop2_out", NULL
, "media_loop2_out mix 0"},
1160 SST_SBA_MIXER_GRAPH_MAP("media_loop2_out mix 0"),
1161 {"sprot_loop_in", NULL
, "sprot_loop_out"},
1162 {"sprot_loop_out", NULL
, "sprot_loop_out mix 0"},
1163 SST_SBA_MIXER_GRAPH_MAP("sprot_loop_out mix 0"),
1165 {"codec_out0", NULL
, "codec_out0 mix 0"},
1166 SST_SBA_MIXER_GRAPH_MAP("codec_out0 mix 0"),
1167 {"codec_out1", NULL
, "codec_out1 mix 0"},
1168 SST_SBA_MIXER_GRAPH_MAP("codec_out1 mix 0"),
1169 {"modem_out", NULL
, "modem_out mix 0"},
1170 SST_SBA_MIXER_GRAPH_MAP("modem_out mix 0"),
1174 static const char * const slot_names
[] = {
1176 "slot 0", "slot 1", "slot 2", "slot 3",
1177 "slot 4", "slot 5", "slot 6", "slot 7", /* not supported by FW */
1180 static const char * const channel_names
[] = {
1182 "codec_out0_0", "codec_out0_1", "codec_out1_0", "codec_out1_1",
1183 "codec_out2_0", "codec_out2_1", "codec_out3_0", "codec_out3_1", /* not supported by FW */
1186 #define SST_INTERLEAVER(xpname, slot_name, slotno) \
1187 SST_SSP_SLOT_CTL(xpname, "tx interleaver", slot_name, slotno, true, \
1188 channel_names, sst_slot_get, sst_slot_put)
1190 #define SST_DEINTERLEAVER(xpname, channel_name, channel_no) \
1191 SST_SSP_SLOT_CTL(xpname, "rx deinterleaver", channel_name, channel_no, false, \
1192 slot_names, sst_slot_get, sst_slot_put)
1194 static const struct snd_kcontrol_new sst_slot_controls
[] = {
1195 SST_INTERLEAVER("codec_out", "slot 0", 0),
1196 SST_INTERLEAVER("codec_out", "slot 1", 1),
1197 SST_INTERLEAVER("codec_out", "slot 2", 2),
1198 SST_INTERLEAVER("codec_out", "slot 3", 3),
1199 SST_DEINTERLEAVER("codec_in", "codec_in0_0", 0),
1200 SST_DEINTERLEAVER("codec_in", "codec_in0_1", 1),
1201 SST_DEINTERLEAVER("codec_in", "codec_in1_0", 2),
1202 SST_DEINTERLEAVER("codec_in", "codec_in1_1", 3),
1205 /* Gain helper with min/max set */
1206 #define SST_GAIN(name, path_id, task_id, instance, gain_var) \
1207 SST_GAIN_KCONTROLS(name, "Gain", SST_GAIN_MIN_VALUE, SST_GAIN_MAX_VALUE, \
1208 SST_GAIN_TC_MIN, SST_GAIN_TC_MAX, \
1209 sst_gain_get, sst_gain_put, \
1210 SST_MODULE_ID_GAIN_CELL, path_id, instance, task_id, \
1211 sst_gain_tlv_common, gain_var)
1213 #define SST_VOLUME(name, path_id, task_id, instance, gain_var) \
1214 SST_GAIN_KCONTROLS(name, "Volume", SST_GAIN_MIN_VALUE, SST_GAIN_MAX_VALUE, \
1215 SST_GAIN_TC_MIN, SST_GAIN_TC_MAX, \
1216 sst_gain_get, sst_gain_put, \
1217 SST_MODULE_ID_VOLUME, path_id, instance, task_id, \
1218 sst_gain_tlv_common, gain_var)
1220 static struct sst_gain_value sst_gains
[];
1222 static const struct snd_kcontrol_new sst_gain_controls
[] = {
1223 SST_GAIN("media0_in", SST_PATH_INDEX_MEDIA0_IN
, SST_TASK_MMX
, 0, &sst_gains
[0]),
1224 SST_GAIN("media1_in", SST_PATH_INDEX_MEDIA1_IN
, SST_TASK_MMX
, 0, &sst_gains
[1]),
1225 SST_GAIN("media2_in", SST_PATH_INDEX_MEDIA2_IN
, SST_TASK_MMX
, 0, &sst_gains
[2]),
1226 SST_GAIN("media3_in", SST_PATH_INDEX_MEDIA3_IN
, SST_TASK_MMX
, 0, &sst_gains
[3]),
1228 SST_GAIN("pcm0_in", SST_PATH_INDEX_PCM0_IN
, SST_TASK_SBA
, 0, &sst_gains
[4]),
1229 SST_GAIN("pcm1_in", SST_PATH_INDEX_PCM1_IN
, SST_TASK_SBA
, 0, &sst_gains
[5]),
1230 SST_GAIN("pcm1_out", SST_PATH_INDEX_PCM1_OUT
, SST_TASK_SBA
, 0, &sst_gains
[6]),
1231 SST_GAIN("pcm2_out", SST_PATH_INDEX_PCM2_OUT
, SST_TASK_SBA
, 0, &sst_gains
[7]),
1233 SST_GAIN("codec_in0", SST_PATH_INDEX_CODEC_IN0
, SST_TASK_SBA
, 0, &sst_gains
[8]),
1234 SST_GAIN("codec_in1", SST_PATH_INDEX_CODEC_IN1
, SST_TASK_SBA
, 0, &sst_gains
[9]),
1235 SST_GAIN("codec_out0", SST_PATH_INDEX_CODEC_OUT0
, SST_TASK_SBA
, 0, &sst_gains
[10]),
1236 SST_GAIN("codec_out1", SST_PATH_INDEX_CODEC_OUT1
, SST_TASK_SBA
, 0, &sst_gains
[11]),
1237 SST_GAIN("media_loop1_out", SST_PATH_INDEX_MEDIA_LOOP1_OUT
, SST_TASK_SBA
, 0, &sst_gains
[12]),
1238 SST_GAIN("media_loop2_out", SST_PATH_INDEX_MEDIA_LOOP2_OUT
, SST_TASK_SBA
, 0, &sst_gains
[13]),
1239 SST_GAIN("sprot_loop_out", SST_PATH_INDEX_SPROT_LOOP_OUT
, SST_TASK_SBA
, 0, &sst_gains
[14]),
1240 SST_VOLUME("media0_in", SST_PATH_INDEX_MEDIA0_IN
, SST_TASK_MMX
, 0, &sst_gains
[15]),
1241 SST_GAIN("modem_in", SST_PATH_INDEX_MODEM_IN
, SST_TASK_SBA
, 0, &sst_gains
[16]),
1242 SST_GAIN("modem_out", SST_PATH_INDEX_MODEM_OUT
, SST_TASK_SBA
, 0, &sst_gains
[17]),
1246 #define SST_GAIN_NUM_CONTROLS 3
1247 /* the SST_GAIN macro above will create three alsa controls for each
1248 * instance invoked, gain, mute and ramp duration, which use the same gain
1249 * cell sst_gain to keep track of data
1250 * To calculate number of gain cell instances we need to device by 3 in
1251 * below caulcation for gain cell memory.
1252 * This gets rid of static number and issues while adding new controls
1254 static struct sst_gain_value sst_gains
[ARRAY_SIZE(sst_gain_controls
)/SST_GAIN_NUM_CONTROLS
];
1256 static const struct snd_kcontrol_new sst_algo_controls
[] = {
1257 SST_ALGO_KCONTROL_BYTES("media_loop1_out", "fir", 272, SST_MODULE_ID_FIR_24
,
1258 SST_PATH_INDEX_MEDIA_LOOP1_OUT
, 0, SST_TASK_SBA
, SBA_VB_SET_FIR
),
1259 SST_ALGO_KCONTROL_BYTES("media_loop1_out", "iir", 300, SST_MODULE_ID_IIR_24
,
1260 SST_PATH_INDEX_MEDIA_LOOP1_OUT
, 0, SST_TASK_SBA
, SBA_VB_SET_IIR
),
1261 SST_ALGO_KCONTROL_BYTES("media_loop1_out", "mdrp", 286, SST_MODULE_ID_MDRP
,
1262 SST_PATH_INDEX_MEDIA_LOOP1_OUT
, 0, SST_TASK_SBA
, SBA_SET_MDRP
),
1263 SST_ALGO_KCONTROL_BYTES("media_loop2_out", "fir", 272, SST_MODULE_ID_FIR_24
,
1264 SST_PATH_INDEX_MEDIA_LOOP2_OUT
, 0, SST_TASK_SBA
, SBA_VB_SET_FIR
),
1265 SST_ALGO_KCONTROL_BYTES("media_loop2_out", "iir", 300, SST_MODULE_ID_IIR_24
,
1266 SST_PATH_INDEX_MEDIA_LOOP2_OUT
, 0, SST_TASK_SBA
, SBA_VB_SET_IIR
),
1267 SST_ALGO_KCONTROL_BYTES("media_loop2_out", "mdrp", 286, SST_MODULE_ID_MDRP
,
1268 SST_PATH_INDEX_MEDIA_LOOP2_OUT
, 0, SST_TASK_SBA
, SBA_SET_MDRP
),
1269 SST_ALGO_KCONTROL_BYTES("sprot_loop_out", "lpro", 192, SST_MODULE_ID_SPROT
,
1270 SST_PATH_INDEX_SPROT_LOOP_OUT
, 0, SST_TASK_SBA
, SBA_VB_LPRO
),
1271 SST_ALGO_KCONTROL_BYTES("codec_in0", "dcr", 52, SST_MODULE_ID_FILT_DCR
,
1272 SST_PATH_INDEX_CODEC_IN0
, 0, SST_TASK_SBA
, SBA_VB_SET_IIR
),
1273 SST_ALGO_KCONTROL_BYTES("codec_in1", "dcr", 52, SST_MODULE_ID_FILT_DCR
,
1274 SST_PATH_INDEX_CODEC_IN1
, 0, SST_TASK_SBA
, SBA_VB_SET_IIR
),
1278 static int sst_algo_control_init(struct device
*dev
)
1281 struct sst_algo_control
*bc
;
1282 /*allocate space to cache the algo parameters in the driver*/
1283 for (i
= 0; i
< ARRAY_SIZE(sst_algo_controls
); i
++) {
1284 bc
= (struct sst_algo_control
*)sst_algo_controls
[i
].private_value
;
1285 bc
->params
= devm_kzalloc(dev
, bc
->max
, GFP_KERNEL
);
1286 if (bc
->params
== NULL
)
1292 static bool is_sst_dapm_widget(struct snd_soc_dapm_widget
*w
)
1295 case snd_soc_dapm_pga
:
1296 case snd_soc_dapm_aif_in
:
1297 case snd_soc_dapm_aif_out
:
1298 case snd_soc_dapm_input
:
1299 case snd_soc_dapm_output
:
1300 case snd_soc_dapm_mixer
:
1308 * sst_send_pipe_gains - send gains for the front-end DAIs
1310 * The gains in the pipes connected to the front-ends are muted/unmuted
1311 * automatically via the digital_mute() DAPM callback. This function sends the
1312 * gains for the front-end pipes.
1314 int sst_send_pipe_gains(struct snd_soc_dai
*dai
, int stream
, int mute
)
1316 struct sst_data
*drv
= snd_soc_dai_get_drvdata(dai
);
1317 struct snd_soc_dapm_widget
*w
;
1318 struct snd_soc_dapm_path
*p
= NULL
;
1320 dev_dbg(dai
->dev
, "enter, dai-name=%s dir=%d\n", dai
->name
, stream
);
1322 if (stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
1323 dev_dbg(dai
->dev
, "Stream name=%s\n",
1324 dai
->playback_widget
->name
);
1325 w
= dai
->playback_widget
;
1326 snd_soc_dapm_widget_for_each_sink_path(w
, p
) {
1327 if (p
->connected
&& !p
->connected(w
, p
->sink
))
1330 if (p
->connect
&& p
->sink
->power
&&
1331 is_sst_dapm_widget(p
->sink
)) {
1332 struct sst_ids
*ids
= p
->sink
->priv
;
1334 dev_dbg(dai
->dev
, "send gains for widget=%s\n",
1336 mutex_lock(&drv
->lock
);
1337 sst_set_pipe_gain(ids
, drv
, mute
);
1338 mutex_unlock(&drv
->lock
);
1342 dev_dbg(dai
->dev
, "Stream name=%s\n",
1343 dai
->capture_widget
->name
);
1344 w
= dai
->capture_widget
;
1345 snd_soc_dapm_widget_for_each_source_path(w
, p
) {
1346 if (p
->connected
&& !p
->connected(w
, p
->sink
))
1349 if (p
->connect
&& p
->source
->power
&&
1350 is_sst_dapm_widget(p
->source
)) {
1351 struct sst_ids
*ids
= p
->source
->priv
;
1353 dev_dbg(dai
->dev
, "send gain for widget=%s\n",
1355 mutex_lock(&drv
->lock
);
1356 sst_set_pipe_gain(ids
, drv
, mute
);
1357 mutex_unlock(&drv
->lock
);
1365 * sst_fill_module_list - populate the list of modules/gains for a pipe
1368 * Fills the widget pointer in the kcontrol private data, and also fills the
1369 * kcontrol pointer in the widget private data.
1371 * Widget pointer is used to send the algo/gain in the .put() handler if the
1372 * widget is powerd on.
1374 * Kcontrol pointer is used to send the algo/gain in the widget power ON/OFF
1375 * event handler. Each widget (pipe) has multiple algos stored in the algo_list.
1377 static int sst_fill_module_list(struct snd_kcontrol
*kctl
,
1378 struct snd_soc_dapm_widget
*w
, int type
)
1380 struct sst_module
*module
= NULL
;
1381 struct snd_soc_component
*c
= snd_soc_dapm_to_component(w
->dapm
);
1382 struct sst_ids
*ids
= w
->priv
;
1385 module
= devm_kzalloc(c
->dev
, sizeof(*module
), GFP_KERNEL
);
1389 if (type
== SST_MODULE_GAIN
) {
1390 struct sst_gain_mixer_control
*mc
= (void *)kctl
->private_value
;
1393 module
->kctl
= kctl
;
1394 list_add_tail(&module
->node
, &ids
->gain_list
);
1395 } else if (type
== SST_MODULE_ALGO
) {
1396 struct sst_algo_control
*bc
= (void *)kctl
->private_value
;
1399 module
->kctl
= kctl
;
1400 list_add_tail(&module
->node
, &ids
->algo_list
);
1402 dev_err(c
->dev
, "invoked for unknown type %d module %s",
1403 type
, kctl
->id
.name
);
1411 * sst_fill_widget_module_info - fill list of gains/algos for the pipe
1412 * @widget: pipe modelled as a DAPM widget
1414 * Fill the list of gains/algos for the widget by looking at all the card
1415 * controls and comparing the name of the widget with the first part of control
1416 * name. First part of control name contains the pipe name (widget name).
1418 static int sst_fill_widget_module_info(struct snd_soc_dapm_widget
*w
,
1419 struct snd_soc_platform
*platform
)
1421 struct snd_kcontrol
*kctl
;
1423 struct snd_card
*card
= platform
->component
.card
->snd_card
;
1426 down_read(&card
->controls_rwsem
);
1428 list_for_each_entry(kctl
, &card
->controls
, list
) {
1429 idx
= strchr(kctl
->id
.name
, ' ');
1432 index
= idx
- (char*)kctl
->id
.name
;
1433 if (strncmp(kctl
->id
.name
, w
->name
, index
))
1436 if (strstr(kctl
->id
.name
, "Volume"))
1437 ret
= sst_fill_module_list(kctl
, w
, SST_MODULE_GAIN
);
1439 else if (strstr(kctl
->id
.name
, "params"))
1440 ret
= sst_fill_module_list(kctl
, w
, SST_MODULE_ALGO
);
1442 else if (strstr(kctl
->id
.name
, "Switch") &&
1443 strstr(kctl
->id
.name
, "Gain")) {
1444 struct sst_gain_mixer_control
*mc
=
1445 (void *)kctl
->private_value
;
1449 } else if (strstr(kctl
->id
.name
, "interleaver")) {
1450 struct sst_enum
*e
= (void *)kctl
->private_value
;
1454 } else if (strstr(kctl
->id
.name
, "deinterleaver")) {
1455 struct sst_enum
*e
= (void *)kctl
->private_value
;
1461 up_read(&card
->controls_rwsem
);
1466 up_read(&card
->controls_rwsem
);
1471 * sst_fill_linked_widgets - fill the parent pointer for the linked widget
1473 static void sst_fill_linked_widgets(struct snd_soc_platform
*platform
,
1474 struct sst_ids
*ids
)
1476 struct snd_soc_dapm_widget
*w
;
1477 unsigned int len
= strlen(ids
->parent_wname
);
1479 list_for_each_entry(w
, &platform
->component
.card
->widgets
, list
) {
1480 if (!strncmp(ids
->parent_wname
, w
->name
, len
)) {
1488 * sst_map_modules_to_pipe - fill algo/gains list for all pipes
1490 static int sst_map_modules_to_pipe(struct snd_soc_platform
*platform
)
1492 struct snd_soc_dapm_widget
*w
;
1495 list_for_each_entry(w
, &platform
->component
.card
->widgets
, list
) {
1496 if (is_sst_dapm_widget(w
) && (w
->priv
)) {
1497 struct sst_ids
*ids
= w
->priv
;
1499 dev_dbg(platform
->dev
, "widget type=%d name=%s\n",
1501 INIT_LIST_HEAD(&ids
->algo_list
);
1502 INIT_LIST_HEAD(&ids
->gain_list
);
1503 ret
= sst_fill_widget_module_info(w
, platform
);
1508 /* fill linked widgets */
1509 if (ids
->parent_wname
!= NULL
)
1510 sst_fill_linked_widgets(platform
, ids
);
1516 int sst_dsp_init_v2_dpcm(struct snd_soc_platform
*platform
)
1519 struct snd_soc_dapm_context
*dapm
=
1520 snd_soc_component_get_dapm(&platform
->component
);
1521 struct sst_data
*drv
= snd_soc_platform_get_drvdata(platform
);
1522 unsigned int gains
= ARRAY_SIZE(sst_gain_controls
)/3;
1524 drv
->byte_stream
= devm_kzalloc(platform
->dev
,
1525 SST_MAX_BIN_BYTES
, GFP_KERNEL
);
1526 if (!drv
->byte_stream
)
1529 snd_soc_dapm_new_controls(dapm
, sst_dapm_widgets
,
1530 ARRAY_SIZE(sst_dapm_widgets
));
1531 snd_soc_dapm_add_routes(dapm
, intercon
,
1532 ARRAY_SIZE(intercon
));
1533 snd_soc_dapm_new_widgets(dapm
->card
);
1535 for (i
= 0; i
< gains
; i
++) {
1536 sst_gains
[i
].mute
= SST_GAIN_MUTE_DEFAULT
;
1537 sst_gains
[i
].l_gain
= SST_GAIN_VOLUME_DEFAULT
;
1538 sst_gains
[i
].r_gain
= SST_GAIN_VOLUME_DEFAULT
;
1539 sst_gains
[i
].ramp_duration
= SST_GAIN_RAMP_DURATION_DEFAULT
;
1542 ret
= snd_soc_add_platform_controls(platform
, sst_gain_controls
,
1543 ARRAY_SIZE(sst_gain_controls
));
1547 /* Initialize algo control params */
1548 ret
= sst_algo_control_init(platform
->dev
);
1551 ret
= snd_soc_add_platform_controls(platform
, sst_algo_controls
,
1552 ARRAY_SIZE(sst_algo_controls
));
1556 ret
= snd_soc_add_platform_controls(platform
, sst_slot_controls
,
1557 ARRAY_SIZE(sst_slot_controls
));
1561 ret
= sst_map_modules_to_pipe(platform
);