linux/sound/soc/intel/atom/sst-atom-controls.c

// SPDX-License-Identifier: GPL-2.0-only
 /*
 *  sst-atom-controls.c - Intel MID Platform driver DPCM ALSA controls for Mrfld
 *
 *  Copyright (C) 2013-14 Intel Corp
 *  Author: Omair Mohammed Abdullah <[email protected]>
 *	Vinod Koul <[email protected]>
 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *  In the dpcm driver modelling when a particular FE/BE/Mixer/Pipe is active
 *  we forward the settings and parameters, rest we keep the values  in
 *  driver and forward when DAPM enables them
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
#define pr_fmt(fmt)

#include <linux/slab.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include "sst-mfld-platform.h"
#include "sst-atom-controls.h"

static int sst_fill_byte_control(struct sst_data *drv,
					 u8 ipc_msg, u8 block,
					 u8 task_id, u8 pipe_id,
					 u16 len, void *cmd_data)
{}

static int sst_fill_and_send_cmd_unlocked(struct sst_data *drv,
				 u8 ipc_msg, u8 block, u8 task_id, u8 pipe_id,
				 void *cmd_data, u16 len)
{}

/**
 * sst_fill_and_send_cmd - generate the IPC message and send it to the FW
 * @drv: sst_data
 * @ipc_msg: type of IPC (CMD, SET_PARAMS, GET_PARAMS)
 * @block: block index
 * @task_id: task index
 * @pipe_id: pipe index
 * @cmd_data: the IPC payload
 * @len: length of data to be sent
 */
static int sst_fill_and_send_cmd(struct sst_data *drv,
				 u8 ipc_msg, u8 block, u8 task_id, u8 pipe_id,
				 void *cmd_data, u16 len)
{}

/*
 * tx map value is a bitfield where each bit represents a FW channel
 *
 *			3 2 1 0		# 0 = codec0, 1 = codec1
 *			RLRLRLRL	# 3, 4 = reserved
 *
 * e.g. slot 0 rx map =	00001100b -> data from slot 0 goes into codec_in1 L,R
 */
static u8 sst_ssp_tx_map[SST_MAX_TDM_SLOTS] =;

/*
 * rx map value is a bitfield where each bit represents a slot
 *
 *			  76543210	# 0 = slot 0, 1 = slot 1
 *
 * e.g. codec1_0 tx map = 00000101b -> data from codec_out1_0 goes into slot 0, 2
 */
static u8 sst_ssp_rx_map[SST_MAX_TDM_SLOTS] =;

/*
 * NOTE: this is invoked with lock held
 */
static int sst_send_slot_map(struct sst_data *drv)
{}

static int sst_slot_enum_info(struct snd_kcontrol *kcontrol,
		       struct snd_ctl_elem_info *uinfo)
{}

/**
 * sst_slot_get - get the status of the interleaver/deinterleaver control
 * @kcontrol: control pointer
 * @ucontrol: User data
 * Searches the map where the control status is stored, and gets the
 * channel/slot which is currently set for this enumerated control. Since it is
 * an enumerated control, there is only one possible value.
 */
static int sst_slot_get(struct snd_kcontrol *kcontrol,
			struct snd_ctl_elem_value *ucontrol)
{}

/* sst_check_and_send_slot_map - helper for checking power state and sending
 * slot map cmd
 *
 * called with lock held
 */
static int sst_check_and_send_slot_map(struct sst_data *drv, struct snd_kcontrol *kcontrol)
{}

/**
 * sst_slot_put - set the status of interleaver/deinterleaver control
 * @kcontrol: control pointer
 * @ucontrol: User data
 * (de)interleaver controls are defined in opposite sense to be user-friendly
 *
 * Instead of the enum value being the value written to the register, it is the
 * register address; and the kcontrol number (register num) is the value written
 * to the register. This is so that there can be only one value for each
 * slot/channel since there is only one control for each slot/channel.
 *
 * This means that whenever an enum is set, we need to clear the bit
 * for that kcontrol_no for all the interleaver OR deinterleaver registers
 */
static int sst_slot_put(struct snd_kcontrol *kcontrol,
			struct snd_ctl_elem_value *ucontrol)
{}

static int sst_send_algo_cmd(struct sst_data *drv,
			      struct sst_algo_control *bc)
{}

/**
 * sst_find_and_send_pipe_algo - send all the algo parameters for a pipe
 * @drv: sst_data
 * @pipe: string identifier
 * @ids: list of algorithms
 * The algos which are in each pipeline are sent to the firmware one by one
 *
 * Called with lock held
 */
