5:1
  B   ˆl–Ü4ý( ©³( 	Å€fàB¦-ÿ¿„N	ß_†I|¥�+a–ßi~”*j"Tâ�Æß¸ÔÅ£Ä ?÷     /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
 * This file is provided under a dual BSD/GPLv2 license.  When using or
 * redistributing this file, you may do so under either license.
 *
 * Copyright(c) 2019 Intel Corporation
 *
 * Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
 */

#ifndef __SOUND_SOC_SOF_AUDIO_H
#define __SOUND_SOC_SOF_AUDIO_H

#include <linux/workqueue.h>

#include <sound/soc.h>
#include <sound/control.h>
#include <sound/sof/stream.h> /* needs to be included before control.h */
#include <sound/sof/control.h>
#include <sound/sof/dai.h>
#include <sound/sof/topology.h>
#include "sof-priv.h"

#define SOF_AUDIO_PCM_DRV_NAME	"sof-audio-component"

/*
 * The ipc4 firmware only supports up to 8 sink or source pins
 * per widget, because only 3 bits are used for queue(pin) ID
 * in ipc4 protocol.
 */
#define SOF_WIDGET_MAX_NUM_PINS	8

/* Widget pin type */
#define SOF_PIN_TYPE_INPUT	0
#define SOF_PIN_TYPE_OUTPUT	1

/* max number of FE PCMs before BEs */
#define SOF_BE_PCM_BASE		16

#define DMA_CHAN_INVALID	0xFFFFFFFF

#define WIDGET_IS_DAI(id) ((id) == snd_soc_dapm_dai_in || (id) == snd_soc_dapm_dai_out)
#define WIDGET_IS_AIF(id) ((id) == snd_soc_dapm_aif_in || (id) == snd_soc_dapm_aif_out)
#define WIDGET_IS_AIF_OR_DAI(id) (WIDGET_IS_DAI(id) || WIDGET_IS_AIF(id))
#define WIDGET_IS_COPIER(id) (WIDGET_IS_AIF_OR_DAI(id) || (id) == snd_soc_dapm_buffer)

#define SOF_DAI_PARAM_INTEL_SSP_MCLK		0
#define SOF_DAI_PARAM_INTEL_SSP_BCLK		1
#define SOF_DAI_PARAM_INTEL_SSP_TDM_SLOTS	2

enum sof_widget_op {
	SOF_WIDGET_PREPARE,
	SOF_WIDGET_SETUP,
	SOF_WIDGET_FREE,
	SOF_WIDGET_UNPREPARE,
};

/*
 * Volume fractional word length define to 16 sets
 * the volume linear gain value to use Qx.16 format
 */
#define VOLUME_FWL	16

#define SOF_TLV_ITEMS 3

static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size)
{
	if (value >= size)
		return volume_map[size - 1];

	return volume_map[value];
}

static inline u32 ipc_to_mixer(u32 value, u32 *volume_map, int size)
{
	int i;

	for (i = 0; i < size; i++) {
		if (volume_map[i] >= value)
			return i;
	}

	return i - 1;
}

struct snd_sof_widget;
struct snd_sof_route;
struct snd_sof_control;
struct snd_sof_dai;
struct snd_sof_pcm;

struct snd_sof_dai_config_data {
	int dai_index;
	int dai_data; /* contains DAI-specific information */
	int dai_node_id; /* contains DAI-specific information for Gateway configuration */
};

/**
 * struct sof_ipc_pcm_ops - IPC-specific PCM ops
 * @hw_params: Function pointer for hw_params
 * @hw_free: Function pointer for hw_free
 * @trigger: Function pointer for trigger
 * @dai_link_fixup: Function pointer for DAI link fixup
 * @pcm_setup: Function pointer for IPC-specific PCM set up that can be used for allocating
 *	       additional memory in the SOF PCM stream structure
 * @pcm_free: Function pointer for PCM free that can be used for freeing any
 *	       additional memory in the SOF PCM stream structure
 * @pointer: Function pointer for pcm pointer
 *	     Note: the @pointer callback may return -EOPNOTSUPP which should be
 *		   handled in a same way as if the callback is not provided
 * @delay: Function pointer for pcm delay reporting
 * @reset_hw_params_during_stop: Flag indicating whether the hw_params should be reset during the
 *				 STOP pcm trigger
 * @ipc_first_on_start: Send IPC before invoking platform trigger during
 *				START/PAUSE_RELEASE triggers
 * @platform_stop_during_hw_free: Invoke the platform trigger during hw_free. This is needed for
 *				  IPC4 where a pipeline is only paused during stop/pause/suspend
 *				  triggers. The FW keeps the host DMA running in this case and
 *				  therefore the host must do the same and should stop the DMA during
 *				  hw_free.
 * @d0i3_supported_in_s0ix: Allow DSP D0I3 during S0iX
 */
struct sof_ipc_pcm_ops {
	int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream,
			 struct snd_pcm_hw_params *params,
			 struct snd_sof_platfor