kernel_samsung_a53x/sound/soc/samsung/abox/abox.h
Nahuel Gómez 50b38430ba sound: abox: Bump buffer sizes up
I'm not sure if this will help, but the idea is to give the codec more room for error, since currently there is audio crackling under moderate CPU load.

Signed-off-by: Nahuel Gómez <nahuelgomez329@gmail.com>
2024-11-17 17:40:16 +01:00

952 lines
25 KiB
C
Executable file

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* ALSA SoC - Samsung Abox driver
*
* Copyright (c) 2016 Samsung Electronics Co. Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __SND_SOC_ABOX_H
#define __SND_SOC_ABOX_H
#include <sound/samsung/abox.h>
#include <linux/miscdevice.h>
#include <linux/dma-direction.h>
#include <soc/samsung/memlogger.h>
#include <soc/samsung/sysevent.h>
#include "abox_qos.h"
#define DEFAULT_CPU_GEAR_ID (0xAB0CDEFA)
#define TEST_CPU_GEAR_ID (DEFAULT_CPU_GEAR_ID + 1)
#define DEFAULT_LIT_FREQ_ID DEFAULT_CPU_GEAR_ID
#define DEFAULT_BIG_FREQ_ID DEFAULT_CPU_GEAR_ID
#define DEFAULT_HMP_BOOST_ID DEFAULT_CPU_GEAR_ID
#define DEFAULT_INT_FREQ_ID DEFAULT_CPU_GEAR_ID
#define DEFAULT_MIF_FREQ_ID DEFAULT_CPU_GEAR_ID
#define DEFAULT_SYS_POWER_ID DEFAULT_CPU_GEAR_ID
#define BUFFER_BYTES_MIN (SZ_512K)
#define BUFFER_BYTES_MAX (SZ_1M)
#define PERIOD_BYTES_MIN (SZ_64)
#define PERIOD_BYTES_MAX (BUFFER_BYTES_MAX / 2)
#define SRAM_FIRMWARE_SIZE CONFIG_SND_SOC_SAMSUNG_ABOX_SRAM_SIZE
#define DRAM_FIRMWARE_SIZE CONFIG_SND_SOC_SAMSUNG_ABOX_DRAM_SIZE
#define IOVA_DRAM_FIRMWARE (0x80000000)
#define IOVA_RDMA_BUFFER_BASE (0x91000000)
#define IOVA_RDMA_BUFFER(x) (IOVA_RDMA_BUFFER_BASE + (SZ_1M * (x)))
#define IOVA_WDMA_BUFFER_BASE (0x92000000)
#define IOVA_WDMA_BUFFER(x) (IOVA_WDMA_BUFFER_BASE + (SZ_1M * (x)))
#define IOVA_COMPR_BUFFER_BASE (0x93000000)
#define IOVA_COMPR_BUFFER(x) (IOVA_COMPR_BUFFER_BASE + (SZ_1M * (x)))
#define IOVA_VDMA_BUFFER_BASE (0x94000000)
#define IOVA_VDMA_BUFFER(x) (IOVA_VDMA_BUFFER_BASE + (SZ_1M * (x)))
#define IOVA_DUAL_BUFFER_BASE (0x98000000)
#define IOVA_DUAL_BUFFER(x) (IOVA_DUAL_BUFFER_BASE + (SZ_1M * (x)))
#define IOVA_DDMA_BUFFER_BASE (0x99000000)
#define IOVA_DDMA_BUFFER(x) (IOVA_DDMA_BUFFER_BASE + (SZ_1M * (x)))
#define IOVA_UDMA_RD_BUFFER_BASE (0x9C000000)
#define IOVA_UDMA_RD_BUFFER(x) (IOVA_UDMA_RD_BUFFER_BASE + \
(SZ_1M * (x)))
#define IOVA_UDMA_WR_BUFFER_BASE (0x9C400000)
#define IOVA_UDMA_WR_BUFFER(x) (IOVA_UDMA_WR_BUFFER_BASE + \
(SZ_1M * (x)))
#define IOVA_UDMA_WR_DUAL_BUFFER_BASE (0x9C800000)
#define IOVA_UDMA_WR_DUAL_BUFFER(x) (IOVA_UDMA_WR_DUAL_BUFFER_BASE + \
(SZ_1M * (x)))
#define IOVA_UDMA_WR_DBG_BUFFER_BASE (0x9CC00000)
#define IOVA_UDMA_WR_DBG_BUFFER(x) (IOVA_UDMA_WR_DBG_BUFFER_BASE + \
(SZ_1M * (x)))
#define IOVA_VSS_FIRMWARE (0xA0000000)
#define IOVA_VSS_PARAMETER (0xA1000000)
#define IOVA_VSS_PCI (0xA2000000)
#define IOVA_VSS_PCI_DOORBELL (0xA3000000)
#define IOVA_DUMP_BUFFER (0xD0000000)
#define IOVA_SILENT_LOG (0xE0000000)
#define PHSY_VSS_FIRMWARE (0xFEE00000)
#define PHSY_VSS_SIZE (SZ_8M)
#define ABOX_LOG_OFFSET (0xb00000)
#define ABOX_LOG_MAJOR_OFFSET (0x900000)
#define ABOX_LOG_SIZE (SZ_1M)
#define ABOX_SLOG_OFFSET (9 * SZ_1M)
#define ABOX_SLOG_DATA_OFFSET (ABOX_SLOG_OFFSET + 0x10)
#define ABOX_PCI_DOORBELL_OFFSET (0x10000)
#define ABOX_PCI_DOORBELL_SIZE (SZ_16K)
#define LIMIT_IN_JIFFIES (msecs_to_jiffies(1000))
#define ABOX_CPU_GEAR_CALL_VSS (0xCA11)
#define ABOX_CPU_GEAR_CALL_KERNEL (0xCA12)
#define ABOX_CPU_GEAR_CALL ABOX_CPU_GEAR_CALL_VSS
#define ABOX_CPU_GEAR_ABSOLUTE (0xABC0ABC0)
#define ABOX_CPU_GEAR_BOOT (0xB00D)
#define ABOX_CPU_GEAR_MAX (1)
#define ABOX_CPU_GEAR_MIN (100)
#define ABOX_CPU_GEAR_DAI 0xDA100000
#define ABOX_SAMPLING_RATES (SNDRV_PCM_RATE_KNOT)
#define ABOX_SAMPLE_FORMATS (SNDRV_PCM_FMTBIT_S16\
| SNDRV_PCM_FMTBIT_S24\
| SNDRV_PCM_FMTBIT_S24_3LE\
| SNDRV_PCM_FMTBIT_S32)
#define ABOX_SUPPLEMENT_SIZE (SZ_128)
#define ABOX_IPC_QUEUE_SIZE (SZ_64)
#define CALLIOPE_VERSION(class, year, month, minor) \
((class << 24) | \
((year - 1 + 'A') << 16) | \
((month - 1 + 'A') << 8) | \
((minor + '0') << 0))
#define ABOX_QUIRK_BIT_ARAM_MODE BIT(0)
#define ABOX_QUIRK_STR_ARAM_MODE "aram mode"
#define ABOX_QUIRK_BIT_INT_SKEW BIT(1)
#define ABOX_QUIRK_STR_INT_SKEW "int skew"
#define ABOX_QUIRK_BIT_SILENT_RESET BIT(2)
#define ABOX_QUIRK_STR_SILENT_RESET "silent reset"
#define ABOX_QUIRK_BIT_FORCE_32BIT BIT(3)
#define ABOX_QUIRK_STR_FORCE_32BIT "force 32bit"
enum abox_dai {
ABOX_NONE,
ABOX_SIFSM,
ABOX_SIFST,
ABOX_RDMA0 = 0x10,
ABOX_RDMA1,
ABOX_RDMA2,
ABOX_RDMA3,
ABOX_RDMA4,
ABOX_RDMA5,
ABOX_RDMA6,
ABOX_RDMA7,
ABOX_RDMA8,
ABOX_RDMA9,
ABOX_RDMA10,
ABOX_RDMA11,
ABOX_WDMA0 = 0x20,
ABOX_WDMA1,
ABOX_WDMA2,
ABOX_WDMA3,
ABOX_WDMA4,
ABOX_WDMA5,
ABOX_WDMA6,
ABOX_WDMA7,
ABOX_WDMA8,
ABOX_WDMA9,
ABOX_WDMA10,
ABOX_WDMA11,
ABOX_WDMA0_DUAL = 0x30,
ABOX_WDMA1_DUAL,
ABOX_WDMA2_DUAL,
ABOX_WDMA3_DUAL,
ABOX_WDMA4_DUAL,
ABOX_WDMA5_DUAL,
ABOX_WDMA6_DUAL,
ABOX_WDMA7_DUAL,
ABOX_WDMA8_DUAL,
ABOX_WDMA9_DUAL,
ABOX_WDMA10_DUAL,
ABOX_WDMA11_DUAL,
ABOX_DDMA0 = 0x40,
ABOX_DDMA1,
ABOX_DDMA2,
ABOX_DDMA3,
ABOX_DDMA4,
ABOX_DDMA5,
ABOX_UAIF0 = 0x50,
ABOX_UAIF1,
ABOX_UAIF2,
ABOX_UAIF3,
ABOX_UAIF4,
ABOX_UAIF5,
ABOX_UAIF6,
ABOX_DSIF,
ABOX_SPDY,
ABOX_RDMA0_BE = 0x60,
ABOX_RDMA1_BE,
ABOX_RDMA2_BE,
ABOX_RDMA3_BE,
ABOX_RDMA4_BE,
ABOX_RDMA5_BE,
ABOX_RDMA6_BE,
ABOX_RDMA7_BE,
ABOX_RDMA8_BE,
ABOX_RDMA9_BE,
ABOX_RDMA10_BE,
ABOX_RDMA11_BE,
ABOX_WDMA0_BE = 0x70,
ABOX_WDMA1_BE,
ABOX_WDMA2_BE,
ABOX_WDMA3_BE,
ABOX_WDMA4_BE,
ABOX_WDMA5_BE,
ABOX_WDMA6_BE,
ABOX_WDMA7_BE,
ABOX_WDMA8_BE,
ABOX_WDMA9_BE,
ABOX_WDMA10_BE,
ABOX_WDMA11_BE,
ABOX_SIFS0 = 0x80, /* Virtual DAI */
ABOX_SIFS1, /* Virtual DAI */
ABOX_SIFS2, /* Virtual DAI */
ABOX_SIFS3, /* Virtual DAI */
ABOX_SIFS4, /* Virtual DAI */
ABOX_SIFS5, /* Virtual DAI */
ABOX_SIFS6, /* Virtual DAI */
ABOX_NSRC0 = 0x90, /* Virtual DAI */
ABOX_NSRC1, /* Virtual DAI */
ABOX_NSRC2, /* Virtual DAI */
ABOX_NSRC3, /* Virtual DAI */
ABOX_NSRC4, /* Virtual DAI */
ABOX_NSRC5, /* Virtual DAI */
ABOX_NSRC6, /* Virtual DAI */
ABOX_NSRC7, /* Virtual DAI */
ABOX_NSRC8, /* Virtual DAI */
ABOX_NSRC9, /* Virtual DAI */
ABOX_NSRC10, /* Virtual DAI */
ABOX_NSRC11, /* Virtual DAI */
ABOX_USB = 0xA0, /* Virtual DAI */
ABOX_FWD, /* Virtual DAI */
ABOX_UDMA_RD0 = 0xC0,
ABOX_UDMA_RD1,
ABOX_UDMA_WR0,
ABOX_UDMA_WR1,
ABOX_UDMA_WR0_DUAL,
ABOX_UDMA_WR1_DUAL,
ABOX_UDMA_WR_DBG0,
};
/* SIFS should be treated as DAI to manage bclk usage and count value */
#define ABOX_DAI_COUNT (ABOX_NSRC0 - ABOX_UAIF0 + 1)
enum abox_widget {
ABOX_WIDGET_SPUS_IN0,
ABOX_WIDGET_SPUS_IN1,
ABOX_WIDGET_SPUS_IN2,
ABOX_WIDGET_SPUS_IN3,
ABOX_WIDGET_SPUS_IN4,
ABOX_WIDGET_SPUS_IN5,
ABOX_WIDGET_SPUS_IN6,
ABOX_WIDGET_SPUS_IN7,
ABOX_WIDGET_SPUS_IN8,
ABOX_WIDGET_SPUS_IN9,
ABOX_WIDGET_SPUS_IN10,
ABOX_WIDGET_SPUS_IN11,
ABOX_WIDGET_SPUS_ASRC0,
ABOX_WIDGET_SPUS_ASRC1,
ABOX_WIDGET_SPUS_ASRC2,
ABOX_WIDGET_SPUS_ASRC3,
ABOX_WIDGET_SPUS_ASRC4,
ABOX_WIDGET_SPUS_ASRC5,
ABOX_WIDGET_SPUS_ASRC6,
ABOX_WIDGET_SPUS_ASRC7,
ABOX_WIDGET_SIFS0,
ABOX_WIDGET_SIFS1,
ABOX_WIDGET_SIFS2,
ABOX_WIDGET_SIFS3,
ABOX_WIDGET_SIFS4,
ABOX_WIDGET_SIFS5,
ABOX_WIDGET_SIFS6,
ABOX_WIDGET_SIFS7,
ABOX_WIDGET_NSRC0,
ABOX_WIDGET_NSRC1,
ABOX_WIDGET_NSRC2,
ABOX_WIDGET_NSRC3,
ABOX_WIDGET_NSRC4,
ABOX_WIDGET_NSRC5,
ABOX_WIDGET_NSRC6,
ABOX_WIDGET_NSRC7,
ABOX_WIDGET_NSRC8,
ABOX_WIDGET_NSRC9,
ABOX_WIDGET_NSRC10,
ABOX_WIDGET_NSRC11,
ABOX_WIDGET_SPUM_ASRC0,
ABOX_WIDGET_SPUM_ASRC1,
ABOX_WIDGET_SPUM_ASRC2,
ABOX_WIDGET_SPUM_ASRC3,
ABOX_WIDGET_UDMA_RD0,
ABOX_WIDGET_UDMA_RD1,
ABOX_WIDGET_UDMA_WR0,
ABOX_WIDGET_UDMA_WR1,
ABOX_WIDGET_COUNT,
};
enum calliope_state {
CALLIOPE_DISABLED,
CALLIOPE_DISABLING,
CALLIOPE_ENABLING,
CALLIOPE_ENABLED,
CALLIOPE_STATE_COUNT,
};
enum system_state {
SYSTEM_CALL,
SYSTEM_OFFLOAD,
SYSTEM_IDLE,
SYSTEM_STATE_COUNT
};
enum llc_state {
LLC_CALL_BUSY,
LLC_CALL_IDLE,
LLC_OFFLOAD_BUSY,
LLC_OFFLOAD_IDLE,
LLC_STATE_COUNT,
};
enum audio_mode {
MODE_NORMAL,
MODE_RINGTONE,
MODE_IN_CALL,
MODE_IN_COMMUNICATION,
MODE_IN_VIDEOCALL,
MODE_RESERVED0,
MODE_RESERVED1,
MODE_IN_LOOPBACK,
};
enum sound_type {
SOUND_TYPE_VOICE,
SOUND_TYPE_SPEAKER,
SOUND_TYPE_HEADSET,
SOUND_TYPE_BTVOICE,
SOUND_TYPE_USB,
SOUND_TYPE_CALLFWD,
};
enum qchannel {
ABOX_CCLK_CORE,
ABOX_ACLK,
ABOX_BCLK_UAIF0,
ABOX_BCLK_UAIF1,
ABOX_BCLK_UAIF2,
ABOX_BCLK_UAIF3,
ABOX_BCLK_UAIF4,
ABOX_BCLK_UAIF5,
ABOX_BCLK_UAIF6,
ABOX_BCLK_RESERVED,
ABOX_BCLK_DSIF,
ABOX_CCLK_ASB = 16,
ABOX_PCMC_CLK,
ABOX_XCLK0,
ABOX_XCLK1,
ABOX_XCLK2,
ABOX_CCLK_ACP,
};
enum abox_region {
ABOX_REG_SFR,
ABOX_REG_SYSREG,
ABOX_REG_SRAM,
ABOX_REG_DEVICE_LAST,
ABOX_REG_GPR = ABOX_REG_DEVICE_LAST,
ABOX_REG_GICD,
ABOX_REG_INT_LAST,
ABOX_REG_DRAM = ABOX_REG_INT_LAST,
ABOX_REG_DUMP,
ABOX_REG_LOG,
ABOX_REG_SLOG,
ABOX_REG_COUNT,
};
enum mux_pcmc {
ABOX_PCMC_OSC,
ABOX_PCMC_CP,
ABOX_PCMC_AUD
};
enum debug_mode {
DEBUG_MODE_NONE,
DEBUG_MODE_DRAM,
DEBUG_MODE_FILE,
DEBUG_MODE_COUNT,
};
struct abox_ipc {
struct device *dev;
int hw_irq;
unsigned long long put_time;
unsigned long long get_time;
size_t size;
ABOX_IPC_MSG msg;
};
struct abox_ipc_action {
struct list_head list;
const struct device *dev;
int ipc_id;
abox_ipc_handler_t handler;
void *data;
};
struct abox_iommu_mapping {
struct list_head list;
unsigned long iova; /* IO virtual address */
unsigned char *area; /* virtual pointer */
dma_addr_t addr; /* physical address */
size_t bytes; /* buffer size in bytes */
};
struct abox_dram_request {
unsigned int id;
bool on;
unsigned long long updated;
};
struct abox_extra_firmware {
struct list_head list;
struct mutex lock;
const struct firmware *firmware;
char name[SZ_32];
unsigned int idx;
unsigned int area;
unsigned int offset;
unsigned int iova;
bool kcontrol;
bool changeable;
};
struct abox_event_notifier {
void *priv;
int (*notify)(void *priv, bool en);
};
struct abox_component {
struct ABOX_COMPONENT_DESCRIPTIOR *desc;
bool registered;
struct list_head value_list;
};
struct abox_component_kcontrol_value {
struct ABOX_COMPONENT_DESCRIPTIOR *desc;
struct ABOX_COMPONENT_CONTROL *control;
struct list_head list;
bool cache_only;
int cache[];
};
struct abox_sram_vts {
struct device *dev;
bool enable;
bool enabled;
struct work_struct request_work;
};
struct abox_pcmc {
struct clk *clk_cp_pcmc;
struct clk *clk_aud_pcmc;
enum mux_pcmc next;
enum mux_pcmc cur;
unsigned long rate_osc;
unsigned long rate_cp_pcmc;
unsigned long rate_aud_pcmc;
struct work_struct request_work;
};
struct abox_data {
struct device *dev;
struct snd_soc_component *cmpnt;
struct regmap *regmap;
struct regmap *timer_regmap;
void __iomem *sfr_base;
void __iomem *sysreg_base;
void __iomem *sram_base;
void __iomem *timer_base;
phys_addr_t sfr_phys;
size_t sfr_size;
phys_addr_t sysreg_phys;
size_t sysreg_size;
phys_addr_t sram_phys;
size_t sram_size;
void *dram_base;
dma_addr_t dram_phys;
void *dump_base;
phys_addr_t dump_phys;
void *slog_base;
phys_addr_t slog_phys;
size_t slog_size;
struct iommu_domain *iommu_domain;
void *ipc_tx_addr;
size_t ipc_tx_size;
void *ipc_rx_addr;
size_t ipc_rx_size;
void *shm_addr;
size_t shm_size;
struct abox2host_hndshk_tag *hndshk_tag;
int clk_diff_ppb;
unsigned int bootargs_offset;
unsigned int slogargs_offset;
unsigned int if_count;
unsigned int rdma_count;
unsigned int wdma_count;
unsigned int udma_rd_count;
unsigned int udma_wr_count;
unsigned int atune_count;
unsigned int calliope_version;
struct list_head firmware_extra;
const char *bootargs;
struct device *dev_gic;
struct device *dev_if[9];
struct device *dev_rdma[16];
struct device *dev_wdma[16];
struct device *dev_udma_rd[4];
struct device *dev_udma_wr[4];
struct workqueue_struct *ipc_workqueue;
struct work_struct ipc_work;
struct abox_ipc ipc_queue[ABOX_IPC_QUEUE_SIZE];
int ipc_queue_start;
int ipc_queue_end;
spinlock_t ipc_queue_lock;
wait_queue_head_t ipc_wait_queue;
wait_queue_head_t boot_wait_queue;
wait_queue_head_t wait_queue;
wait_queue_head_t offline_poll_wait;
struct clk *clk_pll;
struct clk *clk_pll1;
struct clk *clk_audif;
struct clk *clk_cpu;
struct clk *clk_dmic;
struct clk *clk_bus;
struct clk *clk_cnt;
struct clk *clk_sclk;
unsigned int uaif_max_div;
struct pinctrl *pinctrl;
unsigned long quirks;
unsigned int cpu_gear_min;
struct abox_dram_request dram_requests[16];
unsigned long audif_rates[ABOX_DAI_COUNT];
unsigned int sif_rate[SET_SIFS0_FORMAT - SET_SIFS0_RATE];
snd_pcm_format_t sif_format[SET_SIFS0_FORMAT - SET_SIFS0_RATE];
unsigned int sif_channels[SET_SIFS0_FORMAT - SET_SIFS0_RATE];
struct abox_event_notifier event_notifier[ABOX_WIDGET_COUNT];
int apf_coef[2][16];
struct work_struct register_component_work;
struct abox_component components[16];
struct list_head ipc_actions;
struct list_head iommu_maps;
spinlock_t iommu_lock;
bool enabled;
bool restored;
bool no_profiling;
enum debug_mode debug_mode;
bool vss_disabled;
bool system_state[SYSTEM_STATE_COUNT];
bool sifs_cnt_dirty[SET_SIFM0_RATE - SET_SIFS0_RATE];
enum calliope_state calliope_state;
bool failsafe;
bool error;
struct notifier_block qos_nb;
struct notifier_block pm_nb;
struct notifier_block itmon_nb;
int pm_qos_int[5];
int pm_qos_aud[16];
unsigned int pm_qos_stable_min;
unsigned int sys_acp_con[2];
int llc_way[LLC_STATE_COUNT];
struct work_struct restore_data_work;
struct work_struct boot_done_work;
struct delayed_work boot_clear_work;
struct delayed_work wdt_work;
unsigned long long audio_mode_time;
enum audio_mode audio_mode;
enum sound_type sound_type;
struct wakeup_source *ws;
struct memlog *drvlog_desc;
struct memlog_obj *drv_log_file_obj;
struct memlog_obj *drv_log_obj;
struct memlog *dump_desc;
struct sysevent_desc sysevent_desc;
struct sysevent_device *sysevent_dev;
struct abox_sram_vts sram_vts;
struct abox_pcmc pcmc;
};
/* sub-driver list */
extern struct platform_driver samsung_abox_debug_driver;
extern struct platform_driver samsung_abox_pci_driver;
extern struct platform_driver samsung_abox_core_driver;
extern struct platform_driver samsung_abox_dump_driver;
extern struct platform_driver samsung_abox_dma_driver;
extern struct platform_driver samsung_abox_vdma_driver;
extern struct platform_driver samsung_abox_wdma_driver;
extern struct platform_driver samsung_abox_rdma_driver;
extern struct platform_driver samsung_abox_if_driver;
extern struct platform_driver samsung_abox_vss_driver;
extern struct platform_driver samsung_abox_effect_driver;
extern struct platform_driver samsung_abox_tplg_driver;
/**
* Test quirk
* @param[in] data pointer to abox_data structure
* @param[in] quirk quirk bit
* @return true or false
*/
static inline bool abox_test_quirk(struct abox_data *data, unsigned long quirk)
{
return !!(data->quirks & quirk);
}
/**
* Get SFR of sample format
* @param[in] width count of bit in sample
* @param[in] channel count of channel
* @return SFR of sample format
*/
static inline u32 abox_get_format(u32 width, u32 channels)
{
return ((((width / 8) - 1) << 3) | (channels - 1));
}
/**
* Get channel from sample format
* @param[in] format SFR of sample format
* @return count of channel
*/
static inline u32 abox_get_channels(u32 format)
{
return ((format & 0x7) + 1);
}
/**
* Get width from sample format
* @param[in] format SFR of sample format
* @return count of bit in sample
*/
static inline u32 abox_get_width(u32 format)
{
return (((format >> 3) + 1) * 8);
}
/**
* Get enum IPC_ID from SNDRV_PCM_STREAM_*
* @param[in] stream SNDRV_PCM_STREAM_*
* @return IPC_PCMPLAYBACK or IPC_PCMCAPTURE
*/
static inline enum IPC_ID abox_stream_to_ipcid(int stream)
{
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
return IPC_PCMPLAYBACK;
else if (stream == SNDRV_PCM_STREAM_CAPTURE)
return IPC_PCMCAPTURE;
else
return -EINVAL;
}
/**
* Get SNDRV_PCM_STREAM_* from enum IPC_ID
* @param[in] ipcid IPC_PCMPLAYBACK or IPC_PCMCAPTURE
* @return SNDRV_PCM_STREAM_*
*/
static inline int abox_ipcid_to_stream(enum IPC_ID ipcid)
{
if (ipcid == IPC_PCMPLAYBACK)
return SNDRV_PCM_STREAM_PLAYBACK;
else if (ipcid == IPC_PCMCAPTURE)
return SNDRV_PCM_STREAM_CAPTURE;
else
return -EINVAL;
}
/**
* set magic value for the firmware
* @param[in] data pointer to abox_data structure
* @param[in] val magic value
*/
extern void abox_set_magic(struct abox_data *data, unsigned int val);
/**
* test given device is abox or not
* @param[in]
* @return true or false
*/
extern bool is_abox(struct device *dev);
/**
* get pointer to abox_data (internal use only)
* @return pointer to abox_data
*/
extern struct abox_data *abox_get_abox_data(void);
/**
* get pointer to abox_data
* @param[in] dev pointer to struct dev which invokes this API
* @return pointer to abox_data
*/
extern struct abox_data *abox_get_data(struct device *dev);
/**
* set system state
* @param[in] data pointer to abox_data structure
* @param[in] state state
* @param[in] en enable or disable
*/
extern int abox_set_system_state(struct abox_data *data,
enum system_state state, bool en);
/**
* get physical address from abox virtual address
* @param[in] data pointer to abox_data structure
* @param[in] addr abox virtual address
* @return physical address
*/
extern phys_addr_t abox_addr_to_phys_addr(struct abox_data *data,
unsigned int addr);
/**
* get resource information
* @param[in] data pointer to abox_data structure
* @param[in] rid abox region index
* @param[in] kaddr returning kernel virtual address is required
* @param[in] buf_size Pointer to size_t value
* @return resource base address
*/
extern void *abox_get_resource_info(struct abox_data *data, enum abox_region rid,
bool kaddr, size_t *buf_size);
/**
* get kernel address from abox virtual address
* @param[in] data pointer to abox_data structure
* @param[in] addr abox virtual address
* @return kernel address
*/
extern void *abox_addr_to_kernel_addr(struct abox_data *data,
unsigned int addr);
/**
* parse address and size from the offset based description
* @param[in] data pointer to abox_data structure
* @param[in] np device node which contains the property
* @param[in] name name of the property
* @param[out] addr virtual address
* @param[out] dma dma address
* @param[out] size size
* @return 0 or error code
*/
extern int abox_of_get_addr(struct abox_data *data, struct device_node *np,
const char *name, void **addr, dma_addr_t *dma, size_t *size);
/**
* Check specific cpu gear request is idle
* @param[in] dev pointer to struct dev which invokes this API
* @param[in] id key which is used as unique handle
* @return true if it is idle or not has been requested, false on otherwise
*/
extern bool abox_cpu_gear_idle(struct device *dev, unsigned int id);
/**
* Request abox cpu clock level
* @param[in] dev pointer to struct dev which invokes this API
* @param[in] data pointer to abox_data structure
* @param[in] id key which is used as unique handle
* @param[in] level gear level or frequency in kHz
* @param[in] name cookie for logging
* @return error code if any
*/
extern int abox_request_cpu_gear(struct device *dev, struct abox_data *data,
unsigned int id, unsigned int level, const char *name);
/**
* Wait for pending cpu gear change
*/
extern void abox_cpu_gear_barrier(void);
/**
* Request abox cpu clock level synchronously
* @param[in] dev pointer to struct dev which invokes this API
* @param[in] data pointer to abox_data structure
* @param[in] id key which is used as unique handle
* @param[in] level gear level or frequency in kHz
* @param[in] name cookie for logging
* @return error code if any
*/
extern int abox_request_cpu_gear_sync(struct device *dev,
struct abox_data *data, unsigned int id, unsigned int level,
const char *name);
/**
* Clear abox cpu clock requests
* @param[in] dev pointer to struct dev which invokes this API
*/
extern void abox_clear_cpu_gear_requests(struct device *dev);
/**
* Clear mif clock requests
* @param[in] dev pointer to struct dev which invokes this API
*/
extern void abox_clear_mif_requests(struct device *dev);
/**
* Request abox cpu clock level with dai
* @param[in] dev pointer to struct dev which invokes this API
* @param[in] data pointer to abox_data structure
* @param[in] dai DAI which is used as unique handle
* @param[in] level gear level or frequency in kHz
* @return error code if any
*/
static inline int abox_request_cpu_gear_dai(struct device *dev,
struct abox_data *data, struct snd_soc_dai *dai,
unsigned int level)
{
unsigned int id = ABOX_CPU_GEAR_DAI | dai->id;
return abox_request_cpu_gear(dev, data, id, level, dai->name);
}
/**
* Request cluster 0 clock level with DAI
* @param[in] dev pointer to struct dev which invokes this API
* @param[in] dai DAI which is used as unique handle
* @param[in] freq frequency in kHz
* @return error code if any
*/
static inline int abox_request_cl0_freq_dai(struct device *dev,
struct snd_soc_dai *dai, unsigned int freq)
{
unsigned int id = ABOX_CPU_GEAR_DAI | dai->id;
return abox_qos_request_cl0(dev, id, freq, dai->name);
}
/**
* Request cluster 1 clock level with DAI
* @param[in] dev pointer to struct dev which invokes this API
* @param[in] dai DAI which is used as unique handle
* @param[in] freq frequency in kHz
* @return error code if any
*/
static inline int abox_request_cl1_freq_dai(struct device *dev,
struct snd_soc_dai *dai, unsigned int freq)
{
unsigned int id = ABOX_CPU_GEAR_DAI | dai->id;
return abox_qos_request_cl1(dev, id, freq, dai->name);
}
/**
* Request cluster 2 clock level with DAI
* @param[in] dev pointer to struct dev which invokes this API
* @param[in] dai DAI which is used as unique handle
* @param[in] freq frequency in kHz
* @return error code if any
*/
static inline int abox_request_cl2_freq_dai(struct device *dev,
struct snd_soc_dai *dai, unsigned int freq)
{
unsigned int id = ABOX_CPU_GEAR_DAI | dai->id;
return abox_qos_request_cl2(dev, id, freq, dai->name);
}
/**
* Register an notifier to power change notification chain
* @param[in] nb new entry in notifier chain
* @return error code if any
*/
int abox_power_notifier_register(struct notifier_block *nb);
/**
* Unregister an notifier from power change notification chain
* @param[in] nb entry in notifier chain
* @return error code if any
*/
int abox_power_notifier_unregister(struct notifier_block *nb);
/**
* Register uaif to abox
* @param[in] dev pointer to struct dev which invokes this API
* @param[in] data pointer to abox_data structure
* @param[in] id id of the uaif
* @param[in] rate sampling rate
* @param[in] channels number of channels
* @param[in] width number of bit in sample
* @return error code if any
*/
extern int abox_register_bclk_usage(struct device *dev, struct abox_data *data,
enum abox_dai id, unsigned int rate, unsigned int channels,
unsigned int width);
/**
* disable or enable qchannel of a clock
* @param[in] dev pointer to struct dev which invokes this API
* @param[in] data pointer to abox_data structure
* @param[in] clk clock id
* @param[in] disable disable or enable
*/
extern int abox_disable_qchannel(struct device *dev, struct abox_data *data,
enum qchannel clk, int disable);
/**
* wait for restoring abox from suspend
* @param[in] data pointer to abox_data structure
*/
extern void abox_wait_restored(struct abox_data *data);
/**
* register sound card with specific order
* @param[in] dev calling device
* @param[in] card sound card to register
* @param[in] idx order of the sound card
* @return 0 or error code
*/
extern int abox_register_extra_sound_card(struct device *dev,
struct snd_soc_card *card, unsigned int idx);
/**
* add controls for extra firmwares
* @param[in] data pointer to abox_data structure
* @return 0 or error code
*/
extern int abox_add_extra_firmware_controls(struct abox_data *data);
/**
* add or update extra firmware
* @param[in] dev calling device
* @param[in] data pointer to abox_data structure
* @param[in] idx index of firmware. It should be unique.
* @param[in] name name of firmware
* @param[in] area download area of firmware
* @param[in] offset offset of firmware
* @param[in] changeable changeable of firmware
* @return 0 or error code
*/
extern int abox_add_extra_firmware(struct device *dev,
struct abox_data *data, int idx,
const char *name, unsigned int area,
unsigned int offset, bool changeable);
/**
* abox silent reset for abox recovery
* @param[in] data pointer to abox_data structure
* @param[in] reset whether abox silent reset is required
*/
extern void abox_silent_reset(struct abox_data *data, bool reset);
/**
* wait until abox is booted
* @param[in] data pointer to abox_data structure
* @param[in] jiffies timeout in jiffies
* @return if the time is elapsed, 0 or 1. if not, remaining jiffies.
* refer to the wait_event_timeout().
*/
long abox_wait_for_boot(struct abox_data *data, unsigned long jiffies);
/**
* get waiting time in nano seconds
* @param[in] coarse parameter to determine time
*/
extern unsigned long abox_get_waiting_ns(bool coarse);
/**
* get waiting time in jiffies
* @param[in] coarse parameter to determine time
*/
static inline unsigned long abox_get_waiting_jiffies(bool coarse)
{
return nsecs_to_jiffies(abox_get_waiting_ns(coarse));
}
#endif /* __SND_SOC_ABOX_H */