static int sst_find_and_send_pipe_algo(struct sst_data *drv,
					const char *pipe, struct sst_ids *ids)
{}

static int sst_algo_bytes_ctl_info(struct snd_kcontrol *kcontrol,
			    struct snd_ctl_elem_info *uinfo)
{}

static int sst_algo_control_get(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{}

static int sst_algo_control_set(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{}

static int sst_gain_ctl_info(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_info *uinfo)
{}

/**
 * sst_send_gain_cmd - send the gain algorithm IPC to the FW
 * @drv: sst_data
 * @gv:the stored value of gain (also contains rampduration)
 * @task_id: task index
 * @loc_id: location/position index
 * @module_id: module index
 * @mute: flag that indicates whether this was called from the
 *  digital_mute callback or directly. If called from the
 *  digital_mute callback, module will be muted/unmuted based on this
 *  flag. The flag is always 0 if called directly.
 *
 * Called with sst_data.lock held
 *
 * The user-set gain value is sent only if the user-controllable 'mute' control
 * is OFF (indicated by gv->mute). Otherwise, the mute value (MIN value) is
 * sent.
 */
static int sst_send_gain_cmd(struct sst_data *drv, struct sst_gain_value *gv,
			      u16 task_id, u16 loc_id, u16 module_id, int mute)
{}

static int sst_gain_get(struct snd_kcontrol *kcontrol,
			struct snd_ctl_elem_value *ucontrol)
{}

static int sst_gain_put(struct snd_kcontrol *kcontrol,
			struct snd_ctl_elem_value *ucontrol)
{}

static int sst_set_pipe_gain(struct sst_ids *ids,
				struct sst_data *drv, int mute);

static int sst_send_pipe_module_params(struct snd_soc_dapm_widget *w,
		struct snd_kcontrol *kcontrol)
{}

static int sst_generic_modules_event(struct snd_soc_dapm_widget *w,
				     struct snd_kcontrol *k, int event)
{}

static const DECLARE_TLV_DB_SCALE(sst_gain_tlv_common, SST_GAIN_MIN_VALUE * 10, 10, 0);

/* Look up table to convert MIXER SW bit regs to SWM inputs */
static const uint swm_mixer_input_ids[SST_SWM_INPUT_COUNT] =;

/**
 * fill_swm_input - fill in the SWM input ids given the register
 * @cmpnt: ASoC component
 * @swm_input: array of swm_input_ids
 * @reg: the register value is a bit-field inicated which mixer inputs are ON.
 *
 * Use the lookup table to get the input-id and fill it in the
 * structure.
 */
static int fill_swm_input(struct snd_soc_component *cmpnt,
		struct swm_input_ids *swm_input, unsigned int reg)
{}


/*
 * called with lock held
 */
static int sst_set_pipe_gain(struct sst_ids *ids,
			struct sst_data *drv, int mute)
{}

static int sst_swm_mixer_event(struct snd_soc_dapm_widget *w,
			struct snd_kcontrol *k, int event)
{}

/* SBA mixers - 16 inputs */
#define SST_SBA_DECLARE_MIX_CONTROLS(kctl_name)

#define SST_SBA_MIXER_GRAPH_MAP(mix_name)

#define SST_MMX_DECLARE_MIX_CONTROLS(kctl_name)

SST_MMX_DECLARE_MIX_CONTROLS(sst_mix_media0_controls);
SST_MMX_DECLARE_MIX_CONTROLS(sst_mix_media1_controls);

/* 18 SBA mixers */
SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm0_controls);
SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm1_controls);
SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_pcm2_controls);
SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_sprot_l0_controls);
SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l1_controls);
SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_media_l2_controls);
SST_SBA_DECLARE_MIX_CONTROLS(__maybe_unused sst_mix_voip_controls);
SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec0_controls);
SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_codec1_controls);
SST_SBA_DECLARE_MIX_CONTROLS(sst_mix_modem_controls);

/*
 * sst_handle_vb_timer - Start/Stop the DSP scheduler
 *
 * The DSP expects first cmd to be SBA_VB_START, so at first startup send
 * that.
 * DSP expects last cmd to be SBA_VB_IDLE, so at last shutdown send that.
 *
 * Do refcount internally so that we send command only at first start
 * and last end. Since SST driver does its own ref count, invoke sst's
 * power ops always!
 */
int sst_handle_vb_timer(struct snd_soc_dai *dai, bool enable)
{}

int sst_fill_ssp_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
		unsigned int rx_mask, int slots, int slot_width)
{}

static int sst_get_frame_sync_polarity(struct snd_soc_dai *dai,
		unsigned int fmt)
{}

static int sst_get_ssp_mode(struct snd_soc_dai *dai, unsigned int fmt)
{}


int sst_fill_ssp_config(struct snd_soc_dai *dai, unsigned int fmt)
{}

/*
 * sst_ssp_config - contains SSP configuration for media UC
 * this can be overwritten by set_dai_xxx APIs
 */
static const struct sst_ssp_config sst_ssp_configs =;

void sst_fill_ssp_defaults(struct snd_soc_dai *dai)
{}

int send_ssp_cmd(struct snd_soc_dai *dai, const char *id, bool enable)
{}

static int sst_set_be_modules(struct snd_soc_dapm_widget *w,
			 struct snd_kcontrol *k, int event)
{}

static int sst_set_media_path(struct snd_soc_dapm_widget *w,
			      struct snd_kcontrol *k, int event)
{}

static int sst_set_media_loop(struct snd_soc_dapm_widget *w,
			struct snd_kcontrol *k, int event)
{}

static const struct snd_soc_dapm_widget sst_dapm_widgets[] =;

static const struct snd_soc_dapm_route intercon[] =;
static const char * const slot_names[] =;

static const char * const channel_names[] =;

#define SST_INTERLEAVER(xpname, slot_name, slotno)

#define SST_DEINTERLEAVER(xpname, channel_name, channel_no)

static const struct snd_kcontrol_new sst_slot_controls[] =;

/* Gain helper with min/max set */
#define SST_GAIN(name, path_id, task_id, instance, gain_var)

#define SST_VOLUME(name, path_id, task_id, instance, gain_var)

static struct sst_gain_value sst_gains[];

static const struct snd_kcontrol_new sst_gain_controls[] =;

#define SST_GAIN_NUM_CONTROLS
/* the SST_GAIN macro above will create three alsa controls for each
 * instance invoked, gain, mute and ramp duration, which use the same gain
 * cell sst_gain to keep track of data
 * To calculate number of gain cell instances we need to device by 3 in
 * below caulcation for gain cell memory.
 * This gets rid of static number and issues while adding new controls
 */
static struct sst_gain_value sst_gains[ARRAY_SIZE(sst_gain_controls)/SST_GAIN_NUM_CONTROLS];

static const struct snd_kcontrol_new sst_algo_controls[] =;

static int sst_algo_control_init(struct device *dev)
{}

static bool is_sst_dapm_widget(struct snd_soc_dapm_widget *w)
{}

/**
 * sst_send_pipe_gains - send gains for the front-end DAIs
 * @dai: front-end dai
 * @stream: direction
 * @mute: boolean indicating mute status
 *
 * The gains in the pipes connected to the front-ends are muted/unmuted
 * automatically via the digital_mute() DAPM callback. This function sends the
 * gains for the front-end pipes.
 */
int sst_send_pipe_gains(struct snd_soc_dai *dai, int stream, int mute)
{}

/**
 * sst_fill_module_list - populate the list of modules/gains for a pipe
 * @kctl: kcontrol pointer
 * @w: dapm widget
 * @type: widget type
 *
 * Fills the widget pointer in the kcontrol private data, and also fills the
 * kcontrol pointer in the widget private data.
 *
 * Widget pointer is used to send the algo/gain in the .put() handler if the
 * widget is powerd on.
 *
 * Kcontrol pointer is used to send the algo/gain in the widget power ON/OFF
 * event handler. Each widget (pipe) has multiple algos stored in the algo_list.
 */
static int sst_fill_module_list(struct snd_kcontrol *kctl,
	 struct snd_soc_dapm_widget *w, int type)
{}

/**
 * sst_fill_widget_module_info - fill list of gains/algos for the pipe
 * @w: pipe modeled as a DAPM widget
 * @component: ASoC component
 *
 * Fill the list of gains/algos for the widget by looking at all the card
 * controls and comparing the name of the widget with the first part of control
 * name. First part of control name contains the pipe name (widget name).
 */
static int sst_fill_widget_module_info(struct snd_soc_dapm_widget *w,
	struct snd_soc_component *component)
{}

/**
 * sst_fill_linked_widgets - fill the parent pointer for the linked widget
 * @component: ASoC component
 * @ids: sst_ids array
 */
static void sst_fill_linked_widgets(struct snd_soc_component *component,
						struct sst_ids *ids)
{}

/**
 * sst_map_modules_to_pipe - fill algo/gains list for all pipes
 * @component: ASoC component
 */
static int sst_map_modules_to_pipe(struct snd_soc_component *component)
{}

int sst_dsp_init_v2_dpcm(struct snd_soc_component *component)
{}